]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Revert Chess960 fix
[stockfish] / src / search.cpp
index 95a516d70e9a58a5bf3592cadf7826b417af2519..0e249705fa59a89e00d1f689d714bf33bbe024f9 100644 (file)
@@ -124,39 +124,19 @@ namespace {
     // way we are guaranteed that PV moves are always sorted as first.
     bool operator<(const RootMove& m) const {
       return pv_score != m.pv_score ? pv_score < m.pv_score
-                                    : non_pv_score <= m.non_pv_score;
+                                    : non_pv_score < m.non_pv_score;
     }
-    void set_pv(const Move newPv[]);
+
+    void extract_pv_from_tt(Position& pos);
+    void insert_pv_in_tt(Position& pos);
+    std::string pv_info_to_uci(const Position& pos, Value alpha, Value beta, int pvLine = 0);
 
     int64_t nodes;
-    Value pv_score, non_pv_score;
-    Move move, pv[PLY_MAX_PLUS_2];
+    Value pv_score;
+    Value non_pv_score;
+    Move pv[PLY_MAX_PLUS_2];
   };
 
-  RootMove::RootMove() : nodes(0) {
-
-      pv_score = non_pv_score = -VALUE_INFINITE;
-      move = pv[0] = MOVE_NONE;
-  }
-
-  RootMove& RootMove::operator=(const RootMove& rm) {
-
-      pv_score = rm.pv_score; non_pv_score = rm.non_pv_score;
-      nodes = rm.nodes; move = rm.move;
-      set_pv(rm.pv); // Skip costly full pv[] copy
-      return *this;
-  }
-
-  void RootMove::set_pv(const Move newPv[]) {
-
-    Move* p = pv;
-
-    while (*newPv != MOVE_NONE)
-        *p++ = *newPv++;
-
-    *p = MOVE_NONE;
-  }
-
 
   // RootMoveList struct is essentially a std::vector<> of RootMove objects,
   // with an handful of methods above the standard ones.
@@ -169,7 +149,7 @@ namespace {
     void set_non_pv_scores(const Position& pos);
 
     void sort() { insertion_sort<RootMove, Base::iterator>(begin(), end()); }
-    void sort_multipv(int n) { insertion_sort<RootMove, Base::iterator>(begin(), begin() + n); }
+    void sort_multipv(int n) { insertion_sort<RootMove, Base::iterator>(begin(), begin() + n + 1); }
   };
 
 
@@ -274,8 +254,8 @@ namespace {
 
   // Time managment variables
   int SearchStartTime, MaxNodes, MaxDepth, ExactMaxTime;
-  bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
-  bool FirstRootMove, AbortSearch, Quit, AspirationFailLow;
+  bool UseTimeManagement, InfiniteSearch, Pondering, StopOnPonderhit;
+  bool FirstRootMove, StopRequest, QuitRequest, AspirationFailLow;
   TimeManager TimeMgr;
 
   // Log file
@@ -287,6 +267,7 @@ namespace {
 
   // Node counters, used only by thread[0] but try to keep in different cache
   // lines (64 bytes each) from the heavy multi-thread read accessed variables.
+  bool SendSearchedNodes;
   int NodesSincePoll;
   int NodesBetweenPolls = 30000;
 
@@ -295,8 +276,8 @@ namespace {
 
   /// Local functions
 
-  Value id_loop(Position& pos, Move searchMoves[]);
-  Value root_search(Position& pos, SearchStack* ss, Move* pv, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
+  Move id_loop(Position& pos, Move searchMoves[], Move* ponderMove);
+  Value root_search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, RootMoveList& rml);
 
   template <NodeType PvNode, bool SpNode>
   Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
@@ -330,12 +311,8 @@ namespace {
   std::string value_to_uci(Value v);
   int nps(const Position& pos);
   void poll(const Position& pos);
-  void ponderhit();
   void wait_for_stop_or_ponderhit();
   void init_ss_array(SearchStack* ss, int size);
-  void print_pv_info(const Position& pos, Move pv[], Value alpha, Value beta, Value value);
-  void insert_pv_in_tt(const Position& pos, Move pv[]);
-  void extract_pv_from_tt(const Position& pos, Move bestMove, Move pv[]);
 
 #if !defined(_MSC_VER)
   void* init_thread(void* threadID);
@@ -424,14 +401,14 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
            int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]) {
 
   // Initialize global search variables
-  StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false;
+  StopOnPonderhit = StopRequest = QuitRequest = AspirationFailLow = SendSearchedNodes = false;
   NodesSincePoll = 0;
   SearchStartTime = get_system_time();
   ExactMaxTime = maxTime;
   MaxDepth = maxDepth;
   MaxNodes = maxNodes;
   InfiniteSearch = infinite;
-  PonderSearch = ponder;
+  Pondering = ponder;
   UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch;
 
   // Look for a book move, only during games, not tests
@@ -443,11 +420,11 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
       Move bookMove = OpeningBook.get_move(pos, Options["Best Book Move"].value<bool>());
       if (bookMove != MOVE_NONE)
       {
-          if (PonderSearch)
+          if (Pondering)
               wait_for_stop_or_ponderhit();
 
           cout << "bestmove " << bookMove << endl;
-          return true;
+          return !QuitRequest;
       }
   }
 
@@ -474,10 +451,7 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
   MultiPV                   = Options["MultiPV"].value<int>();
   UseLogFile                = Options["Use Search Log"].value<bool>();
 
-  if (UseLogFile)
-      LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
-
-  read_weights(pos.side_to_move());
+  read_evaluation_uci_options(pos.side_to_move());
 
   // Set the number of active threads
   ThreadsMgr.read_uci_options();
@@ -506,23 +480,57 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
 
   // Write search information to log file
   if (UseLogFile)
-      LogFile << "Searching: " << pos.to_fen() << endl
-              << "infinite: "  << infinite
-              << " ponder: "   << ponder
-              << " time: "     << myTime
+  {
+      std::string name = Options["Search Log Filename"].value<std::string>();
+      LogFile.open(name.c_str(), std::ios::out | std::ios::app);
+
+      LogFile << "Searching: "  << pos.to_fen()
+              << "\ninfinite: " << infinite
+              << " ponder: "    << ponder
+              << " time: "      << myTime
               << " increment: " << myIncrement
               << " moves to go: " << movesToGo << endl;
+  }
 
   // We're ready to start thinking. Call the iterative deepening loop function
-  id_loop(pos, searchMoves);
+  Move ponderMove = MOVE_NONE;
+  Move bestMove = id_loop(pos, searchMoves, &ponderMove);
+
+  // Print final search statistics
+  cout << "info nodes " << pos.nodes_searched()
+       << " nps " << nps(pos)
+       << " time " << current_search_time() << endl;
 
   if (UseLogFile)
+  {
+      LogFile << "\nNodes: " << pos.nodes_searched()
+              << "\nNodes/second: " << nps(pos)
+              << "\nBest move: " << move_to_san(pos, bestMove);
+
+      StateInfo st;
+      pos.do_move(bestMove, st);
+      LogFile << "\nPonder move: "
+              << move_to_san(pos, ponderMove) // Works also with MOVE_NONE
+              << endl;
+
+      // Return from think() with unchanged position
+      pos.undo_move(bestMove);
+
       LogFile.close();
+  }
 
   // This makes all the threads to go to sleep
   ThreadsMgr.set_active_threads(1);
 
-  return !Quit;
+  // If we are pondering or in infinite search, we shouldn't print the
+  // best move before we are told to do so.
+  if (!StopRequest && (Pondering || InfiniteSearch))
+      wait_for_stop_or_ponderhit();
+
+  // Could be both MOVE_NONE when searching on a stalemate position
+  cout << "bestmove " << bestMove << " ponder " << ponderMove << endl;
+
+  return !QuitRequest;
 }
 
 
@@ -533,48 +541,43 @@ namespace {
   // been consumed, the user stops the search, or the maximum search depth is
   // reached.
 
-  Value id_loop(Position& pos, Move searchMoves[]) {
+  Move id_loop(Position& pos, Move searchMoves[], Move* ponderMove) {
 
     SearchStack ss[PLY_MAX_PLUS_2];
-    Move pv[PLY_MAX_PLUS_2];
+    Depth depth;
     Move EasyMove = MOVE_NONE;
     Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
 
-    // Moves to search are verified, copied, scored and sorted
+    // Moves to search are verified, scored and sorted
     RootMoveList rml(pos, searchMoves);
 
     // Handle special case of searching on a mate/stale position
     if (rml.size() == 0)
     {
-        if (PonderSearch)
-            wait_for_stop_or_ponderhit();
+        Value s = (pos.is_check() ? -VALUE_MATE : VALUE_DRAW);
 
-        return pos.is_check() ? -VALUE_MATE : VALUE_DRAW;
-    }
+        cout << "info depth " << 1
+             << " score " << value_to_uci(s) << endl;
 
-    // Print RootMoveList startup scoring to the standard output,
-    // so to output information also for iteration 1.
-    cout << set960(pos.is_chess960()) // Is enough to set once at the beginning
-         << "info depth " << 1
-         << "\ninfo depth " << 1
-         << " score " << value_to_uci(rml[0].pv_score)
-         << " time " << current_search_time()
-         << " nodes " << pos.nodes_searched()
-         << " nps " << nps(pos)
-         << " pv " << rml[0].move << "\n";
+        return MOVE_NONE;
+    }
 
     // Initialize
     TT.new_search();
     H.clear();
     init_ss_array(ss, PLY_MAX_PLUS_2);
-    pv[0] = pv[1] = MOVE_NONE;
     ValueByIteration[1] = rml[0].pv_score;
     Iteration = 1;
 
+    // Send initial RootMoveList scoring (iteration 1)
+    cout << set960(pos.is_chess960()) // Is enough to set once at the beginning
+         << "info depth " << Iteration
+         << "\n" << rml[0].pv_info_to_uci(pos, alpha, beta) << endl;
+
     // Is one move significantly better than others after initial scoring ?
     if (   rml.size() == 1
         || rml[0].pv_score > rml[1].pv_score + EasyMoveMargin)
-        EasyMove = rml[0].move;
+        EasyMove = rml[0].pv[0];
 
     // Iterative deepening loop
     while (Iteration < PLY_MAX)
@@ -598,21 +601,19 @@ namespace {
             beta  = Min(ValueByIteration[Iteration - 1] + AspirationDelta,  VALUE_INFINITE);
         }
 
-        // Search to the current depth, rml is updated and sorted, alpha and beta could change
-        value = root_search(pos, ss, pv, rml, &alpha, &beta);
+        depth = (Iteration - 2) * ONE_PLY + InitialDepth;
 
-        // Write PV to transposition table, in case the relevant entries have
-        // been overwritten during the search.
-        insert_pv_in_tt(pos, pv);
+        // Search to the current depth, rml is updated and sorted
+        value = root_search(pos, ss, alpha, beta, depth, rml);
 
-        if (AbortSearch)
+        if (StopRequest)
             break; // Value cannot be trusted. Break out immediately!
 
         //Save info about search result
         ValueByIteration[Iteration] = value;
 
         // Drop the easy move if differs from the new best move
-        if (pv[0] != EasyMove)
+        if (rml[0].pv[0] != EasyMove)
             EasyMove = MOVE_NONE;
 
         if (UseTimeManagement)
@@ -633,7 +634,7 @@ namespace {
 
             // Stop search early if one move seems to be much better than the others
             if (   Iteration >= 8
-                && EasyMove == pv[0]
+                && EasyMove == rml[0].pv[0]
                 && (  (   rml[0].nodes > (pos.nodes_searched() * 85) / 100
                        && current_search_time() > TimeMgr.available_time() / 16)
                     ||(   rml[0].nodes > (pos.nodes_searched() * 98) / 100
@@ -653,7 +654,7 @@ namespace {
 
             if (stopSearch)
             {
-                if (PonderSearch)
+                if (Pondering)
                     StopOnPonderhit = true;
                 else
                     break;
@@ -664,75 +665,29 @@ namespace {
             break;
     }
 
-    // If we are pondering or in infinite search, we shouldn't print the
-    // best move before we are told to do so.
-    if (!AbortSearch && (PonderSearch || InfiniteSearch))
-        wait_for_stop_or_ponderhit();
-    else
-        // Print final search statistics
-        cout << "info nodes " << pos.nodes_searched()
-             << " nps " << nps(pos)
-             << " time " << current_search_time() << endl;
-
-    // Print the best move and the ponder move to the standard output
-    if (pv[0] == MOVE_NONE || MultiPV > 1)
-    {
-        pv[0] = rml[0].move;
-        pv[1] = MOVE_NONE;
-    }
-
-    assert(pv[0] != MOVE_NONE);
-
-    cout << "bestmove " << pv[0];
-
-    if (pv[1] != MOVE_NONE)
-        cout << " ponder " << pv[1];
-
-    cout << endl;
-
-    if (UseLogFile)
-    {
-        if (dbg_show_mean)
-            dbg_print_mean(LogFile);
-
-        if (dbg_show_hit_rate)
-            dbg_print_hit_rate(LogFile);
-
-        LogFile << "\nNodes: " << pos.nodes_searched()
-                << "\nNodes/second: " << nps(pos)
-                << "\nBest move: " << move_to_san(pos, pv[0]);
-
-        StateInfo st;
-        pos.do_move(pv[0], st);
-        LogFile << "\nPonder move: "
-                << move_to_san(pos, pv[1]) // Works also with MOVE_NONE
-                << endl;
-    }
-    return rml[0].pv_score;
+    *ponderMove = rml[0].pv[1];
+    return rml[0].pv[0];
   }
 
 
   // root_search() is the function which searches the root node. It is
-  // similar to search_pv except that it uses a different move ordering
-  // scheme, prints some information to the standard output and handles
-  // the fail low/high loops.
-
-  Value root_search(Position& pos, SearchStack* ss, Move* pv, RootMoveList& rml, Value* alphaPtr, Value* betaPtr) {
+  // similar to search_pv except that it prints some information to the
+  // standard output and handles the fail low/high loops.
 
+  Value root_search(Position& pos, SearchStack* ss, Value alpha,
+                    Value beta, Depth depth, RootMoveList& rml) {
     StateInfo st;
     CheckInfo ci(pos);
     int64_t nodes;
     Move move;
-    Depth depth, ext, newDepth;
-    Value value, alpha, beta;
+    Depth ext, newDepth;
+    Value value, oldAlpha;
     bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
     int researchCountFH, researchCountFL;
 
     researchCountFH = researchCountFL = 0;
-    alpha = *alphaPtr;
-    beta = *betaPtr;
+    oldAlpha = alpha;
     isCheck = pos.is_check();
-    depth = (Iteration - 2) * ONE_PLY + InitialDepth;
 
     // Step 1. Initialize node (polling is omitted at root)
     ss->currentMove = ss->bestMove = MOVE_NONE;
@@ -761,7 +716,7 @@ namespace {
         rml.sort();
 
         // Step 10. Loop through all moves in the root move list
-        for (int i = 0; i < (int)rml.size() && !AbortSearch; i++)
+        for (int i = 0; i < (int)rml.size() && !StopRequest; i++)
         {
             // This is used by time management
             FirstRootMove = (i == 0);
@@ -769,9 +724,19 @@ namespace {
             // Save the current node count before the move is searched
             nodes = pos.nodes_searched();
 
+            // If it's time to send nodes info, do it here where we have the
+            // correct accumulated node counts searched by each thread.
+            if (SendSearchedNodes)
+            {
+                SendSearchedNodes = false;
+                cout << "info nodes " << nodes
+                     << " nps " << nps(pos)
+                     << " time " << current_search_time() << endl;
+            }
+
             // Pick the next root move, and print the move and the move number to
             // the standard output.
-            move = ss->currentMove = rml[i].move;
+            move = ss->currentMove = rml[i].pv[0];
 
             if (current_search_time() >= 1000)
                 cout << "info currmove " << move
@@ -848,21 +813,20 @@ namespace {
                 pos.undo_move(move);
 
                 // Can we exit fail high loop ?
-                if (AbortSearch || value < beta)
+                if (StopRequest || value < beta)
                     break;
 
                 // We are failing high and going to do a research. It's important to update
                 // the score before research in case we run out of time while researching.
-                rml[i].pv_score = value;
                 ss->bestMove = move;
-                extract_pv_from_tt(pos, move, pv);
-                rml[i].set_pv(pv);
+                rml[i].pv_score = value;
+                rml[i].extract_pv_from_tt(pos);
 
-                // Print information to the standard output
-                print_pv_info(pos, pv, alpha, beta, value);
+                // Inform GUI that PV has changed
+                cout << rml[i].pv_info_to_uci(pos, alpha, beta) << endl;
 
                 // Prepare for a research after a fail high, each time with a wider window
-                *betaPtr = beta = Min(beta + AspirationDelta * (1 << researchCountFH), VALUE_INFINITE);
+                beta = Min(beta + AspirationDelta * (1 << researchCountFH), VALUE_INFINITE);
                 researchCountFH++;
 
             } // End of fail high loop
@@ -872,7 +836,7 @@ namespace {
             // ran out of time. In this case, the return value of the search cannot
             // be trusted, and we break out of the loop without updating the best
             // move and/or PV.
-            if (AbortSearch)
+            if (StopRequest)
                 break;
 
             // Remember searched nodes counts for this move
@@ -889,62 +853,50 @@ namespace {
                 // PV move or new best move!
 
                 // Update PV
-                rml[i].pv_score = value;
                 ss->bestMove = move;
-                extract_pv_from_tt(pos, move, pv);
-                rml[i].set_pv(pv);
+                rml[i].pv_score = value;
+                rml[i].extract_pv_from_tt(pos);
 
-                if (MultiPV == 1)
-                {
-                    // We record how often the best move has been changed in each
-                    // iteration. This information is used for time managment: When
-                    // the best move changes frequently, we allocate some more time.
-                    if (i > 0)
-                        BestMoveChangesByIteration[Iteration]++;
+                // We record how often the best move has been changed in each
+                // iteration. This information is used for time managment: When
+                // the best move changes frequently, we allocate some more time.
+                if (MultiPV == 1 && i > 0)
+                    BestMoveChangesByIteration[Iteration]++;
+
+                // Inform GUI that PV has changed, in case of multi-pv UCI protocol
+                // requires we send all the PV lines properly sorted.
+                rml.sort_multipv(i);
 
-                    // Print information to the standard output
-                    print_pv_info(pos, pv, alpha, beta, value);
+                for (int j = 0; j < Min(MultiPV, (int)rml.size()); j++)
+                    cout << rml[j].pv_info_to_uci(pos, alpha, beta, j) << endl;
 
+                // Update alpha. In multi-pv we don't use aspiration window
+                if (MultiPV == 1)
+                {
                     // Raise alpha to setup proper non-pv search upper bound
                     if (value > alpha)
                         alpha = value;
                 }
-                else // MultiPV > 1
-                {
-                    rml.sort_multipv(i);
-                    for (int j = 0; j < Min(MultiPV, (int)rml.size()); j++)
-                    {
-                        cout << "info multipv " << j + 1
-                             << " score " << value_to_uci(rml[j].pv_score)
-                             << " depth " << (j <= i ? Iteration : Iteration - 1)
-                             << " time " << current_search_time()
-                             << " nodes " << pos.nodes_searched()
-                             << " nps " << nps(pos)
-                             << " pv ";
-
-                        for (int k = 0; rml[j].pv[k] != MOVE_NONE && k < PLY_MAX; k++)
-                            cout << rml[j].pv[k] << " ";
-
-                        cout << endl;
-                    }
+                else // Set alpha equal to minimum score among the PV lines
                     alpha = rml[Min(i, MultiPV - 1)].pv_score;
-                }
+
             } // PV move or new best move
 
-            assert(alpha >= *alphaPtr);
+            assert(alpha >= oldAlpha);
 
-            AspirationFailLow = (alpha == *alphaPtr);
+            AspirationFailLow = (alpha == oldAlpha);
 
             if (AspirationFailLow && StopOnPonderhit)
                 StopOnPonderhit = false;
-        }
+
+        } // Root moves loop
 
         // Can we exit fail low loop ?
-        if (AbortSearch || !AspirationFailLow)
+        if (StopRequest || !AspirationFailLow)
             break;
 
         // Prepare for a research after a fail low, each time with a wider window
-        *alphaPtr = alpha = Max(alpha - AspirationDelta * (1 << researchCountFL), -VALUE_INFINITE);
+        oldAlpha = alpha = Max(alpha - AspirationDelta * (1 << researchCountFL), -VALUE_INFINITE);
         researchCountFL++;
 
     } // Fail low loop
@@ -952,6 +904,11 @@ namespace {
     // Sort the moves before to return
     rml.sort();
 
+    // Write PV lines to transposition table, in case the relevant entries
+    // have been overwritten during the search.
+    for (int i = 0; i < Min(MultiPV, (int)rml.size()); i++)
+        rml[i].insert_pv_in_tt(pos);
+
     return alpha;
   }
 
@@ -1012,7 +969,7 @@ namespace {
     }
 
     // Step 2. Check for aborted search and immediate draw
-    if (   AbortSearch
+    if (   StopRequest
         || ThreadsMgr.cutoff_at_splitpoint(threadID)
         || pos.is_draw()
         || ply >= PLY_MAX - 1)
@@ -1400,7 +1357,7 @@ split_point_start: // At split points actual search starts from here
           && ThreadsMgr.active_threads() > 1
           && bestValue < beta
           && ThreadsMgr.available_thread_exists(threadID)
-          && !AbortSearch
+          && !StopRequest
           && !ThreadsMgr.cutoff_at_splitpoint(threadID)
           && Iteration <= 99)
           ThreadsMgr.split<FakeSplit>(pos, ss, ply, &alpha, beta, &bestValue, depth,
@@ -1417,7 +1374,7 @@ split_point_start: // At split points actual search starts from here
     // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.
-    if (!SpNode && !AbortSearch && !ThreadsMgr.cutoff_at_splitpoint(threadID))
+    if (!SpNode && !StopRequest && !ThreadsMgr.cutoff_at_splitpoint(threadID))
     {
         move = bestValue <= oldAlpha ? MOVE_NONE : ss->bestMove;
         vt   = bestValue <= oldAlpha ? VALUE_TYPE_UPPER
@@ -1973,30 +1930,54 @@ split_point_start: // At split points actual search starts from here
   }
 
 
-  // current_search_time() returns the number of milliseconds which have passed
-  // since the beginning of the current search.
+  // init_ss_array() does a fast reset of the first entries of a SearchStack
+  // array and of all the excludedMove and skipNullMove entries.
 
-  int current_search_time() {
+  void init_ss_array(SearchStack* ss, int size) {
 
-    return get_system_time() - SearchStartTime;
+    for (int i = 0; i < size; i++, ss++)
+    {
+        ss->excludedMove = MOVE_NONE;
+        ss->skipNullMove = false;
+        ss->reduction = DEPTH_ZERO;
+        ss->sp = NULL;
+
+        if (i < 3)
+            ss->killers[0] = ss->killers[1] = ss->mateKiller = MOVE_NONE;
+    }
   }
 
 
-  // value_to_uci() converts a value to a string suitable for use with the UCI protocol
+  // value_to_uci() converts a value to a string suitable for use with the UCI
+  // protocol specifications:
+  //
+  // cp <x>     The score from the engine's point of view in centipawns.
+  // mate <y>   Mate in y moves, not plies. If the engine is getting mated
+  //            use negative values for y.
 
   std::string value_to_uci(Value v) {
 
     std::stringstream s;
 
     if (abs(v) < VALUE_MATE - PLY_MAX * ONE_PLY)
-      s << "cp " << int(v) * 100 / int(PawnValueMidgame); // Scale to pawn = 100
+      s << "cp " << int(v) * 100 / int(PawnValueMidgame); // Scale to centipawns
     else
       s << "mate " << (v > 0 ? (VALUE_MATE - v + 1) / 2 : -(VALUE_MATE + v) / 2 );
 
     return s.str();
   }
 
-  // nps() computes the current nodes/second count.
+
+  // current_search_time() returns the number of milliseconds which have passed
+  // since the beginning of the current search.
+
+  int current_search_time() {
+
+    return get_system_time() - SearchStartTime;
+  }
+
+
+  // nps() computes the current nodes/second count
 
   int nps(const Position& pos) {
 
@@ -2025,18 +2006,28 @@ split_point_start: // At split points actual search starts from here
 
         if (command == "quit")
         {
-            AbortSearch = true;
-            PonderSearch = false;
-            Quit = true;
+            // Quit the program as soon as possible
+            Pondering = false;
+            QuitRequest = StopRequest = true;
             return;
         }
         else if (command == "stop")
         {
-            AbortSearch = true;
-            PonderSearch = false;
+            // Stop calculating as soon as possible, but still send the "bestmove"
+            // and possibly the "ponder" token when finishing the search.
+            Pondering = false;
+            StopRequest = true;
         }
         else if (command == "ponderhit")
-            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.
+            Pondering = false;
+
+            if (StopOnPonderhit)
+                StopRequest = true;
+        }
     }
 
     // Print search information
@@ -2058,12 +2049,12 @@ split_point_start: // At split points actual search starts from here
         if (dbg_show_hit_rate)
             dbg_print_hit_rate();
 
-        cout << "info nodes " << pos.nodes_searched() << " nps " << nps(pos)
-             << " time " << t << endl;
+        // Send info on searched nodes as soon as we return to root
+        SendSearchedNodes = true;
     }
 
     // Should we stop the search?
-    if (PonderSearch)
+    if (Pondering)
         return;
 
     bool stillAtFirstMove =    FirstRootMove
@@ -2073,49 +2064,10 @@ split_point_start: // At split points actual search starts from here
     bool noMoreTime =   t > TimeMgr.maximum_time()
                      || stillAtFirstMove;
 
-    if (   (Iteration >= 3 && UseTimeManagement && noMoreTime)
+    if (   (UseTimeManagement && noMoreTime)
         || (ExactMaxTime && t >= ExactMaxTime)
-        || (Iteration >= 3 && MaxNodes && pos.nodes_searched() >= MaxNodes))
-        AbortSearch = true;
-  }
-
-
-  // ponderhit() is called when the program is pondering (i.e. thinking while
-  // it's the opponent's turn to move) in order to let the engine know that
-  // it correctly predicted the opponent's move.
-
-  void ponderhit() {
-
-    int t = current_search_time();
-    PonderSearch = false;
-
-    bool stillAtFirstMove =    FirstRootMove
-                           && !AspirationFailLow
-                           &&  t > TimeMgr.available_time();
-
-    bool noMoreTime =   t > TimeMgr.maximum_time()
-                     || stillAtFirstMove;
-
-    if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit))
-        AbortSearch = true;
-  }
-
-
-  // init_ss_array() does a fast reset of the first entries of a SearchStack
-  // array and of all the excludedMove and skipNullMove entries.
-
-  void init_ss_array(SearchStack* ss, int size) {
-
-    for (int i = 0; i < size; i++, ss++)
-    {
-        ss->excludedMove = MOVE_NONE;
-        ss->skipNullMove = false;
-        ss->reduction = DEPTH_ZERO;
-        ss->sp = NULL;
-
-        if (i < 3)
-            ss->killers[0] = ss->killers[1] = ss->mateKiller = MOVE_NONE;
-    }
+        || (MaxNodes && pos.nodes_searched() >= MaxNodes)) // FIXME
+        StopRequest = true;
   }
 
 
@@ -2124,7 +2076,7 @@ split_point_start: // At split points actual search starts from here
   // 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 (in id_loop()).
+  // after which the bestmove and pondermove will be printed.
 
   void wait_for_stop_or_ponderhit() {
 
@@ -2132,12 +2084,13 @@ split_point_start: // At split points actual search starts from here
 
     while (true)
     {
+        // Wait for a command from stdin
         if (!std::getline(std::cin, command))
             command = "quit";
 
         if (command == "quit")
         {
-            Quit = true;
+            QuitRequest = true;
             break;
         }
         else if (command == "ponderhit" || command == "stop")
@@ -2146,88 +2099,6 @@ split_point_start: // At split points actual search starts from here
   }
 
 
-  // print_pv_info() prints to standard output and eventually to log file information on
-  // the current PV line. It is called at each iteration or after a new pv is found.
-
-  void print_pv_info(const Position& pos, Move pv[], Value alpha, Value beta, Value value) {
-
-    cout << "info depth " << Iteration
-         << " score "     << value_to_uci(value)
-         << (value >= beta ? " lowerbound" : value <= alpha ? " upperbound" : "")
-         << " time "  << current_search_time()
-         << " nodes " << pos.nodes_searched()
-         << " nps "   << nps(pos)
-         << " pv ";
-
-    for (Move* m = pv; *m != MOVE_NONE; m++)
-        cout << *m << " ";
-
-    cout << endl;
-
-    if (UseLogFile)
-    {
-        ValueType t = value >= beta  ? VALUE_TYPE_LOWER :
-                      value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT;
-
-        LogFile << pretty_pv(pos, current_search_time(), Iteration, value, t, pv) << endl;
-    }
-  }
-
-
-  // insert_pv_in_tt() is called at the end of a search iteration, and inserts
-  // the PV back into the TT. This makes sure the old PV moves are searched
-  // first, even if the old TT entries have been overwritten.
-
-  void insert_pv_in_tt(const Position& pos, Move pv[]) {
-
-    StateInfo st;
-    TTEntry* tte;
-    Position p(pos, pos.thread());
-    Value v, m = VALUE_NONE;
-
-    for (int i = 0; pv[i] != MOVE_NONE; i++)
-    {
-        tte = TT.retrieve(p.get_key());
-        if (!tte || tte->move() != pv[i])
-        {
-            v = (p.is_check() ? VALUE_NONE : evaluate(p, m));
-            TT.store(p.get_key(), VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[i], v, m);
-        }
-        p.do_move(pv[i], st);
-    }
-  }
-
-
-  // extract_pv_from_tt() builds a PV by adding moves from the transposition table.
-  // We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes. This
-  // allow to always have a ponder move even when we fail high at root and also a
-  // long PV to print that is important for position analysis.
-
-  void extract_pv_from_tt(const Position& pos, Move bestMove, Move pv[]) {
-
-    StateInfo st;
-    TTEntry* tte;
-    Position p(pos, pos.thread());
-    int ply = 0;
-
-    assert(bestMove != MOVE_NONE);
-
-    pv[ply] = bestMove;
-    p.do_move(pv[ply++], st);
-
-    while (   (tte = TT.retrieve(p.get_key())) != NULL
-           && tte->move() != MOVE_NONE
-           && move_is_legal(p, tte->move())
-           && ply < PLY_MAX
-           && (!p.is_draw() || ply < 2))
-    {
-        pv[ply] = tte->move();
-        p.do_move(pv[ply++], st);
-    }
-    pv[ply] = MOVE_NONE;
-  }
-
-
   // init_thread() is the function which is called when a new thread is
   // launched. It simply calls the idle_loop() function with the supplied
   // threadID. There are two versions of this function; one for POSIX
@@ -2655,16 +2526,128 @@ split_point_start: // At split points actual search starts from here
   }
 
 
-  /// The RootMoveList class
+  /// RootMove and RootMoveList method's definitions
+
+  RootMove::RootMove() {
+
+    nodes = 0;
+    pv_score = non_pv_score = -VALUE_INFINITE;
+    pv[0] = MOVE_NONE;
+  }
+
+  RootMove& RootMove::operator=(const RootMove& rm) {
+
+    const Move* src = rm.pv;
+    Move* dst = pv;
+
+    // Avoid a costly full rm.pv[] copy
+    do *dst++ = *src; while (*src++ != MOVE_NONE);
+
+    nodes = rm.nodes;
+    pv_score = rm.pv_score;
+    non_pv_score = rm.non_pv_score;
+    return *this;
+  }
+
+  // extract_pv_from_tt() builds a PV by adding moves from the transposition table.
+  // We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes. This
+  // allow to always have a ponder move even when we fail high at root and also a
+  // long PV to print that is important for position analysis.
+
+  void RootMove::extract_pv_from_tt(Position& pos) {
+
+    StateInfo state[PLY_MAX_PLUS_2], *st = state;
+    TTEntry* tte;
+    int ply = 1;
+
+    assert(pv[0] != MOVE_NONE && move_is_legal(pos, pv[0]));
+
+    pos.do_move(pv[0], *st++);
+
+    while (   (tte = TT.retrieve(pos.get_key())) != NULL
+           && tte->move() != MOVE_NONE
+           && move_is_legal(pos, tte->move())
+           && ply < PLY_MAX
+           && (!pos.is_draw() || ply < 2))
+    {
+        pv[ply] = tte->move();
+        pos.do_move(pv[ply++], *st++);
+    }
+    pv[ply] = MOVE_NONE;
+
+    do pos.undo_move(pv[--ply]); while (ply);
+  }
+
+  // insert_pv_in_tt() is called at the end of a search iteration, and inserts
+  // the PV back into the TT. This makes sure the old PV moves are searched
+  // first, even if the old TT entries have been overwritten.
+
+  void RootMove::insert_pv_in_tt(Position& pos) {
+
+    StateInfo state[PLY_MAX_PLUS_2], *st = state;
+    TTEntry* tte;
+    Key k;
+    Value v, m = VALUE_NONE;
+    int ply = 0;
+
+    assert(pv[0] != MOVE_NONE && move_is_legal(pos, pv[0]));
+
+    do {
+        k = pos.get_key();
+        tte = TT.retrieve(k);
+
+        // Don't overwrite exsisting correct entries
+        if (!tte || tte->move() != pv[ply])
+        {
+            v = (pos.is_check() ? VALUE_NONE : evaluate(pos, m));
+            TT.store(k, VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[ply], v, m);
+        }
+        pos.do_move(pv[ply], *st++);
+
+    } while (pv[++ply] != MOVE_NONE);
+
+    do pos.undo_move(pv[--ply]); while (ply);
+  }
+
+  // pv_info_to_uci() returns a string with information on the current PV line
+  // formatted according to UCI specification and eventually writes the info
+  // to a log file. It is called at each iteration or after a new pv is found.
+
+  std::string RootMove::pv_info_to_uci(const Position& pos, Value alpha, Value beta, int pvLine) {
+
+    std::stringstream s, l;
+    Move* m = pv;
+
+    while (*m != MOVE_NONE)
+        l << *m++ << " ";
+
+    s << "info depth " << Iteration // FIXME
+      << " seldepth " << int(m - pv)
+      << " multipv " << pvLine + 1
+      << " score " << value_to_uci(pv_score)
+      << (pv_score >= beta ? " lowerbound" : pv_score <= alpha ? " upperbound" : "")
+      << " time "  << current_search_time()
+      << " nodes " << pos.nodes_searched()
+      << " nps "   << nps(pos)
+      << " pv "    << l.str();
+
+    if (UseLogFile && pvLine == 0)
+    {
+        ValueType t = pv_score >= beta  ? VALUE_TYPE_LOWER :
+                      pv_score <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT;
+
+        LogFile << pretty_pv(pos, current_search_time(), Iteration, pv_score, t, pv) << endl;
+    }
+    return s.str();
+  }
 
-  // RootMoveList c'tor
 
   RootMoveList::RootMoveList(Position& pos, Move searchMoves[]) {
 
     SearchStack ss[PLY_MAX_PLUS_2];
     MoveStack mlist[MOVES_MAX];
     StateInfo st;
-    bool includeAllMoves = (searchMoves[0] == MOVE_NONE);
+    Move* sm;
 
     // Initialize search stack
     init_ss_array(ss, PLY_MAX_PLUS_2);
@@ -2673,25 +2656,26 @@ split_point_start: // At split points actual search starts from here
     // Generate all legal moves
     MoveStack* last = generate_moves(pos, mlist);
 
-    // Add each move to the moves[] array
+    // Add each move to the RootMoveList's vector
     for (MoveStack* cur = mlist; cur != last; cur++)
     {
-        bool includeMove = includeAllMoves;
+        // If we have a searchMoves[] list then verify cur->move
+        // is in the list before to add it.
+        for (sm = searchMoves; *sm && *sm != cur->move; sm++) {}
 
-        for (int k = 0; !includeMove && searchMoves[k] != MOVE_NONE; k++)
-            includeMove = (searchMoves[k] == cur->move);
-
-        if (!includeMove)
+        if (searchMoves[0] && *sm != cur->move)
             continue;
 
         // Find a quick score for the move and add to the list
+        pos.do_move(cur->move, st);
+
         RootMove rm;
-        rm.move = ss[0].currentMove = rm.pv[0] = cur->move;
+        rm.pv[0] = ss[0].currentMove = cur->move;
         rm.pv[1] = MOVE_NONE;
-        pos.do_move(cur->move, st);
         rm.pv_score = -qsearch<PV>(pos, ss+1, -VALUE_INFINITE, VALUE_INFINITE, DEPTH_ZERO, 1);
-        pos.undo_move(cur->move);
         push_back(rm);
+
+        pos.undo_move(cur->move);
     }
     sort();
   }
@@ -2709,7 +2693,7 @@ split_point_start: // At split points actual search starts from here
 
       while ((move = mp.get_next_move()) != MOVE_NONE)
           for (Base::iterator it = begin(); it != end(); ++it)
-              if (it->move == move)
+              if (it->pv[0] == move)
               {
                   it->non_pv_score = score--;
                   break;