From: Tord Romstad Date: Thu, 6 Aug 2009 11:27:49 +0000 (+0200) Subject: Added a new function build_pv(), which extends a PV by walking X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=da854fe83a64b2181c372f7b51f8b2190f67840d;p=stockfish Added a new function build_pv(), which extends a PV by walking 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. --- diff --git a/src/search.cpp b/src/search.cpp index f0d24314..d922986b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -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.