bool is_attacked(const board_t * board, int to, int colour) { const uint8 * ptr; int from, piece; ASSERT(board_is_ok(board)); ASSERT(square_is_ok(to)); ASSERT(colour_is_ok(colour)); for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; ASSERT(colour_equal(piece,colour)); if (piece_attack(board,piece,from,to)) return true; } return false; }
bool board_is_ok(const board_t * board) { int sq, piece; int colour, pos; int king, rook; if (board == NULL) return false; // optional heavy DEBUG mode if (!UseSlowDebug) return true; // squares for (sq = 0; sq < SquareNb; sq++) { piece = board->square[sq]; if (square_is_ok(sq)) { pos = board->pos[sq]; if (piece == Empty) { if (pos != -1) return false; } else { if (pos < 0) return false; if (board->list[piece_colour(piece)][pos] != sq) return false; } } else { if (piece != Knight64) return false; } } // white piece list colour = White; pos = 0; if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false; sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false; for (pos++; pos < board->list_size[colour]; pos++) { sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; if (!colour_equal(board->square[sq],colour)) return false; } sq = board->list[colour][pos]; if (sq != SquareNone) return false; // black piece list colour = Black; pos = 0; if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false; sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false; for (pos++; pos < board->list_size[colour]; pos++) { sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; if (!colour_equal(board->square[sq],colour)) return false; } sq = board->list[colour][pos]; if (sq != SquareNone) return false; // TODO: material if (board->number[WhiteKing12] != 1) return false; if (board->number[BlackKing12] != 1) return false; if (!colour_is_ok(board->turn)) return false; // castling status if (board->castle[White][SideH] != SquareNone) { king = board->list[White][0]; if (king < A1 || king > H1) return false; if (board->square[king] != WhiteKing256) return false; rook = board->castle[White][SideH]; if (rook < A1 || rook > H1) return false; if (board->square[rook] != WhiteRook256) return false; if (rook <= king) return false; } if (board->castle[White][SideA] != SquareNone) { king = board->list[White][0]; if (king < A1 || king > H1) return false; if (board->square[king] != WhiteKing256) return false; rook = board->castle[White][SideA]; if (rook < A1 || rook > H1) return false; if (board->square[rook] != WhiteRook256) return false; if (rook >= king) return false; } if (board->castle[Black][SideH] != SquareNone) { king = board->list[Black][0]; if (king < A8 || king > H8) return false; if (board->square[king] != BlackKing256) return false; rook = board->castle[Black][SideH]; if (rook < A8 || rook > H8) return false; if (board->square[rook] != BlackRook256) return false; if (rook <= king) return false; } if (board->castle[Black][SideA] != SquareNone) { king = board->list[Black][0]; if (king < A8 || king > H8) return false; if (board->square[king] != BlackKing256) return false; rook = board->castle[Black][SideA]; if (rook < A8 || rook > H8) return false; if (board->square[rook] != BlackRook256) return false; if (rook >= king) return false; } return true; }
void move_do(board_t * board, int move) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int sq, ep_square; int pawn; ASSERT(board_is_ok(board)); ASSERT(move_is_ok(move)); ASSERT(move_is_pseudo(move,board)); // init me = board->turn; opp = colour_opp(me); from = move_from(move); to = move_to(move); piece = board->square[from]; ASSERT(colour_equal(piece,me)); pos = board->pos[from]; ASSERT(pos>=0); // update turn board->turn = opp; board->key ^= random_64(RandomTurn); // update castling rights old_flags = board_flags(board); if (piece_is_king(piece)) { board->castle[me][SideH] = SquareNone; board->castle[me][SideA] = SquareNone; } if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone; if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone; if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone; if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone; new_flags = board_flags(board); board->key ^= hash_castle_key(new_flags^old_flags); // HACK // update en-passant square ep_square = sq = board->ep_square; if (sq != SquareNone) { board->key ^= random_64(RandomEnPassant+square_file(sq)); board->ep_square = SquareNone; } if (piece_is_pawn(piece) && abs(to-from) == 32) { pawn = piece_make_pawn(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = sq = (from + to) / 2; board->key ^= random_64(RandomEnPassant+square_file(sq)); } } // update ply number (captures are handled later) board->ply_nb++; if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion // update move number if (me == Black) board->move_nb++; // castle if (colour_equal(board->square[to],me)) { int rank; int king_from, king_to; int rook_from, rook_to; int rook; rank = colour_is_white(me) ? Rank1 : Rank8; king_from = from; rook_from = to; if (to > from) { // h side king_to = square_make(FileG,rank); rook_to = square_make(FileF,rank); } else { // a side king_to = square_make(FileC,rank); rook_to = square_make(FileD,rank); } // remove the rook pos = board->pos[rook_from]; ASSERT(pos>=0); rook = Rook64 | me; // HACK square_clear(board,rook_from,rook); // move the king square_move(board,king_from,king_to,piece); // put the rook back square_set(board,rook_to,rook,pos); ASSERT(board->key==hash_key(board)); return; } // remove the captured piece if (piece_is_pawn(piece) && to == ep_square) { // en-passant capture sq = square_ep_dual(to); capture = board->square[sq]; ASSERT(capture==piece_make_pawn(opp)); square_clear(board,sq,capture); board->ply_nb = 0; // conversion } else { capture = board->square[to]; if (capture != Empty) { // normal capture ASSERT(colour_equal(capture,opp)); ASSERT(!piece_is_king(capture)); square_clear(board,to,capture); board->ply_nb = 0; // conversion } } // move the piece if (move_is_promote(move)) { // promote square_clear(board,from,piece); piece = move_promote_hack(move) | me; // HACK square_set(board,to,piece,pos); } else { // normal move square_move(board,from,to,piece); } ASSERT(board->key==hash_key(board)); }
void board_init_list(board_t * board) { int sq_64, sq, piece; int colour, pos; ASSERT(board!=NULL); // init for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = square_from_64(sq_64); board->pos[sq] = -1; } for (piece = 0; piece < 12; piece++) board->number[piece] = 0; // white piece list colour = White; pos = 0; for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = square_from_64(sq_64); piece = board->square[sq]; ASSERT(pos>=0&&pos<=16); if (colour_equal(piece,colour) && piece_is_king(piece)) { board->pos[sq] = (sint8)pos; board->list[colour][pos] = (uint8)sq; pos++; board->number[piece_to_12(piece)]++; } } ASSERT(pos==1); for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = square_from_64(sq_64); piece = board->square[sq]; ASSERT(pos>=0&&pos<=16); if (colour_equal(piece,colour) && !piece_is_king(piece)) { board->pos[sq] = (sint8)pos; board->list[colour][pos] = (uint8)sq; pos++; board->number[piece_to_12(piece)]++; } } ASSERT(pos>=1&&pos<=16); board->list[colour][pos] = SquareNone; board->list_size[colour] = (sint8)pos; // black piece list colour = Black; pos = 0; for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = square_from_64(sq_64); piece = board->square[sq]; ASSERT(pos>=0&&pos<=16); if (colour_equal(piece,colour) && piece_is_king(piece)) { board->pos[sq] = (sint8)pos; board->list[colour][pos] = (uint8)sq; pos++; board->number[piece_to_12(piece)]++; } } ASSERT(pos==1); for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = square_from_64(sq_64); piece = board->square[sq]; ASSERT(pos>=1&&pos<=16); if (colour_equal(piece,colour) && !piece_is_king(piece)) { board->pos[sq] = (sint8)pos; board->list[colour][pos] = (uint8)sq; pos++; board->number[piece_to_12(piece)]++; } } ASSERT(pos>=1&&pos<=16); board->list[colour][pos] = SquareNone; board->list_size[colour] = (sint8)pos; // hash key board->key = hash_key(board); }