elcabesa wrote:
the bug turned out to be in the search code, threat detection in nullmove.
When the nullmove test reports a checkmate I returned beta-1, this was the problem.
I was inspired by stockfish code where they return beta-1 if the move that make a checkmate and the previous move are "connected".
Now I don't return beta -1 but I only set a checkmateThreat and extend the search.
How does this idea fare in testing ? I'm curious, because I've tried everything there is about null threat: the chess programming wiki, as well as the Romstad null threat extension as implemented in SF. But I've never managed to measure any elo gain from it.
What you describe above is quite different from Stockfish, and in fact, much simpler. If we do a null move and get mated, then we stand on the edge of a knife and should be rather careful, so it could make sense to extend the search at this node.
Be careful of transplanting SF idea to your program like that. Your search may be very different from SF, and your program may "reject the transplant". What Stockfish does is rather complicated, and is a brilliant idea of Tord Romstad introduced in Glaurung:
- null moves are only performed at non PV nodes when the eval fails high (which ensures that double null moves are impossible even though SF enforces that condition twice with ss->skipNull flag, just to be sure)
- when the null move fails low, and the null refutation (threat move) is connected to the move played before the null move, AND the parent node was reduced, the search returns beta-1. For the sake of code clarity I think it should be alpha (of course alpha = beta-1, but it makes it clear the purpose is to fail low).
- at the parent node, the alpha=beta-1 becomes a fail high at non PV nodes, or a "doesn't fail low as expected on zero window search" at PV nodes. This triggers a re-search at non reduced depth, and will only work if your implementation of PVS is the same as Stockfish (when zero window fails low at PV node, you extend the depth *before* extending the window). And that is the main reason why it never worked in my engine, as my implementation of PVS is rather like Fruit than SF (it tries to adress search instability this way, and it seems to work well).
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.