fen: simplify fen_check() + fix e.p. when no possible capture

This commit is contained in:
2024-05-27 14:54:44 +02:00
parent a7495b67d2
commit 972046351b
5 changed files with 31 additions and 21 deletions

View File

@@ -68,7 +68,7 @@ static const char *castle_str = "KQkq";
* - inconsistent castle flags (if K & R are not in correct position) * - inconsistent castle flags (if K & R are not in correct position)
* - inconsistent en-passant square (turn, bad pawn 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. * @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"}; char *colstr[2] = { "white", "black"};
int warning = 0; 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 */ /* en passant, depends on who plays next */
if (pos->en_passant != SQUARE_NONE) { if (ep != SQUARE_NONE) {
rank_t eprank = sq_rank(pos->en_passant); rank_t eprank = sq_rank(ep);
file_t epfile = sq_file(pos->en_passant); rank_t rank6 = sq_rel_rank(RANK_6, us);
rank_t rank5 = sq_rel_rank(RANK_5, pos->turn); piece_t pawn = MAKE_PIECE(PAWN, them);
rank_t rank6 = sq_rel_rank(RANK_6, pos->turn); bitboard_t att = bb_pawn_attacks[them][ep] & pos->bb[us][PAWN];
rank_t rank7 = sq_rel_rank(RANK_7, pos->turn);
piece_t pawn = pos->turn == WHITE? B_PAWN: W_PAWN;
if (warn(eprank != rank6 || if (warn(eprank != rank6 ||
pos->board[sq_make(epfile, rank5)] != pawn || pos->board[ep - up] != pawn ||
pos->board[sq_make(epfile, rank6)] != EMPTY || pos->board[ep] != EMPTY ||
pos->board[sq_make(epfile, rank7)] != EMPTY, pos->board[ep + up] != EMPTY ||
att == 0ull,
"fen warn: wrong en-passant settings. (fixed)\n")) { "fen warn: wrong en-passant settings. (fixed)\n")) {
# ifdef DEBUG_FEN # ifdef DEBUG_FEN
printf("ep5=%o ep6=%o ep7=%o\n", sq_make(epfile, rank5), 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) { 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 */ /* castling */
/* where K and R should be for valid castle flag */ /* 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) { if (pos->en_passant == SQUARE_NONE) {
fen[cur++] = '-'; fen[cur++] = '-';
} else { } else {
fen[cur++] = FILE2C(sq_file(pos->en_passant)); strcpy(fen+cur, sq_to_string(pos->en_passant));
fen[cur++] = RANK2C(sq_rank(pos->en_passant)); cur += 2;
} }
fen[cur++] = ' '; fen[cur++] = ' ';

View File

@@ -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 already checking opponent king
* - side-to-move in check more than twice * - side-to-move in check more than twice
* - kings distance is 1 * - 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 * In case of errors, and @strict is true, @bug_on() is called, and program will
* be terminated. * 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) bool pos_ok(const pos_t *pos, const bool strict)
{ {
int n, count = 0, bbcount = 0, error = 0; int n, count = 0, bbcount = 0, error = 0;
color_t us = pos->turn, them = OPPONENT(us);
/* force BUG_ON and WARN_ON */ /* force BUG_ON and WARN_ON */
# pragma push_macro("BUG_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 */ /* occupied board is different from bitboards */
error += warn_on(count != bbcount); error += warn_on(count != bbcount);
/* is opponent already in check ? */ /* 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 ? */ /* 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 */ /* kings distance is less than 2 */
error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2); error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2);
if (strict) { if (strict) {
bug_on(error); bug_on(error);
/* not reached */ /* not reached */

View File

@@ -393,6 +393,14 @@ struct fentest {
"simple movedo/undo: only 2 W knights", "simple movedo/undo: only 2 W knights",
"5n2/1k6/8/8/5K2/8/P7/1N6 w - - 0 1" "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, { __LINE__, FEN,
"illegal EP and castle flags, fix-able by fen parser, SF crash", "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" "4k3/8/8/8/7B/8/8/4K3 w KQkq e6 0 1"

View File

@@ -31,8 +31,7 @@ int main(__unused int ac, __unused char**av)
bitboard_init(); bitboard_init();
while ((fen = next_fen(FEN))) { while ((fen = next_fen(FEN))) {
printf("***** [%s] ", fen); printf("line %3d: [%s] ", cur_line(), fen);
fflush(stdout);
if (!(pos = fen2pos(NULL, fen))) { if (!(pos = fen2pos(NULL, fen))) {
printf("**INVALID\n"); printf("**INVALID\n");
} else { } else {

View File

@@ -287,7 +287,7 @@ int main(int __unused ac, __unused char**av)
while ((fen = next_fen(PERFT | MOVEDO))) { while ((fen = next_fen(PERFT | MOVEDO))) {
test_line = cur_line(); test_line = cur_line();
if (!(fenpos = fen2pos(pos, fen))) { if (!(fenpos = fen2pos(pos, fen))) {
printf("wrong fen %d: [%s]\n", i, fen); printf("wrong fen line = %d: [%s]\n", test_line, fen);
continue; continue;
} }
pos = fenpos; pos = fenpos;