goto finalize;
}
- if (Options["OwnBook"] && !Limits.infinite)
+ if (Options["OwnBook"] && !Limits.infinite && !Limits.mate)
{
Move bookMove = book.probe(RootPos, Options["Book File"], Options["Best Book Move"]);
if (depth > 2 && BestMoveChanges)
bestMoveNeverChanged = false;
+ // Do we have found a "mate in x"?
+ if ( Limits.mate
+ && bestValue >= VALUE_MATE_IN_MAX_PLY
+ && VALUE_MATE - bestValue <= 2 * Limits.mate)
+ Signals.stop = true;
+
// Do we have time for the next iteration? Can we stop searching now?
if (Limits.use_time_management() && !Signals.stopOnPonderhit)
{
// Step 5. Evaluate the position statically and update parent's gain statistics
if (inCheck)
ss->staticEval = ss->evalMargin = eval = VALUE_NONE;
- else
+
+ else if (tte)
{
- eval = ss->staticEval = evaluate(pos, ss->evalMargin);
+ // Following asserts are valid only in single thread condition because
+ // TT access is always racy and its contents cannot be trusted.
+ assert(tte->static_value() != VALUE_NONE || Threads.size() > 1);
+ assert(ttValue != VALUE_NONE || tte->type() == BOUND_NONE || Threads.size() > 1);
+
+ ss->staticEval = eval = tte->static_value();
+ ss->evalMargin = tte->static_value_margin();
+
+ if (eval == VALUE_NONE || ss->evalMargin == VALUE_NONE) // Due to a race
+ eval = ss->staticEval = evaluate(pos, ss->evalMargin);
// Can ttValue be used as a better position evaluation?
- if (tte && ttValue != VALUE_NONE)
- {
+ if (ttValue != VALUE_NONE)
if ( ((tte->type() & BOUND_LOWER) && ttValue > eval)
|| ((tte->type() & BOUND_UPPER) && ttValue < eval))
eval = ttValue;
- }
+ }
+ else
+ {
+ eval = ss->staticEval = evaluate(pos, ss->evalMargin);
+ TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
+ ss->staticEval, ss->evalMargin);
}
+ // Handling of UCI command 'mate in x moves'. We simply return if after
+ // 'x' moves we still have not checkmated the opponent.
+ if (PvNode && !RootNode && !inCheck && Limits.mate && ss->ply > 2 * Limits.mate)
+ return eval;
+
// 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
if (bestValue >= beta) // Failed high
{
- TT.store(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, depth, bestMove);
+ TT.store(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, depth,
+ bestMove, ss->staticEval, ss->evalMargin);
if (!pos.is_capture_or_promotion(bestMove) && !inCheck)
{
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);
+ depth, bestMove, ss->staticEval, ss->evalMargin);
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
ss->staticEval = bestValue = -(ss-1)->staticEval;
ss->evalMargin = VALUE_ZERO;
}
+ else if (tte)
+ {
+ assert(tte->static_value() != VALUE_NONE || Threads.size() > 1);
+
+ ss->staticEval = bestValue = tte->static_value();
+ ss->evalMargin = tte->static_value_margin();
+
+ if (ss->staticEval == VALUE_NONE || ss->evalMargin == VALUE_NONE) // Due to a race
+ ss->staticEval = bestValue = evaluate(pos, ss->evalMargin);
+ }
else
ss->staticEval = bestValue = evaluate(pos, ss->evalMargin);
if (bestValue >= beta)
{
if (!tte)
- TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, DEPTH_NONE, MOVE_NONE);
+ TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER,
+ DEPTH_NONE, MOVE_NONE, ss->staticEval, ss->evalMargin);
return bestValue;
}
}
else // Fail high
{
- TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER, ttDepth, move);
+ TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER,
+ ttDepth, move, ss->staticEval, ss->evalMargin);
+
return value;
}
}
TT.store(posKey, value_to_tt(bestValue, ss->ply),
PvNode && bestValue > oldAlpha ? BOUND_EXACT : BOUND_UPPER,
- ttDepth, bestMove);
+ ttDepth, bestMove, ss->staticEval, ss->evalMargin);
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
tte = TT.probe(pos.key());
if (!tte || tte->move() != pv[ply]) // Don't overwrite correct entries
- TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply]);
+ TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply], VALUE_NONE, VALUE_NONE);
assert(MoveList<LEGAL>(pos).contains(pv[ply]));