#include "movepick.h"
#include "position.h"
#include "search.h"
-#include "timeman.h"
#include "thread.h"
+#include "timeman.h"
#include "tt.h"
#include "uci.h"
#include "syzygy/tbprobe.h"
enum NodeType { NonPV, PV };
// Sizes and phases of the skip-blocks, used for distributing search depths across the threads
- const int SkipSize[] = { 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
- const int SkipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 };
+ constexpr int SkipSize[] = { 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
+ constexpr int SkipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 };
// Razor and futility margins
- const int RazorMargin1 = 590;
- const int RazorMargin2 = 604;
+ constexpr int RazorMargin[] = {0, 590, 604};
Value futility_margin(Depth d, bool improving) {
return Value((175 - 50 * improving) * d / ONE_PLY);
}
Reductions[PV][imp][d][mc] = std::max(Reductions[NonPV][imp][d][mc] - 1, 0);
// Increase reduction for non-PV nodes when eval is not improving
- if (!imp && Reductions[NonPV][imp][d][mc] >= 2)
+ if (!imp && r > 1.0)
Reductions[NonPV][imp][d][mc]++;
}
multiPV = std::min(multiPV, rootMoves.size());
int ct = Options["Contempt"] * PawnValueEg / 100; // From centipawns
- Eval::Contempt = (us == WHITE ? make_score(ct, ct / 2)
- : -make_score(ct, ct / 2));
+ contempt = (us == WHITE ? make_score(ct, ct / 2)
+ : -make_score(ct, ct / 2));
// Iterative deepening loop until requested to stop or the target depth is reached
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
// Reset aspiration window starting size
if (rootDepth >= 5 * ONE_PLY)
{
+ Value previousScore = rootMoves[PVIdx].previousScore;
delta = Value(18);
- alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE);
- beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE);
+ alpha = std::max(previousScore - delta,-VALUE_INFINITE);
+ beta = std::min(previousScore + delta, VALUE_INFINITE);
ct = Options["Contempt"] * PawnValueEg / 100; // From centipawns
- // Adjust contempt based on current bestValue (dynamic contempt)
- ct += int(std::round(48 * atan(float(bestValue) / 128)));
+ // Adjust contempt based on root move's previousScore (dynamic contempt)
+ ct += int(std::round(48 * atan(float(previousScore) / 128)));
- Eval::Contempt = (us == WHITE ? make_score(ct, ct / 2)
- : -make_score(ct, ct / 2));
+ contempt = (us == WHITE ? make_score(ct, ct / 2)
+ : -make_score(ct, ct / 2));
}
// Start with a small aspiration window and, in the case of a fail
timeReduction *= 1.25;
// Use part of the gained time from a previous stable move for the current move
- double unstablePvFactor = 1.0 + mainThread->bestMoveChanges;
- unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
+ double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
+ bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
// Stop the search if we have only one legal move, or if available time elapsed
if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 581)
+ || Time.elapsed() > Time.optimum() * bestMoveInstability * improvingFactor / 581)
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
if (depth < ONE_PLY)
return qsearch<NT>(pos, ss, alpha, beta);
- const bool PvNode = NT == PV;
+ constexpr bool PvNode = NT == PV;
const bool rootNode = PvNode && ss->ply == 0;
assert(-VALUE_INFINITE <= alpha && alpha < beta && beta <= VALUE_INFINITE);
// Step 7. Razoring (skipped when in check)
if ( !PvNode
- && depth <= 2 * ONE_PLY)
+ && depth < 3 * ONE_PLY
+ && eval <= alpha - RazorMargin[depth / ONE_PLY])
{
- if ( depth == ONE_PLY
- && eval + RazorMargin1 <= alpha)
- return qsearch<NonPV>(pos, ss, alpha, alpha+1);
-
- else if (eval + RazorMargin2 <= alpha)
- {
- Value ralpha = alpha - RazorMargin2;
-
- Value v = qsearch<NonPV>(pos, ss, ralpha, ralpha+1);
-
- if (v <= ralpha)
- return v;
- }
+ Value ralpha = alpha - (depth >= 2 * ONE_PLY) * RazorMargin[depth / ONE_PLY];
+ Value v = qsearch<NonPV>(pos, ss, ralpha, ralpha+1);
+ if (depth < 2 * ONE_PLY || v <= ralpha)
+ return v;
}
// Step 8. Futility pruning: child node (skipped when in check)
// Step 11. Internal iterative deepening (skipped when in check)
if ( depth >= 6 * ONE_PLY
&& !ttMove
- && (PvNode || ss->staticEval + 256 >= beta))
+ && (PvNode || ss->staticEval + 128 >= beta))
{
Depth d = 3 * depth / 4 - 2 * ONE_PLY;
search<NT>(pos, ss, alpha, beta, d, cutNode, true);
template <NodeType NT>
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {
- const bool PvNode = NT == PV;
- const bool inCheck = bool(pos.checkers());
+ constexpr bool PvNode = NT == PV;
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
assert(PvNode || (alpha == beta - 1));
Move ttMove, move, bestMove;
Depth ttDepth;
Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha;
- bool ttHit, givesCheck, evasionPrunable;
+ bool ttHit, inCheck, givesCheck, evasionPrunable;
int moveCount;
if (PvNode)
(ss+1)->ply = ss->ply + 1;
ss->currentMove = bestMove = MOVE_NONE;
+ inCheck = pos.checkers();
moveCount = 0;
// Check for an immediate draw or maximum ply reached
static TimePoint lastInfoTime = now();
- int elapsed = Time.elapsed();
+ TimePoint elapsed = Time.elapsed();
TimePoint tick = Limits.startTime + elapsed;
if (tick - lastInfoTime >= 1000)
string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
std::stringstream ss;
- int elapsed = Time.elapsed() + 1;
+ TimePoint elapsed = Time.elapsed() + 1;
const RootMoves& rootMoves = pos.this_thread()->rootMoves;
size_t PVIdx = pos.this_thread()->PVIdx;
size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());