Null move

Discussion of chess software programming and technical issues.

Moderators: Harvey Williamson, bob, hgm

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Post Reply
Robert Pope
Posts: 523
Joined: Sat Mar 25, 2006 7:27 pm

Null move

Post by Robert Pope » Fri Apr 24, 2020 8:09 pm

So, I've always struggled to get a null move search that gives me positive results. I decided to look at the rules that Stockfish uses and see the following:

Code: Select all


    // Step 9. Null move search with verification search (~40 Elo)
1    if (   !PvNode
2        && (ss-1)->currentMove != MOVE_NULL
3        && (ss-1)->statScore < 23397
4        &&  eval >= beta
5        &&  eval >= ss->staticEval
6        &&  ss->staticEval >= beta - 32 * depth - 30 * improving + 120 * ttPv + 292
7        && !excludedMove
8        &&  pos.non_pawn_material(us)
9        && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))

Can anyone help explain the conditions in lines 3-6? I can almost read them, but in particular, I'm confused about the difference between statScore, eval, and staticEval. Those sound like almost the same thing, but must obviously be different.

Dann Corbit
Posts: 11627
Joined: Wed Mar 08, 2006 7:57 pm
Location: Redmond, WA USA
Contact:

Re: Null move

Post by Dann Corbit » Fri Apr 24, 2020 9:07 pm

eval can be a hash lookup, which might be a 40 ply search. It is therefore a much better estimate than static eval.
static eval is the result of calling the evaluation function. Even if we can't find it in the hash, we can get an estimate of the position this way.
statScore is an eval that is stored at each ply of the search and which may be modified by history. This is useful for things like "Am I improving?"
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.

Robert Pope
Posts: 523
Joined: Sat Mar 25, 2006 7:27 pm

Re: Null move

Post by Robert Pope » Sat Apr 25, 2020 1:19 pm

Thanks for the explanation. I don't think I ever had eval as one of the criteria, and that appears to add 30 elo in my initial tests.

Dann Corbit
Posts: 11627
Joined: Wed Mar 08, 2006 7:57 pm
Location: Redmond, WA USA
Contact:

Re: Null move

Post by Dann Corbit » Sat Apr 25, 2020 7:33 pm

As far as I know, I invented this technique. I called it smooth scaling null move at the time.
Of course it is possible that someone preceded me with the idea. And the concept is simple enough.
If a move looks terrible, we reduce it more. If a move looks good we reduce it less.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.

mjlef
Posts: 1454
Joined: Thu Mar 30, 2006 12:08 pm
Contact:

Re: Null move

Post by mjlef » Sun Apr 26, 2020 1:59 am

Robert Pope wrote:
Fri Apr 24, 2020 8:09 pm
So, I've always struggled to get a null move search that gives me positive results. I decided to look at the rules that Stockfish uses and see the following:

Code: Select all


    // Step 9. Null move search with verification search (~40 Elo)
1    if (   !PvNode
2        && (ss-1)->currentMove != MOVE_NULL
3        && (ss-1)->statScore < 23397
4        &&  eval >= beta
5        &&  eval >= ss->staticEval
6        &&  ss->staticEval >= beta - 32 * depth - 30 * improving + 120 * ttPv + 292
7        && !excludedMove
8        &&  pos.non_pawn_material(us)
9        && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))

Can anyone help explain the conditions in lines 3-6? I can almost read them, but in particular, I'm confused about the difference between statScore, eval, and staticEval. Those sound like almost the same thing, but must obviously be different.
Sure. this line:
&& (ss-1)->statScore < 23397
means if the history scores for the move that the opponent just made was very good, do not bother trying nullmove since we are likely to fail low here. This saves time on searches that are unlikel to pass.

this line:
&& eval >= beta

eval is the hash-adjusted eval. This means it took the static eval of the current positions, and if there was a hash entry with better informaion, it gets adjusted. So sometimes eval will just be the static eval, and other times higher or lower than that. This helps in two ways, if the hash adjusted eval is higher than beta, we should probably try a nullmove even if the static eval is under beta, and if the hash adjusted eval is lower than the static eval, then it is unlikely to fail high. The verification search would see it looses if it has to search. I suggested uses of a hash modified eval a very log time ago on rec.games.chess or maybe talkchess. I used it in NOW.

this line:
&& ss->staticEval >= beta - 32 * depth - 30 * improving + 120 * ttPv + 292
gradually allows worse and worse static evals to still have a nullmove run on them. Larry actually came up with this idea in an earlier Komodo. I remember because I was dealing with ailing parents and he actually modified and compiled the code while I was away. The 30 * improving just owers this depth based margin if the position's eval has aimproved from 2 or 4 plies ago. the 120*ttPv raises the margin if the hash move came from a PV node.

Mark

mjlef
Posts: 1454
Joined: Thu Mar 30, 2006 12:08 pm
Contact:

Re: Null move

Post by mjlef » Sun Apr 26, 2020 2:10 am

Dann Corbit wrote:
Sat Apr 25, 2020 7:33 pm
As far as I know, I invented this technique. I called it smooth scaling null move at the time.
Of course it is possible that someone preceded me with the idea. And the concept is simple enough.
If a move looks terrible, we reduce it more. If a move looks good we reduce it less.
Actually with nullmove, the higher the hash adjusted score is above beta, the more many programs reduce. So in this case, the better a position (or search result was), the more it gets reduced. I suppose you could say after the nullmove, an if an eval/search was done for the opponent, then the nullmoe could be considered a worse move, but artifically.

LMR works like you suggest if it uses history reductions. A move with a low history gets reduced more, and the better its history the less it gets reduced.

Mark

Post Reply