Minimax (and thus alpha-beta, which is guaranteed to get the same result) does not care how long it takes to reach the same position, and thus often lead to undecisive behavior of the engine, which starts to aimlessly push pieces around, happy as long as these moves do not permanently destroy the prospects for the planned gain, but just postpone it. This does not only apply to mate, but for other gains as well.
In fact it is often worse for other gains, as the game continues after them. A mate is a mate, but gaining a Pawn in a leaf is a much less reliable gain then when you reach the position after the capture close to the root, so that you could search 4 ply beyond it to make sure there is no backlash. So it starts to intentionally postpone the gain of a poisoned Pawn (e.g. by interjecting checks) to just within the horizon, so it cannot see that it is poisoned, and keep imagining it will gain a Pawn by playing these checks.
A general solution is to award a delayed-loss bonus: when a node scores less than the current evaluation, (so that the side to move expects an unavoidable loss) you award a small bonus. If there are then many moves between the current position and the node where the loss materializes (i.e. where the static eval actually drops), the losing side gets this bonus many times.
You have to pre-adjust the search window, though, when you plan to add a bonus to the search result, to prevent this bonus could make the score cross the window boundary (thus falsely creating the impression it is another bound type than it actually is). In micro-Max the code for this looks like
Code: Select all
Search(alpha, beta)
{
int curEval = Evaluate();
if(alpha < curEval) alpha--;
if(beta <= curEval) beta --;
...
if(bestScore < curEval) bestScore++;
return bestScore;
}