diff --git a/src/evaluate.cpp b/src/evaluate.cpp index dcbfedb499a..ec120a480a3 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -58,14 +58,14 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, const Position& pos, Value nnue = smallNet ? networks.small.evaluate(pos, true, &nnueComplexity, psqtOnly) : networks.big.evaluate(pos, true, &nnueComplexity, false); - const auto adjustEval = [&](int optDiv, int nnueDiv, int pawnCountConstant, int pawnCountMul, - int npmConstant, int evalDiv, int shufflingConstant, - int shufflingDiv) { + const auto adjustEval = [&](int optDiv, int nnueDiv, int npmDiv, int pawnCountConstant, + int pawnCountMul, int npmConstant, int evalDiv, + int shufflingConstant, int shufflingDiv) { // Blend optimism and eval with nnue complexity and material imbalance optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / optDiv; nnue -= nnue * (nnueComplexity * 5 / 3) / nnueDiv; - int npm = pos.non_pawn_material() / 64; + int npm = pos.non_pawn_material() / npmDiv; v = (nnue * (npm + pawnCountConstant + pawnCountMul * pos.count()) + optimism * (npmConstant + npm)) / evalDiv; @@ -76,11 +76,11 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, const Position& pos, }; if (!smallNet) - adjustEval(513, 32395, 919, 11, 145, 1036, 178, 204); + adjustEval(524, 32395, 66, 942, 11, 139, 1058, 178, 204); else if (psqtOnly) - adjustEval(517, 32857, 908, 7, 155, 1019, 224, 238); + adjustEval(517, 32857, 65, 908, 7, 155, 1006, 224, 238); else - adjustEval(499, 32793, 903, 9, 147, 1067, 208, 211); + adjustEval(515, 32793, 63, 944, 9, 140, 1067, 206, 206); // 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); diff --git a/src/movepick.cpp b/src/movepick.cpp index c1119cf11eb..4a93662db43 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -190,8 +190,8 @@ void MovePicker::score() { m.value += bool(pos.check_squares(pt) & to) * 16384; // bonus for escaping from capture - m.value += threatenedPieces & from ? (pt == QUEEN && !(to & threatenedByRook) ? 51000 - : pt == ROOK && !(to & threatenedByMinor) ? 24950 + m.value += threatenedPieces & from ? (pt == QUEEN && !(to & threatenedByRook) ? 51700 + : pt == ROOK && !(to & threatenedByMinor) ? 25600 : !(to & threatenedByPawn) ? 14450 : 0) : 0; @@ -200,7 +200,7 @@ void MovePicker::score() { m.value -= !(threatenedPieces & from) ? (pt == QUEEN ? bool(to & threatenedByRook) * 48150 + bool(to & threatenedByMinor) * 10650 - : pt == ROOK ? bool(to & threatenedByMinor) * 24500 + : pt == ROOK ? bool(to & threatenedByMinor) * 24335 : pt != PAWN ? bool(to & threatenedByPawn) * 14950 : 0) : 0; @@ -241,7 +241,7 @@ Move MovePicker::select(Pred filter) { // moves left, picking the move with the highest score from a list of generated moves. Move MovePicker::next_move(bool skipQuiets) { - auto quiet_threshold = [](Depth d) { return -3550 * d; }; + auto quiet_threshold = [](Depth d) { return -3560 * d; }; top: switch (stage) @@ -310,7 +310,7 @@ Move MovePicker::next_move(bool skipQuiets) { return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2]; })) { - if ((cur - 1)->value > -8000 || (cur - 1)->value <= quiet_threshold(depth)) + if ((cur - 1)->value > -7998 || (cur - 1)->value <= quiet_threshold(depth)) return *(cur - 1); // Remaining quiets are bad diff --git a/src/search.cpp b/src/search.cpp index 6813c1a5f61..183b7bcee5d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -57,9 +57,9 @@ static constexpr double EvalLevel[10] = {1.043, 1.017, 0.952, 1.009, 0.971, // Futility margin Value futility_margin(Depth d, bool noTtCutNode, bool improving, bool oppWorsening) { - Value futilityMult = 118 - 44 * noTtCutNode; + Value futilityMult = 118 - 45 * noTtCutNode; Value improvingDeduction = 52 * improving * futilityMult / 32; - Value worseningDeduction = (310 + 48 * improving) * oppWorsening * futilityMult / 1024; + Value worseningDeduction = (316 + 48 * improving) * oppWorsening * futilityMult / 1024; return futilityMult * d - improvingDeduction - worseningDeduction; } @@ -76,10 +76,10 @@ Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos) { } // History and stats update bonus, based on depth -int stat_bonus(Depth d) { return std::clamp(211 * d - 315, 0, 1291); } +int stat_bonus(Depth d) { return std::clamp(214 * d - 318, 16, 1304); } // History and stats update malus, based on depth -int stat_malus(Depth d) { return (d < 4 ? 572 * d - 285 : 1372); } +int stat_malus(Depth d) { return (d < 4 ? 572 * d - 284 : 1355); } // 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); } @@ -303,12 +303,12 @@ void Search::Worker::iterative_deepening() { // Reset aspiration window starting size Value avg = rootMoves[pvIdx].averageScore; - delta = 11 + avg * avg / 11254; + delta = 10 + avg * avg / 11480; 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] = 125 * avg / (std::abs(avg) + 91); + optimism[us] = 122 * avg / (std::abs(avg) + 92); optimism[~us] = -optimism[us]; // Start with a small aspiration window and, in the case of a fail @@ -752,7 +752,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 - 471 - (276 - 148 * ((ss + 1)->cutoffCnt > 3)) * depth * depth) + if (eval < alpha - 471 - (275 - 148 * ((ss + 1)->cutoffCnt > 3)) * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -763,14 +763,14 @@ Value Search::Worker::search( // The depth condition is important for mate finding. if (!ss->ttPv && depth < 12 && eval - futility_margin(depth, cutNode && !ss->ttHit, improving, opponentWorsening) - - (ss - 1)->statScore / 284 + - (ss - 1)->statScore / 286 >= beta && eval >= beta && eval < VALUE_TB_WIN_IN_MAX_PLY && (!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 < 18001 - && eval >= beta && ss->staticEval >= beta - 21 * depth + 315 && !excludedMove + && eval >= beta && ss->staticEval >= beta - 21 * depth + 312 && !excludedMove && pos.non_pawn_material(us) && ss->ply >= thisThread->nmpMinPly && beta > VALUE_TB_LOSS_IN_MAX_PLY) { @@ -881,7 +881,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 + 436; + 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) @@ -964,7 +964,7 @@ Value Search::Worker::search( { Piece capturedPiece = pos.piece_on(move.to_sq()); Value futilityValue = - ss->staticEval + 288 + 277 * lmrDepth + PieceValue[capturedPiece] + ss->staticEval + 285 + 277 * lmrDepth + PieceValue[capturedPiece] + thisThread->captureHistory[movedPiece][move.to_sq()][type_of(capturedPiece)] / 7; if (futilityValue <= alpha) @@ -972,7 +972,7 @@ Value Search::Worker::search( } // SEE based pruning for captures and checks (~11 Elo) - if (!pos.see_ge(move, -199 * depth)) + if (!pos.see_ge(move, -203 * depth)) continue; } else @@ -992,10 +992,10 @@ Value Search::Worker::search( lmrDepth += history / 5285; Value futilityValue = - ss->staticEval + (bestValue < ss->staticEval - 54 ? 128 : 58) + 131 * lmrDepth; + ss->staticEval + (bestValue < ss->staticEval - 54 ? 128 : 57) + 131 * lmrDepth; // Futility pruning: parent node (~13 Elo) - if (!ss->inCheck && lmrDepth < 15 && futilityValue <= alpha) + if (!ss->inCheck && lmrDepth < 14 && futilityValue <= alpha) { if (bestValue <= futilityValue && std::abs(bestValue) < VALUE_TB_WIN_IN_MAX_PLY && futilityValue < VALUE_TB_WIN_IN_MAX_PLY) @@ -1006,7 +1006,7 @@ Value Search::Worker::search( lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, -26 * lmrDepth * lmrDepth)) + if (!pos.see_ge(move, -27 * lmrDepth * lmrDepth)) continue; } } @@ -1026,11 +1026,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 > 32) + ss->ttPv + && depth >= 4 - (thisThread->completedDepth > 33) + ss->ttPv && std::abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - (64 + 59 * (ss->ttPv && !PvNode)) * depth / 64; + Value singularBeta = ttValue - (65 + 59 * (ss->ttPv && !PvNode)) * depth / 63; Depth singularDepth = newDepth / 2; ss->excludedMove = move; @@ -1134,10 +1134,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()] - 5007; + + (*contHist[3])[movedPiece][move.to_sq()] - 5024; // Decrease/increase reduction for moves with a good/bad history (~8 Elo) - r -= ss->statScore / 12901; + r -= ss->statScore / 13182; // Step 17. Late moves reduction / extension (LMR, ~117 Elo) if (depth >= 2 && moveCount > 1 + rootNode) @@ -1274,7 +1274,7 @@ Value Search::Worker::search( else { // Reduce other moves if we have found at least one score improvement (~2 Elo) - if (depth > 2 && depth < 12 && beta < 13132 && value > -13295) + if (depth > 2 && depth < 12 && beta < 13546 && value > -13478) depth -= 2; assert(depth > 0); @@ -1319,7 +1319,7 @@ Value Search::Worker::search( { int bonus = (depth > 5) + (PvNode || cutNode) + ((ss - 1)->statScore < -14761) + ((ss - 1)->moveCount > 11) - + (!ss->inCheck && bestValue <= ss->staticEval - 144); + + (!ss->inCheck && bestValue <= ss->staticEval - 142); update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus); thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] @@ -1477,7 +1477,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta, if (bestValue > alpha) alpha = bestValue; - futilityBase = ss->staticEval + 246; + futilityBase = ss->staticEval + 250; } const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory, @@ -1625,7 +1625,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 + 1123 - delta * 832 / rootDelta) / 1024 + (!i && reductionScale > 1025); + return (reductionScale + 1150 - delta * 832 / rootDelta) / 1024 + (!i && reductionScale > 1025); } TimePoint Search::Worker::elapsed() const {