Depth depth, int ply, int threadID);
void sp_search(SplitPoint *sp, int threadID);
void sp_search_pv(SplitPoint *sp, int threadID);
- void init_node(const Position &pos, SearchStack ss[], int ply, int threadID);
+ void init_node(SearchStack ss[], int ply, int threadID);
void update_pv(SearchStack ss[], int ply);
void sp_update_pv(SearchStack *pss, SearchStack ss[], int ply);
bool connected_moves(const Position &pos, Move m1, Move m2);
// Initialize, and make an early exit in case of an aborted search,
// an instant draw, maximum ply reached, etc.
- init_node(pos, ss, ply, threadID);
+ init_node(ss, ply, threadID);
// After init_node() that calls poll()
if (AbortSearch || thread_should_stop(threadID))
// Initialize, and make an early exit in case of an aborted search,
// an instant draw, maximum ply reached, etc.
- init_node(pos, ss, ply, threadID);
+ init_node(ss, ply, threadID);
// After init_node() that calls poll()
if (AbortSearch || thread_should_stop(threadID))
// Initialize, and make an early exit in case of an aborted search,
// an instant draw, maximum ply reached, etc.
- init_node(pos, ss, ply, threadID);
+ init_node(ss, ply, threadID);
// After init_node() that calls poll()
if (AbortSearch || thread_should_stop(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));
+ ei.futilityMargin = Value(0); // Manually initialize futilityMargin
+
+ 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();
+ }
+ else
+ staticValue = evaluate(pos, ei, threadID);
if (ply == PLY_MAX - 1)
return evaluate(pos, ei, threadID);
if (bestValue >= beta)
{
- // Update transposition table before to leave
- TT.store(pos, value_to_tt(bestValue, ply), depth, MOVE_NONE, VALUE_TYPE_EXACT);
+ // 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;
}
// 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
+ 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;
if (alpha >= beta && ok_to_history(pos, m)) // Only non capture moves are considered
// NodesBetweenPolls nodes, init_node() also calls poll(), which polls
// for user input and checks whether it is time to stop the search.
- void init_node(const Position &pos, SearchStack ss[], int ply, int threadID) {
+ void init_node(SearchStack ss[], int ply, int threadID) {
assert(ply >= 0 && ply < PLY_MAX);
assert(threadID >= 0 && threadID < ActiveThreads);