Value value_to_tt(Value v, int ply);
Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
Value value_to_tt(Value v, int ply);
Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
- void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus);
+ void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
} // namespace
void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
} // namespace
Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
// When we reach the maximum depth, we can arrive here without a raise of
Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
// When we reach the maximum depth, we can arrive here without a raise of
// the UCI protocol states that we shouldn't print the best move before the
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
// the UCI protocol states that we shouldn't print the best move before the
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
- // until the GUI sends one of those commands (which also raises Signals.stop).
- if (!Signals.stop && (Limits.ponder || Limits.infinite))
- {
- Signals.stopOnPonderhit = true;
- wait(Signals.stop);
- }
+ // until the GUI sends one of those commands (which also raises Threads.stop).
+ Threads.stopOnPonderhit = true;
+
+ while (!Threads.stop && (Threads.ponder || Limits.infinite))
+ {} // Busy wait for a stop or a ponder reset
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
multiPV = std::min(multiPV, rootMoves.size());
// Iterative deepening loop until requested to stop or the target depth is reached
multiPV = std::min(multiPV, rootMoves.size());
// Iterative deepening loop until requested to stop or the target depth is reached
- while ( (rootDepth = rootDepth + ONE_PLY) < DEPTH_MAX
- && !Signals.stop
- && (!Limits.depth || Threads.main()->rootDepth / ONE_PLY <= Limits.depth))
+ while ( (rootDepth += ONE_PLY) < DEPTH_MAX
+ && !Threads.stop
+ && !(Limits.depth && mainThread && rootDepth / ONE_PLY > Limits.depth))
// If search has been stopped, we break immediately. Sorting and
// writing PV back to TT is safe because RootMoves is still
// valid, although it refers to the previous iteration.
// If search has been stopped, we break immediately. Sorting and
// writing PV back to TT is safe because RootMoves is still
// valid, although it refers to the previous iteration.
sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
}
sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
}
// Do we have time for the next iteration? Can we stop searching now?
if (Limits.use_time_management())
{
// Do we have time for the next iteration? Can we stop searching now?
if (Limits.use_time_management())
{
{
// Stop the search if only one legal move is available, or if all
// of the available time has been used, or if we matched an easyMove
{
// Stop the search if only one legal move is available, or if all
// of the available time has been used, or if we matched an easyMove
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
Value bestValue, value, ttValue, eval;
bool ttHit, inCheck, givesCheck, singularExtensionNode, improving;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture;
Value bestValue, value, ttValue, eval;
bool ttHit, inCheck, givesCheck, singularExtensionNode, improving;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture;
int moveCount, quietCount;
// Step 1. Initialize node
int moveCount, quietCount;
// Step 1. Initialize node
assert(0 <= ss->ply && ss->ply < MAX_PLY);
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
+ update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
}
// Penalty for a quiet ttMove that fails low
else if (!pos.capture_or_promotion(ttMove))
{
int penalty = -stat_bonus(depth);
}
// Penalty for a quiet ttMove that fails low
else if (!pos.capture_or_promotion(ttMove))
{
int penalty = -stat_bonus(depth);
- thisThread->history.update(pos.side_to_move(), ttMove, penalty);
- update_cm_stats(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty);
+ thisThread->mainHistory.update(pos.side_to_move(), ttMove, penalty);
+ update_continuation_histories(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty);
Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
pos.do_null_move(st);
Value nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -beta+1)
pos.do_null_move(st);
Value nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -beta+1)
- const PieceToHistory& cmh = *(ss-1)->history;
- const PieceToHistory& fmh = *(ss-2)->history;
- const PieceToHistory& fm2 = *(ss-4)->history;
+ const PieceToHistory* contHist[] = { (ss-1)->contHistory, (ss-2)->contHistory, nullptr, (ss-4)->contHistory };
+ Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
- MovePicker mp(pos, ttMove, depth, ss);
+ MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, contHist, countermove, ss->killers);
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
improving = ss->staticEval >= (ss-2)->staticEval
/* || ss->staticEval == VALUE_NONE Already implicit in the previous condition */
value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
improving = ss->staticEval >= (ss-2)->staticEval
/* || ss->staticEval == VALUE_NONE Already implicit in the previous condition */
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
- && (cmh[moved_piece][to_sq(move)] < CounterMovePruneThreshold)
- && (fmh[moved_piece][to_sq(move)] < CounterMovePruneThreshold))
+ && (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
+ && (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
// Step 14. Make the move
pos.do_move(move, st, givesCheck);
// Step 14. Make the move
pos.do_move(move, st, givesCheck);
- ss->statScore = cmh[moved_piece][to_sq(move)]
- + fmh[moved_piece][to_sq(move)]
- + fm2[moved_piece][to_sq(move)]
- + thisThread->history[~pos.side_to_move()][from_to(move)]
- - 4000; // Correction factor
+ ss->statScore = thisThread->mainHistory[~pos.side_to_move()][from_to(move)]
+ + (*contHist[0])[movedPiece][to_sq(move)]
+ + (*contHist[1])[movedPiece][to_sq(move)]
+ + (*contHist[3])[movedPiece][to_sq(move)]
+ - 4000;
// Decrease/increase reduction by comparing opponent's stat score
if (ss->statScore > 0 && (ss-1)->statScore < 0)
// Decrease/increase reduction by comparing opponent's stat score
if (ss->statScore > 0 && (ss-1)->statScore < 0)
// Finished searching the move. If a stop occurred, the return value of
// the search cannot be trusted, and we return immediately without
// updating best move, PV and TT.
// Finished searching the move. If a stop occurred, the return value of
// the search cannot be trusted, and we return immediately without
// updating best move, PV and TT.
- // All other moves but the PV are set to the lowest value: this is
- // not a problem when sorting because the sort is stable and the
+ // All other moves but the PV are set to the lowest value: this
+ // is not a problem when sorting because the sort is stable and the
// completed. But in this case bestValue is valid because we have fully
// searched our subtree, and we can anyhow save the result in TT.
/*
// completed. But in this case bestValue is valid because we have fully
// searched our subtree, and we can anyhow save the result in TT.
/*
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
// Extra penalty for a quiet TT move in previous ply when it gets refuted
if ((ss-1)->moveCount == 1 && !pos.captured_piece())
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
+ 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
&& !pos.captured_piece()
&& is_ok((ss-1)->currentMove))
}
// Bonus for prior countermove that caused the fail low
else if ( depth >= 3 * ONE_PLY
&& !pos.captured_piece()
&& is_ok((ss-1)->currentMove))
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
+ update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
if (!excludedMove)
tte->save(posKey, value_to_tt(bestValue, ss->ply),
if (!excludedMove)
tte->save(posKey, value_to_tt(bestValue, ss->ply),
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
- MovePicker mp(pos, ttMove, depth, to_sq((ss-1)->currentMove));
+ const PieceToHistory* contHist[4] = {};
+ MovePicker mp(pos, ttMove, depth, &pos.this_thread()->mainHistory, contHist, to_sq((ss-1)->currentMove));
// Loop through the moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move()) != MOVE_NONE)
// Loop through the moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move()) != MOVE_NONE)
- // update_cm_stats() updates countermove and follow-up move history
+ // update_continuation_histories() updates histories of the move pairs formed
+ // by moves at ply -1, -2, and -4 with current move.
- void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus) {
+ void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) {
- thisThread->history.update(c, move, bonus);
- update_cm_stats(ss, pos.moved_piece(move), to_sq(move), bonus);
+ thisThread->mainHistory.update(c, move, bonus);
+ update_continuation_histories(ss, pos.moved_piece(move), to_sq(move), bonus);
- thisThread->history.update(c, quiets[i], -bonus);
- update_cm_stats(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+ thisThread->mainHistory.update(c, quiets[i], -bonus);
+ update_continuation_histories(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
return;
if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10)
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))
return;
if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10)
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))