]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Avoid casting to char* in prefetch()
[stockfish] / src / search.cpp
index 425c2c65d7e098d18b07e9d459c23511f6a2a701..7f733a950f73bb0904fe8abaa35fd458f8c9044a 100644 (file)
@@ -109,7 +109,6 @@ namespace {
   Value value_from_tt(Value v, int ply);
   void update_pv(Move* pv, Move move, Move* childPv);
   void update_stats(const Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt);
-  string uci_pv(const Position& pos, Depth depth, Value alpha, Value beta);
 
 } // namespace
 
@@ -153,19 +152,19 @@ uint64_t Search::perft(Position& pos, Depth depth) {
   CheckInfo ci(pos);
   const bool leaf = (depth == 2 * ONE_PLY);
 
-  for (const ExtMove& ms : MoveList<LEGAL>(pos))
+  for (const auto& m : MoveList<LEGAL>(pos))
   {
       if (Root && depth <= ONE_PLY)
           cnt = 1, nodes++;
       else
       {
-          pos.do_move(ms.move, st, ci, pos.gives_check(ms.move, ci));
+          pos.do_move(m, st, ci, pos.gives_check(m, ci));
           cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
           nodes += cnt;
-          pos.undo_move(ms.move);
+          pos.undo_move(m);
       }
       if (Root)
-          sync_cout << UCI::move(ms.move, pos.is_chess960()) << ": " << cnt << sync_endl;
+          sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
   }
   return nodes;
 }
@@ -200,7 +199,7 @@ void Search::think() {
 
   if (RootMoves.empty())
   {
-      RootMoves.push_back(MOVE_NONE);
+      RootMoves.push_back(RootMove(MOVE_NONE));
       sync_cout << "info depth 0 score "
                 << UCI::value(RootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
                 << sync_endl;
@@ -357,7 +356,7 @@ namespace {
                 if (   multiPV == 1
                     && (bestValue <= alpha || bestValue >= beta)
                     && Time::now() - SearchTime > 3000)
-                    sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
+                    sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
 
                 // In case of failing low/high increase aspiration window and
                 // re-search, otherwise exit the loop.
@@ -390,7 +389,7 @@ namespace {
                           << " time " << Time::now() - SearchTime << sync_endl;
 
             else if (PVIdx + 1 == multiPV || Time::now() - SearchTime > 3000)
-                sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
+                sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
         }
 
         // If skill level is enabled and time is up, pick a sub-optimal best move
@@ -873,7 +872,7 @@ moves_loop: // When in check and at SpNode search starts from here
       }
 
       // Speculative prefetch as early as possible
-      prefetch((char*)TT.first_entry(pos.key_after(move)));
+      prefetch(TT.first_entry(pos.key_after(move)));
 
       // Check for legality just before making the move
       if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
@@ -1239,7 +1238,7 @@ moves_loop: // When in check and at SpNode search starts from here
           continue;
 
       // Speculative prefetch as early as possible
-      prefetch((char*)TT.first_entry(pos.key_after(move)));
+      prefetch(TT.first_entry(pos.key_after(move)));
 
       // Check for legality just before making the move
       if (!pos.legal(move, ci.pinned))
@@ -1384,75 +1383,77 @@ moves_loop: // When in check and at SpNode search starts from here
     // then we choose the move with the resulting highest score.
     for (size_t i = 0; i < multiPV; ++i)
     {
-        int score = RootMoves[i].score;
-
         // This is our magic formula
-        score += (  weakness * int(RootMoves[0].score - score)
-                  + variance * (rng.rand<unsigned>() % weakness)) / 128;
+        int push = (  weakness * int(RootMoves[0].score - RootMoves[i].score)
+                    + variance * (rng.rand<unsigned>() % weakness)) / 128;
 
-        if (score > maxScore)
+        if (RootMoves[i].score + push > maxScore)
         {
-            maxScore = score;
+            maxScore = RootMoves[i].score + push;
             best = RootMoves[i].pv[0];
         }
     }
     return best;
   }
 
+} // namespace
 
-  // uci_pv() formats PV information according to the UCI protocol. UCI
-  // requires that all (if any) unsearched PV lines are sent using a previous
-  // search score.
 
-  string uci_pv(const Position& pos, Depth depth, Value alpha, Value beta) {
+/// UCI::pv() formats PV information according to the UCI protocol. UCI requires
+/// that all (if any) unsearched PV lines are sent using a previous search score.
 
-    std::stringstream ss;
-    Time::point elapsed = Time::now() - SearchTime + 1;
-    size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size());
-    int selDepth = 0;
+string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
 
-    for (Thread* th : Threads)
-        if (th->maxPly > selDepth)
-            selDepth = th->maxPly;
+  std::stringstream ss;
+  Time::point elapsed = Time::now() - SearchTime + 1;
+  size_t multiPV = std::min((size_t)Options["MultiPV"], RootMoves.size());
+  int selDepth = 0;
 
-    for (size_t i = 0; i < uciPVSize; ++i)
-    {
-        bool updated = (i <= PVIdx);
+  for (Thread* th : Threads)
+      if (th->maxPly > selDepth)
+          selDepth = th->maxPly;
 
-        if (depth == ONE_PLY && !updated)
-            continue;
+  for (size_t i = 0; i < multiPV; ++i)
+  {
+      bool updated = (i <= PVIdx);
 
-        Depth d = updated ? depth : depth - ONE_PLY;
-        Value v = updated ? RootMoves[i].score : RootMoves[i].previousScore;
+      if (depth == ONE_PLY && !updated)
+          continue;
 
-        bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY;
-        v = tb ? TB::Score : v;
+      Depth d = updated ? depth : depth - ONE_PLY;
+      Value v = updated ? RootMoves[i].score : RootMoves[i].previousScore;
 
-        if (ss.rdbuf()->in_avail()) // Not at first line
-            ss << "\n";
+      bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY;
+      v = tb ? TB::Score : v;
 
-        ss << "info depth " << d / ONE_PLY
-           << " seldepth "  << selDepth
-           << " multipv "   << i + 1
-           << " score "     << UCI::value(v);
+      if (ss.rdbuf()->in_avail()) // Not at first line
+          ss << "\n";
 
-        if (!tb && i == PVIdx)
-              ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
+      ss << "info"
+         << " depth "    << d / ONE_PLY
+         << " seldepth " << selDepth
+         << " multipv "  << i + 1
+         << " score "    << UCI::value(v);
 
-        ss << " nodes "     << pos.nodes_searched()
-           << " nps "       << pos.nodes_searched() * 1000 / elapsed
-           << " tbhits "    << TB::Hits
-           << " time "      << elapsed
-           << " pv";
+      if (!tb && i == PVIdx)
+          ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
 
-        for (size_t j = 0; j < RootMoves[i].pv.size(); ++j)
-            ss << " " << UCI::move(RootMoves[i].pv[j], pos.is_chess960());
-    }
+      ss << " nodes "    << pos.nodes_searched()
+         << " nps "      << pos.nodes_searched() * 1000 / elapsed;
+
+      if (elapsed > 1000) // Earlier makes little sense
+          ss << " hashfull " << TT.hashfull();
 
-    return ss.str();
+      ss << " tbhits "   << TB::Hits
+         << " time "     << elapsed
+         << " pv";
+
+      for (Move m : RootMoves[i].pv)
+          ss << " " << UCI::move(m, pos.is_chess960());
   }
 
-} // namespace
+  return ss.str();
+}
 
 
 /// RootMove::insert_pv_in_tt() is called at the end of a search iteration, and
@@ -1462,22 +1463,22 @@ moves_loop: // When in check and at SpNode search starts from here
 void RootMove::insert_pv_in_tt(Position& pos) {
 
   StateInfo state[MAX_PLY], *st = state;
-  size_t idx = 0;
+  bool ttHit;
 
-  for ( ; idx < pv.size(); ++idx)
+  for (Move m : pv)
   {
-      bool ttHit;
-      TTEntry* tte = TT.probe(pos.key(), ttHit);
+      assert(MoveList<LEGAL>(pos).contains(m));
 
-      if (!ttHit || tte->move() != pv[idx]) // Don't overwrite correct entries
-          tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[idx], VALUE_NONE, TT.generation());
+      TTEntry* tte = TT.probe(pos.key(), ttHit);
 
-      assert(MoveList<LEGAL>(pos).contains(pv[idx]));
+      if (!ttHit || tte->move() != m) // Don't overwrite correct entries
+          tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, m, VALUE_NONE, TT.generation());
 
-      pos.do_move(pv[idx], *st++);
+      pos.do_move(m, *st++);
   }
 
-  while (idx) pos.undo_move(pv[--idx]);
+  for (size_t i = pv.size(); i > 0; )
+      pos.undo_move(pv[--i]);
 }
 
 
@@ -1486,22 +1487,25 @@ void RootMove::insert_pv_in_tt(Position& pos) {
 /// root. We try hard to have a ponder move to return to the GUI, otherwise in case of
 /// 'ponder on' we have nothing to think on.
 
-Move RootMove::extract_ponder_from_tt(Position& pos)
+bool RootMove::extract_ponder_from_tt(Position& pos)
 {
     StateInfo st;
-    bool found;
+    bool ttHit;
 
     assert(pv.size() == 1);
 
     pos.do_move(pv[0], st);
-    TTEntry* tte = TT.probe(pos.key(), found);
-    Move m = found ? tte->move() : MOVE_NONE;
-    if (!MoveList<LEGAL>(pos).contains(m))
-        m = MOVE_NONE;
-
+    TTEntry* tte = TT.probe(pos.key(), ttHit);
     pos.undo_move(pv[0]);
-    pv.push_back(m);
-    return m;
+
+    if (ttHit)
+    {
+        Move m = tte->move(); // Local copy to be SMP safe
+        if (MoveList<LEGAL>(pos).contains(m))
+           return pv.push_back(m), true;
+    }
+
+    return false;
 }