All pastes #1035988 Raw Edit

board.c

public c v1 · immutable
#1035988 ·published 2008-06-01 16:16 UTC
rendered paste body
#include <stdlib.h>#include <string.h>#include <stdio.h>#include "board.h"#include "attacks.h"#include "bitscan.h"#include "rand.h"/* For FEN conversion, and move->string conversion */char *piecename[2][6] = {	{ "P", "N", "B", "R", "Q", "K" },	{ "p", "n", "b", "r", "q", "k" }};/* Converts int to string. Better than using malloc for 3-length strings. */char *squarename[64] = {	"a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",	"a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",	"a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",	"a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",	"a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",	"a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",	"a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",	"a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"};#ifndef BB_SHIFTFLIP /* see board.h *//* Get a bitboard with only one bit set, on a specified square */bitboard_t bb_square[64] = {	BB(0x0000000000000001), BB(0x0000000000000002), BB(0x0000000000000004), BB(0x0000000000000008),	BB(0x0000000000000010), BB(0x0000000000000020), BB(0x0000000000000040), BB(0x0000000000000080),	BB(0x0000000000000100), BB(0x0000000000000200), BB(0x0000000000000400), BB(0x0000000000000800),	BB(0x0000000000001000), BB(0x0000000000002000), BB(0x0000000000004000), BB(0x0000000000008000),	BB(0x0000000000010000), BB(0x0000000000020000), BB(0x0000000000040000), BB(0x0000000000080000),	BB(0x0000000000100000), BB(0x0000000000200000), BB(0x0000000000400000), BB(0x0000000000800000),	BB(0x0000000001000000), BB(0x0000000002000000), BB(0x0000000004000000), BB(0x0000000008000000),	BB(0x0000000010000000), BB(0x0000000020000000), BB(0x0000000040000000), BB(0x0000000080000000),	BB(0x0000000100000000), BB(0x0000000200000000), BB(0x0000000400000000), BB(0x0000000800000000),	BB(0x0000001000000000), BB(0x0000002000000000), BB(0x0000004000000000), BB(0x0000008000000000),	BB(0x0000010000000000), BB(0x0000020000000000), BB(0x0000040000000000), BB(0x0000080000000000),	BB(0x0000100000000000), BB(0x0000200000000000), BB(0x0000400000000000), BB(0x0000800000000000),	BB(0x0001000000000000), BB(0x0002000000000000), BB(0x0004000000000000), BB(0x0008000000000000),	BB(0x0010000000000000), BB(0x0020000000000000), BB(0x0040000000000000), BB(0x0080000000000000),	BB(0x0100000000000000), BB(0x0200000000000000), BB(0x0400000000000000), BB(0x0800000000000000),	BB(0x1000000000000000), BB(0x2000000000000000), BB(0x4000000000000000), BB(0x8000000000000000),};/* The bitwise negation of SINGLESQUARE(x) */bitboard_t bb_allexcept[64] = {	BB(0xfffffffffffffffe), BB(0xfffffffffffffffd), BB(0xfffffffffffffffb), BB(0xfffffffffffffff7),	BB(0xffffffffffffffef), BB(0xffffffffffffffdf), BB(0xffffffffffffffbf), BB(0xffffffffffffff7f),	BB(0xfffffffffffffeff), BB(0xfffffffffffffdff), BB(0xfffffffffffffbff), BB(0xfffffffffffff7ff),	BB(0xffffffffffffefff), BB(0xffffffffffffdfff), BB(0xffffffffffffbfff), BB(0xffffffffffff7fff),	BB(0xfffffffffffeffff), BB(0xfffffffffffdffff), BB(0xfffffffffffbffff), BB(0xfffffffffff7ffff),	BB(0xffffffffffefffff), BB(0xffffffffffdfffff), BB(0xffffffffffbfffff), BB(0xffffffffff7fffff),	BB(0xfffffffffeffffff), BB(0xfffffffffdffffff), BB(0xfffffffffbffffff), BB(0xfffffffff7ffffff),	BB(0xffffffffefffffff), BB(0xffffffffdfffffff), BB(0xffffffffbfffffff), BB(0xffffffff7fffffff),	BB(0xfffffffeffffffff), BB(0xfffffffdffffffff), BB(0xfffffffbffffffff), BB(0xfffffff7ffffffff),	BB(0xffffffefffffffff), BB(0xffffffdfffffffff), BB(0xffffffbfffffffff), BB(0xffffff7fffffffff),	BB(0xfffffeffffffffff), BB(0xfffffdffffffffff), BB(0xfffffbffffffffff), BB(0xfffff7ffffffffff),	BB(0xffffefffffffffff), BB(0xffffdfffffffffff), BB(0xffffbfffffffffff), BB(0xffff7fffffffffff),	BB(0xfffeffffffffffff), BB(0xfffdffffffffffff), BB(0xfffbffffffffffff), BB(0xfff7ffffffffffff),	BB(0xffefffffffffffff), BB(0xffdfffffffffffff), BB(0xffbfffffffffffff), BB(0xff7fffffffffffff),	BB(0xfeffffffffffffff), BB(0xfdffffffffffffff), BB(0xfbffffffffffffff), BB(0xf7ffffffffffffff),	BB(0xefffffffffffffff), BB(0xdfffffffffffffff), BB(0xbfffffffffffffff), BB(0x7fffffffffffffff),};#endif/* Which squares must be unoccupied for COLOR (1st) to castle on SIDE (2nd) */static bitboard_t castle_clearsquares[2][2] = {	/*   queenside               kingside */	{ BB(0x000000000000000e), BB(0x0000000000000060) }, /* white */	{ BB(0x0e00000000000000), BB(0x6000000000000000) }  /* black */};/* Which squares must be unthreatened for COLOR to castle on SIDE */static bitboard_t castle_safesquares[2][2] = {	/*   queenside               kingside */	{ BB(0x000000000000001e), BB(0x0000000000000070) }, /* white */	{ BB(0x1e00000000000000), BB(0x7000000000000000) }  /* black */};/* A mask for the cols adjacent to a given col - for pawn captures, AND with a * row-mask for the rank you need the pawns to be on */static bitboard_t bb_adjacentcols[8] = {	           BB_FILEB,	BB_FILEA | BB_FILEC,	BB_FILEB | BB_FILED,	BB_FILEC | BB_FILEE,	BB_FILED | BB_FILEF,	BB_FILEE | BB_FILEG,	BB_FILEF | BB_FILEH,	BB_FILEG};/* Rotation translation from normal-oriented square indices to square indices * suitable for setting bits on board_t->occupied{90,45,315}. Note that we * don't use these for move generation at all, just for setting/clearing bits * on the occupied boards. */static int rot90squareindex[64] = {	0,  8, 16, 24, 32, 40, 48, 56,	1,  9, 17, 25, 33, 41, 49, 57,	2, 10, 18, 26, 34, 42, 50, 58,	3, 11, 19, 27, 35, 43, 51, 59,	4, 12, 20, 28, 36, 44, 52, 60,	5, 13, 21, 29, 37, 45, 53, 61,	6, 14, 22, 30, 38, 46, 54, 62,	7, 15, 23, 31, 39, 47, 55, 63};static int rot45squareindex[64] = {	 0,  2,  5,  9, 14, 20, 27, 35,	 1,  4,  8, 13, 19, 26, 34, 42,	 3,  7, 12, 18, 25, 33, 41, 48,	 6, 11, 17, 24, 32, 40, 47, 53,	10, 16, 23, 31, 39, 46, 52, 57,	15, 22, 30, 38, 45, 51, 56, 60,	21, 29, 37, 44, 50, 55, 59, 62,	28, 36, 43, 49, 54, 58, 61, 63};static int rot315squareindex[64] = {	28, 21, 15, 10,  6,  3,  1,  0,	36, 29, 22, 16, 11,  7,  4,  2,	43, 37, 30, 23, 17, 12,  8,  5,	49, 44, 38, 31, 24, 18, 13,  9,	54, 50, 45, 39, 32, 25, 19, 14,	58, 55, 51, 46, 40, 33, 26, 20,	61, 59, 56, 52, 47, 41, 34, 27,	63, 62, 60, 57, 53, 48, 42, 35,};#define ZOBRIST_DEFAULT_HASH 0/* Table of random numbers used to generate the zobrist hash. The indices are * first the color (WHITE/BLACK), then the piece type (PAWN-KING), then the * square the piece is on (A1-H8) */zobrist_t zobrist_piece[2][6][64];/* Whose move is it (WHITE/BLACK)? The value present if white has the move. */zobrist_t zobrist_tomove;/* Which square (A1-H8) is the enpassant square? If enpassant is not possible, * use the key at index 0. */zobrist_t zobrist_ep[64];/* Can (WHITE/BLACK, first) castle on the (KINGSIDE/QUEENSIDE, second)? If so, * the value here is xored into the hash. */zobrist_t zobrist_castle[2][2];/* Have the arrays been initialized? If you reinitialize them in the middle of * play, the keys will get fucked up. */char zobrist_initialized = 0;/** * Initialize the zobrist tables. */void init_zobrist(){	int i, j, k;		/* just in case... */	if (zobrist_initialized)	{		return;	}	rand_init();		/* Init the piece position array */	for (i = 0; i < 2; i++)	{		for (j = 0; j < 6; j++)		{			for (k = 0; k < 64; k++)			{				zobrist_piece[i][j][k] = (zobrist_t)rand64();			}		}	}		/* Init the whose-move-is-it value */	zobrist_tomove = (zobrist_t)rand64();		/* Init the enpassant square array */	for (i = 0; i < 64; i++)	{		zobrist_ep[i] = (zobrist_t)rand64();	}		/* Init the castling rights array */	zobrist_castle[0][0] = (zobrist_t)rand64();	zobrist_castle[0][1] = (zobrist_t)rand64();	zobrist_castle[1][0] = (zobrist_t)rand64();	zobrist_castle[1][1] = (zobrist_t)rand64();		zobrist_initialized = 1;	rand_teardown();	return;}/** * (Re)generate the zobrist hash for a board, store it in board->hash * This shouldn't be used every time you change the zobrist, only when * initializing the board. */void zobrist_gen(board_t *board){	unsigned char color;	piece_t piece;	square_t square;	int i, j;	bitboard_t pos;	zobrist_t hash = ZOBRIST_DEFAULT_HASH;		if (board == NULL)	{		return;	}	if (!zobrist_initialized)	{		init_zobrist();	}		/* XOR in the zobrist for each piece on the board */	for (color = 0; color < 2; color++)	{		for (piece = 0; piece < 6; piece++)		{			pos = board->pos[color][piece];			while (pos)			{				/* Find the first bit */				square = bsf(pos);				/* throw in the hash */				hash ^= zobrist_piece[color][piece][square];				/* and clear the bit */				pos &= BB_ALLEXCEPT(square);			}		}	}	/* Have the hash reflect special conditions on the board */	/* En passant */	hash ^= zobrist_ep[board->ep];	/* Castling rights */	for (i = 0; i < 2; i++)	{		for (j = 0; j < 2; j++)		{			if (board->castle[i][j])			{				hash ^= zobrist_castle[i][j];			}		}	}	/* Who has the move */	if (board->tomove == WHITE)	{		hash ^= zobrist_tomove;	}	board->hash = hash;	return;}/**************************************************************************** * BITBOARD FUNCTIONS ****************************************************************************/static void board_addmoves_pawn(board_t *, square_t, unsigned char, linkedlist_u32_t *, linkedlist_u32_t *);static void board_addmoves_ep(board_t *, unsigned char, linkedlist_u32_t *);static void board_addmoves_king(board_t *, square_t, unsigned char, linkedlist_u32_t *, linkedlist_u32_t *);static void board_addmoves(board_t *, square_t, piece_t, unsigned char, linkedlist_u32_t *, linkedlist_u32_t *);static void board_removepiece(board_t *, square_t, unsigned char, piece_t);static void board_placepiece(board_t *, square_t, unsigned char, piece_t);static void board_regeneratethreatened(board_t *);/** * Generate a fresh board with the default initial starting position. */board_t *board_init(){	board_t *board = malloc(sizeof(board_t));		board->pos[WHITE][PAWN]   = BB_RANK2;	board->pos[WHITE][KNIGHT] = BB_SQUARE(B1) | BB_SQUARE(G1);	board->pos[WHITE][BISHOP] = BB_SQUARE(C1) | BB_SQUARE(F1);	board->pos[WHITE][ROOK]   = BB_SQUARE(A1) | BB_SQUARE(H1);	board->pos[WHITE][QUEEN]  = BB_SQUARE(D1);	board->pos[WHITE][KING]   = BB_SQUARE(E1);	board->pos[BLACK][PAWN]   = BB_RANK7;	board->pos[BLACK][KNIGHT] = BB_SQUARE(B8) | BB_SQUARE(G8);	board->pos[BLACK][BISHOP] = BB_SQUARE(C8) | BB_SQUARE(F8);	board->pos[BLACK][ROOK]   = BB_SQUARE(A8) | BB_SQUARE(H8);	board->pos[BLACK][QUEEN]  = BB_SQUARE(D8);	board->pos[BLACK][KING]   = BB_SQUARE(E8);	board->piecesofcolor[WHITE] = BB_RANK1 | BB_RANK2;	board->piecesofcolor[BLACK] = BB_RANK8 | BB_RANK7;		board->attackedby[WHITE] = BB_RANK3;	board->attackedby[BLACK] = BB_RANK6;		board->occupied    = BB_RANK1 | BB_RANK2 | BB_RANK7 | BB_RANK8;	board->occupied90  = BB_FILEA | BB_FILEB | BB_FILEG | BB_FILEH;	/* These ugly numbers, in contrast to the beautifully simple code	 * above, are in fact correct. Check with ./bbtools/rotvisualizer */	board->occupied45  = BB(0xecc61c3c3c386337);	board->occupied315 = BB(0xfb31861c38618cdf);		/* These lls will be managed together; we just use two to avoid using	 * a generic ll for the (u64,u64) pair in attackedby[]. */	board->undostack_white = ll_u64_init();	board->undostack_black = ll_u64_init();	board->undostack_flags = ll_u64_init();		board->ep = 0;	board->castle[WHITE][QUEENSIDE] = 1;	board->castle[WHITE][KINGSIDE] = 1;	board->castle[BLACK][QUEENSIDE] = 1;	board->castle[BLACK][KINGSIDE] = 1;	board->tomove = WHITE;	board->halfmoves = 0;		zobrist_gen(board);		return board;}/** * Free all memory associated with a board_t. */void board_destroy(board_t *board){	if (board == NULL)	{		return;	}	ll_u64_destroy(board->undostack_white);	ll_u64_destroy(board->undostack_black);	ll_u64_destroy(board->undostack_flags);	free(board);	return;}/** * Generates a FEN string for the given position. Free it yourself when you're * done with it. This function makes no effort to be fast; you shouldn't be * using it during the search process anyway. */#define FEN_MAX_LENGTH 85char *board_fen(board_t *board){	char *fen;	int row, col;	char emptysquares[] = "0"; /* counts consecutive empty squares */	char halfmove[5]; /* halfmove clock string, won't be >999 for sure */	piece_t piece;	unsigned char color;	unsigned char empty_end_of_line;		if (board == NULL)	{		return NULL;	}		fen = malloc(FEN_MAX_LENGTH + 1);	fen[0] = 0;		for (row = 7; row >= 0; row--)	{		emptysquares[0] = '0';		empty_end_of_line = 0;				for (col = 0; col < 8; col++)		{			color = 0; /* really init'ed next line; this makes gcc happy */			piece = board_pieceatsquare(board, SQUARE(col,row), &color);			if (piece == (piece_t)-1)			{				emptysquares[0]++;				if (col == 7)				{					empty_end_of_line = 1;				}			}			else			{				/* print the emptysquare count if it exists */				if (emptysquares[0] != '0')				{					strcat(fen, emptysquares);					emptysquares[0] = '0';				}				strcat(fen, piecename[color][piece]);			}		}		/* we finished printing this row, unless it was empty */		if (empty_end_of_line)		{			strcat(fen, emptysquares);		}		/* print the row separator */		strcat(fen, ((row > 0) ? "/" : " "));	}	/* now all that's left is the flags */	strcat(fen, ((board->tomove == WHITE) ? "w " : "b "));	/* castle privileges - this is kinda messy */	if (!(board->castle[WHITE][QUEENSIDE] || board->castle[WHITE][KINGSIDE] ||	      board->castle[BLACK][QUEENSIDE] || board->castle[BLACK][KINGSIDE]))	{		strcat(fen, "-");	}	else	{		if (board->castle[WHITE][KINGSIDE])  strcat(fen, "K");		if (board->castle[WHITE][QUEENSIDE]) strcat(fen, "Q");		if (board->castle[BLACK][KINGSIDE])  strcat(fen, "k");		if (board->castle[BLACK][QUEENSIDE]) strcat(fen, "q");	}	strcat(fen, " ");	/* enpassant square */	strcat(fen, ((board->ep != 0) ? squarename[board->ep] : "-"));	strcat(fen, " ");	/* move clocks - 0 for absolute move because fuck that shit */	sprintf(halfmove, "%d 0", board->halfmoves);	strcat(fen, halfmove);		return fen;}/** * Gets the piece at the given square index. If the square is empty, -1. * You should already know that there's a piece there when you call this. * If the board is NULL or the square is invalid, -2. * If the third argument is non-null, stores the color of the piece in there * (unmodified if piece not present). */piece_t board_pieceatsquare(board_t *board, square_t square, unsigned char *c){	bitboard_t mask;	piece_t piece;	unsigned char color;		if (board == NULL || square > 63)	{		return -2;	}	mask = BB_SQUARE(square);		/* find what color the piece is */	if (board->piecesofcolor[WHITE] & mask)	{		color = WHITE;	}	else if (board->piecesofcolor[BLACK] & mask)	{		color = BLACK;	}	else	{		return -1;	}		if (c != NULL)	{		*c = color;	}		/* find what piece type it is */	piece = 0;	while (!(board->pos[color][piece] & mask))	{		piece++;	}	return piece;}/** * Is the player whose move it is in check? (1 if so, 0 if not) */int board_incheck(board_t *board){	return board_colorincheck(board, board->tomove);}/** * Is the given player in check? (1 if so, 0 if not) */int board_colorincheck(board_t *board, unsigned char color){	return !!(board->pos[color][KING] & board->attackedby[OTHERCOLOR(color)]);}/** * Given the current board state, returns a bitmask representing all possible * attacks from a given square assuming a piece of the specified type/color at * that square. This is not the same as all the moves the piece at that square * can make - see the special cases: pawns (capture/ep) and kings (castling). * For pawns, forward pushes are NOT reflected in this mask, but diagonally * threatened squares ARE, ONLY IF there is not a friendly piece there. * * Note: Considering how the attackedby bitboards work, realize that we want * to keep both attacks on other color's pieces and attacks on same color's * pieces in here. The board_addmoves functions take care of making sure we * don't capture our own pieces. * * TODO: For a cache-friendly optimization, consider taking the slidingpiece's * index OUT of the occupancy mask before looking up - i.e. for 11101011 and * the rook is the 3rd index from the right, use 11100011 as a lookup key * instead, so subsequent accesses with that mask (if you move the rook along * the column/row, etc) stay in cache. */bitboard_t board_attacksfrom(board_t *board, square_t square, piece_t piece, unsigned char color){	/* Used for rook/bishop attack generation */	int shiftamount;	int diag;	bitboard_t movemask;	bitboard_t rowatk, colatk;	bitboard_t diag45attacks, diag315attacks;		/* NOTE: Because for non-special pieces we can use this function for move	 * generation, do NOT neglect to mask with ~piecesofcolor here. */	switch (piece)	{	case PAWN:		return pawnattacks[color][square];	case KNIGHT:		return knightattacks[square];	case BISHOP:		/* The first table lookup */		diag = rot45diagindex[square];		movemask = rot45attacks[(board->occupied45 >> rot45index_shiftamountright[diag]) & 0xFF]		                       [COL(square)];		diag45attacks = (movemask << rotresult_shiftamountleft[diag])		                >> rotresult_shiftamountright[diag];		/* The second table lookup */		diag = rot315diagindex[square];		movemask = rot315attacks[((board->occupied315 << rot315index_shiftamountleft[diag])		                         >> rot315index_shiftamountright[diag]) & 0xFF]					[COL(square)];		diag315attacks = (movemask << rotresult_shiftamountleft[diag])		                 >> rotresult_shiftamountright[diag];		/* Put them together */		return (diag45attacks | diag315attacks);	case ROOK:		/* The first table lookup */		shiftamount = 8 * ROW(square);		movemask = rowattacks[(board->occupied >> shiftamount) & 0xFF][COL(square)];		rowatk = movemask << shiftamount;		/* The second table lookup */		shiftamount = COL(square);		movemask = colattacks[(board->occupied90 >> (shiftamount * 8)) & 0xFF][ROW(square)];		colatk = movemask << shiftamount;		/* Put them together */		return (rowatk | colatk);	case QUEEN:		return board_attacksfrom(board, square, BISHOP, color) |		       board_attacksfrom(board, square, ROOK, color);	case KING:		/* Here we do special filtering to avoid moving the king into		 * check, because it's cheaper to filter these suicide-moves		 * out here rather than in the searcher. Rely on the searcher		 * only to filter out exposing the king to check, which is		 * harder to compute */		return kingattacks[square] &		       (~(board->attackedby[OTHERCOLOR(color)]));	}	/* If we got to here then piece was invalid */	return BB(0x0);}/** * Generates a linkedlist of "legal" moves for the color to play at the given * position. The moves are guaranteed legal, with all appropriate flags set, * suitable for being given to makemove(), EXCEPT it is possible that the move * might leave the player in check. We leave this task to the searcher - since * it is necessary to call makemove() to see if a move leaves the player in * check, and because the searcher calls makemove() anyway; we don't want to * waste time calling it twice. * We attempt to do some basic (i.e. inexpensive) move ordering here. Captures * come first along with promotions, after that, everything else. * This list needs to be ll_destroy()ed. If there are no legal moves, returns * an empty list; if the board is NULL, returns a null list. */linkedlist_u32_t *board_generatemoves(board_t *board){	linkedlist_u32_t *captures;	linkedlist_u32_t *regular;	bitboard_t position;	piece_t piece;	square_t square;	unsigned char color;	if (board == NULL)	{		return NULL;	}		color = board->tomove;	captures = ll_u32_init();	regular  = ll_u32_init();	/* we only need to do this part once, not once per pawn */	if (board->ep)	{		board_addmoves_ep(board, color, captures);	}	/* now do the rest of the moves */	for (piece = 0; piece < 6; piece++)	{		position = board->pos[color][piece];		while (position)		{			/* find a piece */			square = bsr(position);			/* clear the bit */			position &= BB_ALLEXCEPT(square);			/* special functions for special cases */			switch (piece)			{			case PAWN:				board_addmoves_pawn(board, square, color, captures, regular);				break;			case KING:				board_addmoves_king(board, square, color, captures, regular);				break;			/* for knights, rooks, bishops, queens,			 * we can use attacksfrom() directly */			default:				board_addmoves(board, square, piece, color, captures, regular);			}		}	}	/* put the two sorts of moves into one list with captures first */	ll_u32_append(captures, regular);	return captures;}/** * The board_addmoves* series of functions take pointers to two linkedlists, * and add each legal move for the specified piece of the specified color at * the specified square to the lists, sorted by capture/noncapture. */static void board_addmoves_pawn(board_t *board, square_t square, unsigned char color,                                linkedlist_u32_t *captures, linkedlist_u32_t *regular){	bitboard_t moves, emptysquares;	square_t destsquare;	piece_t captpiece;	move_t move;	/* note enpassant is handled separately. first we do captures: pawns	 * can't move to a square they threaten unless it's a capture */	moves = board_attacksfrom(board, square, PAWN, color) &	        board->piecesofcolor[OTHERCOLOR(color)];	while (moves)	{		destsquare = bsr(moves);		moves &= BB_ALLEXCEPT(destsquare);		captpiece = board_pieceatsquare(board, destsquare, NULL);		move = (square << MOV_INDEX_SRC) |		       (destsquare << MOV_INDEX_DEST) |		       (color << MOV_INDEX_COLOR) |		       (0x1 << MOV_INDEX_CAPT) |		       (captpiece << MOV_INDEX_CAPTPC) |		       (PAWN << MOV_INDEX_PIECE);		/* handle promotions */		if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))		{			move |= (0x1 << MOV_INDEX_PROM);			ll_u32_add(captures, (move | (QUEEN << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (KNIGHT << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (ROOK << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (BISHOP << MOV_INDEX_PROMPC)));		}		else /* normal capture */		{			ll_u32_add(captures, move);		}	}	/* now we handle pushes */	emptysquares = ~(board->occupied);	moves = pawnmoves[color][square] & emptysquares; /* can't push if blocked */	/* handle double push only if a single push was available 	 * XXX: this if/if/elseif block is probably not optimal */	if (moves)	{		if ((ROW(square) == RANK_2) && (color == WHITE))		{			moves |= pawnmoves[color][square + 8] & emptysquares;		}		else if ((ROW(square) == RANK_7) && (color == BLACK))		{			moves |= pawnmoves[color][square - 8] & emptysquares;		}	}	/* and now we have the proper movemask generated */	while (moves)	{		destsquare = bsr(moves);		moves &= BB_ALLEXCEPT(destsquare);		move = (square << MOV_INDEX_SRC) |		       (destsquare << MOV_INDEX_DEST) |		       (color << MOV_INDEX_COLOR) |		       (PAWN << MOV_INDEX_PIECE);		/* handle promotions - add to the captures list because pawn		 * promotions, like captures, change the board's material */		if (ROW(destsquare) == HOMEROW(OTHERCOLOR(color)))		{			move |= (0x1 << MOV_INDEX_PROM);			ll_u32_add(captures, (move | (QUEEN << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (KNIGHT << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (ROOK << MOV_INDEX_PROMPC)));			ll_u32_add(captures, (move | (BISHOP << MOV_INDEX_PROMPC)));		}		else /* normal push */		{			ll_u32_add(regular, move);		}	}	/* and we're done, phew */	return;}/* don't call this if board->ep = 0 */static void board_addmoves_ep(board_t *board, unsigned char color, linkedlist_u32_t *captures){	bitboard_t pawns;	square_t fromsquare; /* we know where the dest is; we need this now */	move_t move;		/* find all pawns eligible to make the capture */	pawns = bb_adjacentcols[COL(board->ep)] & /* the col the pawn is on */	        BB_EP_FROMRANK(color) & /* the rank a pawn needs to be on */		board->pos[color][PAWN] /* where your pawns actually are */;	while (pawns)	{		fromsquare = bsr(pawns);		pawns &= BB_ALLEXCEPT(fromsquare);		move = (fromsquare << MOV_INDEX_SRC) |		       (board->ep << MOV_INDEX_DEST) |		       (0x1 << MOV_INDEX_EP) |		       (0x1 << MOV_INDEX_CAPT) |		       (PAWN << MOV_INDEX_CAPTPC) |		       (PAWN << MOV_INDEX_PIECE);		ll_u32_add(captures, move);	}	return;}/* wrapper for board_addmoves() with a special case handler for castling */static void board_addmoves_king(board_t *board, square_t square, unsigned char color,                               linkedlist_u32_t *captures, linkedlist_u32_t *regular){	move_t move;	square_t destsquare;	int side;		/* deal with castling - iterate side={0,1} */	for (side = 0; side < 2; side++)	{		if (board->castle[color][side])		{			/* If the squares are occupied (1st two lines) or			 * threatened (2nd two) then we cannot castle */			if (!((castle_clearsquares[color][side] &			       board->occupied) ||	                      (castle_safesquares[color][side] &			       board->attackedby[OTHERCOLOR(color)])))			{				/* find where the king will end up */				destsquare = SQUARE(CASTLE_DEST_COL(side),				                    HOMEROW(color));				/* generate and add the move */				move = (square << MOV_INDEX_SRC) |				       (destsquare << MOV_INDEX_DEST) |				       (color << MOV_INDEX_COLOR) |				       (0x1 << MOV_INDEX_CASTLE) |				       (KING << MOV_INDEX_PIECE);				ll_u32_add(regular, move);			}		}	}	/* now the special case is out of the way, the rest is simple */	board_addmoves(board, square, KING, color, captures, regular);	return;}/* for non-special-case pieces: knight bishop rook queen. see above comment */static void board_addmoves(board_t *board, square_t square, piece_t piece, unsigned char color,                           linkedlist_u32_t *captures, linkedlist_u32_t *regular){	bitboard_t moves, capts;	square_t destsquare;	piece_t captpiece;	move_t move;		/* find all destination squares -- all attacked squares, but can't	 * capture our own pieces */	moves = board_attacksfrom(board, square, piece, color) & (~(board->piecesofcolor[color]));	/* separate captures from noncaptures */	capts = moves & board->piecesofcolor[OTHERCOLOR(color)];	moves &= ~capts;	/* process captures first */	while (capts)	{		/* find and clear a bit */		destsquare = bsr(capts);		capts &= BB_ALLEXCEPT(destsquare);		/* find what piece was captured */		captpiece = board_pieceatsquare(board, destsquare, NULL);		/* generate the move_t */		move = (square << MOV_INDEX_SRC) |       /* from square */		       (destsquare << MOV_INDEX_DEST) |  /* to square */		       (color << MOV_INDEX_COLOR) |      /* color flag */		       (0x1 << MOV_INDEX_CAPT) |         /* capture flag */		       (captpiece << MOV_INDEX_CAPTPC) | /* captured piece */		       (piece << MOV_INDEX_PIECE);       /* our piece */		/* and add it to the list */		ll_u32_add(captures, move);	}	/* then process noncapture moves */	while (moves)	{		/* find and clear a bit */		destsquare = bsr(moves);		moves &= BB_ALLEXCEPT(destsquare);		/* generate the move_t */		move = (square << MOV_INDEX_SRC) |      /* from square */		       (destsquare << MOV_INDEX_DEST) | /* to square */		       (color << MOV_INDEX_COLOR) |     /* color flag */		       (piece << MOV_INDEX_PIECE);      /* our piece */		/* and add it to the list */		ll_u32_add(regular, move);	}	return;}/** * The third undo stack keeps track of the enpassant squares and castling * rights and halfmove clock stored in a 64-bit type in the following format: * 00000000 00000000 CCCCCCCC 00BBBBBB AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA *                          40       32                                  0 * A: castle array * B: enpassant square * C: halfmove clock * 0: unused bits *  * The castle array, 4 chars long, is written/read straight from memory as a * 32-bit type. The bits may be reversed or not due to endianness, but they'll * be the same when they come out. Just don't try to extract one element when * in this state (or switch your endianness while running). * * Following are the two position-altering functions which make use of this. */typedef uint64_t undoflags_t;#define UNDOFLAGS_INDEX_EP     32#define UNDOFLAGS_INDEX_HM     40#define UNDOFLAGS_CASTLE(u) ((uint32_t)((u) & 0xFFFFFFFF))#define UNDOFLAGS_EP(u)     ((unsigned char)(((u) >> UNDOFLAGS_INDEX_EP) & 0x3F))#define UNDOFLAGS_HM(u)     ((unsigned char)(((u) >> UNDOFLAGS_INDEX_HM) & 0xFF))/** * Given a move, which MUST be properly formatted AND legal (only use moves * returned by board_generatemoves() or move_islegal() here), applies the move * to change the board position. Updates the zobrist hash, undo stacks, * everything. */void board_applymove(board_t *board, move_t move){	square_t rooksrc, rookdest; /* how the rook moves in castling */	square_t epcapture;         /* where a pawn will disappear from */		/* push the current unrecomputable state data onto the undostack */	ll_u64_add_index(board->undostack_white, 0, board->attackedby[WHITE]);	ll_u64_add_index(board->undostack_black, 0, board->attackedby[BLACK]);	/* really ugly - see above comment at the undoflags_t typedef */	ll_u64_add_index(board->undostack_flags, 0,	                 ((uint64_t)(*((uint32_t *)(board->castle)))) |	                 (((uint64_t)(board->ep)) << UNDOFLAGS_INDEX_EP) |	                 (((uint64_t)(board->halfmoves)) << UNDOFLAGS_INDEX_HM));		/* Take care of captures - we need to remove the captured piece. */	if (MOV_CAPT(move))	{		/* special case - en passant - square behind the dest square */		if (MOV_EP(move))		{			epcapture = (board->tomove == WHITE) ? 			            (MOV_DEST(move) - 8) :				    (MOV_DEST(move) + 8);			board_removepiece(board, epcapture,			                  OTHERCOLOR(board->tomove), PAWN);		}		/* standard capture - square is the dest square */		else		{			board_removepiece(board, MOV_DEST(move),			                  OTHERCOLOR(board->tomove),			                  MOV_CAPTPC(move));		}		board->halfmoves = 0;	}	/* here we detect irreversible moves for the halfmove clock */	else	{		if (MOV_PIECE(move) == PAWN)		{			board->halfmoves = 0;		}		else		{			board->halfmoves++;		}	}		/* castling, need to move the rook. castle privileges handled below */	if (MOV_CASTLE(move))	{		/* detect kingside vs queenside */		if (COL(MOV_DEST(move)) == COL_G)		{			rooksrc  = SQUARE(COL_H,HOMEROW(board->tomove));			rookdest = SQUARE(COL_F,HOMEROW(board->tomove));		}		else		{			rooksrc  = SQUARE(COL_A,HOMEROW(board->tomove));			rookdest = SQUARE(COL_D,HOMEROW(board->tomove));		}		/* and move the rook */		board_removepiece(board, rooksrc, board->tomove, ROOK);		board_placepiece(board, rookdest, board->tomove, ROOK);	}		/* here we move the moving piece itself; in the former case it turns	 * into a different type of piece */	board_removepiece(board, MOV_SRC(move), board->tomove,	                  MOV_PIECE(move));	if (MOV_PROM(move))	{		board_placepiece(board, MOV_DEST(move), board->tomove,		                 MOV_PROMPC(move));	}	else	{		board_placepiece(board, MOV_DEST(move), board->tomove,		                 MOV_PIECE(move));	}	/* detect an enpassantable move */	if (MOV_PIECE(move) == PAWN)	{		/* if the difference between the square values is 16 not 8		 * then it was a double push */		if ((board->tomove == WHITE) &&		    ((MOV_DEST(move) - MOV_SRC(move)) == 16))		{			/* clear the old ep status in the hash */			board->hash ^= zobrist_ep[board->ep];			/* set the new value */			board->ep = MOV_SRC(move) + 8;			/* throw in the new key */			board->hash ^= zobrist_ep[board->ep];		}		else if ((board->tomove == BLACK) &&		         ((MOV_SRC(move) - MOV_DEST(move)) == 16))		{			board->hash ^= zobrist_ep[board->ep];			board->ep = MOV_DEST(move) + 8;			board->hash ^= zobrist_ep[board->ep];		}		else		{			board->hash ^= zobrist_ep[board->ep];			board->ep = 0;			board->hash ^= zobrist_ep[board->ep];		}	}	/* handle castling rights */	else if (MOV_PIECE(move) == KING)	{		if (board->castle[board->tomove][KINGSIDE])		{			board->castle[board->tomove][KINGSIDE] = 0;			board->hash ^= zobrist_castle[board->tomove][KINGSIDE];		}		if (board->castle[board->tomove][QUEENSIDE])		{			board->castle[board->tomove][QUEENSIDE] = 0;			board->hash ^= zobrist_castle[board->tomove][QUEENSIDE];		}	}	else if (MOV_PIECE(move) == ROOK)	{		if ((board->castle[board->tomove][KINGSIDE]) &&		    (COL(MOV_SRC(move)) == COL_H))		{			board->castle[board->tomove][KINGSIDE] = 0;			board->hash ^= zobrist_castle[board->tomove][KINGSIDE];		}		else if ((board->castle[board->tomove][QUEENSIDE]) &&		         (COL(MOV_SRC(move)) == COL_A))		{			board->castle[board->tomove][QUEENSIDE] = 0;			board->hash ^= zobrist_castle[board->tomove][QUEENSIDE];		}	}		/* switch who has the move */	board->tomove = OTHERCOLOR(board->tomove);	board->hash ^= zobrist_tomove;		/* and finally */	board_regeneratethreatened(board);	return;}/** * Go back one move. The cleaner implementation is to keep a stack of the * moves, but it's faster to have the searcher/legalitychecker just pass in * the move again rather than mucking about with data structures. We do keep a * pair of stacks for the attackedby bitmasks, so we don't have to generate * them again when undoing (since they've been generated before for that * position, and regenning them is expensive). * Note if you pass in a move different from the one that was most recently * made, the board state will shit and die horribly. */void board_undomove(board_t *board, move_t move){	undoflags_t previousflags;	square_t rooksrc, rookdest, epcapture;		/* switch who has the move */	board->tomove = OTHERCOLOR(board->tomove);	board->hash ^= zobrist_tomove;		/* The non-special things (see bottom of function for special things)	 * are basically applymove in reverse. First move the piece back. */	board_placepiece(board, MOV_SRC(move), board->tomove, MOV_PIECE(move));	if (MOV_PROM(move))	{		board_removepiece(board, MOV_DEST(move), board->tomove,		                  MOV_PROMPC(move));	}	else	{		board_removepiece(board, MOV_DEST(move), board->tomove,		                  MOV_PIECE(move));	}	/* castling, need to move the rook back. */	if (MOV_CASTLE(move))	{		/* detect kingside vs queenside */		if (COL(MOV_DEST(move)) == COL_G)		{			/* note src is where it needs to end up because we're			 * moving backwards not forwards */			rooksrc  = SQUARE(COL_H,HOMEROW(board->tomove));			rookdest = SQUARE(COL_F,HOMEROW(board->tomove));		}		else		{			rooksrc  = SQUARE(COL_A,HOMEROW(board->tomove));			rookdest = SQUARE(COL_D,HOMEROW(board->tomove));		}		/* and move the rook */		board_placepiece(board, rooksrc, board->tomove, ROOK);		board_removepiece(board, rookdest, board->tomove, ROOK);	}	/* for captures, put the captured piece back */	if (MOV_CAPT(move))	{		/* special case - en passant - square behind the dest square */		if (MOV_EP(move))		{			epcapture = (board->tomove == WHITE) ? 			            (MOV_DEST(move) - 8) :				    (MOV_DEST(move) + 8);			board_placepiece(board, epcapture,			                  OTHERCOLOR(board->tomove), PAWN);		}		/* standard capture - square is the dest square */		else		{			board_placepiece(board, MOV_DEST(move),			                  OTHERCOLOR(board->tomove),			                  MOV_CAPTPC(move));		}	}		/* Get the previous special board state information from the stacks */	board->attackedby[WHITE] = ll_u64_remove_index(board->undostack_white, 0);	board->attackedby[BLACK] = ll_u64_remove_index(board->undostack_black, 0);	previousflags = ll_u64_remove_index(board->undostack_flags, 0);		/* clear the old castle keys */	if (board->castle[WHITE][QUEENSIDE]) { board->hash ^= zobrist_castle[WHITE][QUEENSIDE]; }	if (board->castle[WHITE][KINGSIDE])  { board->hash ^= zobrist_castle[WHITE][KINGSIDE]; }	if (board->castle[BLACK][QUEENSIDE]) { board->hash ^= zobrist_castle[BLACK][QUEENSIDE]; }	if (board->castle[BLACK][KINGSIDE])  { board->hash ^= zobrist_castle[BLACK][KINGSIDE]; }	/* set the new castle rights */	*((uint32_t *)(board->castle)) = UNDOFLAGS_CASTLE(previousflags);	/* set the new castle keys */	if (board->castle[WHITE][QUEENSIDE]) { board->hash ^= zobrist_castle[WHITE][QUEENSIDE]; }	if (board->castle[WHITE][KINGSIDE])  { board->hash ^= zobrist_castle[WHITE][KINGSIDE]; }	if (board->castle[BLACK][QUEENSIDE]) { board->hash ^= zobrist_castle[BLACK][QUEENSIDE]; }	if (board->castle[BLACK][KINGSIDE])  { board->hash ^= zobrist_castle[BLACK][KINGSIDE]; }	/* clear the old ep key */	board->hash ^= zobrist_ep[board->ep];	/* get the new value */	board->ep = UNDOFLAGS_EP(previousflags);	/* set the new key */	board->hash ^= zobrist_ep[board->ep];	/* set the halfmove clock */	board->halfmoves = UNDOFLAGS_HM(previousflags);	return;}/** * The {remove,place}piece functions are wrappers to simplify moving pieces * around on the board. They modify the bits in the piece-specific position * masks, the all-pieces-of-one-color mask, and in the four occupied boards, * and adjust the zobrist hash. */static void board_removepiece(board_t *board, square_t square,                              unsigned char color, piece_t piece){	/* piece-specific position mask */	board->pos[color][piece] &= BB_ALLEXCEPT(square);		/* all the color's pieces */	board->piecesofcolor[color] &= BB_ALLEXCEPT(square);		/* general occupied masks */	board->occupied &= BB_ALLEXCEPT(square);	board->occupied90 &= BB_ALLEXCEPT(rot90squareindex[square]);	board->occupied45 &= BB_ALLEXCEPT(rot45squareindex[square]);	board->occupied315 &= BB_ALLEXCEPT(rot315squareindex[square]);		/* adjust the zobrist */	board->hash ^= zobrist_piece[color][piece][square];}static void board_placepiece(board_t *board, square_t square,                             unsigned char color, piece_t piece){	/* piece-specific position mask */	board->pos[color][piece] |= BB_SQUARE(square);		/* all the color's pieces */	board->piecesofcolor[color] |= BB_SQUARE(square);		/* general occupied masks */	board->occupied |= BB_SQUARE(square);	board->occupied90 |= BB_SQUARE(rot90squareindex[square]);	board->occupied45 |= BB_SQUARE(rot45squareindex[square]);	board->occupied315 |= BB_SQUARE(rot315squareindex[square]);		/* adjust the zobrist */	board->hash ^= zobrist_piece[color][piece][square];}/** * Regenerate the threatened squares masks for both sides. Should be used when * a move is made. Don't use in undomove, use the special stacks instead. */static void board_regeneratethreatened(board_t *board){	bitboard_t mask;	bitboard_t position;	piece_t piece;	square_t square;	unsigned char color;	for (color = 0; color < 2; color++)	{		mask = BB(0x0);		for (piece = 0; piece < 6; piece++)		{			position = board->pos[color][piece];			/* keep going until we've found all the pieces */			while (position)			{				/* Find one of the pieces, clear its bit */				square = bsr(position);				position &= BB_ALLEXCEPT(square);				/* Put the attacks from this square in the mask */				mask |= board_attacksfrom(board, square, piece, color);			}		}		board->attackedby[color] = mask;	}	return;}/**************************************************************************** * END:   BITBOARD FUNCTIONS * BEGIN: MOVE FUNCTIONS ****************************************************************************/static move_t move_fromstring(char *);static move_t move_checksuicide(board_t *, move_t);/** * Parses computer friendly ("d7c8N" or "e1g1") notation to generate a simple * move_t template. Will return 0 on a malformatted move (note 0 is never a * valid move_t). This will only set the prom flag, not castle/ep/capt. As a * result, the resultant move is not suitable for throwing directly into * applyMove. */static move_t move_fromstring(char *str){	size_t length = strlen(str);	move_t move = 0;		/* check for malformatted move string */	if (length < 4 || length > 5 || /* too short/long */	    !(str[0] >= 'a' && str[0] <= 'h') || /* bad src/dest squares */	    !(str[1] >= '1' && str[1] <= '8') ||	    !(str[2] >= 'a' && str[2] <= 'h') ||	    !(str[3] >= '1' && str[3] <= '8') ||	    (length == 5 && /* bad promotion piece */	     !(str[4] == 'N' || str[4] == 'B' ||	       str[4] == 'R' || str[4] == 'Q')))	{		return (move_t)0;	}		/* set the src and dest */	move |= SQUARE((str[0] - 'a'), (str[1] - '1')) << MOV_INDEX_SRC;	move |= SQUARE((str[2] - 'a'), (str[3] - '1')) << MOV_INDEX_DEST;		/* promotion */	if (length == 5)	{		move |= 1 << MOV_INDEX_PROM; /* set the flag */		switch(str[4])		{		case 'N':			move |= KNIGHT << MOV_INDEX_PROMPC;			break;		case 'B':			move |= BISHOP << MOV_INDEX_PROMPC;			break;		case 'R':			move |= ROOK << MOV_INDEX_PROMPC;			break;		default:			move |= QUEEN << MOV_INDEX_PROMPC;		}	}		return move;}/** * A more advanced form of move_fromstring. Given also a board_t, will return * a move_t for the move represented by str if it is 1) properly formatted, * 2) valid, 3) legal. Otherwise returns 0. All appropriate flags will be set, * so this is suitable for applymove. * This code is not fast, as it will apply/undo the move from the board. Use * it for checking the opponent's move, not the engine's move. */move_t move_islegal(board_t *board, char *str){	move_t move;	square_t src, dest;	piece_t piece;	bitboard_t moves, clearsquares;		/* Parse the string */	move = move_fromstring(str);	src = MOV_SRC(move);	dest = MOV_DEST(move);		/* First check: sanity; this also handles if move_fromstring failed */	if (src == dest)	{		return 0;	}	/* Does this piece belong to us */	if (!(BB_SQUARE(src) & board->piecesofcolor[board->tomove]))	{		return 0;	}		/* Find our piece and where it can go */	piece = board_pieceatsquare(board, src, NULL);	moves = board_attacksfrom(board, src, piece, board->tomove) &	        (~(board->piecesofcolor[board->tomove])); /* can't capture own piece */	move |= piece << MOV_INDEX_PIECE; /* set the piece-type flag */		/* of course, pawns and kings are special... */	if (piece == PAWN) /* pushes and enpassants */	{		/* can't make an attacking move unless it's a capture */		moves &= board->piecesofcolor[OTHERCOLOR(board->tomove)];		/* Trying to make an illegal promotion, or not promoting on an		 * advance to the promotion rank */		if ((!!(MOV_PROM(move))) ^		    (!!(ROW(dest) == HOMEROW(OTHERCOLOR(board->tomove)))))		{			return 0;		}		/* move is a regular capture */		if (BB_SQUARE(dest) & moves)		{			move |= 1 << MOV_INDEX_CAPT;			move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;			return move_checksuicide(board, move);		}		/* enpassant */		if (board->ep && dest == board->ep)		{			move |= (0x1 << MOV_INDEX_EP) |			        (0x1 << MOV_INDEX_CAPT) |			        (PAWN << MOV_INDEX_CAPTPC);			return move_checksuicide(board, move);		}		/* check for push */		clearsquares = ~board->occupied;		/* is pawn free to move one square ahead? we don't need to set		 * any special additional flags here */		if (pawnmoves[board->tomove][src] & clearsquares)		{			/* Are we trying to move 1 square ahead? Note: relies			 * on the fact that pawnmoves[][] has one bit set. */			if (BB_SQUARE(dest) == pawnmoves[board->tomove][src])			{				return move_checksuicide(board, move);			}			/* 2-square push from 2nd rank */			if (((board->tomove == WHITE) &&			     (pawnmoves[board->tomove][src+8] & clearsquares) &&			     (BB_SQUARE(dest) == pawnmoves[board->tomove][src+8])) ||			    ((board->tomove == BLACK) &&			     (pawnmoves[board->tomove][src-8] & clearsquares) &&			     (BB_SQUARE(dest) == pawnmoves[board->tomove][src-8])))			{				return move_checksuicide(board, move);			}		}		return 0;	}	/* not a pawn, trying to promote a different piece */	else if (MOV_PROM(move))	{		return 0;	}	/* note - for king moves, we don't need to apply the move to check if	 * it puts the player in check; we use attackedby masks directly */	else if (piece == KING)	{		/* handle castling - queenside */		if (board->castle[board->tomove][QUEENSIDE] &&		    (src == SQUARE(COL_E,HOMEROW(board->tomove))) &&		    (dest == SQUARE(COL_C,HOMEROW(board->tomove)))) /* "e1c1" or "e8c8" */		{			/* check if special squares are blocked or attacked */			if ((castle_clearsquares[board->tomove][QUEENSIDE] & board->occupied) ||	                    (castle_safesquares[board->tomove][QUEENSIDE] &			     board->attackedby[OTHERCOLOR(board->tomove)]))			{				return 0;			}			/* here, the castle is legal */			move |= 0x1 << MOV_INDEX_CASTLE;			return move;		}		/* kingside */		if (board->castle[board->tomove][KINGSIDE] &&		    (src == SQUARE(COL_E,HOMEROW(board->tomove))) &&		    (dest == SQUARE(COL_G,HOMEROW(board->tomove)))) /* "e1g1" or "e8g8" */		{			/* check if special squares are blocked or attacked */			if ((castle_clearsquares[board->tomove][KINGSIDE] & board->occupied) ||	                    (castle_safesquares[board->tomove][KINGSIDE] &			     board->attackedby[OTHERCOLOR(board->tomove)]))			{				return 0;			}			/* here, the castle is legal */			move |= 0x1 << MOV_INDEX_CASTLE;			return move;		}		/* otherwise it must be a normal king move to be legal */		moves &= ~(board->attackedby[OTHERCOLOR(board->tomove)]);		/* we can make this move */		if (BB_SQUARE(dest) & moves)		{			/* making a capture */			if (BB_SQUARE(dest) & board->piecesofcolor[OTHERCOLOR(board->tomove)])			{				move |= 1 << MOV_INDEX_CAPT;				move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;			}			return move;		}		return 0;	}	/* typical case piece - N B R Q */	else	{		/* is this one of our legal moves? */		if (BB_SQUARE(dest) & moves)		{			/* making a capture? */			if (BB_SQUARE(dest) & board->piecesofcolor[OTHERCOLOR(board->tomove)])			{				move |= 1 << MOV_INDEX_CAPT;				move |= board_pieceatsquare(board, dest, NULL) << MOV_INDEX_CAPTPC;			}			return move_checksuicide(board, move);		}		return 0;	}}/** * Given a move on a given position (must be legal and suitably formatted for * applymove), check if making this move would leave the player in check. * Returns the move if it's good, 0 if not. */static move_t move_checksuicide(board_t *board, move_t move){	board_applymove(board, move);	if (board_colorincheck(board, OTHERCOLOR(board->tomove)))	{		board_undomove(board, move);		return 0;	}	board_undomove(board, move);	return move;}/** * Returns the string representation of a move in computer-friendly format * (that is, "squarename[src]squarename[dest]promotionpiece"). Free the string * when you're done with it. */char *move_tostring(move_t m){	char *string;	/* longest move in this format is a promotion, "a7a8Q" */	string = malloc(6);	string[0] = 0;	strcat(string, squarename[MOV_SRC(m)]);	strcat(string, squarename[MOV_DEST(m)]);	if (MOV_PROM(m))	{		/* use WHITE as an index to get the uppercase */		strcat(string, piecename[WHITE][MOV_PROMPC(m)]);	}	return string;}