hash move vs. null move

Discussion of chess software programming and technical issues.

Moderator: Ras

BubbaTough
Posts: 1154
Joined: Fri Jun 23, 2006 5:18 am

Re: hash move vs. null move

Post by BubbaTough »

I'm not sure what you mean about the killers on the next ply. Once the null move has been tried and failed, it's quite possible that the move is an all node. The hash move does indicate that it got a score > alpha at some point, but we don't know it will happen now. Anyways, I'm not sure why killers are relevant here anyways, I wasn't talking about them. Perhaps you meant the threat move?
Its my fault for confusing the nomenclature. I mentioned killer moves just because I had considered implementing threat moves (not knowing they were called this) and after playing around a little decided they were not needed for move ordering because when the null move is searched, the move that would be the threat move often becomes a killer move, so most of the time a separate threat move is not needed. I was never completely convinced of this logic, so I thought I would do some gentle probing when Zach mentioned threat moves to make sure threats moves really were the same idea I had played with earlier or if there is some difference that makes them more powerful that I was overlooking.

-Sam
Harald
Posts: 318
Joined: Thu Mar 09, 2006 1:07 am

Re: hash move vs. null move

Post by Harald »

bob wrote:
hgm wrote:
Zach Wegner wrote: I also try a null move regardless of what is in the hash, always before a real move.
Do I understand correcty from this that you try the null move before the hash move? That sounds like a waste of time, as normally you would expect the hash move to be good. So killers on the next level would be to no avail for the hash-move search, they would be tried in an all-node.

Or don't you consider the hash move a real move?
The null-move should always be searched first. That is the entire idea, that the reduced-depth null-move gives a quick cutoff before any full-depth search is done...
Is this what you do?

check hash
if hash_depth >= depth && hash_value >= beta then return beta
// Could there be a good reason depending on hash_value/depth not to try nullmove?
Under save conditions try nullmove with reduced depth
if nullmove >= beta then return beta
// nullmove is refuted here
// Do you call the refuting move of the opponent in ply+1 the threat_move?
// The refuting move is now a killer in ply+1 unless it is a capture move.
// Is there a special reaction if the nullmove returns we are mated?
// Is there any change of depth here under some conditions?
if there is no hash_move do IID to get a hash_move
if there is a hash_move try hash_move (*)
generate captures and do SEE (+)
try good or equal capture (*)
try killers (*)
generate other moves (+)
try other moves and bad captures (*)
return alpha

(*) if value > alpha then alpha = value and insert move in hash table
if value >= beta return beta
// Never store nullmove in the hash table.

(+) Some moves could get a bonus in move ordering for dealing with the threat_move.

Please correct me if I was wrong or if I have left out an important step.

Harald
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: hash move vs. null move

Post by bob »

hgm wrote:
Zach Wegner wrote:I don't think it is a waste of time, in fact you're the only person I know of that doesn't do this.
Well, uMax searches null move before hash move, but I always thought this was a built-in inefficiency because of the way it has to sneak in the hash move between the generated moves.
The hash move is expected to be good, but the null move is cheaper. In fact the hash move should be better than the null move in virtually all positions (sans zugzwang). Since the null move is never stored as the best move,
Now I am confused, as I remember having this discussion with Bob some years ago, who at the time was strongly advocating erasing a pre-existing hash move by a null move. So I had the impression that storing null moves as hash move was common practice.
That loses me. If you do a null-move first (which you should) you should store a hash entry so that if you reach this position again, at the same (or greater depth) you will fail high without repeating the null move. And the "best" move could be set to the null move, or if there is an existing entry, you could store the proper bound and draft and hold on to the old best move in case the bounds change and the null will not fail high, where the best move might be useful. But there is a risk that this move is no good and I personally do not do the above. When I store an entry I store the current best move, which after a null-move search is a null-move, after searching an ALL node, I store 0 as well since there is no best move.

we can't logically assume that the hash move is a better move to try (i.e. we can't assume the null move failed low before, because the score in the hash and the move might come from different searches).
How do you get a non-null hash move if the null move has always failed high?
If the null move has always failed high, the best move to try is always a null move, although so long as you keep the hash entry around, you won't need to search at all.

I'm not sure what you mean about the killers on the next ply. Once the null move has been tried and failed, it's quite possible that the move is an all node. The hash move does indicate that it got a score > alpha at some point, but we don't know it will happen now. Anyways, I'm not sure why killers are relevant here anyways, I wasn't talking about them. Perhaps you meant the threat move?
He was talking about the "null move refutation move" which is the move at the next ply that causes the null-move search to fail low. But since that move was a refutation move, it becomes a killer and will be tried early anyway.
Sam equated the threat move to a later killer move, and I simply used hs terminology.

If beta > 0, the most common reason the null move fails low is a simple threat against one of your pieces, which is usually easy to evade. The case where it really is an all node is fairly rare, as in cut-nodes you are playing an opponent who tries anything, and most of what can be tried is not very subtle, or even outright stupid. When eval < beta I don't even try the null move, (in Joker) as the opponent is going to refute it by standing pat for some depths to come.
If so, that is kept for all moves on the next ply, so, assuming that the current node is an all node (since the null move failed low), then the threat move could help refute the hash move and every other move after it.
The refutation of the null move is very unikely to be a refutation of the hash move. If you have a real threat against you, the hash move must somehow solve it, or it could not have failed high before.