size_t Search::perft(Position& pos, Depth depth) {
- // At the last ply just return the number of legal moves (leaf nodes)
- if (depth == ONE_PLY)
- return MoveList<LEGAL>(pos).size();
-
StateInfo st;
size_t cnt = 0;
CheckInfo ci(pos);
+ const bool leaf = depth == 2 * ONE_PLY;
for (MoveList<LEGAL> it(pos); *it; ++it)
{
pos.do_move(*it, st, ci, pos.move_gives_check(*it, ci));
- cnt += perft(pos, depth - ONE_PLY);
+ cnt += leaf ? MoveList<LEGAL>(pos).size() : perft(pos, depth - ONE_PLY);
pos.undo_move(*it);
}
-
return cnt;
}
Value bestValue, alpha, beta, delta;
memset(ss-1, 0, 4 * sizeof(Stack));
- depth = BestMoveChanges = 0;
- bestValue = delta = -VALUE_INFINITE;
(ss-1)->currentMove = MOVE_NULL; // Hack to skip update gains
+
+ depth = BestMoveChanges = 0;
+ bestValue = delta = alpha = -VALUE_INFINITE;
+ beta = VALUE_INFINITE;
+
TT.new_search();
History.clear();
Gains.clear();
// MultiPV loop. We perform a full root search for each PV line
for (PVIdx = 0; PVIdx < PVSize; PVIdx++)
{
- // Set aspiration window default width
- if (depth >= 5 && abs(RootMoves[PVIdx].prevScore) < VALUE_KNOWN_WIN)
+ // Reset aspiration window starting size
+ if (depth >= 5)
{
delta = Value(16);
- alpha = RootMoves[PVIdx].prevScore - delta;
- beta = RootMoves[PVIdx].prevScore + delta;
- }
- else
- {
- alpha = -VALUE_INFINITE;
- beta = VALUE_INFINITE;
+ alpha = std::max(RootMoves[PVIdx].prevScore - delta,-VALUE_INFINITE);
+ beta = std::min(RootMoves[PVIdx].prevScore + delta, VALUE_INFINITE);
}
// Start with a small aspiration window and, in case of fail high/low,
if (Signals.stop)
return;
- // In case of failing high/low increase aspiration window and
+ // In case of failing low/high increase aspiration window and
// research, otherwise exit the loop.
- if (bestValue > alpha && bestValue < beta)
- break;
-
- // Give some update (without cluttering the UI) before to research
- if (Time::now() - SearchTime > 3000)
- sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
-
- if (abs(bestValue) >= VALUE_KNOWN_WIN)
+ if (bestValue <= alpha)
{
- alpha = -VALUE_INFINITE;
- beta = VALUE_INFINITE;
+ alpha = std::max(bestValue - delta, -VALUE_INFINITE);
+
+ Signals.failedLowAtRoot = true;
+ Signals.stopOnPonderhit = false;
}
else if (bestValue >= beta)
- {
- beta += delta;
- delta += delta / 2;
- }
+ beta = std::min(bestValue + delta, VALUE_INFINITE);
+
else
- {
- Signals.failedLowAtRoot = true;
- Signals.stopOnPonderhit = false;
+ break;
- alpha -= delta;
- delta += delta / 2;
- }
+ delta += delta / 2;
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+
+ // Give some update (without cluttering the UI) before to research
+ if (Time::now() - SearchTime > 3000)
+ sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
}
// Sort the PV lines searched so far and update the GUI
&& tte
&& tte->depth() >= depth
&& ttValue != VALUE_NONE // Only in case of TT access race
- && ( PvNode ? tte->type() == BOUND_EXACT
- : ttValue >= beta ? (tte->type() & BOUND_LOWER)
- : (tte->type() & BOUND_UPPER)))
+ && ( PvNode ? tte->bound() == BOUND_EXACT
+ : ttValue >= beta ? (tte->bound() & BOUND_LOWER)
+ : (tte->bound() & BOUND_UPPER)))
{
TT.refresh(tte);
ss->currentMove = ttMove; // Can be MOVE_NONE
// Can ttValue be used as a better position evaluation?
if (ttValue != VALUE_NONE)
- if ( ((tte->type() & BOUND_LOWER) && ttValue > eval)
- || ((tte->type() & BOUND_UPPER) && ttValue < eval))
+ if ( ((tte->bound() & BOUND_LOWER) && ttValue > eval)
+ || ((tte->bound() & BOUND_UPPER) && ttValue < eval))
eval = ttValue;
}
else
&& depth >= (PvNode ? 6 * ONE_PLY : 8 * ONE_PLY)
&& ttMove != MOVE_NONE
&& !excludedMove // Recursive singular search is not allowed
- && (tte->type() & BOUND_LOWER)
+ && (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3 * ONE_PLY;
// Step 11. Loop through moves
if ( tte
&& tte->depth() >= ttDepth
&& ttValue != VALUE_NONE // Only in case of TT access race
- && ( PvNode ? tte->type() == BOUND_EXACT
- : ttValue >= beta ? (tte->type() & BOUND_LOWER)
- : (tte->type() & BOUND_UPPER)))
+ && ( PvNode ? tte->bound() == BOUND_EXACT
+ : ttValue >= beta ? (tte->bound() & BOUND_LOWER)
+ : (tte->bound() & BOUND_UPPER)))
{
ss->currentMove = ttMove; // Can be MOVE_NONE
return ttValue;
void RootMove::extract_pv_from_tt(Position& pos) {
StateInfo state[MAX_PLY_PLUS_2], *st = state;
- TTEntry* tte;
+ const TTEntry* tte;
int ply = 0;
Move m = pv[0];
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY_PLUS_2], *st = state;
- TTEntry* tte;
+ const TTEntry* tte;
int ply = 0;
do {