X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=dbfb94696ac3d60f92f2a0c22fcc52deb8b4f819;hp=4a1a352349f966ecf5efd224540dc894bd9821ff;hb=22ef36803ed0f1597d8f40731c6e2d3aa01debf2;hpb=59b2486bc3d153b8946661c7a6a501f4410b4e66 diff --git a/src/search.cpp b/src/search.cpp index 4a1a3523..dbfb9469 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -73,10 +73,10 @@ namespace { // Futility and reductions lookup tables, initialized at startup int FutilityMoveCounts[2][16]; // [improving][depth] - int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber] + int Reductions[2][64][64]; // [improving][depth][moveNumber] template Depth reduction(bool i, Depth d, int mn) { - return Reductions[PvNode][i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] * ONE_PLY; + return (Reductions[i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] - PvNode) * ONE_PLY; } // History and stats update bonus, based on depth @@ -162,12 +162,11 @@ void Search::init() { { double r = log(d) * log(mc) / 1.95; - Reductions[NonPV][imp][d][mc] = int(std::round(r)); - Reductions[PV][imp][d][mc] = std::max(Reductions[NonPV][imp][d][mc] - 1, 0); + Reductions[imp][d][mc] = std::round(r); // Increase reduction for non-PV nodes when eval is not improving if (!imp && r > 1.0) - Reductions[NonPV][imp][d][mc]++; + Reductions[imp][d][mc]++; } for (int d = 0; d < 16; ++d) @@ -227,10 +226,9 @@ void MainThread::search() { // Threads.stop. However, if we are pondering or in an infinite search, // the UCI protocol states that we shouldn't print the best move before the // GUI sends a "stop" or "ponderhit" command. We therefore simply wait here - // until the GUI sends one of those commands (which also raises Threads.stop). - Threads.stopOnPonderhit = true; + // until the GUI sends one of those commands. - while (!Threads.stop && (Threads.ponder || Limits.infinite)) + while (!Threads.stop && (ponder || Limits.infinite)) {} // Busy wait for a stop or a ponder reset // Stop the threads if not already stopped (also raise the stop if @@ -259,27 +257,23 @@ void MainThread::search() { // Find out minimum score and reset votes for moves which can be voted for (Thread* th: Threads) - { minScore = std::min(minScore, th->rootMoves[0].score); - votes[th->rootMoves[0].pv[0]] = 0; - } // Vote according to score and depth - auto square = [](int64_t x) { return x * x; }; for (Thread* th : Threads) - votes[th->rootMoves[0].pv[0]] += 200 + (square(th->rootMoves[0].score - minScore + 1) - * int64_t(th->completedDepth)); + { + int64_t s = th->rootMoves[0].score - minScore + 1; + votes[th->rootMoves[0].pv[0]] += 200 + s * s * int(th->completedDepth); + } // Select best thread - int64_t bestVote = votes[this->rootMoves[0].pv[0]]; + auto bestVote = votes[this->rootMoves[0].pv[0]]; for (Thread* th : Threads) - { if (votes[th->rootMoves[0].pv[0]] > bestVote) { bestVote = votes[th->rootMoves[0].pv[0]]; bestThread = th; } - } } previousScore = bestThread->rootMoves[0].score; @@ -448,7 +442,7 @@ void Thread::search() { { failedHighCnt = 0; failedLow = true; - Threads.stopOnPonderhit = false; + mainThread->stopOnPonderhit = false; } } else if (bestValue >= beta) @@ -497,7 +491,7 @@ void Thread::search() { // Do we have time for the next iteration? Can we stop searching now? if ( Limits.use_time_management() && !Threads.stop - && !Threads.stopOnPonderhit) + && !mainThread->stopOnPonderhit) { double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0; fallingEval = std::max(0.5, std::min(1.5, fallingEval)); @@ -515,8 +509,8 @@ void Thread::search() { { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". - if (Threads.ponder) - Threads.stopOnPonderhit = true; + if (mainThread->ponder) + mainThread->stopOnPonderhit = true; else Threads.stop = true; } @@ -574,8 +568,8 @@ namespace { Move ttMove, move, excludedMove, bestMove; Depth extension, newDepth; Value bestValue, value, ttValue, eval, maxValue, pureStaticEval; - bool ttHit, pvHit, inCheck, givesCheck, improving; - bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture; + bool ttHit, ttPv, inCheck, givesCheck, improving; + bool captureOrPromotion, doFullDepthSearch, moveCountPruning, ttCapture; Piece movedPiece; int moveCount, captureCount, quietCount; @@ -640,7 +634,7 @@ namespace { ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE; ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0] : ttHit ? tte->move() : MOVE_NONE; - pvHit = (ttHit && tte->pv_hit()) || (PvNode && depth > 4 * ONE_PLY); + ttPv = (ttHit && tte->is_pv()) || (PvNode && depth > 4 * ONE_PLY); // At non-PV nodes we check for an early TT cutoff if ( !PvNode @@ -707,7 +701,7 @@ namespace { if ( b == BOUND_EXACT || (b == BOUND_LOWER ? value >= beta : value <= alpha)) { - tte->save(posKey, value_to_tt(value, ss->ply), pvHit, b, + tte->save(posKey, value_to_tt(value, ss->ply), ttPv, b, std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY), MOVE_NONE, VALUE_NONE); @@ -748,9 +742,7 @@ namespace { { if ((ss-1)->currentMove != MOVE_NULL) { - int p = (ss-1)->statScore; - int bonus = p > 0 ? (-p - 2500) / 512 : - p < 0 ? (-p + 2500) / 512 : 0; + int bonus = -(ss-1)->statScore / 512; pureStaticEval = evaluate(pos); ss->staticEval = eval = pureStaticEval + bonus; @@ -758,7 +750,7 @@ namespace { else ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::Tempo; - tte->save(posKey, VALUE_NONE, pvHit, BOUND_NONE, DEPTH_NONE, MOVE_NONE, pureStaticEval); + tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, pureStaticEval); } // Step 7. Razoring (~2 Elo) @@ -873,7 +865,6 @@ namespace { tte = TT.probe(posKey, ttHit); ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE; ttMove = ttHit ? tte->move() : MOVE_NONE; - pvHit = ttHit && tte->pv_hit(); } moves_loop: // When in check, search starts from here @@ -888,12 +879,12 @@ moves_loop: // When in check, search starts from here ss->killers); value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc - skipQuiets = false; + moveCountPruning = false; ttCapture = ttMove && pos.capture_or_promotion(ttMove); // Step 12. Loop through all pseudo-legal moves until no moves remain // or a beta cutoff occurs. - while ((move = mp.next_move(skipQuiets)) != MOVE_NONE) + while ((move = mp.next_move(moveCountPruning)) != MOVE_NONE) { assert(is_ok(move)); @@ -922,8 +913,9 @@ moves_loop: // When in check, search starts from here movedPiece = pos.moved_piece(move); givesCheck = gives_check(pos, move); - moveCountPruning = depth < 16 * ONE_PLY - && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY]; + // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold + moveCountPruning = depth < 16 * ONE_PLY + && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY]; // Step 13. Extensions (~70 Elo) @@ -957,11 +949,13 @@ moves_loop: // When in check, search starts from here else if (cutNode && singularBeta > beta) return beta; } - else if ( givesCheck // Check extension (~2 Elo) - && pos.see_ge(move)) + + // Check extension (~2 Elo) + else if ( givesCheck + && (pos.blockers_for_king(~us) & from_sq(move) || pos.see_ge(move))) extension = ONE_PLY; - // Extension if castling + // Castling extension else if (type_of(move) == CASTLING) extension = ONE_PLY; @@ -979,10 +973,7 @@ moves_loop: // When in check, search starts from here { // Move count based pruning (~30 Elo) if (moveCountPruning) - { - skipQuiets = true; continue; - } // Reduced depth of the next LMR search int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY; @@ -1034,7 +1025,7 @@ moves_loop: // When in check, search starts from here Depth r = reduction(improving, depth, moveCount); // Decrease reduction if position is or has been on the PV - if (pvHit) + if (ttPv) r -= ONE_PLY; // Decrease reduction if opponent's move count is high (~10 Elo) @@ -1215,7 +1206,7 @@ moves_loop: // When in check, search starts from here bestValue = std::min(bestValue, maxValue); if (!excludedMove) - tte->save(posKey, value_to_tt(bestValue, ss->ply), pvHit, + tte->save(posKey, value_to_tt(bestValue, ss->ply), ttPv, bestValue >= beta ? BOUND_LOWER : PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER, depth, bestMove, pureStaticEval); @@ -1279,7 +1270,7 @@ moves_loop: // When in check, search starts from here tte = TT.probe(posKey, ttHit); ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE; ttMove = ttHit ? tte->move() : MOVE_NONE; - pvHit = ttHit && tte->pv_hit(); + pvHit = ttHit && tte->is_pv(); if ( !PvNode && ttHit @@ -1595,10 +1586,10 @@ void MainThread::check_time() { } // We should not stop pondering until told so by the GUI - if (Threads.ponder) + if (ponder) return; - if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10) + if ( (Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit)) || (Limits.movetime && elapsed >= Limits.movetime) || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes)) Threads.stop = true;