Skip to content

Commit

Permalink
VVLTC search tune
Browse files Browse the repository at this point in the history
Search parameters were tuned using 16k games at
VVLTC. They were tuned starting with the new
parameters (in search only) of PR #5039.

Passed VVLTC:
https://tests.stockfishchess.org/tests/view/65c8a8fc1d8e83c78bfcd163
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 20826 W: 5355 L: 5100 D: 10371
Ptnml(0-2): 1, 1941, 6275, 2194, 2

Passed 2nd VVLTC:
https://tests.stockfishchess.org/tests/view/65cadc2d1d8e83c78bfcfdaf
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 17710 W: 4611 L: 4352 D: 8747
Ptnml(0-2): 1, 1586, 5422, 1845, 1

STC Elo estimate:
https://tests.stockfishchess.org/tests/view/65cb6aed1d8e83c78bfd0802
Elo: -1.46 ± 1.8 (95%) LOS: 5.5%
Total: 40000 W: 10267 L: 10435 D: 19298
Ptnml(0-2): 200, 4860, 10023, 4742, 175
nElo: -2.77 ± 3.4 (95%) PairsRatio: 0.97

Bench: 1198939
  • Loading branch information
XInTheDark authored and Disservin committed Feb 14, 2024
1 parent 7ccde25 commit 5c03883
Showing 1 changed file with 32 additions and 32 deletions.
64 changes: 32 additions & 32 deletions src/search.cpp
Expand Up @@ -55,7 +55,7 @@ namespace {

// Futility margin
Value futility_margin(Depth d, bool noTtCutNode, bool improving) {
Value futilityMult = 116 - 47 * noTtCutNode;
Value futilityMult = 117 - 44 * noTtCutNode;
return (futilityMult * d - 3 * futilityMult / 2 * improving);
}

Expand All @@ -66,15 +66,15 @@ constexpr int futility_move_count(bool improving, Depth depth) {
// Add correctionHistory value to raw staticEval and guarantee evaluation does not hit the tablebase range
Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos) {
auto cv = w.correctionHistory[pos.side_to_move()][pawn_structure_index<Correction>(pos)];
v += cv * std::abs(cv) / 12890;
v += cv * std::abs(cv) / 12475;
return std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
}

// History and stats update bonus, based on depth
int stat_bonus(Depth d) { return std::min(253 * d - 356, 1117); }
int stat_bonus(Depth d) { return std::min(246 * d - 351, 1136); }

// History and stats update malus, based on depth
int stat_malus(Depth d) { return std::min(517 * d - 308, 1206); }
int stat_malus(Depth d) { return std::min(519 * d - 306, 1258); }

// Add a small random component to draw evaluations to avoid 3-fold blindness
Value value_draw(size_t nodes) { return VALUE_DRAW - 1 + Value(nodes & 0x2); }
Expand Down Expand Up @@ -297,12 +297,12 @@ void Search::Worker::iterative_deepening() {

// Reset aspiration window starting size
Value avg = rootMoves[pvIdx].averageScore;
delta = 9 + avg * avg / 12480;
delta = 9 + avg * avg / 12487;
alpha = std::max(avg - delta, -VALUE_INFINITE);
beta = std::min(avg + delta, VALUE_INFINITE);

// Adjust optimism based on root move's averageScore (~4 Elo)
optimism[us] = 131 * avg / (std::abs(avg) + 95);
optimism[us] = 134 * avg / (std::abs(avg) + 97);
optimism[~us] = -optimism[us];

// Start with a small aspiration window and, in the case of a fail
Expand Down Expand Up @@ -482,7 +482,7 @@ void Search::Worker::clear() {
h->fill(-71);

for (size_t i = 1; i < reductions.size(); ++i)
reductions[i] = int((20.37 + std::log(size_t(options["Threads"])) / 2) * std::log(i));
reductions[i] = int((18.79 + std::log(size_t(options["Threads"])) / 2) * std::log(i));
}


Expand Down Expand Up @@ -723,7 +723,7 @@ Value Search::Worker::search(
// Use static evaluation difference to improve quiet move ordering (~9 Elo)
if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture)
{
int bonus = std::clamp(-14 * int((ss - 1)->staticEval + ss->staticEval), -1661, 1495);
int bonus = std::clamp(-14 * int((ss - 1)->staticEval + ss->staticEval), -1723, 1455);
bonus = bonus > 0 ? 2 * bonus : bonus / 2;
thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus;
if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION)
Expand All @@ -744,7 +744,7 @@ Value Search::Worker::search(
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
// return a fail low.
// Adjust razor margin according to cutoffCnt. (~1 Elo)
if (eval < alpha - 450 - (332 - 160 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
if (eval < alpha - 438 - (332 - 154 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
{
value = qsearch<NonPV>(pos, ss, alpha - 1, alpha);
if (value < alpha)
Expand All @@ -755,22 +755,22 @@ Value Search::Worker::search(
// The depth condition is important for mate finding.
if (!ss->ttPv && depth < 11
&& eval - futility_margin(depth, cutNode && !ss->ttHit, improving)
- (ss - 1)->statScore / 327
- (ss - 1)->statScore / 314
>= beta
&& eval >= beta && eval < 28702 // smaller than TB wins
&& eval >= beta && eval < 30016 // smaller than TB wins
&& (!ttMove || ttCapture))
return beta > VALUE_TB_LOSS_IN_MAX_PLY ? (eval + beta) / 2 : eval;

// Step 9. Null move search with verification search (~35 Elo)
if (!PvNode && (ss - 1)->currentMove != Move::null() && (ss - 1)->statScore < 17379
&& eval >= beta && eval >= ss->staticEval && ss->staticEval >= beta - 21 * depth + 329
if (!PvNode && (ss - 1)->currentMove != Move::null() && (ss - 1)->statScore < 16620
&& eval >= beta && eval >= ss->staticEval && ss->staticEval >= beta - 21 * depth + 330
&& !excludedMove && pos.non_pawn_material(us) && ss->ply >= thisThread->nmpMinPly
&& beta > VALUE_TB_LOSS_IN_MAX_PLY)
{
assert(eval - beta >= 0);

// Null move dynamic reduction based on depth and eval
Depth R = std::min(int(eval - beta) / 148, 6) + depth / 3 + 4;
Depth R = std::min(int(eval - beta) / 154, 6) + depth / 3 + 4;

ss->currentMove = Move::null();
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
Expand Down Expand Up @@ -820,7 +820,7 @@ Value Search::Worker::search(
// Step 11. ProbCut (~10 Elo)
// If we have a good enough capture (or queen promotion) and a reduced search returns a value
// much above beta, we can (almost) safely prune the previous move.
probCutBeta = beta + 182 - 68 * improving;
probCutBeta = beta + 181 - 68 * improving;
if (
!PvNode && depth > 3
&& std::abs(beta) < VALUE_TB_WIN_IN_MAX_PLY
Expand Down Expand Up @@ -876,7 +876,7 @@ Value Search::Worker::search(
moves_loop: // When in check, search starts here

// Step 12. A small Probcut idea, when we are in check (~4 Elo)
probCutBeta = beta + 446;
probCutBeta = beta + 452;
if (ss->inCheck && !PvNode && ttCapture && (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 4 && ttValue >= probCutBeta
&& std::abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && std::abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
Expand Down Expand Up @@ -959,15 +959,15 @@ Value Search::Worker::search(
{
Piece capturedPiece = pos.piece_on(move.to_sq());
int futilityEval =
ss->staticEval + 279 + 295 * lmrDepth + PieceValue[capturedPiece]
ss->staticEval + 277 + 292 * lmrDepth + PieceValue[capturedPiece]
+ thisThread->captureHistory[movedPiece][move.to_sq()][type_of(capturedPiece)]
/ 7;
if (futilityEval < alpha)
continue;
}

// SEE based pruning for captures and checks (~11 Elo)
if (!pos.see_ge(move, -204 * depth))
if (!pos.see_ge(move, -197 * depth))
continue;
}
else
Expand All @@ -979,16 +979,16 @@ Value Search::Worker::search(
+ thisThread->pawnHistory[pawn_structure_index(pos)][movedPiece][move.to_sq()];

// Continuation history based pruning (~2 Elo)
if (lmrDepth < 6 && history < -4215 * depth)
if (lmrDepth < 6 && history < -4211 * depth)
continue;

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

lmrDepth += history / 6658;
lmrDepth += history / 6437;

// Futility pruning: parent node (~13 Elo)
if (!ss->inCheck && lmrDepth < 15
&& ss->staticEval + (bestValue < ss->staticEval - 58 ? 139 : 55)
&& ss->staticEval + (bestValue < ss->staticEval - 57 ? 144 : 57)
+ 121 * lmrDepth
<= alpha)
continue;
Expand Down Expand Up @@ -1016,11 +1016,11 @@ Value Search::Worker::search(
// so changing them requires tests at these types of time controls.
// Recursive singular search is avoided.
if (!rootNode && move == ttMove && !excludedMove
&& depth >= 4 - (thisThread->completedDepth > 29) + ss->ttPv
&& depth >= 4 - (thisThread->completedDepth > 30) + ss->ttPv
&& std::abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3)
{
Value singularBeta = ttValue - (62 + 52 * (ss->ttPv && !PvNode)) * depth / 64;
Value singularBeta = ttValue - (60 + 54 * (ss->ttPv && !PvNode)) * depth / 64;
Depth singularDepth = newDepth / 2;

ss->excludedMove = move;
Expand Down Expand Up @@ -1071,7 +1071,7 @@ Value Search::Worker::search(
else if (PvNode && move == ttMove && move.to_sq() == prevSq
&& thisThread->captureHistory[movedPiece][move.to_sq()]
[type_of(pos.piece_on(move.to_sq()))]
> 4356)
> 4394)
extension = 1;
}

Expand Down Expand Up @@ -1123,10 +1123,10 @@ Value Search::Worker::search(
ss->statScore = 2 * thisThread->mainHistory[us][move.from_to()]
+ (*contHist[0])[movedPiece][move.to_sq()]
+ (*contHist[1])[movedPiece][move.to_sq()]
+ (*contHist[3])[movedPiece][move.to_sq()] - 4409;
+ (*contHist[3])[movedPiece][move.to_sq()] - 4392;

// Decrease/increase reduction for moves with a good/bad history (~8 Elo)
r -= ss->statScore / 14894;
r -= ss->statScore / 14189;

// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
if (depth >= 2 && moveCount > 1 + rootNode)
Expand Down Expand Up @@ -1261,7 +1261,7 @@ Value Search::Worker::search(
else
{
// Reduce other moves if we have found at least one score improvement (~2 Elo)
if (depth > 2 && depth < 13 && beta < 13710 && value > -12589)
if (depth > 2 && depth < 13 && beta < 13652 && value > -12761)
depth -= 2;

assert(depth > 0);
Expand Down Expand Up @@ -1304,7 +1304,7 @@ Value Search::Worker::search(
// Bonus for prior countermove that caused the fail low
else if (!priorCapture && prevSq != SQ_NONE)
{
int bonus = (depth > 5) + (PvNode || cutNode) + ((ss - 1)->statScore < -15401)
int bonus = (depth > 5) + (PvNode || cutNode) + ((ss - 1)->statScore < -15736)
+ ((ss - 1)->moveCount > 11);
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
stat_bonus(depth) * bonus);
Expand Down Expand Up @@ -1462,7 +1462,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
if (bestValue > alpha)
alpha = bestValue;

futilityBase = ss->staticEval + 204;
futilityBase = ss->staticEval + 206;
}

const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory,
Expand Down Expand Up @@ -1542,7 +1542,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,
continue;

// Do not search moves with bad enough SEE values (~5 Elo)
if (!pos.see_ge(move, -75))
if (!pos.see_ge(move, -74))
continue;
}

Expand Down Expand Up @@ -1610,7 +1610,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta,

Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) {
int reductionScale = reductions[d] * reductions[mn];
return (reductionScale + 1177 - delta * 776 / rootDelta) / 1024 + (!i && reductionScale > 842);
return (reductionScale + 1118 - delta * 793 / rootDelta) / 1024 + (!i && reductionScale > 863);
}

namespace {
Expand Down Expand Up @@ -1699,7 +1699,7 @@ void update_all_stats(const Position& pos,

if (!pos.capture_stage(bestMove))
{
int bestMoveBonus = bestValue > beta + 167 ? quietMoveBonus // larger bonus
int bestMoveBonus = bestValue > beta + 166 ? quietMoveBonus // larger bonus
: stat_bonus(depth); // smaller bonus

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

0 comments on commit 5c03883

Please sign in to comment.