1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-11 19:49:14 +00:00

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 <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2010-01-08 11:45:46 +01:00
parent dba072c449
commit 5b21c10afb

View file

@ -1400,7 +1400,7 @@ namespace {
const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8)); const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8));
const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2); 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; futilityValue = staticValue + FutilityValueMargin;
staticValue = refine_eval(tte, staticValue, ply); staticValue = refine_eval(tte, staticValue, ply);
@ -1492,8 +1492,8 @@ namespace {
if (move == excludedMove) if (move == excludedMove)
continue; continue;
singleEvasion = (isCheck && mp.number_of_evasions() == 1);
moveIsCheck = pos.move_is_check(move, ci); moveIsCheck = pos.move_is_check(move, ci);
singleEvasion = (isCheck && mp.number_of_evasions() == 1);
captureOrPromotion = pos.move_is_capture_or_promotion(move); captureOrPromotion = pos.move_is_capture_or_promotion(move);
// Decide the new search depth // Decide the new search depth
@ -1606,9 +1606,9 @@ namespace {
break; 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. // 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); return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
// If the search is not aborted, update the transposition table, // If the search is not aborted, update the transposition table,
@ -1622,12 +1622,13 @@ namespace {
{ {
BetaCounter.add(pos.side_to_move(), depth, threadID); BetaCounter.add(pos.side_to_move(), depth, threadID);
move = ss[ply].pv[ply]; 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)) if (!pos.move_is_capture_or_promotion(move))
{ {
update_history(pos, move, depth, movesSearched, moveCount); update_history(pos, move, depth, movesSearched, moveCount);
update_killers(move, ss[ply]); 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); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
@ -1652,7 +1653,7 @@ namespace {
EvalInfo ei; EvalInfo ei;
StateInfo st; StateInfo st;
Move ttMove, move; Move ttMove, move;
Value staticValue, bestValue, value, futilityValue; Value staticValue, bestValue, value, futilityBase, futilityValue;
bool isCheck, enoughMaterial, moveIsCheck; bool isCheck, enoughMaterial, moveIsCheck;
const TTEntry* tte = NULL; const TTEntry* tte = NULL;
int moveCount = 0; int moveCount = 0;
@ -1669,39 +1670,33 @@ namespace {
if (pos.is_draw()) if (pos.is_draw())
return VALUE_DRAW; return VALUE_DRAW;
// Transposition table lookup, only when not in PV if (ply >= PLY_MAX - 1)
if (!pvNode) return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
{
tte = TT.retrieve(pos.get_key());
if (tte && ok_to_use_TT(tte, depth, beta, ply))
{
assert(tte->type() != VALUE_TYPE_EVAL);
return value_from_tt(tte->value(), ply); // 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); ttMove = (tte ? tte->move() : MOVE_NONE);
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);
}
isCheck = pos.is_check(); isCheck = pos.is_check();
ei.futilityMargin = Value(0); // Manually initialize futilityMargin ei.futilityMargin = Value(0); // Manually initialize futilityMargin
// Evaluate the position statically // Evaluate the position statically
if (isCheck) if (isCheck)
staticValue = -VALUE_INFINITE; staticValue = -VALUE_INFINITE;
else if (tte && (tte->type() & VALUE_TYPE_EVAL)) 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); staticValue = value_from_tt(tte->value(), ply);
}
else else
staticValue = evaluate(pos, ei, threadID); 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 // Initialize "stand pat score", and return it immediately if it is
// at least beta. // at least beta.
bestValue = staticValue; bestValue = staticValue;
@ -1724,6 +1719,7 @@ namespace {
MovePicker mp = MovePicker(pos, ttMove, depth, H); MovePicker mp = MovePicker(pos, ttMove, depth, H);
CheckInfo ci(pos); CheckInfo ci(pos);
enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame; 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 // Loop through the moves until no moves remain or a beta cutoff
// occurs. // occurs.
@ -1732,11 +1728,12 @@ namespace {
{ {
assert(move_is_ok(move)); assert(move_is_ok(move));
moveIsCheck = pos.move_is_check(move, ci);
// Update current move
moveCount++; moveCount++;
ss[ply].currentMove = move; ss[ply].currentMove = move;
moveIsCheck = pos.move_is_check(move, ci);
// Futility pruning // Futility pruning
if ( enoughMaterial if ( enoughMaterial
&& !isCheck && !isCheck
@ -1746,12 +1743,9 @@ namespace {
&& !move_is_promotion(move) && !move_is_promotion(move)
&& !pos.move_is_passed_pawn_push(move)) && !pos.move_is_passed_pawn_push(move))
{ {
futilityValue = staticValue futilityValue = futilityBase
+ Max(pos.midgame_value_of_piece_on(move_to(move)), + pos.endgame_value_of_piece_on(move_to(move))
pos.endgame_value_of_piece_on(move_to(move))) + (move_is_ep(move) ? PawnValueEndgame : Value(0));
+ (move_is_ep(move) ? PawnValueEndgame : Value(0))
+ FutilityMarginQS
+ ei.futilityMargin;
if (futilityValue < alpha) 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. // and no legal moves were found, it is checkmate.
if (!moveCount && pos.is_check()) // Mate! if (!moveCount && pos.is_check()) // Mate!
return value_mated_in(ply); return value_mated_in(ply);
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
// Update transposition table // Update transposition table
move = ss[ply].pv[ply]; Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
if (!pvNode) if (bestValue < beta)
{ {
// If bestValue isn't changed it means it is still the static evaluation of // If bestValue isn't changed it means it is still the static evaluation
// the node, so keep this info to avoid a future costly evaluation() call. // 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); 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) // Update killers only for good checking moves
TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE); if (!pos.move_is_capture_or_promotion(move))
else update_killers(move, ss[ply]);
TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move);
} }
// Update killers only for good check moves assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
if (alpha >= beta && !pos.move_is_capture_or_promotion(move))
update_killers(move, ss[ply]);
return bestValue; return bestValue;
} }