X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=0e9674a05cc6bad59c7f4089edf8ac3f73301dab;hb=02708a4a1153d59c058f8056bc31713322130392;hp=517499b543971798d432ab0856049ce11a8343a2;hpb=e89bc30fdc93f739869d0d4b285a2cfc3e7a74ee;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 517499b5..0e9674a0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -18,6 +18,7 @@ along with this program. If not, see . */ +#include #include #include #include // For std::memset @@ -69,9 +70,9 @@ namespace { // Reductions lookup table, initialized at startup int Reductions[MAX_MOVES]; // [depth or moveNumber] - template Depth reduction(bool i, Depth d, int mn) { + Depth reduction(bool i, Depth d, int mn) { int r = Reductions[d / ONE_PLY] * Reductions[mn] / 1024; - return ((r + 512) / 1024 + (!i && r > 1024) - PvNode) * ONE_PLY; + return ((r + 512) / 1024 + (!i && r > 1024)) * ONE_PLY; } constexpr int futility_move_count(bool improving, int depth) { @@ -148,7 +149,7 @@ namespace { void Search::init() { for (int i = 1; i < MAX_MOVES; ++i) - Reductions[i] = int(1024 * std::log(i) / std::sqrt(1.95)); + Reductions[i] = int(733.3 * std::log(i)); } @@ -240,10 +241,8 @@ void MainThread::search() { // Vote according to score and depth for (Thread* th : Threads) - { - int64_t s = th->rootMoves[0].score - minScore + 1; - votes[th->rootMoves[0].pv[0]] += 200 + s * s * int(th->completedDepth); - } + votes[th->rootMoves[0].pv[0]] += + (th->rootMoves[0].score - minScore + 14) * int(th->completedDepth); // Select best thread auto bestVote = votes[this->rootMoves[0].pv[0]]; @@ -593,7 +592,10 @@ namespace { // starts with statScore = 0. Later grandchildren start with the last calculated // statScore of the previous grandchild. This influences the reduction rules in // LMR which are based on the statScore of parent position. - (ss+2)->statScore = 0; + if (rootNode) + (ss + 4)->statScore = 0; + else + (ss + 2)->statScore = 0; // Step 4. Transposition table lookup. We don't want the score of a partial // search to overwrite a previous full search TT value, so we use a different @@ -606,15 +608,6 @@ namespace { : ttHit ? tte->move() : MOVE_NONE; ttPv = (ttHit && tte->is_pv()) || (PvNode && depth > 4 * ONE_PLY); - // If position has been searched at higher depths and we are shuffling, - // return value_draw. - if ( pos.rule50_count() > 36 - 6 * (pos.count() > 14) - && ss->ply > 36 - 6 * (pos.count() > 14) - && ttHit - && tte->depth() > depth - && pos.count() > 0) - return VALUE_DRAW; - // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ttHit @@ -860,6 +853,7 @@ moves_loop: // When in check, search starts from here value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc moveCountPruning = false; ttCapture = ttMove && pos.capture_or_promotion(ttMove); + int singularExtensionLMRmultiplier = 0; // Step 12. Loop through all pseudo-legal moves until no moves remain // or a beta cutoff occurs. @@ -903,7 +897,7 @@ moves_loop: // When in check, search starts from here && move == ttMove && !rootNode && !excludedMove // Avoid recursive singular search - /* && ttValue != VALUE_NONE Already implicit in the next condition */ + /* && ttValue != VALUE_NONE Already implicit in the next condition */ && abs(ttValue) < VALUE_KNOWN_WIN && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3 * ONE_PLY @@ -916,7 +910,12 @@ moves_loop: // When in check, search starts from here ss->excludedMove = MOVE_NONE; if (value < singularBeta) + { extension = ONE_PLY; + singularExtensionLMRmultiplier++; + if (value < singularBeta - std::min(3 * depth / ONE_PLY, 39)) + singularExtensionLMRmultiplier++; + } // Multi-cut pruning // Our ttMove is assumed to fail high, and now we failed high also on a reduced @@ -939,9 +938,8 @@ moves_loop: // When in check, search starts from here // Shuffle extension else if ( PvNode && pos.rule50_count() > 18 - && ss->ply > 18 && depth < 3 * ONE_PLY - && ss->ply < 3 * thisThread->rootDepth / ONE_PLY) // To avoid infinite loops + && ss->ply < 3 * thisThread->rootDepth / ONE_PLY) // To avoid too deep searches extension = ONE_PLY; // Passed pawn extension @@ -970,7 +968,7 @@ moves_loop: // When in check, search starts from here continue; // Reduced depth of the next LMR search - int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), DEPTH_ZERO); + int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), DEPTH_ZERO); lmrDepth /= ONE_PLY; // Countermoves based pruning (~20 Elo) @@ -1013,18 +1011,22 @@ moves_loop: // When in check, search starts from here // Step 16. Reduced depth search (LMR). If the move fails high it will be // re-searched at full depth. if ( depth >= 3 * ONE_PLY - && moveCount > 1 - && (!captureOrPromotion || moveCountPruning)) + && moveCount > 1 + 3 * rootNode + && ( !captureOrPromotion + || moveCountPruning + || ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha)) { - Depth r = reduction(improving, depth, moveCount); + Depth r = reduction(improving, depth, moveCount); // Decrease reduction if position is or has been on the PV if (ttPv) - r -= ONE_PLY; + r -= 2 * ONE_PLY; // Decrease reduction if opponent's move count is high (~10 Elo) if ((ss-1)->moveCount > 15) r -= ONE_PLY; + // Decrease reduction if move has been singularly extended + r -= singularExtensionLMRmultiplier * ONE_PLY; if (!captureOrPromotion) { @@ -1211,8 +1213,8 @@ moves_loop: // When in check, search starts from here } - // qsearch() is the quiescence search function, which is called by the main - // search function with depth zero, or recursively with depth less than ONE_PLY. + // qsearch() is the quiescence search function, which is called by the main search + // function with zero depth, or recursively with further decreasing depth per call. template Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {