X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=ba1fef4d07e8081a56c73e354c915f8bf037f894;hp=23402939a67bcea1ed663b821dd9fcecb742ec58;hb=b8efa0daac897e1b8f3efb9ca09ec4151492f1e0;hpb=2bceba7f5162198834ca9f3dca0258e7eac1f797 diff --git a/src/search.cpp b/src/search.cpp index 23402939..ba1fef4d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -71,12 +71,16 @@ namespace { return Value((175 - 50 * improving) * d / ONE_PLY); } - // Futility and reductions lookup tables, initialized at startup - int FutilityMoveCounts[2][16]; // [improving][depth] - int Reductions[2][64][64]; // [improving][depth][moveNumber] + // Reductions lookup table, initialized at startup + int Reductions[64]; // [depth or moveNumber] template Depth reduction(bool i, Depth d, int mn) { - return (Reductions[i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] - PvNode) * ONE_PLY; + int r = Reductions[std::min(d / ONE_PLY, 63)] * Reductions[std::min(mn, 63)] / 1024; + return ((r + 512) / 1024 + (!i && r > 1024) - PvNode) * ONE_PLY; + } + + constexpr int futility_move_count(bool improving, int depth) { + return (5 + depth * depth) * (1 + improving) / 2; } // History and stats update bonus, based on depth @@ -156,24 +160,8 @@ namespace { void Search::init() { - for (int imp = 0; imp <= 1; ++imp) - for (int d = 1; d < 64; ++d) - for (int mc = 1; mc < 64; ++mc) - { - double r = log(d) * log(mc) / 1.95; - - Reductions[imp][d][mc] = std::round(r); - - // Increase reduction for non-PV nodes when eval is not improving - if (!imp && r > 1.0) - Reductions[imp][d][mc]++; - } - - for (int d = 0; d < 16; ++d) - { - FutilityMoveCounts[0][d] = int(2.4 + 0.74 * pow(d, 1.78)); - FutilityMoveCounts[1][d] = int(5.0 + 1.00 * pow(d, 2.00)); - } + for (int i = 1; i < 64; ++i) + Reductions[i] = int(1024 * std::log(i) / std::sqrt(1.95)); } @@ -309,7 +297,6 @@ void Thread::search() { MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr); double timeReduction = 1.0; Color us = rootPos.side_to_move(); - bool failedLow; std::memset(ss-7, 0, 10 * sizeof(Stack)); for (int i = 7; i > 0; i--) @@ -320,7 +307,7 @@ void Thread::search() { beta = VALUE_INFINITE; if (mainThread) - mainThread->bestMoveChanges = 0, failedLow = false; + mainThread->bestMoveChanges = 0; size_t multiPV = Options["MultiPV"]; Skill skill(Options["Skill Level"]); @@ -361,7 +348,7 @@ void Thread::search() { // Age out PV variability metric if (mainThread) - mainThread->bestMoveChanges *= 0.517, failedLow = false; + mainThread->bestMoveChanges *= 0.517; // Save the last iteration's scores before first PV line is searched and // all the move scores except the (new) PV are set to -VALUE_INFINITE. @@ -441,7 +428,6 @@ void Thread::search() { if (mainThread) { failedHighCnt = 0; - failedLow = true; mainThread->stopOnPonderhit = false; } } @@ -493,19 +479,19 @@ void Thread::search() { && !Threads.stop && !mainThread->stopOnPonderhit) { - double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0; + double fallingEval = (306 + 9 * (mainThread->previousScore - bestValue)) / 581.0; fallingEval = std::max(0.5, std::min(1.5, fallingEval)); // If the bestMove is stable over several iterations, reduce time accordingly timeReduction = lastBestMoveDepth + 10 * ONE_PLY < completedDepth ? 1.95 : 1.0; + double reduction = std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction; // Use part of the gained time from a previous stable move for the current move double bestMoveInstability = 1.0 + mainThread->bestMoveChanges; - bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction; // Stop the search if we have only one legal move, or if available time elapsed if ( rootMoves.size() == 1 - || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval) + || Time.elapsed() > Time.optimum() * fallingEval * reduction * bestMoveInstability) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". @@ -926,12 +912,13 @@ moves_loop: // When in check, search starts from here && move == ttMove && !rootNode && !excludedMove // Avoid recursive singular search - && ttValue != VALUE_NONE + /* && ttValue != VALUE_NONE Already implicit in the next condition */ + && abs(ttValue) < VALUE_KNOWN_WIN && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3 * ONE_PLY && pos.legal(move)) { - Value singularBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE); + Value singularBeta = ttValue - 2 * depth / ONE_PLY; ss->excludedMove = move; value = search(pos, ss, singularBeta - 1, singularBeta, depth / 2, cutNode); ss->excludedMove = MOVE_NONE; @@ -966,8 +953,7 @@ moves_loop: // When in check, search starts from here && bestValue > VALUE_MATED_IN_MAX_PLY) { // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold - moveCountPruning = depth < 16 * ONE_PLY - && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY]; + moveCountPruning = moveCount >= futility_move_count(improving,depth / ONE_PLY); if ( !captureOrPromotion && !givesCheck