by H.G.Muller » 23 Oct 2006, 08:35
Futility pruning of frontier nodes isn't really pruning. It is merely a more efficient implementation of minimax, bringing as much of the code as possible in the if-part that decides if you are going to stand pat in QS. So that you don't waste time making and unmaking when making a stand-pat cutoff in cases where you know in advance such a cutoff will occur.
So the score of the 1-ply node will not really be affected at all by the fact that you 'prune' the futile moves. That the score seems alpha-dependent is just the ordinary alpha dependence of scoring you get from alpha-beta: with a higher alpha the seach gets lazy, and you might get a weaker upper bound (below alpha) as you would have gotten for the same search with a much lower alpha. But the hashing algorithm takes fully account of that, by storing the fact that the score is merely an upper bound, so that a score you obtained with large alpha, that is above the current alpha, is not accepted as a valid score.
For deeper futility pruning, the most lgical solution is to treat the criterion on which you decided to prune as a score estimate. You prune because you are confident that the score will be out-of-window. If you are doing hard fail, that is all you have to know. If, for the benifit of storing sharper bounds in the hash table, you do soft fail, you should store the most pessimistic case. (And hard fail might still be too pessimistic.)
So if you priune when eval + victim < alpha - MARGIN, you are really doing it because the best possible score you can expect, eval + victim + MARGIN, is too low. But you can use that latter score for updating your soft-fail upper bound to the score (in the below-alpha range). The true score might ly even below this, but you cannot know that without doing the search (to see if he had good captures that would be better than stending pat) or the true, rather than the lazy evaluation (to conclude that the move really earns much less positional points than MARGIN).
The same with null-move pruning: it assumes that your best move is better than the null-move score, so the value you store in the hash table for a position in which the null move fails high could be the null-move score, rather than beta.