diff --git a/src/search.cpp b/src/search.cpp index 11dcdb34..3c638ca0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -277,7 +277,7 @@ void MainThread::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). - if (!Threads.stop && (Limits.ponder || Limits.infinite)) + if (!Threads.stop && (Threads.ponder || Limits.infinite)) { Threads.stopOnPonderhit = true; wait(Threads.stop); @@ -499,7 +499,7 @@ 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 (Limits.ponder) + if (Threads.ponder) Threads.stopOnPonderhit = true; else Threads.stop = true; @@ -1489,7 +1489,7 @@ moves_loop: // When in check search starts from here } // An engine may not stop pondering until told so by the GUI - if (Limits.ponder) + if (Threads.ponder) return; if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10) diff --git a/src/search.h b/src/search.h index 477570e3..bbdbdfd9 100644 --- a/src/search.h +++ b/src/search.h @@ -72,14 +72,13 @@ typedef std::vector RootMoves; /// LimitsType struct stores information sent by GUI about available time to -/// search the current move, maximum depth/time, if we are in analysis mode or -/// if we have to ponder while it's our opponent's turn to move. +/// search the current move, maximum depth/time, or if we are in analysis mode. struct LimitsType { LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = - npmsec = movestogo = depth = movetime = mate = infinite = ponder = 0; + npmsec = movestogo = depth = movetime = mate = infinite = 0; } bool use_time_management() const { @@ -87,7 +86,7 @@ struct LimitsType { } std::vector searchmoves; - int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite, ponder; + int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite; int64_t nodes; TimePoint startTime; }; diff --git a/src/thread.cpp b/src/thread.cpp index 86fce6aa..6d3364d5 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -183,11 +183,12 @@ uint64_t ThreadPool::tb_hits() const { /// and starts a new search, then returns immediately. void ThreadPool::start_thinking(Position& pos, StateListPtr& states, - const Search::LimitsType& limits) { + const Search::LimitsType& limits, bool ponderMode) { main()->wait_for_search_finished(); stopOnPonderhit = stop = false; + ponder = ponderMode; Search::Limits = limits; Search::RootMoves rootMoves; diff --git a/src/thread.h b/src/thread.h index c1b635b7..ee43bfb5 100644 --- a/src/thread.h +++ b/src/thread.h @@ -96,12 +96,12 @@ struct ThreadPool : public std::vector { void exit(); // be initialized and valid during the whole thread lifetime. MainThread* main() { return static_cast(at(0)); } - void start_thinking(Position&, StateListPtr&, const Search::LimitsType&); + void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false); void read_uci_options(); uint64_t nodes_searched() const; uint64_t tb_hits() const; - std::atomic_bool stop, stopOnPonderhit; + std::atomic_bool stop, ponder, stopOnPonderhit; private: StateListPtr setupStates; diff --git a/src/uci.cpp b/src/uci.cpp index 8f6416bd..58b38779 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -115,6 +115,7 @@ namespace { Search::LimitsType limits; string token; + bool ponderMode = false; limits.startTime = now(); // As early as possible! @@ -133,9 +134,9 @@ namespace { else if (token == "movetime") is >> limits.movetime; else if (token == "mate") is >> limits.mate; else if (token == "infinite") limits.infinite = 1; - else if (token == "ponder") limits.ponder = 1; + else if (token == "ponder") ponderMode = true; - Threads.start_thinking(pos, States, limits); + Threads.start_thinking(pos, States, limits, ponderMode); } } // namespace @@ -167,11 +168,11 @@ void UCI::loop(int argc, char* argv[]) { token.clear(); // getline() could return empty or blank line is >> skipws >> token; - // The GUI sends 'ponderhit' to tell us to ponder on the same move the - // opponent has played. In case Threads.stopOnPonderhit is set we are - // waiting for 'ponderhit' to stop the search (for instance because we - // already ran out of time), otherwise we should continue searching but - // switching from pondering to normal search. + // The GUI sends 'ponderhit' to tell us the user has played the expected move. + // So 'ponderhit' will be sent if we were told to ponder on the same move the + // user has played. We should continue searching but switch from pondering to + // normal search. In case Threads.stopOnPonderhit is set we are waiting for + // 'ponderhit' to stop the search, for instance if max search depth is reached. if ( token == "quit" || token == "stop" || (token == "ponderhit" && Threads.stopOnPonderhit)) @@ -180,7 +181,7 @@ void UCI::loop(int argc, char* argv[]) { Threads.main()->start_searching(true); // Could be sleeping } else if (token == "ponderhit") - Search::Limits.ponder = 0; // Switch to normal search + Threads.ponder = false; // Switch to normal search else if (token == "uci") sync_cout << "id name " << engine_info(true)