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
- // 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;
+ delta += delta / 2;
- if (abs(bestValue) >= VALUE_KNOWN_WIN)
- {
- alpha = -VALUE_INFINITE;
- beta = VALUE_INFINITE;
- }
- else if (bestValue >= beta)
- {
- beta += delta;
- delta += delta / 2;
- }
- else
+ // In case of failing low/high increase aspiration window and
+ // research, otherwise exit the loop.
+ if (bestValue <= alpha)
{
+ alpha = std::max(bestValue - delta, -VALUE_INFINITE);
+
Signals.failedLowAtRoot = true;
Signals.stopOnPonderhit = false;
-
- alpha -= delta;
- delta += delta / 2;
}
+ else if (bestValue >= beta)
+ beta = std::min(bestValue + delta, VALUE_INFINITE);
+
+ else
+ break;
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
assert(PvNode || (alpha == beta - 1));
assert(depth > DEPTH_ZERO);
- Move movesSearched[64];
+ Move quietsSearched[64];
StateInfo st;
const TTEntry *tte;
SplitPoint* splitPoint;
Value eval, nullValue, futilityValue;
bool inCheck, givesCheck, pvMove, singularExtensionNode;
bool captureOrPromotion, dangerous, doFullDepthSearch;
- int moveCount, playedMoveCount;
+ int moveCount, quietCount;
// Step 1. Initialize node
Thread* thisThread = pos.this_thread();
- moveCount = playedMoveCount = 0;
+ moveCount = quietCount = 0;
inCheck = pos.checkers();
if (SpNode)
pvMove = PvNode && moveCount == 1;
ss->currentMove = move;
- if (!SpNode && !captureOrPromotion && playedMoveCount < 64)
- movesSearched[playedMoveCount++] = move;
+ if (!SpNode && !captureOrPromotion && quietCount < 64)
+ quietsSearched[quietCount++] = move;
// Step 14. Make the move
pos.do_move(move, st, ci, givesCheck);
// If we have pruned all the moves without searching return a fail-low score
if (bestValue == -VALUE_INFINITE)
- {
- assert(!playedMoveCount);
-
bestValue = alpha;
- }
- if (bestValue >= beta) // Failed high
+ TT.store(posKey, value_to_tt(bestValue, ss->ply),
+ bestValue >= beta ? BOUND_LOWER :
+ PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
+ depth, bestMove, ss->staticEval, ss->evalMargin);
+
+ // Quiet best move: update killers, history and countermoves
+ if ( bestValue >= beta
+ && !pos.is_capture_or_promotion(bestMove)
+ && !inCheck)
{
- 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)
+ if (ss->killers[0] != bestMove)
{
- if (bestMove != ss->killers[0])
- {
- ss->killers[1] = ss->killers[0];
- ss->killers[0] = bestMove;
- }
-
- // Increase history value of the cut-off move
- Value bonus = Value(int(depth) * int(depth));
- History.update(pos.piece_moved(bestMove), to_sq(bestMove), bonus);
- if (is_ok((ss-1)->currentMove))
- Countermoves.update(pos.piece_on(prevMoveSq), prevMoveSq, bestMove);
+ ss->killers[1] = ss->killers[0];
+ ss->killers[0] = bestMove;
+ }
- // Decrease history of all the other played non-capture moves
- for (int i = 0; i < playedMoveCount - 1; i++)
- {
- Move m = movesSearched[i];
- History.update(pos.piece_moved(m), to_sq(m), -bonus);
- }
+ // Increase history value of the cut-off move and decrease all the other
+ // played non-capture moves.
+ Value bonus = Value(int(depth) * int(depth));
+ History.update(pos.piece_moved(bestMove), to_sq(bestMove), bonus);
+ for (int i = 0; i < quietCount - 1; i++)
+ {
+ Move m = quietsSearched[i];
+ History.update(pos.piece_moved(m), to_sq(m), -bonus);
}
+
+ if (is_ok((ss-1)->currentMove))
+ Countermoves.update(pos.piece_on(prevMoveSq), prevMoveSq, bestMove);
}
- 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, ss->staticEval, ss->evalMargin);
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
: DEPTH_QS_NO_CHECKS;
- // Transposition table lookup. At PV nodes, we don't use the TT for
- // pruning, but only for move ordering.
+ // Transposition table lookup
posKey = pos.key();
tte = TT.probe(posKey);
ttMove = tte ? tte->move() : MOVE_NONE;