&& (ss-1)->statScore < 17329
&& eval >= beta
&& eval >= ss->staticEval
- && ss->staticEval >= beta - 21 * depth - improvement / 13 + 258
+ && ss->staticEval >= beta - 21 * depth + 258
&& !excludedMove
&& pos.non_pawn_material(us)
- && (ss->ply >= thisThread->nmpMinPly))
+ && ss->ply >= thisThread->nmpMinPly
+ && beta > VALUE_TB_LOSS_IN_MAX_PLY)
{
assert(eval - beta >= 0);
if (nullValue >= beta)
{
// Do not return unproven mate or TB scores
- if (nullValue >= VALUE_TB_WIN_IN_MAX_PLY)
- nullValue = beta;
+ nullValue = std::min(nullValue, VALUE_TB_WIN_IN_MAX_PLY-1);
- if (thisThread->nmpMinPly || (abs(beta) < VALUE_KNOWN_WIN && depth < 14))
+ if (thisThread->nmpMinPly || depth < 14)
return nullValue;
assert(!thisThread->nmpMinPly); // Recursive verification is not allowed
else if (ttValue >= beta)
extension = -2 - !PvNode;
+ // If we are on a cutNode, reduce it based on depth (negative extension) (~1 Elo)
+ else if (cutNode)
+ extension = depth > 8 && depth < 17 ? -3 : -1;
+
// If the eval of ttMove is less than value, we reduce it (negative extension) (~1 Elo)
else if (ttValue <= value)
extension = -1;
// Step 4. Static evaluation of the position
if (ss->inCheck)
- {
- ss->staticEval = VALUE_NONE;
bestValue = futilityBase = -VALUE_INFINITE;
- }
else
{
if (ss->ttHit)
}
else
// In case of null move search use previous static eval with a different sign
- ss->staticEval = bestValue =
- (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
- : -(ss-1)->staticEval;
+ ss->staticEval = bestValue = (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
+ : -(ss-1)->staticEval;
// Stand pat. Return immediately if static value is at least beta
if (bestValue >= beta)
// or a beta cutoff occurs.
while ((move = mp.next_move()) != MOVE_NONE)
{
- assert(is_ok(move));
-
- // Check for legality
- if (!pos.legal(move))
- continue;
+ assert(is_ok(move));
- givesCheck = pos.gives_check(move);
- capture = pos.capture_stage(move);
+ // Check for legality
+ if (!pos.legal(move))
+ continue;
- moveCount++;
+ givesCheck = pos.gives_check(move);
+ capture = pos.capture_stage(move);
- // Step 6. Pruning.
- if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
- {
- // Futility pruning and moveCount pruning (~10 Elo)
- if ( !givesCheck
- && to_sq(move) != prevSq
- && futilityBase > -VALUE_KNOWN_WIN
- && type_of(move) != PROMOTION)
- {
- if (moveCount > 2)
- continue;
+ moveCount++;
- futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];
-
- if (futilityValue <= alpha)
- {
- bestValue = std::max(bestValue, futilityValue);
- continue;
- }
+ // Step 6. Pruning.
+ if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
+ {
+ // Futility pruning and moveCount pruning (~10 Elo)
+ if ( !givesCheck
+ && to_sq(move) != prevSq
+ && futilityBase > -VALUE_KNOWN_WIN
+ && type_of(move) != PROMOTION)
+ {
+ if (moveCount > 2)
+ continue;
- if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
- {
- bestValue = std::max(bestValue, futilityBase);
- continue;
- }
- }
+ futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];
- // We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter
- // and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead.
- if (quietCheckEvasions > 1)
- break;
+ if (futilityValue <= alpha)
+ {
+ bestValue = std::max(bestValue, futilityValue);
+ continue;
+ }
- // Continuation history based pruning (~3 Elo)
- if ( !capture
- && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0
- && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0)
- continue;
+ if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
+ {
+ bestValue = std::max(bestValue, futilityBase);
+ continue;
+ }
+ }
- // Do not search moves with bad enough SEE values (~5 Elo)
- if (!pos.see_ge(move, Value(-95)))
- continue;
- }
+ // We prune after the second quiet check evasion move, where being 'in check' is
+ // implicitly checked through the counter, and being a 'quiet move' apart from
+ // being a tt move is assumed after an increment because captures are pushed ahead.
+ if (quietCheckEvasions > 1)
+ break;
+
+ // Continuation history based pruning (~3 Elo)
+ if ( !capture
+ && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0
+ && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0)
+ continue;
+
+ // Do not search moves with bad enough SEE values (~5 Elo)
+ if (!pos.see_ge(move, Value(-95)))
+ continue;
+ }
- // Speculative prefetch as early as possible
- prefetch(TT.first_entry(pos.key_after(move)));
+ // Speculative prefetch as early as possible
+ prefetch(TT.first_entry(pos.key_after(move)));
- // Update the current move
- ss->currentMove = move;
- ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck]
- [capture]
- [pos.moved_piece(move)]
- [to_sq(move)];
+ // Update the current move
+ ss->currentMove = move;
+ ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck]
+ [capture]
+ [pos.moved_piece(move)]
+ [to_sq(move)];
- quietCheckEvasions += !capture && ss->inCheck;
+ quietCheckEvasions += !capture && ss->inCheck;
- // Step 7. Make and search the move
- pos.do_move(move, st, givesCheck);
- value = -qsearch<nodeType>(pos, ss+1, -beta, -alpha, depth - 1);
- pos.undo_move(move);
+ // Step 7. Make and search the move
+ pos.do_move(move, st, givesCheck);
+ value = -qsearch<nodeType>(pos, ss+1, -beta, -alpha, depth - 1);
+ pos.undo_move(move);
- assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
+ assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
- // Step 8. Check for a new best move
- if (value > bestValue)
- {
- bestValue = value;
+ // Step 8. Check for a new best move
+ if (value > bestValue)
+ {
+ bestValue = value;
- if (value > alpha)
- {
- bestMove = move;
+ if (value > alpha)
+ {
+ bestMove = move;
- if (PvNode) // Update pv even in fail-high case
- update_pv(ss->pv, move, (ss+1)->pv);
+ if (PvNode) // Update pv even in fail-high case
+ update_pv(ss->pv, move, (ss+1)->pv);
- if (PvNode && value < beta) // Update alpha here!
- alpha = value;
- else
- break; // Fail high
- }
- }
+ if (PvNode && value < beta) // Update alpha here!
+ alpha = value;
+ else
+ break; // Fail high
+ }
+ }
}
// Step 9. Check for mate