// Depth limit for selective search:
Depth SelectiveDepth = 7*OnePly;
+ // Use dynamic LMR?
+ const bool UseDynamicLMR = false;
+
// Use internal iterative deepening?
const bool UseIIDAtPVNodes = true;
const bool UseIIDAtNonPVNodes = false;
&& !move_is_killer(move, ss[ply]))
{
// LMR dynamic reduction
- Depth R = (moveCount >= 2 * LMRNonPVMoves && depth > 7*OnePly ? 2*OnePly : OnePly);
+ Depth R = UseDynamicLMR
+ && moveCount >= 2 * LMRNonPVMoves
+ && depth > 7*OnePly ? 2*OnePly : OnePly;
ss[ply].reduction = R;
value = -search(pos, ss, -(beta-1), newDepth-R, ply+1, true, threadID);
return VALUE_DRAW;
// Transposition table lookup, only when not in PV
+ TTEntry* tte = NULL;
bool pvNode = (beta - alpha != 1);
if (!pvNode)
{
- const TTEntry* tte = TT.retrieve(pos);
+ tte = TT.retrieve(pos);
if (tte && ok_to_use_TT(tte, depth, beta, ply))
+ {
+ assert(tte->type() != VALUE_TYPE_EVAL);
+
return value_from_tt(tte->value(), ply);
+ }
}
// Evaluate the position statically
EvalInfo ei;
+ Value staticValue;
bool isCheck = pos.is_check();
- Value staticValue = (isCheck ? -VALUE_INFINITE : evaluate(pos, ei, threadID));
+
+ if (isCheck)
+ staticValue = -VALUE_INFINITE;
+
+ else if (tte && tte->type() == VALUE_TYPE_EVAL)
+ {
+ // Use the cached evaluation score if possible
+ assert(tte->value() == evaluate(pos, ei, threadID));
+ assert(ei.futilityMargin == Value(0));
+
+ staticValue = tte->value();
+ ei.futilityMargin = Value(0); // manually initialize futilityMargin
+ }
+ else
+ staticValue = evaluate(pos, ei, threadID);
if (ply == PLY_MAX - 1)
return evaluate(pos, ei, threadID);
Value bestValue = staticValue;
if (bestValue >= beta)
+ {
+ // Store the score to avoid a future costly evaluation() call
+ if (!isCheck && !tte && ei.futilityMargin == 0)
+ TT.store(pos, value_to_tt(bestValue, ply), Depth(-127*OnePly), MOVE_NONE, VALUE_TYPE_EVAL);
+
return bestValue;
+ }
if (bestValue > alpha)
alpha = bestValue;
// Initialize a MovePicker object for the current position, and prepare
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth == 0) will be generated.
- MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth, isCheck ? NULL : &ei);
+ MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth);
Move move;
int moveCount = 0;
Bitboard dcCandidates = mp.discovered_check_candidates();
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
// Update transposition table
- TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_EXACT);
+ if (!pvNode)
+ {
+ Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
+ if (bestValue < beta)
+ TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_UPPER);
+ else
+ TT.store(pos, value_to_tt(bestValue, ply), d, MOVE_NONE, VALUE_TYPE_LOWER);
+ }
// Update killers only for good check moves
Move m = ss[ply].currentMove;
|| ( !FailHigh && !fail_high_ply_1() && !Problem
&& t > 6*(MaxSearchTime + ExtraSearchTime));
- if ( (Iteration >= 2 && (!InfiniteSearch && overTime))
+ if ( (Iteration >= 3 && (!InfiniteSearch && overTime))
|| (ExactMaxTime && t >= ExactMaxTime)
|| (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
AbortSearch = true;
void ponderhit() {
int t = current_search_time();
PonderSearch = false;
- if(Iteration >= 2 &&
+ if(Iteration >= 3 &&
(!InfiniteSearch && (StopOnPonderhit ||
t > AbsoluteMaxSearchTime ||
(RootMoveNumber == 1 &&