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 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++] = ' ';

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 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 */

View File

@@ -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"

View File

@@ -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 {

View File

@@ -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;