]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Use rml[0].pv[] instead of dedicated pv[] array
[stockfish] / src / search.cpp
index 95a516d70e9a58a5bf3592cadf7826b417af2519..fceaccb524fec10493a68961222ccd7a225e49d8 100644 (file)
@@ -124,37 +124,34 @@ 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[]);
 
     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) {
+  RootMove::RootMove() {
 
-      pv_score = non_pv_score = -VALUE_INFINITE;
-      move = pv[0] = MOVE_NONE;
+    nodes = 0;
+    pv_score = non_pv_score = -VALUE_INFINITE;
+    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[]) {
+    const Move* src = rm.pv;
+    Move* dst = pv;
 
-    Move* p = pv;
+    // Avoid a costly full rm.pv[] copy
+    do *dst++ = *src; while (*src++ != MOVE_NONE);
 
-    while (*newPv != MOVE_NONE)
-        *p++ = *newPv++;
-
-    *p = MOVE_NONE;
+    nodes = rm.nodes;
+    pv_score = rm.pv_score;
+    non_pv_score = rm.non_pv_score;
+    return *this;
   }
 
 
@@ -296,7 +293,7 @@ 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);
+  Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
 
   template <NodeType PvNode, bool SpNode>
   Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
@@ -536,7 +533,6 @@ namespace {
   Value id_loop(Position& pos, Move searchMoves[]) {
 
     SearchStack ss[PLY_MAX_PLUS_2];
-    Move pv[PLY_MAX_PLUS_2];
     Move EasyMove = MOVE_NONE;
     Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
 
@@ -561,20 +557,19 @@ namespace {
          << " time " << current_search_time()
          << " nodes " << pos.nodes_searched()
          << " nps " << nps(pos)
-         << " pv " << rml[0].move << "\n";
+         << " pv " << rml[0].pv[0] << "\n";
 
     // 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;
 
     // 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)
@@ -599,11 +594,7 @@ namespace {
         }
 
         // Search to the current depth, rml is updated and sorted, alpha and beta could change
-        value = root_search(pos, ss, pv, rml, &alpha, &beta);
-
-        // Write PV to transposition table, in case the relevant entries have
-        // been overwritten during the search.
-        insert_pv_in_tt(pos, pv);
+        value = root_search(pos, ss, rml, &alpha, &beta);
 
         if (AbortSearch)
             break; // Value cannot be trusted. Break out immediately!
@@ -612,7 +603,7 @@ namespace {
         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 +624,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
@@ -675,18 +666,10 @@ namespace {
              << " 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];
+    cout << "bestmove " << rml[0].pv[0];
 
-    if (pv[1] != MOVE_NONE)
-        cout << " ponder " << pv[1];
+    if (rml[0].pv[1] != MOVE_NONE)
+        cout << " ponder " << rml[0].pv[1];
 
     cout << endl;
 
@@ -700,12 +683,12 @@ namespace {
 
         LogFile << "\nNodes: " << pos.nodes_searched()
                 << "\nNodes/second: " << nps(pos)
-                << "\nBest move: " << move_to_san(pos, pv[0]);
+                << "\nBest move: " << move_to_san(pos, rml[0].pv[0]);
 
         StateInfo st;
-        pos.do_move(pv[0], st);
+        pos.do_move(rml[0].pv[0], st);
         LogFile << "\nPonder move: "
-                << move_to_san(pos, pv[1]) // Works also with MOVE_NONE
+                << move_to_san(pos, rml[0].pv[1]) // Works also with MOVE_NONE
                 << endl;
     }
     return rml[0].pv_score;
@@ -717,7 +700,7 @@ namespace {
   // 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) {
+  Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr) {
 
     StateInfo st;
     CheckInfo ci(pos);
@@ -771,7 +754,7 @@ namespace {
 
             // 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
@@ -855,11 +838,10 @@ namespace {
                 // 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);
+                extract_pv_from_tt(pos, move, rml[i].pv);
 
                 // Print information to the standard output
-                print_pv_info(pos, pv, alpha, beta, value);
+                print_pv_info(pos, rml[i].pv, alpha, beta, value);
 
                 // Prepare for a research after a fail high, each time with a wider window
                 *betaPtr = beta = Min(beta + AspirationDelta * (1 << researchCountFH), VALUE_INFINITE);
@@ -891,8 +873,7 @@ namespace {
                 // Update PV
                 rml[i].pv_score = value;
                 ss->bestMove = move;
-                extract_pv_from_tt(pos, move, pv);
-                rml[i].set_pv(pv);
+                extract_pv_from_tt(pos, move, rml[i].pv);
 
                 if (MultiPV == 1)
                 {
@@ -903,7 +884,7 @@ namespace {
                         BestMoveChangesByIteration[Iteration]++;
 
                     // Print information to the standard output
-                    print_pv_info(pos, pv, alpha, beta, value);
+                    print_pv_info(pos, rml[i].pv, alpha, beta, value);
 
                     // Raise alpha to setup proper non-pv search upper bound
                     if (value > alpha)
@@ -952,6 +933,10 @@ namespace {
     // Sort the moves before to return
     rml.sort();
 
+    // Write PV to transposition table, in case the relevant entries have
+    // been overwritten during the search.
+    insert_pv_in_tt(pos, rml[0].pv);
+
     return alpha;
   }
 
@@ -2657,14 +2642,12 @@ split_point_start: // At split points actual search starts from here
 
   /// The RootMoveList class
 
-  // 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;
-
-        for (int k = 0; !includeMove && searchMoves[k] != MOVE_NONE; k++)
-            includeMove = (searchMoves[k] == cur->move);
+        // 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++) {}
 
-        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;