std::string move_to_string(const Move m){ Square to = move_to(m); int type = move_type(m); if(type >= MovePN && type <= MovePQ) return square_to_string(move_from(m)) + square_to_string(to) + piece_to_char(Piece(type+Black)); return square_to_string(move_from(m)) + square_to_string(to); }
bool board_to_fen(const board_t * board, char fen[], int size) { int pos; int file, rank; int sq, piece; int c; int len; ASSERT(board!=NULL); ASSERT(fen!=NULL); ASSERT(size>=92); // init if (size < 92) return false; pos = 0; // piece placement for (rank = Rank8; rank >= Rank1; rank--) { for (file = FileA; file <= FileH;) { sq = SQUARE_MAKE(file,rank); piece = board->square[sq]; ASSERT(piece==Empty||piece_is_ok(piece)); if (piece == Empty) { len = 0; for (; file <= FileH && board->square[SQUARE_MAKE(file,rank)] == Empty; file++) { len++; } ASSERT(len>=1&&len<=8); c = '0' + len; } else { c = piece_to_char(piece); file++; } fen[pos++] = c; } fen[pos++] = '/'; } fen[pos-1] = ' '; // HACK: remove the last '/' // active colour fen[pos++] = (COLOUR_IS_WHITE(board->turn)) ? 'w' : 'b'; fen[pos++] = ' '; // castling if (board->flags == FlagsNone) { fen[pos++] = '-'; } else { if ((board->flags & FlagsWhiteKingCastle) != 0) fen[pos++] = 'K'; if ((board->flags & FlagsWhiteQueenCastle) != 0) fen[pos++] = 'Q'; if ((board->flags & FlagsBlackKingCastle) != 0) fen[pos++] = 'k'; if ((board->flags & FlagsBlackQueenCastle) != 0) fen[pos++] = 'q'; } fen[pos++] = ' '; // en-passant if (board->ep_square == SquareNone) { fen[pos++] = '-'; } else { square_to_string(board->ep_square,&fen[pos],3); pos += 2; } fen[pos++] = ' '; // halfmove clock sprintf(&fen[pos],"%d 1",board->ply_nb); return true; }
const std::string move_to_san(Position &pos, Move m) { std::string str; assert(pos.is_ok()); assert(move_is_ok(m)); Square from, to; Piece pc; from = move_from(m); to = move_to(m); pc = pos.piece_on(move_from(m)); if(m == MOVE_NONE) { str = "(none)"; return str; } else if(m == MOVE_NULL) { str = "(null)"; return str; } else if(move_is_long_castle(m) || (int(to - from) == -2 && type_of_piece(pc) == KING)) str = "O-O-O"; else if(move_is_short_castle(m) || (int(to - from) == 2 && type_of_piece(pc) == KING)) str = "O-O"; else { str = ""; if(type_of_piece(pc) == PAWN) { if(pos.move_is_capture(m)) str += file_to_char(square_file(move_from(m))); } else { str += piece_type_to_char(type_of_piece(pc), true); Ambiguity amb = move_ambiguity(pos, m); switch(amb) { case AMBIGUITY_NONE: break; case AMBIGUITY_FILE: str += file_to_char(square_file(from)); break; case AMBIGUITY_RANK: str += rank_to_char(square_rank(from)); break; case AMBIGUITY_BOTH: str += square_to_string(from); break; default: assert(false); } } if(pos.move_is_capture(m)) str += "x"; str += square_to_string(move_to(m)); if(move_promotion(m)) { str += "="; str += piece_type_to_char(move_promotion(m), true); } } // Is the move check? We don't use pos.move_is_check(m) here, because // Position::move_is_check doesn't detect all checks (not castling moves, // promotions and en passant captures). UndoInfo u; pos.do_move(m, u); if(pos.is_check()) str += pos.is_mate()? "#" : "+"; pos.undo_move(m, u); return str; }
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; }
bool move_to_san(int move, const board_t * board, char string[], int size) { int from, to, piece; char tmp_string[256]; ASSERT(move_is_ok(move)); ASSERT(board_is_ok(board)); ASSERT(string!=NULL); ASSERT(size>=8); ASSERT(move_is_legal(move,board)); if (size < 8) return false; // init from = move_from(move); to = move_to(move); string[0] = '\0'; // castle if (move_is_castle(move,board)) { if (to > from) { strcat(string,"O-O"); } else { strcat(string,"O-O-O"); } goto check; } // from piece = board->square[from]; if (piece_is_pawn(piece)) { // pawn if (move_is_capture(move,board)) { sprintf(tmp_string,"%c",file_to_char(square_file(from))); strcat(string,tmp_string); } } else { // piece sprintf(tmp_string,"%c",toupper(piece_to_char(piece))); strcat(string,tmp_string); // ambiguity switch (ambiguity(move,board)) { case AMBIGUITY_NONE: break; case AMBIGUITY_FILE: sprintf(tmp_string,"%c",file_to_char(square_file(from))); strcat(string,tmp_string); break; case AMBIGUITY_RANK: sprintf(tmp_string,"%c",rank_to_char(square_rank(from))); strcat(string,tmp_string); break; case AMBIGUITY_SQUARE: if (!square_to_string(from,tmp_string,256)) return false; strcat(string,tmp_string); break; default: ASSERT(false); break; } } // capture if (move_is_capture(move,board)) strcat(string,"x"); // to if (!square_to_string(to,tmp_string,256)) return false; strcat(string,tmp_string); // promote if (move_is_promote(move)) { sprintf(tmp_string,"=%c",toupper(piece_to_char(move_promote(move,board)))); strcat(string,tmp_string); } // check check: if (move_is_mate(move,board)) { strcat(string,"#"); } else if (move_is_check(move,board)) { strcat(string,"+"); } return true; }
static bool san_to_lan(const char san[], const board_t * board, char string[], int size) { int len; int left, right; int c; int king, rook; char king_string[3], rook_string[3]; ASSERT(san!=NULL); ASSERT(board_is_ok(board)); ASSERT(string!=NULL); ASSERT(size>=8); // init if (size < 8) return false; strcpy(string,"???????"); len = strlen(san); left = 0; right = len; // skip trailing '+' or '#' if (left < right) { c = san[right-1]; if (c == '+' || c == '#') right--; } // castling ASSERT(left==0); if (false) { } else if (right == 3 && strncmp(san,"O-O",3) == 0) { if (board->castle[board->turn][SideH] == SquareNone) return false; king = king_pos(board,board->turn); rook = board->castle[board->turn][SideH]; square_to_string(king,king_string,3); square_to_string(rook,rook_string,3); sprintf(string,"K%s?%s?",king_string,rook_string); } else if (right == 5 && strncmp(san,"O-O-O",5) == 0) { if (board->castle[board->turn][SideA] == SquareNone) return false; king = king_pos(board,board->turn); rook = board->castle[board->turn][SideA]; square_to_string(king,king_string,3); square_to_string(rook,rook_string,3); sprintf(string,"K%s?%s?",king_string,rook_string); } else { // moved piece if (left < right) { c = san[left]; if (char_is_piece(c)) { string[0] = c; left++; } } // promotion if (left < right) { c = toupper(san[right-1]); if (char_is_piece(c)) { string[6] = c; right--; // skip '=' if (left < right && san[right-1] == '=') right--; } } // to-square rank if (left < right) { c = san[right-1]; if (char_is_rank(c)) { string[5] = c; right--; } } // to-square file if (left < right) { c = san[right-1]; if (char_is_file(c)) { string[4] = c; right--; } } // captured piece if (left < right) { c = san[right-1]; if (char_is_piece(c)) { string[3] = c; right--; } } // skip middle '-' or 'x' if (left < right) { c = san[right-1]; if (c == '-' || c == 'x') right--; } // from-square file if (left < right) { c = san[left]; if (char_is_file(c)) { string[1] = c; left++; } } // from-square rank if (left < right) { c = san[left]; if (char_is_rank(c)) { string[2] = c; left++; } } if (left != right) return false; } // end return true; }