bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
- static Book book; // Define static to initialize the PRNG only once
+ static Book book; // Defined static to initialize the PRNG only once
// Initialize global search-related variables
StopOnPonderhit = StopRequest = QuitRequest = AspirationFailLow = false;
Limits = limits;
TimeMgr.init(Limits, pos.startpos_ply_counter());
- // Set output steram in normal or chess960 mode
+ // Set output stream in normal or chess960 mode
cout << set960(pos.is_chess960());
// Look for a book move
}
}
- // Set best timer interval to avoid lagging under time pressure
+ // Set best timer interval to avoid lagging under time pressure. Timer is
+ // used to check for remaining available thinking time.
if (TimeMgr.available_time())
Threads.set_timer(std::min(100, std::max(TimeMgr.available_time() / 8, 20)));
else
Threads[i].maxPly = 0;
}
- // Write to log file and keep it open to be accessed during the search
+ // Start async mode to catch UCI commands sent to us while searching,
+ // like "quit", "stop", etc.
+ Threads.start_listener();
+
+ // Write current search header to log file
if (Options["Use Search Log"].value<bool>())
{
Log log(Options["Search Log Filename"].value<string>());
<< endl;
}
- // Start async mode to catch UCI commands sent to us while searching,
- // like "quit", "stop", etc.
- Threads.start_listener();
-
// We're ready to start thinking. Call the iterative deepening loop function
Move ponderMove = MOVE_NONE;
Move bestMove = id_loop(pos, searchMoves, &ponderMove);
- Threads.set_timer(0);
-
- // Write final search statistics and close log file
+ // Write current search final statistics to log file
if (Options["Use Search Log"].value<bool>())
{
int e = elapsed_search_time();
// From now on any UCI command will be read in-sync with Threads.getline()
Threads.stop_listener();
+ // Stop timer, no need to check for available time any more
+ Threads.set_timer(0);
+
// If we are pondering or in infinite search, we shouldn't print the
// best move before we are told to do so.
- if (!StopRequest && (Limits.ponder || Limits.infinite))
+ if (Limits.ponder || Limits.infinite)
wait_for_stop_or_ponderhit();
// Could be MOVE_NONE when searching on a stalemate position
// while the program is pondering. The point is to work around a wrinkle in
// the UCI protocol: When pondering, the engine is not allowed to give a
// "bestmove" before the GUI sends it a "stop" or "ponderhit" command.
- // We simply wait here until one of these commands is sent, and return,
- // after which the bestmove and pondermove will be printed.
+ // We simply wait here until one of these commands (that raise StopRequest) is
+ // sent, and return, after which the bestmove and pondermove will be printed.
void wait_for_stop_or_ponderhit() {
string cmd;
+ StopOnPonderhit = true;
- // Wait for a command from stdin
- while (cmd != "ponderhit" && cmd != "stop" && cmd != "quit")
+ while (!StopRequest)
+ {
Threads.getline(cmd);
-
- if (cmd == "quit")
- QuitRequest = true;
+ do_uci_async_cmd(cmd);
+ }
}
void do_uci_async_cmd(const std::string& cmd) {
if (cmd == "quit")
- {
- // Quit the program as soon as possible
- Limits.ponder = false;
QuitRequest = StopRequest = true;
- }
+
else if (cmd == "stop")
- {
- // Stop calculating as soon as possible, but still send the "bestmove"
- // and possibly the "ponder" token when finishing the search.
- Limits.ponder = false;
StopRequest = true;
- }
+
else if (cmd == "ponderhit")
{
// The opponent has played the expected move. GUI sends "ponderhit" if