mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-24 02:57:11 +08:00
Randomize draw eval
The patch adds a small random component (+-1) to VALUE_DRAW for the evaluation of draw positions (mostly 3folds). This random component is not static, but potentially different for each visit of the node (hence derived from the node counter). The effect is that in positions with many 3fold draw lines, different lines are followed at each iteration. This keeps the search much more dynamic, as opposed to being locked to one particular 3fold. An example of a position where master suffers from 3fold-blindness and this patch solves quickly is the famous TCEC game 53: FEN: 3r2k1/pr6/1p3q1p/5R2/3P3p/8/5RP1/3Q2K1 b - - 0 51 master doesn't see that this is a lost position (draw eval up to depth 50) as Qf6-e6 d4-d5 (found by patch at depth 23) leads to a loss. The 3fold-blindness is more important at longer TC, the patch was yellow STC and LTC, but passed VLTC: STC LLR: -2.95 (-2.94,2.94) [0.00,5.00] Total: 46328 W: 10048 L: 9953 D: 26327 http://tests.stockfishchess.org/tests/view/5b9c0ca20ebc592cf275f7c7 LTC LLR: -2.95 (-2.94,2.94) [0.00,5.00] Total: 54663 W: 8938 L: 8846 D: 36879 http://tests.stockfishchess.org/tests/view/5b9ca1610ebc592cf27601d3 VLTC LLR: 2.95 (-2.94,2.94) [0.00,5.00] Total: 31789 W: 4512 L: 4284 D: 22993 http://tests.stockfishchess.org/tests/view/5b9d1a670ebc592cf276076d Credit to @crossbr for pointing to this problem repeatedly, and giving the hint that many draw lines are typical in those situations. Bench: 4756639
This commit is contained in:
committed by
Stéphane Nicolet
parent
cb0111d3db
commit
97d2cc9a9c
@@ -85,6 +85,13 @@ namespace {
|
|||||||
return d > 17 ? 0 : 29 * d * d + 138 * d - 134;
|
return d > 17 ? 0 : 29 * d * d + 138 * d - 134;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a small random component to draw evaluations to keep search dynamic
|
||||||
|
// and to avoid 3fold-blindness.
|
||||||
|
Value value_draw(Depth depth, Thread* thisThread) {
|
||||||
|
return depth < 4 ? VALUE_DRAW
|
||||||
|
: VALUE_DRAW + Value(2 * (thisThread->nodes.load(std::memory_order_relaxed) % 2) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Skill structure is used to implement strength limit
|
// Skill structure is used to implement strength limit
|
||||||
struct Skill {
|
struct Skill {
|
||||||
explicit Skill(int l) : level(l) {}
|
explicit Skill(int l) : level(l) {}
|
||||||
@@ -535,7 +542,7 @@ namespace {
|
|||||||
&& !rootNode
|
&& !rootNode
|
||||||
&& pos.has_game_cycle(ss->ply))
|
&& pos.has_game_cycle(ss->ply))
|
||||||
{
|
{
|
||||||
alpha = VALUE_DRAW;
|
alpha = value_draw(depth, pos.this_thread());
|
||||||
if (alpha >= beta)
|
if (alpha >= beta)
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
@@ -584,7 +591,8 @@ namespace {
|
|||||||
if ( Threads.stop.load(std::memory_order_relaxed)
|
if ( Threads.stop.load(std::memory_order_relaxed)
|
||||||
|| pos.is_draw(ss->ply)
|
|| pos.is_draw(ss->ply)
|
||||||
|| ss->ply >= MAX_PLY)
|
|| ss->ply >= MAX_PLY)
|
||||||
return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) : VALUE_DRAW;
|
return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos)
|
||||||
|
: value_draw(depth, pos.this_thread());
|
||||||
|
|
||||||
// Step 3. Mate distance pruning. Even if we mate at the next move our score
|
// Step 3. Mate distance pruning. Even if we mate at the next move our score
|
||||||
// would be at best mate_in(ss->ply+1), but if alpha is already bigger because
|
// would be at best mate_in(ss->ply+1), but if alpha is already bigger because
|
||||||
|
|||||||
Reference in New Issue
Block a user