nkarve / surge

A fast bitboard-based chess move generator in C++
MIT License
59 stars 15 forks source link

Bug #6

Closed ivankrylatskoe closed 3 years ago

ivankrylatskoe commented 3 years ago

There is a bug in move generation algorithm in the following position: 6k1/8/8/8/1Pp5/8/B7/6K1 b - b3 0 1 The pawn on c4 can take b3 en passant. But the algorithm prohibits this move. The buggy line is the following: b1 = pawn_attacks<Them>(last_ply_info.epsq) & bitboard_of(Us, PAWN) & not_pinned; It prohibits pinned pawns to move. In this case the pinned pawn moves accross the pinning diagonal, and therefore can move.

ivankrylatskoe commented 3 years ago

Or maybe the fix should be placed in the block: //For each pinned pawn...

nkarve commented 3 years ago

I believe adding if(pawn_attacks<Us>(s) & SQUARE_BB[history[game_ply].epsq] & LINE[our_king][s]) *list++ = Move(s, history[game_ply].epsq, EN_PASSANT) in the else block starting at line 557 should work (on a side note, I'm amazed this bug escaped all the perft tests I did)

nkarve commented 3 years ago

However, I'll try and find a more efficient solution using attacks from the E.P. square, since this one checks for E.P. for every pinned pawn

nkarve commented 3 years ago

OK, found one:

b2 = pawn_attacks<Them>(history[game_ply].epsq) & bitboard_of(Us, PAWN);
b1 = b2 & not_pinned;
...
b1 = b2 & pinned & LINE[history[game_ply].epsq][our_king];
if (b1) {
    *list++ = Move(bsf(b1), history[game_ply].epsq, EN_PASSANT);
}

which seems to be optimal.

ivankrylatskoe commented 3 years ago

Thanks a lot!