X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=7873e7dc552d5ec0cadb8db902df5fe186b31eb6;hp=e93c5045578193a5e493e1000e34ae8eb7990518;hb=e385f194e970f0675bd4c3509bca4a6c81b6df5e;hpb=df6cb446eaf21c5d07bbd15496da0471aff6ab3f diff --git a/src/search.cpp b/src/search.cpp index e93c5045..7873e7dc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -75,9 +75,6 @@ namespace { int FutilityMoveCounts[2][16]; // [improving][depth] int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber] - // Threshold used for countermoves based pruning - const int CounterMovePruneThreshold = 0; - 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; } @@ -134,8 +131,8 @@ namespace { } } - int stableCnt; Key expectedPosKey; + int stableCnt; Move pv[3]; }; @@ -154,6 +151,32 @@ namespace { void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus); void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); + // perft() is our utility to verify move generation. All the leaf nodes up + // to the given depth are generated and counted, and the sum is returned. + template + uint64_t perft(Position& pos, Depth depth) { + + StateInfo st; + uint64_t cnt, nodes = 0; + const bool leaf = (depth == 2 * ONE_PLY); + + for (const auto& m : MoveList(pos)) + { + if (Root && depth <= ONE_PLY) + cnt = 1, nodes++; + else + { + pos.do_move(m, st); + cnt = leaf ? MoveList(pos).size() : perft(pos, depth - ONE_PLY); + nodes += cnt; + pos.undo_move(m); + } + if (Root) + sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl; + } + return nodes; + } + } // namespace @@ -193,56 +216,25 @@ void Search::clear() { TT.clear(); for (Thread* th : Threads) - { - th->counterMoves.fill(MOVE_NONE); - th->mainHistory.fill(0); - - for (auto& to : th->contHistory) - for (auto& h : to) - h.fill(0); - - th->contHistory[NO_PIECE][0].fill(CounterMovePruneThreshold - 1); - } + th->clear(); Threads.main()->callsCnt = 0; Threads.main()->previousScore = VALUE_INFINITE; } -/// Search::perft() is our utility to verify move generation. All the leaf nodes -/// up to the given depth are generated and counted, and the sum is returned. -template -uint64_t Search::perft(Position& pos, Depth depth) { - - StateInfo st; - uint64_t cnt, nodes = 0; - const bool leaf = (depth == 2 * ONE_PLY); - - for (const auto& m : MoveList(pos)) - { - if (Root && depth <= ONE_PLY) - cnt = 1, nodes++; - else - { - pos.do_move(m, st); - cnt = leaf ? MoveList(pos).size() : perft(pos, depth - ONE_PLY); - nodes += cnt; - pos.undo_move(m); - } - if (Root) - sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl; - } - return nodes; -} - -template uint64_t Search::perft(Position&, Depth); - - /// MainThread::search() is called by the main thread when the program receives /// the UCI 'go' command. It searches from the root position and outputs the "bestmove". void MainThread::search() { + if (Limits.perft) + { + nodes = perft(rootPos, Limits.perft * ONE_PLY); + sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl; + return; + } + Color us = rootPos.side_to_move(); Time.init(Limits, us, rootPos.game_ply()); TT.new_search(); @@ -253,7 +245,7 @@ void MainThread::search() { if (rootMoves.empty()) { - rootMoves.push_back(RootMove(MOVE_NONE)); + rootMoves.emplace_back(MOVE_NONE); sync_cout << "info depth 0 score " << UCI::value(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW) << sync_endl; @@ -304,7 +296,9 @@ void MainThread::search() { Depth depthDiff = th->completedDepth - bestThread->completedDepth; Value scoreDiff = th->rootMoves[0].score - bestThread->rootMoves[0].score; - if (scoreDiff > 0 && depthDiff >= 0) + // Select the thread with the best score, always if it is a mate + if ( scoreDiff > 0 + && (depthDiff >= 0 || th->rootMoves[0].score >= VALUE_MATE_IN_MAX_PLY)) bestThread = th; } } @@ -451,16 +445,20 @@ void Thread::search() { // Sort the PV lines searched so far and update the GUI std::stable_sort(rootMoves.begin(), rootMoves.begin() + PVIdx + 1); - if (!mainThread) - continue; - - if (Threads.stop || PVIdx + 1 == multiPV || Time.elapsed() > 3000) + if ( mainThread + && (Threads.stop || PVIdx + 1 == multiPV || Time.elapsed() > 3000)) sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; } if (!Threads.stop) completedDepth = rootDepth; + // Have we found a "mate in x"? + if ( Limits.mate + && bestValue >= VALUE_MATE_IN_MAX_PLY + && VALUE_MATE - bestValue <= 2 * Limits.mate) + Threads.stop = true; + if (!mainThread) continue; @@ -468,12 +466,6 @@ void Thread::search() { if (skill.enabled() && skill.time_to_pick(rootDepth)) skill.pick_best(multiPV); - // Have we found a "mate in x"? - if ( Limits.mate - && bestValue >= VALUE_MATE_IN_MAX_PLY - && VALUE_MATE - bestValue <= 2 * Limits.mate) - Threads.stop = true; - // Do we have time for the next iteration? Can we stop searching now? if (Limits.use_time_management()) { @@ -955,7 +947,8 @@ moves_loop: // When in check search starts from here && moveCount > 1 && (!captureOrPromotion || moveCountPruning)) { - Depth r = reduction(improving, depth, moveCount); + int mch = std::max(1, moveCount - (ss-1)->moveCount / 16); + Depth r = reduction(improving, depth, mch); if (captureOrPromotion) r -= r ? ONE_PLY : DEPTH_ZERO; @@ -1242,8 +1235,7 @@ moves_loop: // When in check search starts from here // to search the moves. Because the depth is <= 0 here, only captures, // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will // be generated. - const PieceToHistory* contHist[4] = {}; - MovePicker mp(pos, ttMove, depth, &pos.this_thread()->mainHistory, contHist, to_sq((ss-1)->currentMove)); + MovePicker mp(pos, ttMove, depth, &pos.this_thread()->mainHistory, to_sq((ss-1)->currentMove)); // Loop through the moves until no moves remain or a beta cutoff occurs while ((move = mp.next_move()) != MOVE_NONE) @@ -1491,7 +1483,7 @@ moves_loop: // When in check search starts from here if (Threads.ponder) return; - if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10) + if ( (Limits.use_time_management() && elapsed > Time.maximum()) || (Limits.movetime && elapsed >= Limits.movetime) || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes)) Threads.stop = true;