diff --git a/src/fen.c b/src/fen.c index bf7a3f0..6cbb0ae 100644 --- a/src/fen.c +++ b/src/fen.c @@ -68,7 +68,7 @@ static const char *castle_str = "KQkq"; * - inconsistent castle flags (if K & R are not in correct position) * - inconsistent en-passant square (turn, bad pawn position) * - * pos_check() is also called, leading to fatal errors if something is wrong. + * pos_ok() is also called, leading to fatal errors if something is wrong. * * @return: 0 if OK, 1 if OK after fix, -1 if fatal issue. */ @@ -76,19 +76,22 @@ static int fen_check(pos_t *pos) { char *colstr[2] = { "white", "black"}; int warning = 0; + color_t us = pos->turn, them = OPPONENT(us); + int up = sq_up(us); /* pawn up */ + square_t ep = pos->en_passant; /* en passant, depends on who plays next */ - if (pos->en_passant != SQUARE_NONE) { - rank_t eprank = sq_rank(pos->en_passant); - file_t epfile = sq_file(pos->en_passant); - rank_t rank5 = sq_rel_rank(RANK_5, pos->turn); - rank_t rank6 = sq_rel_rank(RANK_6, pos->turn); - rank_t rank7 = sq_rel_rank(RANK_7, pos->turn); - piece_t pawn = pos->turn == WHITE? B_PAWN: W_PAWN; + if (ep != SQUARE_NONE) { + rank_t eprank = sq_rank(ep); + rank_t rank6 = sq_rel_rank(RANK_6, us); + piece_t pawn = MAKE_PIECE(PAWN, them); + bitboard_t att = bb_pawn_attacks[them][ep] & pos->bb[us][PAWN]; + if (warn(eprank != rank6 || - pos->board[sq_make(epfile, rank5)] != pawn || - pos->board[sq_make(epfile, rank6)] != EMPTY || - pos->board[sq_make(epfile, rank7)] != EMPTY, + pos->board[ep - up] != pawn || + pos->board[ep] != EMPTY || + pos->board[ep + up] != EMPTY || + att == 0ull, "fen warn: wrong en-passant settings. (fixed)\n")) { # ifdef DEBUG_FEN printf("ep5=%o ep6=%o ep7=%o\n", sq_make(epfile, rank5), @@ -100,7 +103,7 @@ static int fen_check(pos_t *pos) } for (int color = WHITE; color <= BLACK; ++color) { - rank_t rank1 = color == WHITE? RANK_1: RANK_8; + rank_t rank1 = sq_rel_rank(RANK_1, color); /* castling */ /* where K and R should be for valid castle flag */ @@ -338,8 +341,8 @@ char *pos2fen(const pos_t *pos, char *fen) if (pos->en_passant == SQUARE_NONE) { fen[cur++] = '-'; } else { - fen[cur++] = FILE2C(sq_file(pos->en_passant)); - fen[cur++] = RANK2C(sq_rank(pos->en_passant)); + strcpy(fen+cur, sq_to_string(pos->en_passant)); + cur += 2; } fen[cur++] = ' '; diff --git a/src/position.c b/src/position.c index 08cb05c..bfbec93 100644 --- a/src/position.c +++ b/src/position.c @@ -336,7 +336,7 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa * - side-to-move already checking opponent king * - side-to-move in check more than twice * - kings distance is 1 - * - TODO: discrepancy between piece bitboards and ALL_PIECES bitboards (per color) + * - TODO: - castling / e.p. flags * * In case of errors, and @strict is true, @bug_on() is called, and program will * be terminated. @@ -349,6 +349,7 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa bool pos_ok(const pos_t *pos, const bool strict) { int n, count = 0, bbcount = 0, error = 0; + color_t us = pos->turn, them = OPPONENT(us); /* force BUG_ON and WARN_ON */ # pragma push_macro("BUG_ON") @@ -391,12 +392,11 @@ bool pos_ok(const pos_t *pos, const bool strict) /* occupied board is different from bitboards */ error += warn_on(count != bbcount); /* is opponent already in check ? */ - error += warn_on(pos_checkers(pos, OPPONENT(pos->turn))); + error += warn_on(pos_checkers(pos, them)); /* is color to play in check more than twice ? */ - error += warn_on(popcount64(pos_checkers(pos, pos->turn)) > 2); + error += warn_on(popcount64(pos_checkers(pos, us)) > 2); /* kings distance is less than 2 */ error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2); - if (strict) { bug_on(error); /* not reached */ diff --git a/test/common-test.h b/test/common-test.h index ca63679..8973c8f 100644 --- a/test/common-test.h +++ b/test/common-test.h @@ -393,6 +393,14 @@ struct fentest { "simple movedo/undo: only 2 W knights", "5n2/1k6/8/8/5K2/8/P7/1N6 w - - 0 1" }, + { __LINE__, FEN, + "legal EP", + "4k3/8/8/3pP3/8/8/8/4K3 w - d6 0 1" + }, + { __LINE__, FEN, + "illegal EP, fix-able by fen parser", + "4k3/8/8/3p1P2/8/8/8/4K3 w - d6 0 1" + }, { __LINE__, FEN, "illegal EP and castle flags, fix-able by fen parser, SF crash", "4k3/8/8/8/7B/8/8/4K3 w KQkq e6 0 1" diff --git a/test/fen-test.c b/test/fen-test.c index f395c45..415e996 100644 --- a/test/fen-test.c +++ b/test/fen-test.c @@ -31,8 +31,7 @@ int main(__unused int ac, __unused char**av) bitboard_init(); while ((fen = next_fen(FEN))) { - printf("***** [%s] ", fen); - fflush(stdout); + printf("line %3d: [%s] ", cur_line(), fen); if (!(pos = fen2pos(NULL, fen))) { printf("**INVALID\n"); } else { diff --git a/test/perft-test.c b/test/perft-test.c index 63d3cb4..9a41d1f 100644 --- a/test/perft-test.c +++ b/test/perft-test.c @@ -287,7 +287,7 @@ int main(int __unused ac, __unused char**av) while ((fen = next_fen(PERFT | MOVEDO))) { test_line = cur_line(); if (!(fenpos = fen2pos(pos, fen))) { - printf("wrong fen %d: [%s]\n", i, fen); + printf("wrong fen line = %d: [%s]\n", test_line, fen); continue; } pos = fenpos;