From 5b21c10afba744f2a984fbe4546701e7ffeee241 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Fri, 8 Jan 2010 11:45:46 +0100 Subject: [PATCH] Sync qsearch with search So to have the same layout and be as much similar as possible. The only functional change is that now we try ttMove as first also in PV nodes and at the end we save the ttMove, as it happens in search. This should have almost zero impact on ELO but it seems the correct thing to do. Signed-off-by: Marco Costalba --- src/search.cpp | 88 +++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index a13453cf..4a8dd17f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1400,7 +1400,7 @@ namespace { const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8)); const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2); - // Enhance position with TT value if possible + // Enhance score accuracy with TT value if possible futilityValue = staticValue + FutilityValueMargin; staticValue = refine_eval(tte, staticValue, ply); @@ -1492,8 +1492,8 @@ namespace { if (move == excludedMove) continue; - singleEvasion = (isCheck && mp.number_of_evasions() == 1); moveIsCheck = pos.move_is_check(move, ci); + singleEvasion = (isCheck && mp.number_of_evasions() == 1); captureOrPromotion = pos.move_is_capture_or_promotion(move); // Decide the new search depth @@ -1606,9 +1606,9 @@ namespace { break; } - // All legal moves have been searched. A special case: If there were + // All legal moves have been searched. A special case: If there were // no legal moves, it must be mate or stalemate. - if (moveCount == 0) + if (!moveCount) return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW); // If the search is not aborted, update the transposition table, @@ -1622,12 +1622,13 @@ namespace { { BetaCounter.add(pos.side_to_move(), depth, threadID); move = ss[ply].pv[ply]; + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move); if (!pos.move_is_capture_or_promotion(move)) { update_history(pos, move, depth, movesSearched, moveCount); update_killers(move, ss[ply]); } - TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move); + } assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1652,7 +1653,7 @@ namespace { EvalInfo ei; StateInfo st; Move ttMove, move; - Value staticValue, bestValue, value, futilityValue; + Value staticValue, bestValue, value, futilityBase, futilityValue; bool isCheck, enoughMaterial, moveIsCheck; const TTEntry* tte = NULL; int moveCount = 0; @@ -1669,18 +1670,21 @@ namespace { if (pos.is_draw()) return VALUE_DRAW; - // Transposition table lookup, only when not in PV - if (!pvNode) + if (ply >= PLY_MAX - 1) + return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID); + + // Transposition table lookup. At PV nodes, we don't use the TT for + // pruning, but only for move ordering. + tte = TT.retrieve(pos.get_key()); + ttMove = (tte ? tte->move() : MOVE_NONE); + + if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply)) { - tte = TT.retrieve(pos.get_key()); - if (tte && ok_to_use_TT(tte, depth, beta, ply)) - { - assert(tte->type() != VALUE_TYPE_EVAL); + assert(tte->type() != VALUE_TYPE_EVAL); - return value_from_tt(tte->value(), ply); - } + ss[ply].currentMove = ttMove; // Can be MOVE_NONE + return value_from_tt(tte->value(), ply); } - ttMove = (tte ? tte->move() : MOVE_NONE); isCheck = pos.is_check(); ei.futilityMargin = Value(0); // Manually initialize futilityMargin @@ -1688,20 +1692,11 @@ namespace { // Evaluate the position statically if (isCheck) staticValue = -VALUE_INFINITE; - else if (tte && (tte->type() & VALUE_TYPE_EVAL)) - { - // Use the cached evaluation score if possible - assert(ei.futilityMargin == Value(0)); - staticValue = value_from_tt(tte->value(), ply); - } else staticValue = evaluate(pos, ei, threadID); - if (ply >= PLY_MAX - 1) - return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID); - // Initialize "stand pat score", and return it immediately if it is // at least beta. bestValue = staticValue; @@ -1724,6 +1719,7 @@ namespace { MovePicker mp = MovePicker(pos, ttMove, depth, H); CheckInfo ci(pos); enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame; + futilityBase = staticValue + FutilityMarginQS + ei.futilityMargin; // Loop through the moves until no moves remain or a beta cutoff // occurs. @@ -1732,11 +1728,12 @@ namespace { { assert(move_is_ok(move)); + moveIsCheck = pos.move_is_check(move, ci); + + // Update current move moveCount++; ss[ply].currentMove = move; - moveIsCheck = pos.move_is_check(move, ci); - // Futility pruning if ( enoughMaterial && !isCheck @@ -1746,12 +1743,9 @@ namespace { && !move_is_promotion(move) && !pos.move_is_passed_pawn_push(move)) { - futilityValue = staticValue - + Max(pos.midgame_value_of_piece_on(move_to(move)), - pos.endgame_value_of_piece_on(move_to(move))) - + (move_is_ep(move) ? PawnValueEndgame : Value(0)) - + FutilityMarginQS - + ei.futilityMargin; + futilityValue = futilityBase + + pos.endgame_value_of_piece_on(move_to(move)) + + (move_is_ep(move) ? PawnValueEndgame : Value(0)); if (futilityValue < alpha) { @@ -1787,31 +1781,31 @@ namespace { } } - // All legal moves have been searched. A special case: If we're in check + // All legal moves have been searched. A special case: If we're in check // and no legal moves were found, it is checkmate. if (!moveCount && pos.is_check()) // Mate! return value_mated_in(ply); - assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); - // Update transposition table - move = ss[ply].pv[ply]; - if (!pvNode) + Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1)); + if (bestValue < beta) { - // If bestValue isn't changed it means it is still the static evaluation of - // the node, so keep this info to avoid a future costly evaluation() call. + // 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.futilityMargin ? VALUE_TYPE_EV_UP : VALUE_TYPE_UPPER); - Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1)); + TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE); + } + else + { + move = ss[ply].pv[ply]; + TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move); - if (bestValue < beta) - TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE); - else - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move); + // Update killers only for good checking moves + if (!pos.move_is_capture_or_promotion(move)) + update_killers(move, ss[ply]); } - // Update killers only for good check moves - if (alpha >= beta && !pos.move_is_capture_or_promotion(move)) - update_killers(move, ss[ply]); + assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); return bestValue; } -- 2.39.2