]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Retire now unused input_available()
[stockfish] / src / search.cpp
index 30e0502086fddb09cd0b9d41222855f478c4e178..320f480c2df854ac575ab4f4776f120d5c933a84 100644 (file)
@@ -24,6 +24,7 @@
 #include <iostream>
 #include <sstream>
 #include <vector>
+#include <algorithm>
 
 #include "book.h"
 #include "evaluate.h"
@@ -128,7 +129,7 @@ namespace {
 
   inline Value futility_margin(Depth d, int mn) {
 
-    return d < 7 * ONE_PLY ? FutilityMargins[Max(d, 1)][Min(mn, 63)]
+    return d < 7 * ONE_PLY ? FutilityMargins[std::max(int(d), 1)][std::min(mn, 63)]
                            : 2 * VALUE_INFINITE;
   }
 
@@ -144,7 +145,7 @@ namespace {
 
   template <bool PvNode> inline Depth reduction(Depth d, int mn) {
 
-    return (Depth) Reductions[PvNode][Min(d / ONE_PLY, 63)][Min(mn, 63)];
+    return (Depth) Reductions[PvNode][std::min(int(d) / ONE_PLY, 63)][std::min(mn, 63)];
   }
 
   // Easy move margin. An easy move candidate must be at least this much
@@ -290,7 +291,7 @@ namespace {
         *dangerous = true;
     }
 
-    return Min(result, ONE_PLY);
+    return std::min(result, ONE_PLY);
   }
 
 } // namespace
@@ -372,7 +373,7 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
 
   // Set best NodesBetweenPolls interval to avoid lagging under time pressure
   if (Limits.maxNodes)
-      NodesBetweenPolls = Min(Limits.maxNodes, 30000);
+      NodesBetweenPolls = std::min(Limits.maxNodes, 30000);
   else if (Limits.time && Limits.time < 1000)
       NodesBetweenPolls = 1000;
   else if (Limits.time && Limits.time < 5000)
@@ -416,7 +417,7 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
   // Do we have to play with skill handicap? In this case enable MultiPV that
   // we will use behind the scenes to retrieve a set of possible moves.
   SkillLevelEnabled = (SkillLevel < 20);
-  MultiPV = (SkillLevelEnabled ? Max(UCIMultiPV, 4) : UCIMultiPV);
+  MultiPV = (SkillLevelEnabled ? std::max(UCIMultiPV, 4) : UCIMultiPV);
 
   // Wake up needed threads and reset maxPly counter
   for (int i = 0; i < Threads.size(); i++)
@@ -438,6 +439,10 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
           << 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);
@@ -461,6 +466,9 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
   // This makes all the threads to go to sleep
   Threads.set_size(1);
 
+  // From now on any UCI command will be read in-sync with Threads.getline()
+  Threads.stop_listener();
+
   // 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))
@@ -526,7 +534,7 @@ namespace {
         Rml.bestMoveChanges = 0;
 
         // MultiPV loop. We perform a full root search for each PV line
-        for (MultiPVIdx = 0; MultiPVIdx < Min(MultiPV, (int)Rml.size()); MultiPVIdx++)
+        for (MultiPVIdx = 0; MultiPVIdx < std::min(MultiPV, (int)Rml.size()); MultiPVIdx++)
         {
             // Calculate dynamic aspiration window based on previous iterations
             if (depth >= 5 && abs(Rml[MultiPVIdx].prevScore) < VALUE_KNOWN_WIN)
@@ -534,11 +542,11 @@ namespace {
                 int prevDelta1 = bestValues[depth - 1] - bestValues[depth - 2];
                 int prevDelta2 = bestValues[depth - 2] - bestValues[depth - 3];
 
-                aspirationDelta = Min(Max(abs(prevDelta1) + abs(prevDelta2) / 2, 16), 24);
+                aspirationDelta = std::min(std::max(abs(prevDelta1) + abs(prevDelta2) / 2, 16), 24);
                 aspirationDelta = (aspirationDelta + 7) / 8 * 8; // Round to match grainSize
 
-                alpha = Max(Rml[MultiPVIdx].prevScore - aspirationDelta, -VALUE_INFINITE);
-                beta  = Min(Rml[MultiPVIdx].prevScore + aspirationDelta,  VALUE_INFINITE);
+                alpha = std::max(Rml[MultiPVIdx].prevScore - aspirationDelta, -VALUE_INFINITE);
+                beta  = std::min(Rml[MultiPVIdx].prevScore + aspirationDelta,  VALUE_INFINITE);
             }
             else
             {
@@ -584,7 +592,7 @@ namespace {
                 // protocol requires to send all the PV lines also if are still
                 // to be searched and so refer to the previous search's score.
                 if ((value > alpha && value < beta) || current_search_time() > 2000)
-                    for (int i = 0; i < Min(UCIMultiPV, (int)Rml.size()); i++)
+                    for (int i = 0; i < std::min(UCIMultiPV, (int)Rml.size()); i++)
                     {
                         bool updated = (i <= MultiPVIdx);
 
@@ -606,7 +614,7 @@ namespace {
                 // research, otherwise exit the fail high/low loop.
                 if (value >= beta)
                 {
-                    beta = Min(beta + aspirationDelta, VALUE_INFINITE);
+                    beta = std::min(beta + aspirationDelta, VALUE_INFINITE);
                     aspirationDelta += aspirationDelta / 2;
                 }
                 else if (value <= alpha)
@@ -614,7 +622,7 @@ namespace {
                     AspirationFailLow = true;
                     StopOnPonderhit = false;
 
-                    alpha = Max(alpha - aspirationDelta, -VALUE_INFINITE);
+                    alpha = std::max(alpha - aspirationDelta, -VALUE_INFINITE);
                     aspirationDelta += aspirationDelta / 2;
                 }
                 else
@@ -766,8 +774,8 @@ namespace {
     // Step 3. Mate distance pruning
     if (!RootNode)
     {
-        alpha = Max(value_mated_in(ss->ply), alpha);
-        beta = Min(value_mate_in(ss->ply+1), beta);
+        alpha = std::max(value_mated_in(ss->ply), alpha);
+        beta = std::min(value_mate_in(ss->ply+1), beta);
         if (alpha >= beta)
             return alpha;
     }
@@ -1688,8 +1696,8 @@ split_point_start: // At split points actual search starts from here
     Value v = value_from_tt(tte->value(), ply);
 
     return   (   tte->depth() >= depth
-              || v >= Max(VALUE_MATE_IN_PLY_MAX, beta)
-              || v < Min(VALUE_MATED_IN_PLY_MAX, beta))
+              || v >= std::max(VALUE_MATE_IN_PLY_MAX, beta)
+              || v < std::min(VALUE_MATED_IN_PLY_MAX, beta))
 
           && (   ((tte->type() & VALUE_TYPE_LOWER) && v >= beta)
               || ((tte->type() & VALUE_TYPE_UPPER) && v < beta));
@@ -1911,38 +1919,6 @@ split_point_start: // At split points actual search starts from here
     static int lastInfoTime;
     int t = current_search_time();
 
-    //  Poll for input
-    if (input_available())
-    {
-        // We are line oriented, don't read single chars
-        string command;
-
-        if (!std::getline(std::cin, command) || command == "quit")
-        {
-            // Quit the program as soon as possible
-            Limits.ponder = false;
-            QuitRequest = StopRequest = true;
-            return;
-        }
-        else if (command == "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 (command == "ponderhit")
-        {
-            // The opponent has played the expected move. GUI sends "ponderhit" if
-            // we were told to ponder on the same move the opponent has played. We
-            // should continue searching but switching from pondering to normal search.
-            Limits.ponder = false;
-
-            if (StopOnPonderhit)
-                StopRequest = true;
-        }
-    }
-
     // Print search information
     if (t < 1000)
         lastInfoTime = 0;
@@ -1987,14 +1963,14 @@ split_point_start: // At split points actual search starts from here
 
   void wait_for_stop_or_ponderhit() {
 
-    string command;
+    string cmd;
 
     // Wait for a command from stdin
-    while (   std::getline(std::cin, command)
-           && command != "ponderhit" && command != "stop" && command != "quit") {};
+    while (cmd != "ponderhit" && cmd != "stop" && cmd != "quit")
+        Threads.getline(cmd);
 
-    if (command != "ponderhit" && command != "stop")
-        QuitRequest = true; // Must be "quit" or getline() returned false
+    if (cmd == "quit")
+        QuitRequest = true;
   }
 
 
@@ -2009,9 +1985,9 @@ split_point_start: // At split points actual search starts from here
     // Rml list is already sorted by score in descending order
     int s;
     int max_s = -VALUE_INFINITE;
-    int size = Min(MultiPV, (int)Rml.size());
+    int size = std::min(MultiPV, (int)Rml.size());
     int max = Rml[0].score;
-    int var = Min(max - Rml[size - 1].score, PawnValueMidgame);
+    int var = std::min(max - Rml[size - 1].score, int(PawnValueMidgame));
     int wk = 120 - 2 * SkillLevel;
 
     // PRNG sequence should be non deterministic
@@ -2247,3 +2223,34 @@ void Thread::idle_loop(SplitPoint* sp) {
       }
   }
 }
+
+
+// ThreadsManager::do_uci_async_cmd() processes the commands from GUI received
+// by listener thread while the other threads are searching.
+
+void ThreadsManager::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
+      // we were told to ponder on the same move the opponent has played. We
+      // should continue searching but switching from pondering to normal search.
+      Limits.ponder = false;
+
+      if (StopOnPonderhit)
+          StopRequest = true;
+  }
+}