X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=473bf46dd4e00a835f7c648c63b37da2852aa4a5;hp=204e5fc8b7440cf941c893fe3a4deafc68285d3c;hb=70b1b79264b2a160f72dd2aa92c2f80045e4cd83;hpb=5fc8b27db9a1d9fffeb46d0e2ef40803c55fd4f9 diff --git a/src/search.cpp b/src/search.cpp index 204e5fc8..473bf46d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -107,7 +107,6 @@ namespace { Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); bool connected_threat(const Position& pos, Move m, Move threat); - Value refine_eval(const TTEntry* tte, Value ttValue, Value defaultEval); Move do_skill_level(); string uci_pv(const Position& pos, int depth, Value alpha, Value beta); @@ -486,7 +485,7 @@ namespace { Move ttMove, move, excludedMove, bestMove, threatMove; Depth ext, newDepth; Value bestValue, value, ttValue; - Value refinedValue, nullValue, futilityValue; + Value eval, nullValue, futilityValue; bool inCheck, givesCheck, pvMove, singularExtensionNode; bool captureOrPromotion, dangerous, doFullDepthSearch; int moveCount, playedMoveCount; @@ -576,40 +575,45 @@ namespace { // Step 5. Evaluate the position statically and update parent's gain statistics if (inCheck) - ss->eval = ss->evalMargin = refinedValue = VALUE_NONE; + ss->staticEval = ss->evalMargin = eval = VALUE_NONE; else if (tte) { assert(tte->static_value() != VALUE_NONE); + assert(ttValue != VALUE_NONE || tte->type() == BOUND_NONE); - ss->eval = tte->static_value(); + ss->staticEval = eval = tte->static_value(); ss->evalMargin = tte->static_value_margin(); - refinedValue = refine_eval(tte, ttValue, ss->eval); + + // Can ttValue be used as a better position evaluation? + if ( ((tte->type() & BOUND_LOWER) && ttValue > eval) + || ((tte->type() & BOUND_UPPER) && ttValue < eval)) + eval = ttValue; } else { - refinedValue = ss->eval = evaluate(pos, ss->evalMargin); + eval = ss->staticEval = evaluate(pos, ss->evalMargin); TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, - ss->eval, ss->evalMargin); + ss->staticEval, ss->evalMargin); } // Update gain for the parent non-capture move given the static position // evaluation before and after the move. - if ( (move = (ss-1)->currentMove) != MOVE_NULL - && (ss-1)->eval != VALUE_NONE - && ss->eval != VALUE_NONE + if ( (move = (ss-1)->currentMove) != MOVE_NULL + && (ss-1)->staticEval != VALUE_NONE + && ss->staticEval != VALUE_NONE && !pos.captured_piece_type() && type_of(move) == NORMAL) { Square to = to_sq(move); - H.update_gain(pos.piece_on(to), to, -(ss-1)->eval - ss->eval); + H.update_gain(pos.piece_on(to), to, -(ss-1)->staticEval - ss->staticEval); } // Step 6. Razoring (is omitted in PV nodes) if ( !PvNode && depth < 4 * ONE_PLY && !inCheck - && refinedValue + razor_margin(depth) < beta + && eval + razor_margin(depth) < beta && ttMove == MOVE_NONE && abs(beta) < VALUE_MATE_IN_MAX_PLY && !pos.pawn_on_7th(pos.side_to_move())) @@ -629,17 +633,17 @@ namespace { && !ss->skipNullMove && depth < 4 * ONE_PLY && !inCheck - && refinedValue - FutilityMargins[depth][0] >= beta + && eval - FutilityMargins[depth][0] >= beta && abs(beta) < VALUE_MATE_IN_MAX_PLY && pos.non_pawn_material(pos.side_to_move())) - return refinedValue - FutilityMargins[depth][0]; + return eval - FutilityMargins[depth][0]; // Step 8. Null move search with verification search (is omitted in PV nodes) if ( !PvNode && !ss->skipNullMove && depth > ONE_PLY && !inCheck - && refinedValue >= beta + && eval >= beta && abs(beta) < VALUE_MATE_IN_MAX_PLY && pos.non_pawn_material(pos.side_to_move())) { @@ -649,7 +653,7 @@ namespace { Depth R = 3 * ONE_PLY + depth / 4; // Null move dynamic reduction based on value - if (refinedValue - PawnValueMg > beta) + if (eval - PawnValueMg > beta) R += ONE_PLY; pos.do_null_move(st); @@ -730,7 +734,7 @@ namespace { // Step 10. Internal iterative deepening if ( depth >= (PvNode ? 5 * ONE_PLY : 8 * ONE_PLY) && ttMove == MOVE_NONE - && (PvNode || (!inCheck && ss->eval + Value(256) >= beta))) + && (PvNode || (!inCheck && ss->staticEval + Value(256) >= beta))) { Depth d = (PvNode ? depth - 2 * ONE_PLY : depth / 2); @@ -862,7 +866,7 @@ split_point_start: // At split points actual search starts from here // We illogically ignore reduction condition depth >= 3*ONE_PLY for predicted depth, // but fixing this made program slightly weaker. Depth predictedDepth = newDepth - reduction(depth, moveCount); - futilityValue = ss->eval + ss->evalMargin + futility_margin(predictedDepth, moveCount) + futilityValue = ss->staticEval + ss->evalMargin + futility_margin(predictedDepth, moveCount) + H.gain(pos.piece_moved(move), to_sq(move)); if (futilityValue < beta) @@ -1038,7 +1042,7 @@ split_point_start: // At split points actual search starts from here if (bestValue >= beta) // Failed high { TT.store(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, depth, - bestMove, ss->eval, ss->evalMargin); + bestMove, ss->staticEval, ss->evalMargin); if (!pos.is_capture_or_promotion(bestMove) && !inCheck) { @@ -1063,7 +1067,7 @@ split_point_start: // At split points actual search starts from here else // Failed low or PV search TT.store(posKey, value_to_tt(bestValue, ss->ply), PvNode && bestMove != MOVE_NONE ? BOUND_EXACT : BOUND_UPPER, - depth, bestMove, ss->eval, ss->evalMargin); + depth, bestMove, ss->staticEval, ss->evalMargin); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1127,7 +1131,7 @@ split_point_start: // At split points actual search starts from here // Evaluate the position statically if (inCheck) { - ss->eval = ss->evalMargin = VALUE_NONE; + ss->staticEval = ss->evalMargin = VALUE_NONE; bestValue = futilityBase = -VALUE_INFINITE; enoughMaterial = false; } @@ -1137,18 +1141,18 @@ split_point_start: // At split points actual search starts from here { assert(tte->static_value() != VALUE_NONE); - ss->eval = bestValue = tte->static_value(); + ss->staticEval = bestValue = tte->static_value(); ss->evalMargin = tte->static_value_margin(); } else - ss->eval = bestValue = evaluate(pos, ss->evalMargin); + ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); // Stand pat. Return immediately if static value is at least beta if (bestValue >= beta) { if (!tte) TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, - DEPTH_NONE, MOVE_NONE, ss->eval, ss->evalMargin); + DEPTH_NONE, MOVE_NONE, ss->staticEval, ss->evalMargin); return bestValue; } @@ -1156,7 +1160,7 @@ split_point_start: // At split points actual search starts from here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = ss->eval + ss->evalMargin + Value(128); + futilityBase = ss->staticEval + ss->evalMargin + Value(128); enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMg; } @@ -1223,7 +1227,7 @@ split_point_start: // At split points actual search starts from here && givesCheck && move != ttMove && !pos.is_capture_or_promotion(move) - && ss->eval + PawnValueMg / 4 < beta + && ss->staticEval + PawnValueMg / 4 < beta && !check_is_dangerous(pos, move, futilityBase, beta)) continue; @@ -1255,7 +1259,7 @@ split_point_start: // At split points actual search starts from here else // Fail high { TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER, - ttDepth, move, ss->eval, ss->evalMargin); + ttDepth, move, ss->staticEval, ss->evalMargin); return value; } @@ -1270,7 +1274,7 @@ split_point_start: // At split points actual search starts from here TT.store(posKey, value_to_tt(bestValue, ss->ply), PvNode && bestMove != MOVE_NONE ? BOUND_EXACT : BOUND_UPPER, - ttDepth, bestMove, ss->eval, ss->evalMargin); + ttDepth, bestMove, ss->staticEval, ss->evalMargin); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1436,23 +1440,6 @@ split_point_start: // At split points actual search starts from here } - // refine_eval() returns the transposition table score if possible, otherwise - // falls back on static position evaluation. Note that we never return VALUE_NONE - // even if v == VALUE_NONE. - - Value refine_eval(const TTEntry* tte, Value v, Value defaultEval) { - - assert(tte); - assert(v != VALUE_NONE || !tte->type()); - - if ( ((tte->type() & BOUND_LOWER) && v >= defaultEval) - || ((tte->type() & BOUND_UPPER) && v < defaultEval)) - return v; - - return defaultEval; - } - - // When playing with strength handicap choose best move among the MultiPV set // using a statistical rule dependent on SkillLevel. Idea by Heinz van Saanen.