19
const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
23
static const bool Strict = false;
29
bool board_from_fen(board_t *board, const char string[]) {
47
for (rank = 7; rank >= 0; rank--) {
49
for (file = 0; file < 8;) {
51
sq = square_make(file,rank);
53
if (c >= '1' && c <= '8') { // empty square(s)
56
if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
58
for (i = 0; i < len; i++) {
59
board->square[sq++] = Empty;
65
piece = piece_from_char(c);
66
if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
68
board->square[sq++] = piece;
76
if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
83
if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
94
my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
102
if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
105
board->flags = FlagsNone;
107
if (c == '-') { // no castling rights
114
board->flags |= FlagsWhiteKingCastle;
119
board->flags |= FlagsWhiteQueenCastle;
124
board->flags |= FlagsBlackKingCastle;
129
board->flags |= FlagsBlackQueenCastle;
136
if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
139
if (c == '-') { // no en-passant
146
if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
147
file = file_from_char(c);
150
if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
151
rank = rank_from_char(c);
154
sq = square_make(file,rank);
157
board->ep_square = sq;
162
board->move_nb = 0; // HACK, in case of broken syntax
165
if (!Strict) goto update;
166
my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
171
if (!Strict) goto update;
172
my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
175
board->ply_nb = atoi(&string[pos]);
176
do c = string[++pos]; while (isdigit(c));
183
if (!Strict) goto update;
184
my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
189
if (!Strict) goto update;
190
my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
193
board->move_nb = atoi(&string[pos]) - 1;
194
do c = string[++pos]; while (isdigit(c));
199
board_init_list(board);
206
bool board_to_fen(const board_t *board, char string[], int size) {
214
ASSERT(board_is_ok(board));
215
ASSERT(string!=NULL);
220
if (size < 92) return false;
226
for (rank = 7; rank >= 0; rank--) {
228
for (file = 0; file < 8;) {
230
sq = square_make(file,rank);
231
piece = board->square[sq];
232
ASSERT(piece==Empty||piece_is_ok(piece));
234
if (piece == Empty) {
237
for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) {
241
ASSERT(len>=1&&len<=8);
246
c = piece_to_char(piece);
256
string[pos-1] = ' '; // HACK: remove the last '/'
260
string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b';
265
if (board->flags == FlagsNone) {
268
if ((board->flags & FlagsWhiteKingCastle) != 0) string[pos++] = 'K';
269
if ((board->flags & FlagsWhiteQueenCastle) != 0) string[pos++] = 'Q';
270
if ((board->flags & FlagsBlackKingCastle) != 0) string[pos++] = 'k';
271
if ((board->flags & FlagsBlackQueenCastle) != 0) string[pos++] = 'q';
278
if (board->ep_square == SquareNone) {
281
if (!square_to_string(board->ep_square,&string[pos],3)) return false;
287
// halfmove clock and fullmove number
289
sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1);