Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
- void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
- void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
+ void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietCount, int bonus);
+ void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCount, int bonus);
inline bool gives_check(const Position& pos, Move move) {
Color us = pos.side_to_move();
void Thread::search() {
- Stack stack[MAX_PLY+7], *ss = stack+4; // To reference from (ss-4) to (ss+2)
+ // To allow access to (ss-5) up to (ss+2), the stack must be oversized.
+ // The former is needed to allow update_continuation_histories(ss-1, ...),
+ // which accesses its argument at ss-4, also near the root.
+ // The latter is needed for statScores and killer initialization.
+ Stack stack[MAX_PLY+8], *ss = stack+5;
Move pv[MAX_PLY+1];
Value bestValue, alpha, beta, delta;
Move lastBestMove = MOVE_NONE;
Color us = rootPos.side_to_move();
bool failedLow;
- std::memset(ss-4, 0, 7 * sizeof(Stack));
- for (int i = 4; i > 0; i--)
+ std::memset(ss-5, 0, 8 * sizeof(Stack));
+ for (int i = 5; i > 0; i--)
(ss-i)->continuationHistory = &this->continuationHistory[NO_PIECE][0]; // Use as sentinel
ss->pv = pv;
if ( Limits.use_time_management()
&& !Threads.stop
&& !Threads.stopOnPonderhit)
+ {
+ double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
+ fallingEval = std::max(0.5, std::min(1.5, fallingEval));
+
+ // If the bestMove is stable over several iterations, reduce time accordingly
+ timeReduction = 1.0;
+ for (int i : {3, 4, 5})
+ if (lastBestMoveDepth * i < completedDepth)
+ timeReduction *= 1.25;
+
+ // Use part of the gained time from a previous stable move for the current move
+ double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
+ bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
+
+ // Stop the search if we have only one legal move, or if available time elapsed
+ if ( rootMoves.size() == 1
+ || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
{
- double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
- fallingEval = std::max(0.5, std::min(1.5, fallingEval));
-
- // If the bestMove is stable over several iterations, reduce time accordingly
- timeReduction = 1.0;
- for (int i : {3, 4, 5})
- if (lastBestMoveDepth * i < completedDepth)
- timeReduction *= 1.25;
-
- // Use part of the gained time from a previous stable move for the current move
- double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
- bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
-
- // Stop the search if we have only one legal move, or if available time elapsed
- if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
- {
- // If we are allowed to ponder do not stop the search now but
- // keep pondering until the GUI sends "ponderhit" or "stop".
- if (Threads.ponder)
- Threads.stopOnPonderhit = true;
- else
- Threads.stop = true;
- }
+ // If we are allowed to ponder do not stop the search now but
+ // keep pondering until the GUI sends "ponderhit" or "stop".
+ if (Threads.ponder)
+ Threads.stopOnPonderhit = true;
+ else
+ Threads.stop = true;
}
+ }
}
if (!mainThread)
update_quiet_stats(pos, ss, ttMove, nullptr, 0, stat_bonus(depth));
// Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
- if ( (ss-1)->moveCount == 1
- || ((ss-1)->currentMove == (ss-1)->killers[0] && (ss-1)->killers[0]))
- if (!pos.captured_piece())
+ if ( ((ss-1)->moveCount == 1 || (ss-1)->currentMove == (ss-1)->killers[0])
+ && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
}
// Penalty for a quiet ttMove that fails low
update_capture_stats(pos, bestMove, capturesSearched, captureCount, stat_bonus(depth + ONE_PLY));
// Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
- if ( (ss-1)->moveCount == 1
- || ((ss-1)->currentMove == (ss-1)->killers[0] && (ss-1)->killers[0]))
- if (!pos.captured_piece())
+ if ( ((ss-1)->moveCount == 1 || ((ss-1)->currentMove == (ss-1)->killers[0]))
+ && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
}
// Bonus for prior countermove that caused the fail low
else if ( (depth >= 3 * ONE_PLY || PvNode)
- && !pos.captured_piece()
- && is_ok((ss-1)->currentMove))
+ && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
if (PvNode)
// update_capture_stats() updates move sorting heuristics when a new capture best move is found
void update_capture_stats(const Position& pos, Move move,
- Move* captures, int captureCnt, int bonus) {
+ Move* captures, int captureCount, int bonus) {
CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory;
Piece moved_piece = pos.moved_piece(move);
captureHistory[moved_piece][to_sq(move)][captured] << bonus;
// Decrease all the other played capture moves
- for (int i = 0; i < captureCnt; ++i)
+ for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(captures[i]);
captured = type_of(pos.piece_on(to_sq(captures[i])));
// update_quiet_stats() updates move sorting heuristics when a new quiet best move is found
void update_quiet_stats(const Position& pos, Stack* ss, Move move,
- Move* quiets, int quietsCnt, int bonus) {
+ Move* quiets, int quietCount, int bonus) {
if (ss->killers[0] != move)
{
}
// Decrease all the other played quiet moves
- for (int i = 0; i < quietsCnt; ++i)
+ for (int i = 0; i < quietCount; ++i)
{
thisThread->mainHistory[us][from_to(quiets[i])] << -bonus;
update_continuation_histories(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
assert(pv.size() == 1);
- if (!pv[0])
+ if (pv[0] == MOVE_NONE)
return false;
pos.do_move(pv[0], st);