}
else
{
- for (Thread* th : Threads)
- {
- th->bestMoveChanges = 0;
- if (th != this)
- th->start_searching();
- }
-
- Thread::search(); // Let's start searching!
+ Threads.start_searching(); // start non-main threads
+ Thread::search(); // main thread start searching
}
+ if (rootPos.two_boards() && !Threads.abort && Options["Protocol"] == "xboard")
+ {
+ while (!Threads.stop && (Partner.sitRequested || Partner.weDead) && Time.elapsed() < Limits.time[us] - 1000)
+ {}
+ }
+
// When we reach the maximum depth, we can arrive here without a raise of
// 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
if (Limits.npmsec)
Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
- Thread* bestThread = this;
+ bestThread = this;
- // Check if there are threads with a better score than main thread
- if ( int(Options["MultiPV"]) == 1
- && !Limits.depth
- && !(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"]))
- && rootMoves[0].pv[0] != MOVE_NONE)
- {
- std::map<Move, int64_t> votes;
- Value minScore = this->rootMoves[0].score;
-
- // Find minimum score
- for (Thread* th: Threads)
- minScore = std::min(minScore, th->rootMoves[0].score);
-
- // Vote according to score and depth, and select the best thread
- for (Thread* th : Threads)
- {
- votes[th->rootMoves[0].pv[0]] +=
- (th->rootMoves[0].score - minScore + 14) * int(th->completedDepth);
-
- if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY)
- {
- // Make sure we pick the shortest mate / TB conversion or stave off mate the longest
- if (th->rootMoves[0].score > bestThread->rootMoves[0].score)
- bestThread = th;
- }
- else if ( th->rootMoves[0].score >= VALUE_TB_WIN_IN_MAX_PLY
- || ( th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY
- && votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]]))
- bestThread = th;
- }
- }
+ if (int(Options["MultiPV"]) == 1 &&
+ !Limits.depth &&
+ !(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"])) &&
+ rootMoves[0].pv[0] != MOVE_NONE)
+ bestThread = Threads.get_best_thread();
bestPreviousScore = bestThread->rootMoves[0].score;
for (Thread* th : *this)
{
- th->nodes = th->tbHits = th->nmpMinPly = 0;
+ th->nodes = th->tbHits = th->nmpMinPly = th->bestMoveChanges = 0;
th->rootDepth = th->completedDepth = 0;
th->rootMoves = rootMoves;
- th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
+ th->rootPos.set(pos.variant(), pos.fen(), pos.is_chess960(), &setupStates->back(), th);
}
setupStates->back() = tmp;
MainThread* main() const { return static_cast<MainThread*>(front()); }
uint64_t nodes_searched() const { return accumulate(&Thread::nodes); }
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
+ Thread* get_best_thread() const;
+ void start_searching();
+ void wait_for_search_finished() const;
std::atomic_bool stop, increaseDepth;
+ std::atomic_bool abort, sit;
-private:
StateListPtr setupStates;
+private:
uint64_t accumulate(std::atomic<uint64_t> Thread::* member) const {
uint64_t sum = 0;