fen: simplify fen_check() + fix e.p. when no possible capture
This commit is contained in:
31
src/fen.c
31
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 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++] = ' ';
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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"
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user