// for match (TC 60+0.6) results spanning a wide range of k values.
PRNG rng(now());
double floatLevel = Options["UCI_LimitStrength"] ?
- Utility::clamp(std::pow((Options["UCI_Elo"] - 1346.6) / 143.4, 1 / 0.806), 0.0, 20.0) :
+ std::clamp(std::pow((Options["UCI_Elo"] - 1346.6) / 143.4, 1 / 0.806), 0.0, 20.0) :
double(Options["Skill Level"]);
int intLevel = int(floatLevel) +
((floatLevel - int(floatLevel)) * 1024 > rng.rand<unsigned>() % 1024 ? 1 : 0);
{
double fallingEval = (318 + 6 * (mainThread->bestPreviousScore - bestValue)
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
- fallingEval = Utility::clamp(fallingEval, 0.5, 1.5);
+ fallingEval = std::clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.92 : 0.95;
Key posKey;
Move ttMove, move, excludedMove, bestMove;
Depth extension, newDepth;
- Value bestValue, value, ttValue, eval, maxValue, probcutBeta;
+ Value bestValue, value, ttValue, eval, maxValue, probCutBeta;
bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
ttCapture, singularQuietLMR;
else
{
if ((ss-1)->currentMove != MOVE_NULL)
- {
- int bonus = -(ss-1)->statScore / 512;
-
- ss->staticEval = eval = evaluate(pos) + bonus;
- }
+ ss->staticEval = eval = evaluate(pos);
else
ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
&& eval <= alpha - RazorMargin)
return qsearch<NT>(pos, ss, alpha, beta);
- improving = (ss-2)->staticEval == VALUE_NONE ? (ss->staticEval > (ss-4)->staticEval
- || (ss-4)->staticEval == VALUE_NONE) : ss->staticEval > (ss-2)->staticEval;
+ improving = (ss-2)->staticEval == VALUE_NONE
+ ? ss->staticEval > (ss-4)->staticEval || (ss-4)->staticEval == VALUE_NONE
+ : ss->staticEval > (ss-2)->staticEval;
// Step 8. Futility pruning: child node (~50 Elo)
if ( !PvNode
}
}
- probcutBeta = beta + 176 - 49 * improving;
+ probCutBeta = beta + 176 - 49 * improving;
// Step 10. ProbCut (~10 Elo)
// If we have a good enough capture and a reduced search returns a value
if ( !PvNode
&& depth > 4
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY
+ // if value from transposition table is lower than probCutBeta, don't attempt probCut
+ // there and in further interactions with transposition table cutoff depth is set to depth - 3
+ // because probCut search has depth set to depth - 4 but we also do a move before it
+ // so effective depth is equal to depth - 3
&& !( ttHit
&& tte->depth() >= depth - 3
&& ttValue != VALUE_NONE
- && ttValue < probcutBeta))
+ && ttValue < probCutBeta))
{
+ // if ttMove is a capture and value from transposition table is good enough produce probCut
+ // cutoff without digging into actual probCut search
if ( ttHit
&& tte->depth() >= depth - 3
&& ttValue != VALUE_NONE
- && ttValue >= probcutBeta
+ && ttValue >= probCutBeta
&& ttMove
&& pos.capture_or_promotion(ttMove))
- return probcutBeta;
+ return probCutBeta;
- assert(probcutBeta < VALUE_INFINITE);
- MovePicker mp(pos, ttMove, probcutBeta - ss->staticEval, &captureHistory);
+ assert(probCutBeta < VALUE_INFINITE);
+ MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
int probCutCount = 0;
while ( (move = mp.next_move()) != MOVE_NONE
pos.do_move(move, st);
// Perform a preliminary qsearch to verify that the move holds
- value = -qsearch<NonPV>(pos, ss+1, -probcutBeta, -probcutBeta+1);
+ value = -qsearch<NonPV>(pos, ss+1, -probCutBeta, -probCutBeta+1);
// If the qsearch held, perform the regular search
- if (value >= probcutBeta)
- value = -search<NonPV>(pos, ss+1, -probcutBeta, -probcutBeta+1, depth - 4, !cutNode);
+ if (value >= probCutBeta)
+ value = -search<NonPV>(pos, ss+1, -probCutBeta, -probCutBeta+1, depth - 4, !cutNode);
pos.undo_move(move);
- if (value >= probcutBeta)
+ if (value >= probCutBeta)
{
+ // if transposition table doesn't have equal or more deep info write probCut data into it
if ( !(ttHit
&& tte->depth() >= depth - 3
&& ttValue != VALUE_NONE))
}
}
- // Step 11. Internal iterative deepening (~1 Elo)
- if (depth >= 7 && !ttMove)
- {
- search<NT>(pos, ss, alpha, beta, depth - 7, cutNode);
-
- tte = TT.probe(posKey, ttHit);
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
- ttMove = ttHit ? tte->move() : MOVE_NONE;
- }
+ // Step 11. If the position is not in TT, decrease depth by 2
+ if ( PvNode
+ && depth >= 6
+ && !ttMove)
+ depth -= 2;
moves_loop: // When in check, search starts from here
&& (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move)))
extension = 1;
- // Passed pawn extension
- else if ( move == ss->killers[0]
- && pos.advanced_pawn_push(move)
- && pos.pawn_passed(us, to_sq(move)))
- extension = 1;
-
// Last captures extension
else if ( PieceValue[EG][pos.captured_piece()] > PawnValueEg
&& pos.non_pawn_material() <= 2 * RookValueMg)
// Castling extension
if ( type_of(move) == CASTLING
- && popcount(pos.pieces(us) & ~pos.pieces(PAWN) & (to_sq(move) & KingSide ? KingSide : QueenSide)) <= 3)
+ && popcount(pos.pieces(us) & ~pos.pieces(PAWN) & (to_sq(move) & KingSide ? KingSide : QueenSide)) <= 2)
extension = 1;
// Late irreversible move extension
r++;
}
- Depth d = Utility::clamp(newDepth - r, 1, newDepth);
+ Depth d = std::clamp(newDepth - r, 1, newDepth);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
{
assert(type_of(move) != ENPASSANT); // Due to !pos.advanced_pawn_push
+ // moveCount pruning
+ if (moveCount > abs(depth) + 2)
+ continue;
+
futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];
if (futilityValue <= alpha)
}
// Do not search moves with negative SEE values
- if ( !ss->inCheck && !pos.see_ge(move))
+ if (!ss->inCheck && !pos.see_ge(move))
continue;
// Speculative prefetch as early as possible