Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
int r = Reductions[d] * Reductions[mn];
- return (r + 1449 - int(delta) * 1001 / 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(341 * 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[us] = optimism[~us] = VALUE_ZERO;
+ optimism[WHITE] = optimism[BLACK] = VALUE_ZERO;
if (mainThread)
{
- int rootComplexity;
- Eval::evaluate(rootPos, &rootComplexity);
-
- mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45);
+ 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)
// 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];
{
if (depth < 2 - capture)
continue;
- // don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges
- Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & occupied;
+ // Don't prune the move if opp. King/Queen/Rook is attacked by a slider after the exchanges.
+ // Since in see_ge we don't update occupied when the king recaptures, we also don't prune the
+ // move when the opp. King gets a discovered slider attack DURING the exchanges.
+ Bitboard leftEnemies = pos.pieces(~us, ROOK, QUEEN, KING) & occupied;
Bitboard attacks = 0;
occupied |= to_sq(move);
while (leftEnemies && !attacks)
{
Square sq = pop_lsb(leftEnemies);
- attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied;
- // exclude Queen/Rook(s) which were already threatened before SEE
- if (attacks && (sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))))
+ attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied;
+ // Exclude Queen/Rook(s) which were already threatened before SEE
+ if (attacks && sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))
attacks = 0;
}
if (!attacks)
(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)
+ && ( (improving && complexity > 971)
+ || value < (5 * alpha + 75 * beta) / 87
+ || depth < 6)
+ && beta < 12535
+ && value > -12535)
depth -= 1;
assert(depth > 0);
+ alpha = value;
}
else
{