From your remarks, I get the impression that you use a lazy eval for your futility pruning decision. ie You're not evaluating after making the move.hgm wrote:OK, I misunderstood, and thought that isInCheck was testing the in-check status before the move. Testing if a move delivers check without actually making it should not be so difficult, btw.
If checks can be considered futile, depends on how you treat a position where the STM is in check. If such a player is allowed to stand pat, normal futility considerations apply. If you extend for the evasion, or do anything else that is special and might lead to a lower score than the current eval, checks are non-futile.
Probably you do the latter.
For the future, even in the face of this you could still do all the tricks described above if you would have a routine Generate_Checks, that you would run in stead of Generate_Captures when the futility condition is met. With bitboard such a routine is probably easier to make than for array representations. This might become more efficient if you somehow combine it with King-safety information on the Pawn shield: if the Pawn shield is intact, the only non-captures that can deliver check are R or Q moves to last rank. Generating these moves is far less work than generating all moves with all pieces, and then checking them one-by-one to see if they deliver check. (For R & Q that are already on last rank, you would have to test if they can deliver a discovered check.)
Did you test the difference ? In my engine, this seemed too dangerous.
Tony