Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
int r = Reductions[d] * Reductions[mn];
- return (r + 1449 - int(delta) * 1032 / int(rootDelta)) / 1024 + (!i && r > 941);
+ return (r + 1449 - int(delta) * 937 / int(rootDelta)) / 1024 + (!i && r > 941);
}
constexpr int futility_move_count(bool improving, Depth depth) {
// History and stats update bonus, based on depth
int stat_bonus(Depth d) {
- return std::min(340 * d - 470, 1855);
+ return std::min(341 * d - 470, 1710);
}
// Add a small random component to draw evaluations to avoid 3-fold blindness
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
+ optimism[WHITE] = optimism[BLACK] = VALUE_ZERO;
if (mainThread)
{
+
+ if (!rootPos.checkers())
+ {
+ int rootComplexity;
+ Eval::evaluate(rootPos, &rootComplexity);
+ mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45);
+ }
+
if (mainThread->bestPreviousScore == VALUE_INFINITE)
for (int i = 0; i < 4; ++i)
mainThread->iterValue[i] = VALUE_ZERO;
multiPV = std::min(multiPV, rootMoves.size());
- complexityAverage.set(153, 1);
-
- optimism[us] = optimism[~us] = VALUE_ZERO;
-
int searchAgainCounter = 0;
// Iterative deepening loop until requested to stop or the target depth is reached
timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.57 : 0.65;
double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction);
double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size();
- int complexity = mainThread->complexityAverage.value();
- double complexPosition = std::min(1.03 + (complexity - 241) / 1552.0, 1.45);
- double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition;
+ double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * mainThread->complexity;
// Cap used time in case of a single legal move for a better viewer experience in tournaments
// yielding correct scores and sufficiently fast moves.
(ss+2)->cutoffCnt = 0;
ss->doubleExtensions = (ss-1)->doubleExtensions;
Square prevSq = is_ok((ss-1)->currentMove) ? to_sq((ss-1)->currentMove) : SQ_NONE;
-
- // Initialize statScore to zero for the grandchildren of the current position.
- // So statScore is shared between all grandchildren and only the first grandchild
- // starts with statScore = 0. Later grandchildren start with the last calculated
- // statScore of the previous grandchild. This influences the reduction rules in
- // LMR which are based on the statScore of parent position.
- if (!rootNode)
- (ss+2)->statScore = 0;
+ ss->statScore = 0;
// Step 4. Transposition table lookup.
excludedMove = ss->excludedMove;
tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
}
- thisThread->complexityAverage.update(complexity);
-
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
{
// Step 7. Razoring (~1 Elo).
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
// return a fail low.
- if (eval < alpha - 426 - 252 * depth * depth)
+ if (eval < alpha - 426 - 256 * depth * depth)
{
value = qsearch<NonPV>(pos, ss, alpha - 1, alpha);
if (value < alpha)
&& (ss-1)->statScore < 18755
&& eval >= beta
&& eval >= ss->staticEval
- && ss->staticEval >= beta - 19 * depth - improvement / 13 + 253 + complexity / 25
+ && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + complexity / 25
&& !excludedMove
&& pos.non_pawn_material(us)
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
assert(eval - beta >= 0);
// Null move dynamic reduction based on depth, eval and complexity of position
- Depth R = std::min(int(eval - beta) / 168, 6) + depth / 3 + 4 - (complexity > 825);
+ Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4 - (complexity > 825);
ss->currentMove = MOVE_NULL;
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
Eval::NNUE::hint_common_parent_position(pos);
}
- // Step 11. If the position is not in TT, decrease depth by 3.
+ // Step 11. If the position is not in TT, decrease depth by 2 (or by 4 if the TT entry for the current position was hit and the stored depth is greater than or equal to the current depth).
// Use qsearch if depth is equal or below zero (~9 Elo)
if ( PvNode
&& !ttMove)
- depth -= 3;
+ depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth);
if (depth <= 0)
return qsearch<PV>(pos, ss, alpha, beta);
{
// Futility pruning for captures (~2 Elo)
if ( !givesCheck
- && !PvNode
&& lmrDepth < 6
&& !ss->inCheck
&& ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
lmrDepth = std::max(lmrDepth, 0);
- Bitboard occupied;
// Prune moves with negative SEE (~4 Elo)
- if (!pos.see_ge(move, occupied, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
+ if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 16 * lmrDepth)))
continue;
}
}
if (singularQuietLMR)
r--;
- // Decrease reduction if we move a threatened piece (~1 Elo)
- if ( depth > 9
- && (mp.threatenedPieces & from_sq(move)))
- r--;
-
// Increase reduction if next ply has a lot of fail high (~5 Elo)
if ((ss+1)->cutoffCnt > 3)
r++;
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
+ (*contHist[3])[movedPiece][to_sq(move)]
- - 4182;
+ - 4082;
// Decrease/increase reduction for moves with a good/bad history (~25 Elo)
- r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19));
+ r -= ss->statScore / (11079 + 4626 * (depth > 6 && depth < 19));
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
// We use various heuristics for the sons of a node after the first son has
(ss+1)->pv[0] = MOVE_NONE;
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false);
+
+ if (moveCount > 1 && newDepth >= depth && !capture)
+ update_continuation_histories(ss, movedPiece, to_sq(move), -stat_bonus(newDepth));
}
// Step 19. Undo move
if (PvNode && value < beta) // Update alpha! Always alpha < beta
{
- alpha = value;
// Reduce other moves if we have found at least one score improvement (~1 Elo)
if ( depth > 1
- && depth < 6
- && beta < 10534
- && alpha > -10534)
- depth -= 1;
+ && ((improving && complexity > 971) || (value < (5 * alpha + 75 * beta) / 87) || depth < 6)
+ && beta < 12535
+ && value > -12535) {
+ bool extraReduction = depth > 2 && alpha > -12535 && bestValue != -VALUE_INFINITE && (value - bestValue) > (7 * (beta - alpha)) / 8;
+ depth -= 1 + extraReduction;
+ }
assert(depth > 0);
+ alpha = value;
}
else
{
prevSq);
int quietCheckEvasions = 0;
- Bitboard occupied;
// Step 5. Loop through all pseudo-legal moves until no moves remain
// or a beta cutoff occurs.
continue;
}
- if (futilityBase <= alpha && !pos.see_ge(move, occupied, VALUE_ZERO + 1))
+ if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
{
bestValue = std::max(bestValue, futilityBase);
continue;
continue;
// Do not search moves with bad enough SEE values (~5 Elo)
- if (!pos.see_ge(move, occupied, Value(-110)))
+ if (!pos.see_ge(move, Value(-110)))
continue;
}