mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Post-NNUEv10 tune
Tune search parameters after the switch to NNUEv10. The change is neutral at STC but increases with the TC. The main changes are more aggressive corrections, futility pruning, and extensions. Failed STC LLR: -2.96 (-2.94,2.94) <0.00,2.00> Total: 108320 W: 27616 L: 27719 D: 52985 Ptnml(0-2): 332, 12833, 27884, 12828, 283 https://tests.stockfishchess.org/tests/view/69212e623b03dd3a060e6114 Passed LTC LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 43272 W: 11117 L: 10788 D: 21367 Ptnml(0-2): 20, 4543, 12180, 4874, 19 https://tests.stockfishchess.org/tests/view/692130813b03dd3a060e6123 Passed VLTC LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 22714 W: 5840 L: 5581 D: 11293 Ptnml(0-2): 2, 2152, 6795, 2401, 7 https://tests.stockfishchess.org/tests/view/6921387b3b03dd3a060e6191 Passed VLTC SMP LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 11868 W: 3142 L: 2896 D: 5830 Ptnml(0-2): 0, 1007, 3676, 1249, 2 https://tests.stockfishchess.org/tests/view/69212e953b03dd3a060e611b closes https://github.com/official-stockfish/Stockfish/pull/6444 bench 2907929
This commit is contained in:
committed by
Joost VandeVondele
parent
035cb146d4
commit
d9fd516547
+6
-6
@@ -65,7 +65,7 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks,
|
||||
Value nnue = (125 * psqt + 131 * positional) / 128;
|
||||
|
||||
// Re-evaluate the position when higher eval accuracy is worth the time spent
|
||||
if (smallNet && (std::abs(nnue) < 236))
|
||||
if (smallNet && (std::abs(nnue) < 277))
|
||||
{
|
||||
std::tie(psqt, positional) = networks.big.evaluate(pos, accumulators, caches.big);
|
||||
nnue = (125 * psqt + 131 * positional) / 128;
|
||||
@@ -74,14 +74,14 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks,
|
||||
|
||||
// Blend optimism and eval with nnue complexity
|
||||
int nnueComplexity = std::abs(psqt - positional);
|
||||
optimism += optimism * nnueComplexity / 468;
|
||||
nnue -= nnue * nnueComplexity / 18000;
|
||||
optimism += optimism * nnueComplexity / 476;
|
||||
nnue -= nnue * nnueComplexity / 18236;
|
||||
|
||||
int material = 535 * pos.count<PAWN>() + pos.non_pawn_material();
|
||||
int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777;
|
||||
int material = 534 * pos.count<PAWN>() + pos.non_pawn_material();
|
||||
int v = (nnue * (77871 + material) + optimism * (7191 + material)) / 77871;
|
||||
|
||||
// Damp down the evaluation linearly when shuffling
|
||||
v -= v * pos.rule50_count() / 212;
|
||||
v -= v * pos.rule50_count() / 199;
|
||||
|
||||
// Guarantee evaluation does not hit the tablebase range
|
||||
v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
|
||||
|
||||
+95
-89
@@ -88,7 +88,7 @@ int correction_value(const Worker& w, const Position& pos, const Stack* const ss
|
||||
+ (*(ss - 4)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()]
|
||||
: 8;
|
||||
|
||||
return 9536 * pcv + 8494 * micv + 10132 * (wnpcv + bnpcv) + 7156 * cntcv;
|
||||
return 10347 * pcv + 8821 * micv + 11168 * (wnpcv + bnpcv) + 7841 * cntcv;
|
||||
}
|
||||
|
||||
// Add correctionHistory value to raw staticEval and guarantee evaluation
|
||||
@@ -104,10 +104,10 @@ void update_correction_history(const Position& pos,
|
||||
const Move m = (ss - 1)->currentMove;
|
||||
const Color us = pos.side_to_move();
|
||||
|
||||
constexpr int nonPawnWeight = 165;
|
||||
constexpr int nonPawnWeight = 178;
|
||||
|
||||
workerThread.pawnCorrectionHistory[pawn_correction_history_index(pos)][us] << bonus;
|
||||
workerThread.minorPieceCorrectionHistory[minor_piece_index(pos)][us] << bonus * 145 / 128;
|
||||
workerThread.minorPieceCorrectionHistory[minor_piece_index(pos)][us] << bonus * 156 / 128;
|
||||
workerThread.nonPawnCorrectionHistory[non_pawn_index<WHITE>(pos)][WHITE][us]
|
||||
<< bonus * nonPawnWeight / 128;
|
||||
workerThread.nonPawnCorrectionHistory[non_pawn_index<BLACK>(pos)][BLACK][us]
|
||||
@@ -117,8 +117,8 @@ void update_correction_history(const Position& pos,
|
||||
{
|
||||
const Square to = m.to_sq();
|
||||
const Piece pc = pos.piece_on(m.to_sq());
|
||||
(*(ss - 2)->continuationCorrectionHistory)[pc][to] << bonus * 137 / 128;
|
||||
(*(ss - 4)->continuationCorrectionHistory)[pc][to] << bonus * 64 / 128;
|
||||
(*(ss - 2)->continuationCorrectionHistory)[pc][to] << bonus * 127 / 128;
|
||||
(*(ss - 4)->continuationCorrectionHistory)[pc][to] << bonus * 59 / 128;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ void Search::Worker::iterative_deepening() {
|
||||
beta = std::min(avg + delta, VALUE_INFINITE);
|
||||
|
||||
// Adjust optimism based on root move's averageScore
|
||||
optimism[us] = 137 * avg / (std::abs(avg) + 91);
|
||||
optimism[us] = 142 * avg / (std::abs(avg) + 91);
|
||||
optimism[~us] = -optimism[us];
|
||||
|
||||
// Start with a small aspiration window and, in the case of a fail
|
||||
@@ -467,20 +467,23 @@ void Search::Worker::iterative_deepening() {
|
||||
uint64_t nodesEffort =
|
||||
rootMoves[0].effort * 100000 / std::max(size_t(1), size_t(nodes));
|
||||
|
||||
double fallingEval =
|
||||
(11.325 + 2.115 * (mainThread->bestPreviousAverageScore - bestValue)
|
||||
+ 0.987 * (mainThread->iterValue[iterIdx] - bestValue))
|
||||
/ 100.0;
|
||||
fallingEval = std::clamp(fallingEval, 0.5688, 1.5698);
|
||||
double fallingEval = (11.85 + 2.24 * (mainThread->bestPreviousAverageScore - bestValue)
|
||||
+ 0.93 * (mainThread->iterValue[iterIdx] - bestValue))
|
||||
/ 100.0;
|
||||
|
||||
fallingEval = std::clamp(fallingEval, 0.57, 1.70);
|
||||
|
||||
// If the bestMove is stable over several iterations, reduce time accordingly
|
||||
double k = 0.5189;
|
||||
double center = lastBestMoveDepth + 11.57;
|
||||
timeReduction = 0.723 + 0.79 / (1.104 + std::exp(-k * (completedDepth - center)));
|
||||
double reduction =
|
||||
(1.455 + mainThread->previousTimeReduction) / (2.2375 * timeReduction);
|
||||
double bestMoveInstability = 1.04 + 1.8956 * totBestMoveChanges / threads.size();
|
||||
double highBestMoveEffort = completedDepth >= 10 && nodesEffort >= 92425 ? 0.666 : 1.0;
|
||||
double k = 0.51;
|
||||
double center = lastBestMoveDepth + 12.15;
|
||||
|
||||
timeReduction = 0.66 + 0.85 / (0.98 + std::exp(-k * (completedDepth - center)));
|
||||
|
||||
double reduction = (1.43 + mainThread->previousTimeReduction) / (2.28 * timeReduction);
|
||||
|
||||
double bestMoveInstability = 1.02 + 2.14 * totBestMoveChanges / threads.size();
|
||||
|
||||
double highBestMoveEffort = completedDepth >= 10 && nodesEffort >= 93337 ? 0.75 : 1.0;
|
||||
|
||||
double totalTime = mainThread->tm.optimum() * fallingEval * reduction
|
||||
* bestMoveInstability * highBestMoveEffort;
|
||||
@@ -502,7 +505,7 @@ void Search::Worker::iterative_deepening() {
|
||||
threads.stop = true;
|
||||
}
|
||||
else
|
||||
threads.increaseDepth = mainThread->ponder || elapsedTime <= totalTime * 0.503;
|
||||
threads.increaseDepth = mainThread->ponder || elapsedTime <= totalTime * 0.50;
|
||||
}
|
||||
|
||||
mainThread->iterValue[iterIdx] = bestValue;
|
||||
@@ -582,7 +585,7 @@ void Search::Worker::clear() {
|
||||
h.fill(-529);
|
||||
|
||||
for (size_t i = 1; i < reductions.size(); ++i)
|
||||
reductions[i] = int(2809 / 128.0 * std::log(i));
|
||||
reductions[i] = int(2747 / 128.0 * std::log(i));
|
||||
|
||||
refreshTable.clear(networks[numaAccessToken]);
|
||||
}
|
||||
@@ -702,11 +705,12 @@ Value Search::Worker::search(
|
||||
// Bonus for a quiet ttMove that fails high
|
||||
if (!ttCapture)
|
||||
update_quiet_histories(pos, ss, *this, ttData.move,
|
||||
std::min(130 * depth - 71, 1043));
|
||||
std::min(132 * depth - 72, 985));
|
||||
|
||||
|
||||
// Extra penalty for early quiet moves of the previous ply
|
||||
if (prevSq != SQ_NONE && (ss - 1)->moveCount < 4 && !priorCapture)
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -2142);
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -2060);
|
||||
}
|
||||
|
||||
// Partial workaround for the graph history interaction problem
|
||||
@@ -825,11 +829,11 @@ Value Search::Worker::search(
|
||||
// Use static evaluation difference to improve quiet move ordering
|
||||
if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture)
|
||||
{
|
||||
int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -200, 156) + 58;
|
||||
int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -209, 167) + 59;
|
||||
mainHistory[~us][((ss - 1)->currentMove).raw()] << evalDiff * 9;
|
||||
if (!ttHit && type_of(pos.piece_on(prevSq)) != PAWN
|
||||
&& ((ss - 1)->currentMove).type_of() != PROMOTION)
|
||||
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 14;
|
||||
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 13;
|
||||
}
|
||||
|
||||
// Set up the improving flag, which is true if current static evaluation is
|
||||
@@ -844,25 +848,25 @@ Value Search::Worker::search(
|
||||
// Hindsight adjustment of reductions based on static evaluation difference.
|
||||
if (priorReduction >= 3 && !opponentWorsening)
|
||||
depth++;
|
||||
if (priorReduction >= 2 && depth >= 2 && ss->staticEval + (ss - 1)->staticEval > 173)
|
||||
if (priorReduction >= 2 && depth >= 2 && ss->staticEval + (ss - 1)->staticEval > 169)
|
||||
depth--;
|
||||
|
||||
// Step 7. Razoring
|
||||
// If eval is really low, skip search entirely and return the qsearch value.
|
||||
// For PvNodes, we must have a guard against mates being returned.
|
||||
if (!PvNode && eval < alpha - 514 - 294 * depth * depth)
|
||||
if (!PvNode && eval < alpha - 485 - 281 * depth * depth)
|
||||
return qsearch<NonPV>(pos, ss, alpha, beta);
|
||||
|
||||
// Step 8. Futility pruning: child node
|
||||
// The depth condition is important for mate finding.
|
||||
{
|
||||
auto futility_margin = [&](Depth d) {
|
||||
Value futilityMult = 81 - 21 * !ss->ttHit;
|
||||
Value futilityMult = 76 - 23 * !ss->ttHit;
|
||||
|
||||
return futilityMult * d //
|
||||
- 2094 * improving * futilityMult / 1024 //
|
||||
- 2474 * improving * futilityMult / 1024 //
|
||||
- 331 * opponentWorsening * futilityMult / 1024 //
|
||||
+ std::abs(correctionValue) / 158105;
|
||||
+ std::abs(correctionValue) / 174665;
|
||||
};
|
||||
|
||||
if (!ss->ttPv && depth < 14 && eval - futility_margin(depth) >= beta && eval >= beta
|
||||
@@ -871,7 +875,7 @@ Value Search::Worker::search(
|
||||
}
|
||||
|
||||
// Step 9. Null move search with verification search
|
||||
if (cutNode && ss->staticEval >= beta - 18 * depth + 390 && !excludedMove
|
||||
if (cutNode && ss->staticEval >= beta - 18 * depth + 350 && !excludedMove
|
||||
&& pos.non_pawn_material(us) && ss->ply >= nmpMinPly && !is_loss(beta))
|
||||
{
|
||||
assert((ss - 1)->currentMove != Move::null());
|
||||
@@ -905,6 +909,7 @@ Value Search::Worker::search(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
improving |= ss->staticEval >= beta;
|
||||
|
||||
// Step 10. Internal iterative reductions
|
||||
@@ -916,7 +921,7 @@ Value Search::Worker::search(
|
||||
// Step 11. ProbCut
|
||||
// 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 + 224 - 64 * improving;
|
||||
probCutBeta = beta + 235 - 63 * improving;
|
||||
if (depth >= 3
|
||||
&& !is_decisive(beta)
|
||||
// If value from transposition table is lower than probCutBeta, don't attempt
|
||||
@@ -926,7 +931,7 @@ Value Search::Worker::search(
|
||||
assert(probCutBeta < VALUE_INFINITE && probCutBeta > beta);
|
||||
|
||||
MovePicker mp(pos, ttData.move, probCutBeta - ss->staticEval, &captureHistory);
|
||||
Depth probCutDepth = std::clamp(depth - 5 - (ss->staticEval - beta) / 306, 0, depth);
|
||||
Depth probCutDepth = std::clamp(depth - 5 - (ss->staticEval - beta) / 315, 0, depth);
|
||||
|
||||
while ((move = mp.next_move()) != Move::none())
|
||||
{
|
||||
@@ -1046,8 +1051,8 @@ moves_loop: // When in check, search starts here
|
||||
// Futility pruning for captures
|
||||
if (!givesCheck && lmrDepth < 7)
|
||||
{
|
||||
Value futilityValue = ss->staticEval + 231 + 211 * lmrDepth
|
||||
+ PieceValue[capturedPiece] + 130 * captHist / 1024;
|
||||
Value futilityValue = ss->staticEval + 232 + 217 * lmrDepth
|
||||
+ PieceValue[capturedPiece] + 131 * captHist / 1024;
|
||||
|
||||
if (futilityValue <= alpha)
|
||||
continue;
|
||||
@@ -1055,7 +1060,7 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
// SEE based pruning for captures and checks
|
||||
// Avoid pruning sacrifices of our last piece for stalemate
|
||||
int margin = std::max(157 * depth + captHist / 29, 0);
|
||||
int margin = std::max(166 * depth + captHist / 29, 0);
|
||||
if ((alpha >= VALUE_DRAW || pos.non_pawn_material(us) != PieceValue[movedPiece])
|
||||
&& !pos.see_ge(move, -margin))
|
||||
continue;
|
||||
@@ -1067,21 +1072,21 @@ moves_loop: // When in check, search starts here
|
||||
+ pawnHistory[pawn_history_index(pos)][movedPiece][move.to_sq()];
|
||||
|
||||
// Continuation history based pruning
|
||||
if (history < -4312 * depth)
|
||||
if (history < -4083 * depth)
|
||||
continue;
|
||||
|
||||
history += 76 * mainHistory[us][move.raw()] / 32;
|
||||
history += 69 * mainHistory[us][move.raw()] / 32;
|
||||
|
||||
// (*Scaler): Generally, lower divisors scales well
|
||||
lmrDepth += history / 3220;
|
||||
lmrDepth += history / 3208;
|
||||
|
||||
Value futilityValue = ss->staticEval + 47 + 171 * !bestMove + 134 * lmrDepth
|
||||
+ 90 * (ss->staticEval > alpha);
|
||||
Value futilityValue = ss->staticEval + 42 + 161 * !bestMove + 127 * lmrDepth
|
||||
+ 85 * (ss->staticEval > alpha);
|
||||
|
||||
// Futility pruning: parent node
|
||||
// (*Scaler): Generally, more frequent futility pruning
|
||||
// scales well
|
||||
if (!ss->inCheck && lmrDepth < 11 && futilityValue <= alpha)
|
||||
if (!ss->inCheck && lmrDepth < 13 && futilityValue <= alpha)
|
||||
{
|
||||
if (bestValue <= futilityValue && !is_decisive(bestValue)
|
||||
&& !is_win(futilityValue))
|
||||
@@ -1092,7 +1097,7 @@ moves_loop: // When in check, search starts here
|
||||
lmrDepth = std::max(lmrDepth, 0);
|
||||
|
||||
// Prune moves with negative SEE
|
||||
if (!pos.see_ge(move, -27 * lmrDepth * lmrDepth))
|
||||
if (!pos.see_ge(move, -25 * lmrDepth * lmrDepth))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1107,12 +1112,11 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
// (*Scaler) Generally, higher singularBeta (i.e closer to ttValue)
|
||||
// and lower extension margins scale well.
|
||||
|
||||
if (!rootNode && move == ttData.move && !excludedMove && depth >= 6 + ss->ttPv
|
||||
&& is_valid(ttData.value) && !is_decisive(ttData.value) && (ttData.bound & BOUND_LOWER)
|
||||
&& ttData.depth >= depth - 3)
|
||||
{
|
||||
Value singularBeta = ttData.value - (56 + 81 * (ss->ttPv && !PvNode)) * depth / 60;
|
||||
Value singularBeta = ttData.value - (53 + 75 * (ss->ttPv && !PvNode)) * depth / 60;
|
||||
Depth singularDepth = newDepth / 2;
|
||||
|
||||
ss->excludedMove = move;
|
||||
@@ -1121,11 +1125,11 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
if (value < singularBeta)
|
||||
{
|
||||
int corrValAdj = std::abs(correctionValue) / 229958;
|
||||
int doubleMargin = -4 + 198 * PvNode - 212 * !ttCapture - corrValAdj
|
||||
- 921 * ttMoveHistory / 127649 - (ss->ply > rootDepth) * 45;
|
||||
int tripleMargin = 76 + 308 * PvNode - 250 * !ttCapture + 92 * ss->ttPv - corrValAdj
|
||||
- (ss->ply * 2 > rootDepth * 3) * 52;
|
||||
int corrValAdj = std::abs(correctionValue) / 230673;
|
||||
int doubleMargin = -4 + 199 * PvNode - 201 * !ttCapture - corrValAdj
|
||||
- 897 * ttMoveHistory / 127649 - (ss->ply > rootDepth) * 42;
|
||||
int tripleMargin = 73 + 302 * PvNode - 248 * !ttCapture + 90 * ss->ttPv - corrValAdj
|
||||
- (ss->ply * 2 > rootDepth * 3) * 50;
|
||||
|
||||
extension =
|
||||
1 + (value < singularBeta - doubleMargin) + (value < singularBeta - tripleMargin);
|
||||
@@ -1171,33 +1175,32 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
// Decrease reduction for PvNodes (*Scaler)
|
||||
if (ss->ttPv)
|
||||
r -= 2618 + PvNode * 991 + (ttData.value > alpha) * 903
|
||||
+ (ttData.depth >= depth) * (978 + cutNode * 1051);
|
||||
|
||||
r -= 2719 + PvNode * 983 + (ttData.value > alpha) * 922
|
||||
+ (ttData.depth >= depth) * (934 + cutNode * 1011);
|
||||
// These reduction adjustments have no proven non-linear scaling
|
||||
|
||||
r += 843; // Base reduction offset to compensate for other tweaks
|
||||
r -= moveCount * 66;
|
||||
r -= std::abs(correctionValue) / 30450;
|
||||
r += 714; // Base reduction offset to compensate for other tweaks
|
||||
r -= moveCount * 73;
|
||||
r -= std::abs(correctionValue) / 30370;
|
||||
|
||||
// Increase reduction for cut nodes
|
||||
if (cutNode)
|
||||
r += 3094 + 1056 * !ttData.move;
|
||||
r += 3372 + 997 * !ttData.move;
|
||||
|
||||
// Increase reduction if ttMove is a capture
|
||||
if (ttCapture)
|
||||
r += 1415;
|
||||
r += 1119;
|
||||
|
||||
// Increase reduction if next ply has a lot of fail high
|
||||
if ((ss + 1)->cutoffCnt > 2)
|
||||
r += 1051 + allNode * 814;
|
||||
r += 991 + allNode * 923;
|
||||
|
||||
// For first picked move (ttMove) reduce reduction
|
||||
if (move == ttData.move)
|
||||
r -= 2018;
|
||||
r -= 2151;
|
||||
|
||||
if (capture)
|
||||
ss->statScore = 803 * int(PieceValue[pos.captured_piece()]) / 128
|
||||
ss->statScore = 868 * int(PieceValue[pos.captured_piece()]) / 128
|
||||
+ captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())];
|
||||
else
|
||||
ss->statScore = 2 * mainHistory[us][move.raw()]
|
||||
@@ -1205,7 +1208,8 @@ moves_loop: // When in check, search starts here
|
||||
+ (*contHist[1])[movedPiece][move.to_sq()];
|
||||
|
||||
// Decrease/increase reduction for moves with a good/bad history
|
||||
r -= ss->statScore * 794 / 8192;
|
||||
r -= ss->statScore * 850 / 8192;
|
||||
|
||||
|
||||
// Step 17. Late moves reduction / extension (LMR)
|
||||
if (depth >= 2 && moveCount > 1)
|
||||
@@ -1245,13 +1249,12 @@ moves_loop: // When in check, search starts here
|
||||
{
|
||||
// Increase reduction if ttMove is not present
|
||||
if (!ttData.move)
|
||||
r += 1118;
|
||||
r += 1140;
|
||||
|
||||
// Note that if expected reduction is high, we reduce search depth here
|
||||
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha,
|
||||
newDepth - (r > 3212) - (r > 4784 && newDepth > 2), !cutNode);
|
||||
newDepth - (r > 3957) - (r > 5654 && newDepth > 2), !cutNode);
|
||||
}
|
||||
|
||||
// For PV nodes only, do a full PV search on the first move or after a fail high,
|
||||
// otherwise let the parent node fail low with value <= alpha and try another move.
|
||||
if (PvNode && (moveCount == 1 || value > alpha))
|
||||
@@ -1403,25 +1406,25 @@ moves_loop: // When in check, search starts here
|
||||
// Bonus for prior quiet countermove that caused the fail low
|
||||
else if (!priorCapture && prevSq != SQ_NONE)
|
||||
{
|
||||
int bonusScale = -228;
|
||||
bonusScale -= (ss - 1)->statScore / 104;
|
||||
bonusScale += std::min(63 * depth, 508);
|
||||
int bonusScale = -215;
|
||||
bonusScale -= (ss - 1)->statScore / 100;
|
||||
bonusScale += std::min(56 * depth, 489);
|
||||
bonusScale += 184 * ((ss - 1)->moveCount > 8);
|
||||
bonusScale += 143 * (!ss->inCheck && bestValue <= ss->staticEval - 92);
|
||||
bonusScale += 149 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 70);
|
||||
bonusScale += 147 * (!ss->inCheck && bestValue <= ss->staticEval - 107);
|
||||
bonusScale += 156 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 65);
|
||||
|
||||
bonusScale = std::max(bonusScale, 0);
|
||||
|
||||
const int scaledBonus = std::min(144 * depth - 92, 1365) * bonusScale;
|
||||
const int scaledBonus = std::min(141 * depth - 87, 1351) * bonusScale;
|
||||
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
|
||||
scaledBonus * 400 / 32768);
|
||||
scaledBonus * 406 / 32768);
|
||||
|
||||
mainHistory[~us][((ss - 1)->currentMove).raw()] << scaledBonus * 220 / 32768;
|
||||
mainHistory[~us][((ss - 1)->currentMove).raw()] << scaledBonus * 243 / 32768;
|
||||
|
||||
if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION)
|
||||
pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq]
|
||||
<< scaledBonus * 1164 / 32768;
|
||||
<< scaledBonus * 1160 / 32768;
|
||||
}
|
||||
|
||||
// Bonus for prior capture countermove that caused the fail low
|
||||
@@ -1429,9 +1432,10 @@ moves_loop: // When in check, search starts here
|
||||
{
|
||||
Piece capturedPiece = pos.captured_piece();
|
||||
assert(capturedPiece != NO_PIECE);
|
||||
captureHistory[pos.piece_on(prevSq)][prevSq][type_of(capturedPiece)] << 964;
|
||||
captureHistory[pos.piece_on(prevSq)][prevSq][type_of(capturedPiece)] << 1012;
|
||||
}
|
||||
|
||||
|
||||
if (PvNode)
|
||||
bestValue = std::min(bestValue, maxValue);
|
||||
|
||||
@@ -1579,9 +1583,10 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
|
||||
if (bestValue > alpha)
|
||||
alpha = bestValue;
|
||||
|
||||
futilityBase = ss->staticEval + 352;
|
||||
futilityBase = ss->staticEval + 351;
|
||||
}
|
||||
|
||||
|
||||
const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory};
|
||||
|
||||
Square prevSq = ((ss - 1)->currentMove).is_ok() ? ((ss - 1)->currentMove).to_sq() : SQ_NONE;
|
||||
@@ -1640,7 +1645,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
|
||||
continue;
|
||||
|
||||
// Do not search moves with bad enough SEE values
|
||||
if (!pos.see_ge(move, -78))
|
||||
if (!pos.see_ge(move, -80))
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1713,9 +1718,10 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
|
||||
|
||||
Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) const {
|
||||
int reductionScale = reductions[d] * reductions[mn];
|
||||
return reductionScale - delta * 757 / rootDelta + !i * reductionScale * 218 / 512 + 1200;
|
||||
return reductionScale - delta * 608 / rootDelta + !i * reductionScale * 238 / 512 + 1182;
|
||||
}
|
||||
|
||||
|
||||
// elapsed() returns the time elapsed since the search started. If the
|
||||
// 'nodestime' option is enabled, it will return the count of nodes searched
|
||||
// instead. This function is called to check whether the search should be
|
||||
@@ -1809,35 +1815,35 @@ void update_all_stats(const Position& pos,
|
||||
Piece movedPiece = pos.moved_piece(bestMove);
|
||||
PieceType capturedPiece;
|
||||
|
||||
int bonus = std::min(121 * depth - 77, 1633) + 375 * (bestMove == ttMove);
|
||||
int malus = std::min(825 * depth - 196, 2159) - 16 * moveCount;
|
||||
int bonus = std::min(116 * depth - 81, 1515) + 347 * (bestMove == ttMove);
|
||||
int malus = std::min(848 * depth - 207, 2446) - 17 * moveCount;
|
||||
|
||||
if (!pos.capture_stage(bestMove))
|
||||
{
|
||||
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 881 / 1024);
|
||||
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 910 / 1024);
|
||||
|
||||
// Decrease stats for all non-best quiet moves
|
||||
for (Move move : quietsSearched)
|
||||
update_quiet_histories(pos, ss, workerThread, move, -malus * 1083 / 1024);
|
||||
update_quiet_histories(pos, ss, workerThread, move, -malus * 1085 / 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increase stats for the best move in case it was a capture move
|
||||
capturedPiece = type_of(pos.piece_on(bestMove.to_sq()));
|
||||
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus * 1482 / 1024;
|
||||
captureHistory[movedPiece][bestMove.to_sq()][capturedPiece] << bonus * 1395 / 1024;
|
||||
}
|
||||
|
||||
// Extra penalty for a quiet early move that was not a TT move in
|
||||
// previous ply when it gets refuted.
|
||||
if (prevSq != SQ_NONE && ((ss - 1)->moveCount == 1 + (ss - 1)->ttHit) && !pos.captured_piece())
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 614 / 1024);
|
||||
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 602 / 1024);
|
||||
|
||||
// Decrease stats for all non-best capture moves
|
||||
for (Move move : capturesSearched)
|
||||
{
|
||||
movedPiece = pos.moved_piece(move);
|
||||
capturedPiece = type_of(pos.piece_on(move.to_sq()));
|
||||
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1397 / 1024;
|
||||
captureHistory[movedPiece][move.to_sq()][capturedPiece] << -malus * 1448 / 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1845,8 +1851,8 @@ void update_all_stats(const Position& pos,
|
||||
// Updates histories of the move pairs formed by moves
|
||||
// at ply -1, -2, -3, -4, and -6 with current move.
|
||||
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) {
|
||||
static constexpr std::array<ConthistBonus, 6> conthist_bonuses = {
|
||||
{{1, 1157}, {2, 648}, {3, 288}, {4, 576}, {5, 140}, {6, 441}}};
|
||||
static std::array<ConthistBonus, 6> conthist_bonuses = {
|
||||
{{1, 1133}, {2, 683}, {3, 312}, {4, 582}, {5, 149}, {6, 474}}};
|
||||
|
||||
for (const auto [i, weight] : conthist_bonuses)
|
||||
{
|
||||
@@ -1867,13 +1873,13 @@ void update_quiet_histories(
|
||||
workerThread.mainHistory[us][move.raw()] << bonus; // Untuned to prevent duplicate effort
|
||||
|
||||
if (ss->ply < LOW_PLY_HISTORY_SIZE)
|
||||
workerThread.lowPlyHistory[ss->ply][move.raw()] << bonus * 761 / 1024;
|
||||
workerThread.lowPlyHistory[ss->ply][move.raw()] << bonus * 805 / 1024;
|
||||
|
||||
update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 955 / 1024);
|
||||
update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 896 / 1024);
|
||||
|
||||
int pIndex = pawn_history_index(pos);
|
||||
workerThread.pawnHistory[pIndex][pos.moved_piece(move)][move.to_sq()]
|
||||
<< bonus * (bonus > 0 ? 850 : 550) / 1024;
|
||||
<< bonus * (bonus > 0 ? 905 : 505) / 1024;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user