// 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;
&& 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
// 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
+ && !( ttHit
+ && tte->depth() >= depth - 3
&& ttValue != VALUE_NONE
&& ttValue < probCutBeta))
{
}
}
- // 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
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
// Mark this node as being searched
ThreadHolding th(thisThread, posKey, ss->ply);
- // Step 12. Loop through all pseudo-legal moves until no moves remain
+ // Step 11. Loop through all pseudo-legal moves until no moves remain
// or a beta cutoff occurs.
while ((move = mp.next_move(moveCountPruning)) != MOVE_NONE)
{
// Calculate new depth for this move
newDepth = depth - 1;
- // Step 13. Pruning at shallow depth (~200 Elo)
+ // Step 12. Pruning at shallow depth (~200 Elo)
if ( !rootNode
&& pos.non_pawn_material(us)
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
}
}
- // Step 14. Extensions (~75 Elo)
+ // Step 13. Extensions (~75 Elo)
// Singular extension search (~70 Elo). If all moves but one fail low on a
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
[movedPiece]
[to_sq(move)];
- // Step 15. Make the move
+ // Step 14. Make the move
pos.do_move(move, st, givesCheck);
- // Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
+ // Step 15. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
// re-searched at full depth.
if ( depth >= 3
&& moveCount > 1 + 2 * rootNode + 2 * (PvNode && abs(bestValue) < 2)
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);
didLMR = false;
}
- // Step 17. Full depth search when LMR is skipped or fails high
+ // Step 16. Full depth search when LMR is skipped or fails high
if (doFullDepthSearch)
{
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false);
}
- // Step 18. Undo move
+ // Step 17. Undo move
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
- // Step 19. Check for a new best move
+ // Step 18. Check for a new best move
// Finished searching the move. If a stop occurred, the return value of
// the search cannot be trusted, and we return immediately without
// updating best move, PV and TT.
return VALUE_DRAW;
*/
- // Step 20. Check for mate and stalemate
+ // Step 19. Check for mate and stalemate
// All legal moves have been searched and if there are no legal moves, it
// must be a mate or a stalemate. If we are in a singular extension search then
// return a fail low score.
{
assert(type_of(move) != ENPASSANT); // Due to !pos.advanced_pawn_push
+ // moveCount pruning
+ if (moveCount > 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
[pos.moved_piece(move)]
[to_sq(move)];
+ if ( !captureOrPromotion
+ && moveCount >= abs(depth) + 1
+ && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold
+ && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold)
+ continue;
+
// Make and search the move
pos.do_move(move, st, givesCheck);
value = -qsearch<NT>(pos, ss+1, -beta, -alpha, depth - 1);