]> git.sesse.net Git - stockfish/commitdiff
Added a new function build_pv(), which extends a PV by walking
authorTord Romstad <tord@glaurungchess.com>
Thu, 6 Aug 2009 11:27:49 +0000 (13:27 +0200)
committerTord Romstad <tord@glaurungchess.com>
Thu, 6 Aug 2009 11:27:49 +0000 (13:27 +0200)
down the transposition table.

When the search was stopped before a fail high at the root was
resolved, Stockfish would often print a very short PV, sometimes
consisting of just a single move. This was not only a little
user-unfriendly, but also harmed the strength a little in
ponder-on games: Single-move PVs mean that there is no ponder
move to search.

It is perhaps worth considering to remove the pv[][] array
entirely, and always build the entire PV from the transposition
table. This would simplify the source code somewhat and probably
make the program infinitesimally faster, at the expense of
sometimes getting shorter PVs or PVs with rubbish moves near
the end.

src/search.cpp

index f0d2431487641dc765f5c56d1a7a029f7cf439ef..d922986b7fd7b3744441e92e352391925dd5d967 100644 (file)
@@ -306,6 +306,7 @@ namespace {
   void update_history(const Position& pos, Move m, Depth depth, Move movesSearched[], int moveCount);
   void update_killers(Move m, SearchStack& ss);
   void slowdown(const Position& pos);
+  void build_pv(const Position& pos, Move pv[]);
 
   bool fail_high_ply_1();
   int current_search_time();
@@ -975,6 +976,7 @@ namespace {
             // Update PV
             rml.set_move_score(i, value);
             update_pv(ss, 0);
+            build_pv(pos, ss[0].pv);
             rml.set_move_pv(i, ss[0].pv);
 
             if (MultiPV == 1)
@@ -2430,7 +2432,7 @@ namespace {
   }
 
 
-  // slowdown() simply wastes CPU cycles doing nothing useful.  It's used
+  // slowdown() simply wastes CPU cycles doing nothing useful. It's used
   // in strength handicap mode.
 
   void slowdown(const Position &pos) {
@@ -2444,6 +2446,37 @@ namespace {
   }
 
 
+  // build_pv() extends a PV by adding moves from the transposition table at
+  // the end. This should ensure that the PV is almost always at least two
+  // plies long, which is important, because otherwise we will often get
+  // single-move PVs when the search stops while failing high, and a
+  // single-move PV means that we don't have a ponder move.
+
+  void build_pv(const Position& pos, Move pv[]) {
+    int ply;
+    Position p(pos);
+    StateInfo st[100];
+
+    for (ply = 0; pv[ply] != MOVE_NONE; ply++)
+        p.do_move(pv[ply], st[ply]);
+
+    bool stop;
+    const TTEntry* tte;
+    for (stop = false, tte = TT.retrieve(p.get_key());
+         tte && tte->move() != MOVE_NONE && !stop;
+         tte = TT.retrieve(p.get_key()), ply++)
+    {
+        if (!move_is_legal(p, tte->move(), p.pinned_pieces(p.side_to_move())))
+            break;
+        pv[ply] = tte->move();
+        p.do_move(pv[ply], st[ply]);
+        for (int j = 0; j < ply; j++)
+            if (st[j].key == p.get_key()) stop = true;
+    }
+    pv[ply] = MOVE_NONE;
+  }
+
+
   // fail_high_ply_1() checks if some thread is currently resolving a fail
   // high at ply 1 at the node below the first root node.  This information
   // is used for time managment.