X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=791cbc6fb580901a567296d23a0eeed08f892969;hp=3f482e77146490cad1fc57e4ca06fd5efec64726;hb=b366c7dc38145278a00c51a560a4f7b6e03a0b2a;hpb=f352008958c0a2556cf22f6a8afba77ea574a994 diff --git a/src/search.cpp b/src/search.cpp index 3f482e77..791cbc6f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -203,8 +203,8 @@ namespace { // Extensions. Configurable UCI options // Array index 0 is used at non-PV nodes, index 1 at PV nodes. - Depth CheckExtension[2], SingleEvasionExtension[2], PawnPushTo7thExtension[2]; - Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2]; + Depth CheckExtension[2], PawnPushTo7thExtension[2], PassedPawnExtension[2]; + Depth PawnEndgameExtension[2], MateThreatExtension[2]; // Minimum depth for use of singular extension const Depth SingularExtensionDepth[2] = { 8 * ONE_PLY /* non-PV */, 6 * ONE_PLY /* PV */}; @@ -289,7 +289,7 @@ namespace { } template - Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool singleEvasion, bool mateThreat, bool* dangerous); + Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool mateThreat, bool* dangerous); bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue); bool connected_moves(const Position& pos, Move m1, Move m2); @@ -297,6 +297,7 @@ namespace { Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply); + bool ok_to_use_TT_PV(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply); bool connected_threat(const Position& pos, Move m, Move threat); Value refine_eval(const TTEntry* tte, Value defaultEval, int ply); void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount); @@ -355,7 +356,6 @@ namespace { return rm != Rml.end() ? rm->pv[0] : MOVE_NONE; } - int number_of_evasions() const { return (int)Rml.size(); } RootMoveList::iterator rm; bool firstCall; @@ -501,8 +501,6 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[ CheckExtension[1] = Options["Check Extension (PV nodes)"].value(); CheckExtension[0] = Options["Check Extension (non-PV nodes)"].value(); - SingleEvasionExtension[1] = Options["Single Evasion Extension (PV nodes)"].value(); - SingleEvasionExtension[0] = Options["Single Evasion Extension (non-PV nodes)"].value(); PawnPushTo7thExtension[1] = Options["Pawn Push to 7th Extension (PV nodes)"].value(); PawnPushTo7thExtension[0] = Options["Pawn Push to 7th Extension (non-PV nodes)"].value(); PassedPawnExtension[1] = Options["Passed Pawn Extension (PV nodes)"].value(); @@ -787,7 +785,7 @@ namespace { ValueType vt; Value bestValue, value, oldAlpha; Value refinedValue, nullValue, futilityBase, futilityValueScaled; // Non-PV specific - bool isPvMove, isCheck, singleEvasion, singularExtensionNode, moveIsCheck, captureOrPromotion, dangerous; + bool isPvMove, isCheck, singularExtensionNode, moveIsCheck, captureOrPromotion, dangerous; bool mateThreat = false; int moveCount = 0, playedMoveCount = 0; int threadID = pos.thread(); @@ -841,14 +839,10 @@ namespace { tte = TT.retrieve(posKey); ttMove = tte ? tte->move() : MOVE_NONE; - // At PV nodes, we don't use the TT for pruning, but only for move ordering. - // This is to avoid problems in the following areas: - // - // * Repetition draw detection - // * Fifty move rule detection - // * Searching for a mate - // * Printing of full PV line - if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply)) + // At PV nodes we check for exact scores within (alha, beta) range, while + // at non-PV nodes we check for and return a fail high/low. Biggest advantage + // at probing at PV nodes is to have a smooth experience in analysis mode. + if (!Root && tte && (PvNode ? ok_to_use_TT_PV(tte, depth, alpha, beta, ply) : ok_to_use_TT(tte, depth, beta, ply))) { TT.refresh(tte); ss->bestMove = ttMove; // Can be MOVE_NONE @@ -991,7 +985,6 @@ split_point_start: // At split points actual search starts from here MovePickerExt mp(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta)); CheckInfo ci(pos); ss->bestMove = MOVE_NONE; - singleEvasion = !SpNode && isCheck && mp.number_of_evasions() == 1; futilityBase = ss->eval + ss->evalMargin; singularExtensionNode = !Root && !SpNode @@ -1053,7 +1046,7 @@ split_point_start: // At split points actual search starts from here captureOrPromotion = pos.move_is_capture_or_promotion(move); // Step 11. Decide the new search depth - ext = extension(pos, move, captureOrPromotion, moveIsCheck, singleEvasion, mateThreat, &dangerous); + ext = extension(pos, move, captureOrPromotion, moveIsCheck, mateThreat, &dangerous); // Singular extension search. If all moves but one fail low on a search of (alpha-s, beta-s), // and just one fails high on (alpha, beta), then that move is singular and should be extended. @@ -1703,22 +1696,19 @@ split_point_start: // At split points actual search starts from here // extended, as example because the corresponding UCI option is set to zero, // the move is marked as 'dangerous' so, at least, we avoid to prune it. template - Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, - bool singleEvasion, bool mateThreat, bool* dangerous) { + Depth extension(const Position& pos, Move m, bool captureOrPromotion, + bool moveIsCheck, bool mateThreat, bool* dangerous) { assert(m != MOVE_NONE); Depth result = DEPTH_ZERO; - *dangerous = moveIsCheck | singleEvasion | mateThreat; + *dangerous = moveIsCheck | mateThreat; if (*dangerous) { if (moveIsCheck && pos.see_sign(m) >= 0) result += CheckExtension[PvNode]; - if (singleEvasion) - result += SingleEvasionExtension[PvNode]; - if (mateThreat) result += MateThreatExtension[PvNode]; } @@ -1804,7 +1794,9 @@ split_point_start: // At split points actual search starts from here // ok_to_use_TT() returns true if a transposition table score - // can be used at a given point in search. + // can be used at a given point in search. There are two versions + // one to be used in non-PV nodes and one in PV nodes where we look + // for an exact score that falls between (alha, beta) boundaries. bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply) { @@ -1818,6 +1810,17 @@ split_point_start: // At split points actual search starts from here || ((tte->type() & VALUE_TYPE_UPPER) && v < beta)); } + bool ok_to_use_TT_PV(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply) { + + Value v = value_from_tt(tte->value(), ply); + + return tte->depth() >= depth + && tte->type() == VALUE_TYPE_EXACT + && tte->move() != MOVE_NONE + && v < beta + && v > alpha; + } + // refine_eval() returns the transposition table score if // possible otherwise falls back on static position evaluation.