Focusing on the problem of forks (or more generally double attacks), to escape one you have to threaten something. What is this 'something' depends on the "sensitivity" of the player (in this case, an engine).hgm wrote: The problem is what to do next. Should I give an extension to see what can be salvaged? Or should I use a null-move score to figure out how bad it is exactly, and return that score (which will likely mean a fail low, where a fail high was needed). Searching all moves is likely to come up with a delaying tactic to push the problem over the horizon. Two ply later the problem will then still exist, and I will still recognize it, but I will have the same problem again, unless I keep extending until I used up all delay moves.
Therefore, if your engine understands, say, threatening the King, it will presumably extend checks and mate threats; therefore if a code to statically detect if there is a double attack, after the move that triggered the extension, still detects a double, and there is no further extension possible, it means that the resolution, if any, lies beyond the horizon, and the threat is a killer (as far as your engine knows).
Otherwise, you evaded the threat.
What I think should be done, in summary, is showing no mercy with a position with a "static" threat, unless some extension evades the threat.
Since you cannot prove in advance that there is a double attack threatened in a few plies, you have to rely to your "extension policy".
This is what I try to do with my engine, indeed...the result are...ahem...
The part in which this mechanism doesn't work, I think, is the Qsearch, where you don't have many moves, besides captures (and checks, if you included them: I didn't). In that case I am still trying to convince myself that null move pruning in qsearch wouldn't be too heavy: one day I'll give it a try...when I have time...
Cheers, Mauro