}
-/// Search::clear() resets search state to zero, to obtain reproducible results
+/// Search::clear() resets search state to its initial value, to obtain reproducible results
void Search::clear() {
th->history.clear();
th->counterMoveHistory.clear();
th->resetCalls = true;
+
CounterMoveStats& cm = th->counterMoveHistory[NO_PIECE][0];
- int* t = &cm[NO_PIECE][0];
- std::fill(t, t + sizeof(cm), CounterMovePruneThreshold - 1);
+ auto* t = &cm[NO_PIECE][0];
+ std::fill(t, t + sizeof(cm)/sizeof(*t), CounterMovePruneThreshold - 1);
}
Threads.main()->previousScore = VALUE_INFINITE;
// Step 1. Initialize node
Thread* thisThread = pos.this_thread();
inCheck = pos.checkers();
- moveCount = quietCount = ss->moveCount = 0;
+ moveCount = quietCount = ss->moveCount = 0;
ss->history = 0;
bestValue = -VALUE_INFINITE;
ss->ply = (ss-1)->ply + 1;
}
else if ( givesCheck
&& !moveCountPruning
- && pos.see_ge(move, VALUE_ZERO))
+ && pos.see_ge(move))
extension = ONE_PLY;
// Calculate new depth for this move
// Decrease reduction for moves that escape a capture. Filter out
// castling moves, because they are coded as "king captures rook" and
// hence break make_move().
- else if ( type_of(move) == NORMAL
- && !pos.see_ge(make_move(to_sq(move), from_sq(move)), VALUE_ZERO))
+ else if ( type_of(move) == NORMAL
+ && !pos.see_ge(make_move(to_sq(move), from_sq(move))))
r -= 2 * ONE_PLY;
ss->history = cmh[moved_piece][to_sq(move)]
: inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()];
else if (bestMove)
{
-
// Quiet best move: update move sorting heuristics
if (!pos.capture_or_promotion(bestMove))
update_stats(pos, ss, bestMove, quietsSearched, quietCount, stat_bonus(depth));
Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha;
bool ttHit, givesCheck, evasionPrunable;
Depth ttDepth;
+ int moveCount;
if (PvNode)
{
ss->currentMove = bestMove = MOVE_NONE;
ss->ply = (ss-1)->ply + 1;
+ moveCount = 0;
// Check for an instant draw or if the maximum ply has been reached
if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
: pos.gives_check(move);
+ moveCount++;
+
// Futility pruning
if ( !InCheck
&& !givesCheck
// Detect non-capture evasions that are candidates to be pruned
evasionPrunable = InCheck
- && depth != DEPTH_ZERO
+ && (depth != DEPTH_ZERO || moveCount > 2)
&& bestValue > VALUE_MATED_IN_MAX_PLY
&& !pos.capture(move);
// Don't search moves with negative SEE values
if ( (!InCheck || evasionPrunable)
&& type_of(move) != PROMOTION
- && !pos.see_ge(move, VALUE_ZERO))
+ && !pos.see_ge(move))
continue;
// Speculative prefetch as early as possible
// Check for legality just before making the move
if (!pos.legal(move))
+ {
+ moveCount--;
continue;
+ }
ss->currentMove = move;
for (size_t i = 0; i < multiPV; ++i)
{
- bool updated = (i <= PVIdx);
+ bool updated = (i <= PVIdx && rootMoves[i].score != -VALUE_INFINITE);
if (depth == ONE_PLY && !updated)
continue;