X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=ba0a4f0c596386b623f52ee8b15ddcf9bbaef22b;hb=2ea323aec6a2c18f97c574efe2073a4ae185c7bd;hp=1a01601b8144f9d68a8cdd0b3c30356acc0d5d68;hpb=93f64577c34677017726894cf8268ca1ffc3593b;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 1a01601b..ba0a4f0c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -188,7 +188,7 @@ namespace { const Depth IIDDepth[2] = { 8 * OnePly /* non-PV */, 5 * OnePly /* PV */}; // At Non-PV nodes we do an internal iterative deepening search - // when the static evaluation is at most IIDMargin below beta. + // when the static evaluation is bigger then beta - IIDMargin. const Value IIDMargin = Value(0x100); // Step 11. Decide the new search depth @@ -1095,7 +1095,7 @@ namespace { if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply)) { // Refresh tte entry to avoid aging - TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove); + TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->king_danger()); ss[ply].currentMove = ttMove; // Can be MOVE_NONE return value_from_tt(tte->value(), ply); @@ -1106,8 +1106,11 @@ namespace { isCheck = pos.is_check(); if (!isCheck) { - if (tte && (tte->type() & VALUE_TYPE_EVAL)) - ss[ply].eval = value_from_tt(tte->value(), ply); + if (tte && tte->static_value() != VALUE_NONE) + { + ss[ply].eval = tte->static_value(); + ei.kingDanger[pos.side_to_move()] = tte->king_danger(); + } else ss[ply].eval = evaluate(pos, ei, threadID); @@ -1204,8 +1207,8 @@ namespace { } // Step 9. Internal iterative deepening - if ( depth >= IIDDepth[PvNode] - && ttMove == MOVE_NONE + if ( depth >= IIDDepth[PvNode] + && (ttMove == MOVE_NONE || (PvNode && tte->depth() <= depth - 4 * OnePly)) && (PvNode || (!isCheck && ss[ply].eval >= beta - IIDMargin))) { Depth d = (PvNode ? depth - 2 * OnePly : depth / 2); @@ -1306,8 +1309,8 @@ namespace { value = -search(pos, ss, -beta, -alpha, newDepth, ply+1, false, threadID); else { - // Step 14. Reduced search - // if the move fails high will be re-searched at full depth. + // Step 14. Reduced depth search + // If the move fails high will be re-searched at full depth. bool doFullDepthSearch = true; if ( depth >= 3 * OnePly @@ -1322,6 +1325,16 @@ namespace { value = -search(pos, ss, -(alpha+1), -alpha, newDepth-ss[ply].reduction, ply+1, true, threadID); doFullDepthSearch = (value > alpha); } + + // The move failed high, but if reduction is very big we could + // face a false positive, retry with a less aggressive reduction, + // if the move fails high again then go with full depth search. + if (doFullDepthSearch && ss[ply].reduction > 2 * OnePly) + { + ss[ply].reduction = OnePly; + value = -search(pos, ss, -(alpha+1), -alpha, newDepth-ss[ply].reduction, ply+1, true, threadID); + doFullDepthSearch = (value > alpha); + } } // Step 15. Full depth search @@ -1385,13 +1398,13 @@ namespace { return bestValue; if (bestValue <= oldAlpha) - TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE); + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE, ss[ply].eval, ei.kingDanger[pos.side_to_move()]); else if (bestValue >= beta) { TM.incrementBetaCounter(pos.side_to_move(), depth, threadID); move = ss[ply].pv[ply]; - TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move); + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move, ss[ply].eval, ei.kingDanger[pos.side_to_move()]); if (!pos.move_is_capture_or_promotion(move)) { update_history(pos, move, depth, movesSearched, moveCount); @@ -1399,7 +1412,7 @@ namespace { } } else - TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, depth, ss[ply].pv[ply]); + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, depth, ss[ply].pv[ply], ss[ply].eval, ei.kingDanger[pos.side_to_move()]); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1449,8 +1462,6 @@ namespace { if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply)) { - assert(tte->type() != VALUE_TYPE_EVAL); - ss[ply].currentMove = ttMove; // Can be MOVE_NONE return value_from_tt(tte->value(), ply); } @@ -1460,8 +1471,11 @@ namespace { // Evaluate the position statically if (isCheck) staticValue = -VALUE_INFINITE; - else if (tte && (tte->type() & VALUE_TYPE_EVAL)) - staticValue = value_from_tt(tte->value(), ply); + else if (tte && tte->static_value() != VALUE_NONE) + { + staticValue = tte->static_value(); + ei.kingDanger[pos.side_to_move()] = tte->king_danger(); + } else staticValue = evaluate(pos, ei, threadID); @@ -1478,8 +1492,8 @@ namespace { if (bestValue >= beta) { // Store the score to avoid a future costly evaluation() call - if (!isCheck && !tte && ei.kingDanger[pos.side_to_move()] == 0) - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_EV_LO, Depth(-127*OnePly), MOVE_NONE); + if (!isCheck && !tte) + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, Depth(-127*OnePly), MOVE_NONE, ss[ply].eval, ei.kingDanger[pos.side_to_move()]); return bestValue; } @@ -1577,20 +1591,19 @@ namespace { { // If bestValue isn't changed it means it is still the static evaluation // of the node, so keep this info to avoid a future evaluation() call. - ValueType type = (bestValue == staticValue && !ei.kingDanger[pos.side_to_move()] ? VALUE_TYPE_EV_UP : VALUE_TYPE_UPPER); - TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE); + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, d, MOVE_NONE, ss[ply].eval, ei.kingDanger[pos.side_to_move()]); } else if (bestValue >= beta) { move = ss[ply].pv[ply]; - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move); + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move, ss[ply].eval, ei.kingDanger[pos.side_to_move()]); // Update killers only for good checking moves if (!pos.move_is_capture_or_promotion(move)) update_killers(move, ss[ply]); } else - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, d, ss[ply].pv[ply]); + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, d, ss[ply].pv[ply], ss[ply].eval, ei.kingDanger[pos.side_to_move()]); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1684,7 +1697,7 @@ namespace { pos.do_move(move, st, ci, moveIsCheck); // Step 14. Reduced search - // if the move fails high will be re-searched at full depth. + // If the move fails high will be re-searched at full depth. bool doFullDepthSearch = true; if ( !dangerous @@ -1699,6 +1712,17 @@ namespace { value = -search(pos, ss, -(localAlpha+1), -localAlpha, newDepth-ss[sp->ply].reduction, sp->ply+1, true, threadID); doFullDepthSearch = (value > localAlpha); } + + // The move failed high, but if reduction is very big we could + // face a false positive, retry with a less aggressive reduction, + // if the move fails high again then go with full depth search. + if (doFullDepthSearch && ss[sp->ply].reduction > 2 * OnePly) + { + ss[sp->ply].reduction = OnePly; + Value localAlpha = sp->alpha; + value = -search(pos, ss, -(localAlpha+1), -localAlpha, newDepth-ss[sp->ply].reduction, sp->ply+1, true, threadID); + doFullDepthSearch = (value > localAlpha); + } } // Step 15. Full depth search