X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=7d5e45fc326ace7a19b2071bcdf1581e88f492ca;hp=20beb23a11c44e0f75bcd99a08c506d7373e1658;hb=6aef4429fd15ca4f8e285affe83dd0a553883607;hpb=b5178597bd71c210de9e4245e26153c24fbb2c13 diff --git a/src/search.cpp b/src/search.cpp index 20beb23a..7d5e45fc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -309,6 +309,8 @@ namespace { 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); @@ -628,7 +630,7 @@ namespace { // Write PV to transposition table, in case the relevant entries have // been overwritten during the search. - TT.insert_pv(p, pv); + insert_pv_in_tt(p, pv); if (AbortSearch) break; // Value cannot be trusted. Break out immediately! @@ -895,7 +897,7 @@ namespace { // the score before research in case we run out of time while researching. rml.set_move_score(i, value); ss->bestMove = move; - TT.extract_pv(pos, move, pv, PLY_MAX); + extract_pv_from_tt(pos, move, pv); rml.set_move_pv(i, pv); // Print information to the standard output @@ -935,7 +937,7 @@ namespace { // Update PV rml.set_move_score(i, value); ss->bestMove = move; - TT.extract_pv(pos, move, pv, PLY_MAX); + extract_pv_from_tt(pos, move, pv); rml.set_move_pv(i, pv); if (MultiPV == 1) @@ -1083,13 +1085,17 @@ namespace { isCheck = pos.is_check(); if (!isCheck) { - if (tte && tte->static_value() != VALUE_NONE) + if (tte) { + assert(tte->static_value() != VALUE_NONE); ss->eval = tte->static_value(); ei.kingDanger[pos.side_to_move()] = tte->king_danger(); } else + { ss->eval = evaluate(pos, ei); + TT.store(posKey, VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, MOVE_NONE, ss->eval, ei.kingDanger[pos.side_to_move()]); + } refinedValue = refine_eval(tte, ss->eval, ply); // Enhance accuracy with TT value if possible update_gains(pos, (ss-1)->currentMove, (ss-1)->eval, ss->eval); @@ -1107,10 +1113,6 @@ namespace { && !value_is_mate(beta) && !pos.has_pawn_on_7th(pos.side_to_move())) { - // Pass ss->eval to qsearch() and avoid an evaluate call - if (!tte || tte->static_value() == VALUE_NONE) - TT.store(posKey, ss->eval, VALUE_TYPE_EXACT, Depth(-127*OnePly), MOVE_NONE, ss->eval, ei.kingDanger[pos.side_to_move()]); - Value rbeta = beta - razor_margin(depth); Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply); if (v < rbeta) @@ -1476,8 +1478,9 @@ namespace { } else { - if (tte && tte->static_value() != VALUE_NONE) + if (tte) { + assert(tte->static_value() != VALUE_NONE); ei.kingDanger[pos.side_to_move()] = tte->king_danger(); bestValue = tte->static_value(); } @@ -1491,7 +1494,7 @@ namespace { if (bestValue >= beta) { if (!tte) - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, Depth(-127*OnePly), MOVE_NONE, ss->eval, ei.kingDanger[pos.side_to_move()]); + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, DEPTH_NONE, MOVE_NONE, ss->eval, ei.kingDanger[pos.side_to_move()]); return bestValue; } @@ -2271,6 +2274,61 @@ namespace { } + // 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()); + EvalInfo ei; + Value v; + + 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, ei)); + TT.store(p.get_key(), VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[i], v, ei.kingDanger[pos.side_to_move()]); + } + 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