Skip to content

Commit 36db936

Browse files
XInTheDarkDisservin
authored andcommitted
VLTC Search parameters tune
The SPSA tuning was done for 44k games at 120+1.2. https://tests.stockfishchess.org/tests/view/656ee2a76980e15f69c7767f. Note that the tune was originally done in combination with the recent dual NNUE idea (see #4910). VLTC: https://tests.stockfishchess.org/tests/view/65731ccbf09ce1261f12246e LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 52806 W: 13069 L: 12760 D: 26977 Ptnml(0-2): 19, 5498, 15056, 5815, 15 VLTC SMP: https://tests.stockfishchess.org/tests/view/65740ffaf09ce1261f1239ba LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 27630 W: 6934 L: 6651 D: 14045 Ptnml(0-2): 1, 2643, 8243, 2928, 0 Estimated close to neutral at LTC: https://tests.stockfishchess.org/tests/view/6575485a8ec68176cf7d9423 Elo: -0.59 ± 1.8 (95%) LOS: 26.6% Total: 32060 W: 7859 L: 7913 D: 16288 Ptnml(0-2): 20, 3679, 8676, 3645, 10 nElo: -1.21 ± 3.8 (95%) PairsRatio: 0.99 closes #4912 Bench: 1283323
1 parent 8724503 commit 36db936

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

src/search.cpp

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,27 @@ enum NodeType {
7777

7878
// Futility margin
7979
Value futility_margin(Depth d, bool noTtCutNode, bool improving) {
80-
return Value((125 - 43 * noTtCutNode) * (d - improving));
80+
return Value((116 - 44 * noTtCutNode) * (d - improving));
8181
}
8282

8383
// Reductions lookup table initialized at startup
8484
int Reductions[MAX_MOVES]; // [depth or moveNumber]
8585

8686
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
8787
int reductionScale = Reductions[d] * Reductions[mn];
88-
return (reductionScale + 1487 - int(delta) * 976 / int(rootDelta)) / 1024
89-
+ (!i && reductionScale > 808);
88+
return (reductionScale + 1346 - int(delta) * 896 / int(rootDelta)) / 1024
89+
+ (!i && reductionScale > 880);
9090
}
9191

9292
constexpr int futility_move_count(bool improving, Depth depth) {
9393
return improving ? (3 + depth * depth) : (3 + depth * depth) / 2;
9494
}
9595

9696
// History and stats update bonus, based on depth
97-
int stat_bonus(Depth d) { return std::min(291 * d - 350, 1200); }
97+
int stat_bonus(Depth d) { return std::min(268 * d - 352, 1153); }
9898

9999
// History and stats update malus, based on depth
100-
int stat_malus(Depth d) { return std::min(361 * d - 361, 1182); }
100+
int stat_malus(Depth d) { return std::min(400 * d - 354, 1201); }
101101

102102
// Add a small random component to draw evaluations to avoid 3-fold blindness
103103
Value value_draw(const Thread* thisThread) {
@@ -367,12 +367,12 @@ void Thread::search() {
367367

368368
// Reset aspiration window starting size
369369
Value avg = rootMoves[pvIdx].averageScore;
370-
delta = Value(10) + int(avg) * avg / 15335;
370+
delta = Value(9) + int(avg) * avg / 14847;
371371
alpha = std::max(avg - delta, -VALUE_INFINITE);
372372
beta = std::min(avg + delta, VALUE_INFINITE);
373373

374374
// Adjust optimism based on root move's averageScore (~4 Elo)
375-
optimism[us] = 110 * avg / (std::abs(avg) + 121);
375+
optimism[us] = 121 * avg / (std::abs(avg) + 109);
376376
optimism[~us] = -optimism[us];
377377

378378
// Start with a small aspiration window and, in the case of a fail
@@ -746,7 +746,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
746746
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
747747
if (is_ok((ss - 1)->currentMove) && !(ss - 1)->inCheck && !priorCapture)
748748
{
749-
int bonus = std::clamp(-14 * int((ss - 1)->staticEval + ss->staticEval), -1449, 1449);
749+
int bonus = std::clamp(-13 * int((ss - 1)->staticEval + ss->staticEval), -1555, 1452);
750750
thisThread->mainHistory[~us][from_to((ss - 1)->currentMove)] << bonus;
751751
if (type_of(pos.piece_on(prevSq)) != PAWN && type_of((ss - 1)->currentMove) != PROMOTION)
752752
thisThread->pawnHistory[pawn_structure(pos)][pos.piece_on(prevSq)][prevSq] << bonus / 4;
@@ -765,7 +765,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
765765
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
766766
// return a fail low.
767767
// Adjust razor margin according to cutoffCnt. (~1 Elo)
768-
if (eval < alpha - 474 - (270 - 174 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
768+
if (eval < alpha - 472 - (284 - 165 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
769769
{
770770
value = qsearch<NonPV>(pos, ss, alpha - 1, alpha);
771771
if (value < alpha)
@@ -776,22 +776,22 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
776776
// The depth condition is important for mate finding.
777777
if (!ss->ttPv && depth < 9
778778
&& eval - futility_margin(depth, cutNode && !ss->ttHit, improving)
779-
- (ss - 1)->statScore / 321
779+
- (ss - 1)->statScore / 337
780780
>= beta
781-
&& eval >= beta && eval < 29462 // smaller than TB wins
781+
&& eval >= beta && eval < 29008 // smaller than TB wins
782782
&& (!ttMove || ttCapture))
783783
return (eval + beta) / 2;
784784

785785
// Step 9. Null move search with verification search (~35 Elo)
786-
if (!PvNode && (ss - 1)->currentMove != MOVE_NULL && (ss - 1)->statScore < 17257 && eval >= beta
787-
&& eval >= ss->staticEval && ss->staticEval >= beta - 24 * depth + 281 && !excludedMove
786+
if (!PvNode && (ss - 1)->currentMove != MOVE_NULL && (ss - 1)->statScore < 17496 && eval >= beta
787+
&& eval >= ss->staticEval && ss->staticEval >= beta - 23 * depth + 304 && !excludedMove
788788
&& pos.non_pawn_material(us) && ss->ply >= thisThread->nmpMinPly
789789
&& beta > VALUE_TB_LOSS_IN_MAX_PLY)
790790
{
791791
assert(eval - beta >= 0);
792792

793793
// Null move dynamic reduction based on depth and eval
794-
Depth R = std::min(int(eval - beta) / 152, 6) + depth / 3 + 4;
794+
Depth R = std::min(int(eval - beta) / 144, 6) + depth / 3 + 4;
795795

796796
ss->currentMove = MOVE_NULL;
797797
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
@@ -805,7 +805,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
805805
// Do not return unproven mate or TB scores
806806
if (nullValue >= beta && nullValue < VALUE_TB_WIN_IN_MAX_PLY)
807807
{
808-
if (thisThread->nmpMinPly || depth < 14)
808+
if (thisThread->nmpMinPly || depth < 15)
809809
return nullValue;
810810

811811
assert(!thisThread->nmpMinPly); // Recursive verification is not allowed
@@ -838,7 +838,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
838838
if (cutNode && depth >= 8 && !ttMove)
839839
depth -= 2;
840840

841-
probCutBeta = beta + 168 - 70 * improving;
841+
probCutBeta = beta + 163 - 67 * improving;
842842

843843
// Step 11. ProbCut (~10 Elo)
844844
// If we have a good enough capture (or queen promotion) and a reduced search returns a value
@@ -896,7 +896,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
896896
moves_loop: // When in check, search starts here
897897

898898
// Step 12. A small Probcut idea, when we are in check (~4 Elo)
899-
probCutBeta = beta + 416;
899+
probCutBeta = beta + 425;
900900
if (ss->inCheck && !PvNode && ttCapture && (tte->bound() & BOUND_LOWER)
901901
&& tte->depth() >= depth - 4 && ttValue >= probCutBeta
902902
&& abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
@@ -983,14 +983,14 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
983983
{
984984
Piece capturedPiece = pos.piece_on(to_sq(move));
985985
int futilityEval =
986-
ss->staticEval + 239 + 291 * lmrDepth + PieceValue[capturedPiece]
986+
ss->staticEval + 238 + 305 * lmrDepth + PieceValue[capturedPiece]
987987
+ captureHistory[movedPiece][to_sq(move)][type_of(capturedPiece)] / 7;
988988
if (futilityEval < alpha)
989989
continue;
990990
}
991991

992992
// SEE based pruning for captures and checks (~11 Elo)
993-
if (!pos.see_ge(move, Value(-185) * depth))
993+
if (!pos.see_ge(move, Value(-187) * depth))
994994
continue;
995995
}
996996
else
@@ -1001,18 +1001,18 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
10011001
+ thisThread->pawnHistory[pawn_structure(pos)][movedPiece][to_sq(move)];
10021002

10031003
// Continuation history based pruning (~2 Elo)
1004-
if (lmrDepth < 6 && history < -3645 * depth)
1004+
if (lmrDepth < 6 && history < -3752 * depth)
10051005
continue;
10061006

10071007
history += 2 * thisThread->mainHistory[us][from_to(move)];
10081008

1009-
lmrDepth += history / 7836;
1009+
lmrDepth += history / 7838;
10101010
lmrDepth = std::max(lmrDepth, -1);
10111011

10121012
// Futility pruning: parent node (~13 Elo)
1013-
if (!ss->inCheck && lmrDepth < 13
1014-
&& ss->staticEval + (bestValue < ss->staticEval - 62 ? 123 : 77)
1015-
+ 127 * lmrDepth
1013+
if (!ss->inCheck && lmrDepth < 14
1014+
&& ss->staticEval + (bestValue < ss->staticEval - 57 ? 124 : 71)
1015+
+ 118 * lmrDepth
10161016
<= alpha)
10171017
continue;
10181018

@@ -1039,11 +1039,11 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
10391039
// so changing them requires tests at these types of time controls.
10401040
// Recursive singular search is avoided.
10411041
if (!rootNode && move == ttMove && !excludedMove
1042-
&& depth >= 4 - (thisThread->completedDepth > 24) + 2 * (PvNode && tte->is_pv())
1042+
&& depth >= 4 - (thisThread->completedDepth > 27) + 2 * (PvNode && tte->is_pv())
10431043
&& abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && (tte->bound() & BOUND_LOWER)
10441044
&& tte->depth() >= depth - 3)
10451045
{
1046-
Value singularBeta = ttValue - (64 + 57 * (ss->ttPv && !PvNode)) * depth / 64;
1046+
Value singularBeta = ttValue - (66 + 58 * (ss->ttPv && !PvNode)) * depth / 64;
10471047
Depth singularDepth = newDepth / 2;
10481048

10491049
ss->excludedMove = move;
@@ -1057,7 +1057,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
10571057
singularQuietLMR = !ttCapture;
10581058

10591059
// Avoid search explosion by limiting the number of double extensions
1060-
if (!PvNode && value < singularBeta - 18 && ss->doubleExtensions <= 11)
1060+
if (!PvNode && value < singularBeta - 17 && ss->doubleExtensions <= 11)
10611061
{
10621062
extension = 2;
10631063
depth += depth < 15;
@@ -1092,18 +1092,18 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
10921092
}
10931093

10941094
// Check extensions (~1 Elo)
1095-
else if (givesCheck && depth > 9)
1095+
else if (givesCheck && depth > 10)
10961096
extension = 1;
10971097

10981098
// Quiet ttMove extensions (~1 Elo)
10991099
else if (PvNode && move == ttMove && move == ss->killers[0]
1100-
&& (*contHist[0])[movedPiece][to_sq(move)] >= 4194)
1100+
&& (*contHist[0])[movedPiece][to_sq(move)] >= 4325)
11011101
extension = 1;
11021102

11031103
// Recapture extensions (~1 Elo)
11041104
else if (PvNode && move == ttMove && to_sq(move) == prevSq
11051105
&& captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))]
1106-
> 4000)
1106+
> 4146)
11071107
extension = 1;
11081108
}
11091109

@@ -1162,10 +1162,10 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
11621162
ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)]
11631163
+ (*contHist[0])[movedPiece][to_sq(move)]
11641164
+ (*contHist[1])[movedPiece][to_sq(move)]
1165-
+ (*contHist[3])[movedPiece][to_sq(move)] - 3848;
1165+
+ (*contHist[3])[movedPiece][to_sq(move)] - 3817;
11661166

11671167
// Decrease/increase reduction for moves with a good/bad history (~25 Elo)
1168-
r -= ss->statScore / 14200;
1168+
r -= ss->statScore / 14767;
11691169

11701170
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
11711171
// We use various heuristics for the sons of a node after the first son has
@@ -1188,7 +1188,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
11881188
{
11891189
// Adjust full-depth search based on LMR results - if the result
11901190
// was good enough search deeper, if it was bad enough search shallower.
1191-
const bool doDeeperSearch = value > (bestValue + 50 + 2 * newDepth); // (~1 Elo)
1191+
const bool doDeeperSearch = value > (bestValue + 53 + 2 * newDepth); // (~1 Elo)
11921192
const bool doShallowerSearch = value < bestValue + newDepth; // (~2 Elo)
11931193

11941194
newDepth += doDeeperSearch - doShallowerSearch;
@@ -1303,7 +1303,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
13031303
else
13041304
{
13051305
// Reduce other moves if we have found at least one score improvement (~2 Elo)
1306-
if (depth > 2 && depth < 12 && beta < 13828 && value > -11369)
1306+
if (depth > 2 && depth < 12 && beta < 13782 && value > -11541)
13071307
depth -= 2;
13081308

13091309
assert(depth > 0);
@@ -1342,7 +1342,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
13421342
// Bonus for prior countermove that caused the fail low
13431343
else if (!priorCapture && prevSq != SQ_NONE)
13441344
{
1345-
int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 657)
1345+
int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 656)
13461346
+ ((ss - 1)->moveCount > 10);
13471347
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
13481348
stat_bonus(depth) * bonus);
@@ -1475,7 +1475,7 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {
14751475
if (bestValue > alpha)
14761476
alpha = bestValue;
14771477

1478-
futilityBase = ss->staticEval + 200;
1478+
futilityBase = ss->staticEval + 182;
14791479
}
14801480

14811481
const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory,
@@ -1555,7 +1555,7 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {
15551555
continue;
15561556

15571557
// Do not search moves with bad enough SEE values (~5 Elo)
1558-
if (!pos.see_ge(move, Value(-90)))
1558+
if (!pos.see_ge(move, Value(-77)))
15591559
continue;
15601560
}
15611561

@@ -1691,7 +1691,7 @@ void update_all_stats(const Position& pos,
16911691

16921692
if (!pos.capture_stage(bestMove))
16931693
{
1694-
int bestMoveBonus = bestValue > beta + 168 ? quietMoveBonus // larger bonus
1694+
int bestMoveBonus = bestValue > beta + 173 ? quietMoveBonus // larger bonus
16951695
: stat_bonus(depth); // smaller bonus
16961696

16971697
// Increase stats for the best move in case it was a quiet move

0 commit comments

Comments
 (0)