void board_disp(const board_t * board) { int file, rank, sq; int piece, c; char fen[256]; ASSERT(board!=NULL); if (!board_to_fen(board,fen,256)) ASSERT(false); my_log("POLYGLOT %s\n",fen); my_log("POLYGLOT\n"); for (rank = 7; rank >= 0; rank--) { my_log("POLYGLOT "); for (file = 0; file < 8; file++) { sq = square_make(file,rank); piece = board->square[sq]; c = (piece != Empty) ? piece_to_char(piece) : '-'; my_log("%c ",c); } my_log("\n"); } my_log("POLYGLOT\n"); my_log("POLYGLOT %s to play\n",(colour_is_black(board->turn))?"black":"white"); my_log("POLYGLOT\n"); }
void board_clear(board_t * board) { int file, rank, sq; int colour, pos; int piece; ASSERT(board!=NULL); // edge squares for (sq = 0; sq < SquareNb; sq++) { board->square[sq] = Knight64; // HACK: uncoloured knight board->pos[sq] = -1; } // empty squares for (rank = 0; rank < 8; rank++) { for (file = 0; file < 8; file++) { sq = square_make(file,rank); board->square[sq] = Empty; } } // piece lists for (colour = 0; colour < 3; colour++) { for (pos = 0; pos < 32; pos++) { // HACK board->list[colour][pos] = SquareNone; } board->list_size[colour] = 0; } // material for (piece = 0; piece < 12; piece++) { board->number[piece] = 0; } // rest board->turn = ColourNone; board->castle[White][SideH] = SquareNone; board->castle[White][SideA] = SquareNone; board->castle[Black][SideH] = SquareNone; board->castle[Black][SideA] = SquareNone; board->ep_square = SquareNone; board->ply_nb = 0; board->move_nb = 0; board->key = 0; }
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)); }
bool board_from_fen(board_t * board, const char string[]) { int pos; int file, rank, sq; int c; int i, len; int piece; int king_pos[ColourNb]; ASSERT(board!=NULL); ASSERT(string!=NULL); board_clear(board); king_pos[White] = SquareNone; king_pos[Black] = SquareNone; pos = 0; c = string[pos]; // piece placement for (rank = 7; rank >= 0; rank--) { for (file = 0; file < 8;) { sq = square_make(file,rank); if (c >= '1' && c <= '8') { // empty square(s) len = c - '0'; if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); for (i = 0; i < len; i++) { board->square[sq++] = Empty; file++; } } else { // piece piece = piece_from_char(c); if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); if (piece_is_king(piece)) king_pos[piece_colour(piece)] = sq; board->square[sq++] = piece; file++; } c = string[++pos]; } if (rank > 0) { if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = string[++pos]; } } // active colour if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = string[++pos]; switch (c) { case 'w': board->turn = White; break; case 'b': board->turn = Black; break; default: my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); break; } c = string[++pos]; // castling if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = string[++pos]; board->castle[White][SideH] = SquareNone; board->castle[White][SideA] = SquareNone; board->castle[Black][SideH] = SquareNone; board->castle[Black][SideA] = SquareNone; if (c == '-') { // no castling rights c = string[++pos]; } else { // TODO: filter out illegal rights do { if (false) { } else if (c == 'K') { for (sq = H1; sq > king_pos[White]; sq--) { if (board->square[sq] == WhiteRook256) { board->castle[White][SideH] = sq; break; } } } else if (c == 'Q') { for (sq = A1; sq < king_pos[White]; sq++) { if (board->square[sq] == WhiteRook256) { board->castle[White][SideA] = sq; break; } } } else if (c == 'k') { for (sq = H8; sq > king_pos[Black]; sq--) { if (board->square[sq] == BlackRook256) { board->castle[Black][SideH] = sq; break; } } } else if (c == 'q') { for (sq = A8; sq < king_pos[Black]; sq++) { if (board->square[sq] == BlackRook256) { board->castle[Black][SideA] = sq; break; } } } else if (c >= 'A' && c <= 'H') { // white castling right sq = square_make(file_from_char(tolower(c)),Rank1); if (sq > king_pos[White]) { // h side board->castle[White][SideH] = sq; } else { // a side board->castle[White][SideA] = sq; } } else if (c >= 'a' && c <= 'h') { // black castling right sq = square_make(file_from_char(tolower(c)),Rank8); if (sq > king_pos[Black]) { // h side board->castle[Black][SideH] = sq; } else { // a side board->castle[Black][SideA] = sq; } } else { my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } c = string[++pos]; } while (c != ' '); } // en-passant if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = string[++pos]; if (c == '-') { // no en-passant sq = SquareNone; c = string[++pos]; } else { if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); file = file_from_char(c); c = string[++pos]; if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); rank = rank_from_char(c); c = string[++pos]; sq = square_make(file,rank); } board->ep_square = sq; // halfmove clock board->ply_nb = 0; board->move_nb = 0; // HACK, in case of broken syntax if (c != ' ') { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } c = string[++pos]; if (!isdigit(c)) { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } board->ply_nb = atoi(&string[pos]); do c = string[++pos]; while (isdigit(c)); // fullmove number board->move_nb = 0; if (c != ' ') { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } c = string[++pos]; if (!isdigit(c)) { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } board->move_nb = atoi(&string[pos]) - 1; do c = string[++pos]; while (isdigit(c)); // board update update: board_init_list(board); return true; }
bool board_to_fen(const board_t * board, char string[], int size) { int pos; int file, rank; int sq, piece; int c; int len; int old_pos; ASSERT(board_is_ok(board)); ASSERT(string!=NULL); ASSERT(size>=92); // init if (size < 92) return false; pos = 0; // piece placement for (rank = 7; rank >= 0; rank--) { for (file = 0; file < 8;) { sq = square_make(file,rank); piece = board->square[sq]; ASSERT(piece==Empty||piece_is_ok(piece)); if (piece == Empty) { len = 0; for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) { len++; } ASSERT(len>=1&&len<=8); c = '0' + len; } else { c = piece_to_char(piece); file++; } string[pos++] = c; } string[pos++] = '/'; } string[pos-1] = ' '; // HACK: remove the last '/' // active colour string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b'; string[pos++] = ' '; // castling old_pos = pos; if (option_get_bool("Chess960")) { // FEN-960 if (board->castle[White][SideH] != SquareNone) { string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH]))); } if (board->castle[White][SideA] != SquareNone) { string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA]))); } if (board->castle[Black][SideH] != SquareNone) { string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH]))); } if (board->castle[Black][SideA] != SquareNone) { string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA]))); } } else { // FEN if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K'; if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q'; if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k'; if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q'; } if (pos == old_pos) string[pos++] = '-'; string[pos++] = ' '; // en-passant if (board->ep_square == SquareNone) { string[pos++] = '-'; } else { if (!square_to_string(board->ep_square,&string[pos],3)) return false; pos += 2; } string[pos++] = ' '; // halfmove clock and fullmove number sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1); return true; }