ss->pv = pv;
- bestValue = delta = alpha = -VALUE_INFINITE;
- beta = VALUE_INFINITE;
- optimism[WHITE] = optimism[BLACK] = VALUE_ZERO;
+ bestValue = -VALUE_INFINITE;
if (mainThread)
{
selDepth = 0;
// Reset aspiration window starting size
- if (rootDepth >= 4)
- {
- Value prev = rootMoves[pvIdx].averageScore;
- delta = Value(10) + int(prev) * prev / 16502;
- alpha = std::max(prev - delta,-VALUE_INFINITE);
- beta = std::min(prev + delta, VALUE_INFINITE);
-
- // Adjust optimism based on root move's previousScore
- int opt = 120 * prev / (std::abs(prev) + 161);
- optimism[ us] = Value(opt);
- optimism[~us] = -optimism[us];
- }
+ Value prev = rootMoves[pvIdx].averageScore;
+ delta = Value(10) + int(prev) * prev / 16502;
+ alpha = std::max(prev - delta,-VALUE_INFINITE);
+ beta = std::min(prev + delta, VALUE_INFINITE);
+
+ // Adjust optimism based on root move's previousScore
+ int opt = 102 * prev / (std::abs(prev) + 147);
+ optimism[ us] = Value(opt);
+ optimism[~us] = -optimism[us];
// Start with a small aspiration window and, in the case of a fail
// high/low, re-search with a bigger window until we don't fail
ss->staticEval = eval = tte->eval();
if (eval == VALUE_NONE)
ss->staticEval = eval = evaluate(pos);
- else
- {
- if (PvNode)
- Eval::NNUE::hint_common_parent_position(pos);
- }
+ else if (PvNode)
+ Eval::NNUE::hint_common_parent_position(pos);
// ttValue can be used as a better position evaluation (~7 Elo)
if ( ttValue != VALUE_NONE
// Use qsearch if depth is equal or below zero (~9 Elo)
if ( PvNode
&& !ttMove)
- depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth);
+ depth -= 2 + 2 * (ss->ttHit && tte->depth() >= depth);
if (depth <= 0)
return qsearch<PV>(pos, ss, alpha, beta);
{
if (depth < 2 - capture)
continue;
- // 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;
+ // Don't prune the move if opp. King/Queen/Rook gets a discovered attack during or after the exchanges
+ Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK);
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
+ // Exclude Queen/Rook(s) which were already threatened before SEE (opp King can't be in check when it's our turn)
if (attacks && sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))
attacks = 0;
}
// Decrease reduction if position is or has been on the PV
// and node is not likely to fail low. (~3 Elo)
+ // Decrease further on cutNodes. (~1 Elo)
if ( ss->ttPv
&& !likelyFailLow)
- r -= 2;
+ r -= cutNode && tte->depth() >= depth + 3 ? 3 : 2;
// Decrease reduction if opponent's move count is high (~1 Elo)
if ((ss-1)->moveCount > 7)
if ((ss+1)->cutoffCnt > 3)
r++;
+ else if (move == ttMove)
+ r--;
+
ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)]
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
if (PvNode && !rootNode) // Update pv even in fail-high case
update_pv(ss->pv, move, (ss+1)->pv);
- if (PvNode && value < beta) // Update alpha! Always alpha < beta
+ if (value >= beta)
+ {
+ ss->cutoffCnt += 1 + !ttMove;
+ assert(value >= beta); // Fail high
+ break;
+ }
+ else
{
// Reduce other moves if we have found at least one score improvement (~1 Elo)
if ( depth > 1
depth -= 1;
assert(depth > 0);
- alpha = value;
- }
- else
- {
- ss->cutoffCnt++;
- assert(value >= beta); // Fail high
- break;
+ alpha = value; // Update alpha! Always alpha < beta
}
}
}