diff --git a/src/evaluate.cpp b/src/evaluate.cpp index b6342f18..bda7132a 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -148,7 +148,7 @@ void NNUE::verify() { // Returns a static, purely materialistic evaluation of the position from // the point of view of the given color. It can be divided by PawnValue to get // an approximation of the material advantage on the board in terms of pawns. -Value Eval::simple_eval(const Position& pos, Color c) { +int Eval::simple_eval(const Position& pos, Color c) { return PawnValue * (pos.count(c) - pos.count(~c)) + (pos.non_pawn_material(c) - pos.non_pawn_material(~c)); } @@ -160,7 +160,7 @@ Value Eval::evaluate(const Position& pos) { assert(!pos.checkers()); - Value v; + int v; Color stm = pos.side_to_move(); int shuffling = pos.rule50_count(); int simpleEval = simple_eval(pos, stm) + (int(pos.key() & 7) - 3); @@ -170,13 +170,13 @@ Value Eval::evaluate(const Position& pos) { + std::abs(pos.this_thread()->rootSimpleEval); if (lazy) - v = Value(simpleEval); + v = simpleEval; else { int nnueComplexity; Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); - Value optimism = pos.this_thread()->optimism[stm]; + int optimism = pos.this_thread()->optimism[stm]; // Blend optimism and eval with nnue complexity and material imbalance optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512; @@ -190,7 +190,7 @@ Value Eval::evaluate(const Position& pos) { v = v * (200 - shuffling) / 214; // Guarantee evaluation does not hit the tablebase range - v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); + v = std::clamp(int(v), VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); return v; } diff --git a/src/evaluate.h b/src/evaluate.h index c2b08aaf..0a7ec61a 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -31,7 +31,7 @@ namespace Eval { std::string trace(Position& pos); -Value simple_eval(const Position& pos, Color c); +int simple_eval(const Position& pos, Color c); Value evaluate(const Position& pos); extern std::string currentEvalFileName; diff --git a/src/movepick.cpp b/src/movepick.cpp index cae01891..14b6c87a 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -127,7 +127,7 @@ MovePicker::MovePicker(const Position& p, // Constructor for ProbCut: we generate captures with SEE greater // than or equal to the given threshold. -MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph) : +MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceToHistory* cph) : pos(p), captureHistory(cph), ttMove(ttm), @@ -211,8 +211,8 @@ void MovePicker::score() { else // Type == EVASIONS { if (pos.capture_stage(m)) - m.value = PieceValue[pos.piece_on(m.to_sq())] - Value(type_of(pos.moved_piece(m))) - + (1 << 28); + m.value = + PieceValue[pos.piece_on(m.to_sq())] - type_of(pos.moved_piece(m)) + (1 << 28); else m.value = (*mainHistory)[pos.side_to_move()][m.from_to()] + (*continuationHistory[0])[pos.moved_piece(m)][m.to_sq()] @@ -268,8 +268,7 @@ top: case GOOD_CAPTURE : if (select([&]() { // Move losing capture to endBadCaptures to be tried later - return pos.see_ge(*cur, Value(-cur->value)) ? true - : (*endBadCaptures++ = *cur, false); + return pos.see_ge(*cur, -cur->value) ? true : (*endBadCaptures++ = *cur, false); })) return *(cur - 1); diff --git a/src/movepick.h b/src/movepick.h index ad4be8e9..c429f8ae 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -171,7 +171,7 @@ class MovePicker { const CapturePieceToHistory*, const PieceToHistory**, const PawnHistory*); - MovePicker(const Position&, Move, Value, const CapturePieceToHistory*); + MovePicker(const Position&, Move, int, const CapturePieceToHistory*); Move next_move(bool skipQuiets = false); private: @@ -190,7 +190,7 @@ class MovePicker { Move ttMove; ExtMove refutations[3], *cur, *endMoves, *endBadCaptures; int stage; - Value threshold; + int threshold; Depth depth; ExtMove moves[MAX_MOVES]; }; diff --git a/src/nnue/evaluate_nnue.h b/src/nnue/evaluate_nnue.h index 05c98bc5..f80aa398 100644 --- a/src/nnue/evaluate_nnue.h +++ b/src/nnue/evaluate_nnue.h @@ -30,10 +30,10 @@ #include "../misc.h" #include "nnue_architecture.h" #include "nnue_feature_transformer.h" +#include "../types.h" namespace Stockfish { class Position; -enum Value : int; } namespace Stockfish::Eval::NNUE { diff --git a/src/position.cpp b/src/position.cpp index 810bba57..4fba3c23 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1029,7 +1029,7 @@ Key Position::key_after(Move m) const { // Tests if the SEE (Static Exchange Evaluation) // value of move is greater or equal to the given threshold. We'll use an // algorithm similar to alpha-beta pruning with a null window. -bool Position::see_ge(Move m, Value threshold) const { +bool Position::see_ge(Move m, int threshold) const { assert(m.is_ok()); diff --git a/src/position.h b/src/position.h index 3e932759..7e0c3eef 100644 --- a/src/position.h +++ b/src/position.h @@ -141,7 +141,7 @@ class Position { void undo_null_move(); // Static Exchange Evaluation - bool see_ge(Move m, Value threshold = VALUE_ZERO) const; + bool see_ge(Move m, int threshold = 0) const; // Accessing hash keys Key key() const; diff --git a/src/search.cpp b/src/search.cpp index 0d41f48d..9dc4ee98 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -77,13 +77,13 @@ enum NodeType { // Futility margin Value futility_margin(Depth d, bool noTtCutNode, bool improving) { - return Value((116 - 44 * noTtCutNode) * (d - improving)); + return ((116 - 44 * noTtCutNode) * (d - improving)); } // Reductions lookup table initialized at startup int Reductions[MAX_MOVES]; // [depth or moveNumber] -Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { +Depth reduction(bool i, Depth d, int mn, int delta, int rootDelta) { int reductionScale = Reductions[d] * Reductions[mn]; return (reductionScale + 1346 - int(delta) * 896 / int(rootDelta)) / 1024 + (!i && reductionScale > 880); @@ -95,7 +95,7 @@ constexpr int futility_move_count(bool improving, Depth depth) { // Guarantee evaluation does not hit the tablebase range constexpr Value to_static_eval(const Value v) { - return std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); + return std::clamp(int(v), VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); } // History and stats update bonus, based on depth @@ -292,13 +292,13 @@ void Thread::search() { // (ss + 2) is needed for initialization of cutOffCnt and killers. Stack stack[MAX_PLY + 10], *ss = stack + 7; Move pv[MAX_PLY + 1]; - Value alpha, beta, delta; + Value alpha, beta; Move lastBestMove = Move::none(); Depth lastBestMoveDepth = 0; MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr); double timeReduction = 1, totBestMoveChanges = 0; - Color us = rootPos.side_to_move(); - int iterIdx = 0; + Color us = rootPos.side_to_move(); + int delta, iterIdx = 0; std::memset(ss - 7, 0, 10 * sizeof(Stack)); for (int i = 7; i > 0; --i) @@ -374,7 +374,7 @@ void Thread::search() { Value avg = rootMoves[pvIdx].averageScore; delta = Value(9) + int(avg) * avg / 14847; alpha = std::max(avg - delta, -VALUE_INFINITE); - beta = std::min(avg + delta, VALUE_INFINITE); + beta = std::min(avg + delta, int(VALUE_INFINITE)); // Adjust optimism based on root move's averageScore (~4 Elo) optimism[us] = 121 * avg / (std::abs(avg) + 109); @@ -425,7 +425,7 @@ void Thread::search() { } else if (bestValue >= beta) { - beta = std::min(bestValue + delta, VALUE_INFINITE); + beta = std::min(bestValue + delta, int(VALUE_INFINITE)); ++failedHighCnt; } else @@ -989,7 +989,7 @@ moves_loop: // When in check, search starts here // Calculate new depth for this move newDepth = depth - 1; - Value delta = beta - alpha; + int delta = beta - alpha; Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); @@ -1018,7 +1018,7 @@ moves_loop: // When in check, search starts here } // SEE based pruning for captures and checks (~11 Elo) - if (!pos.see_ge(move, Value(-187) * depth)) + if (!pos.see_ge(move, -187 * depth)) continue; } else @@ -1048,7 +1048,7 @@ moves_loop: // When in check, search starts here lmrDepth = std::max(lmrDepth, 0); // Prune moves with negative SEE (~4 Elo) - if (!pos.see_ge(move, Value(-26 * lmrDepth * lmrDepth))) + if (!pos.see_ge(move, -26 * lmrDepth * lmrDepth)) continue; } } @@ -1617,7 +1617,7 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { continue; // Do not search moves with bad enough SEE values (~5 Elo) - if (!pos.see_ge(move, Value(-77))) + if (!pos.see_ge(move, -77)) continue; } @@ -1863,7 +1863,7 @@ Move Skill::pick_best(size_t multiPV) { // RootMoves are already sorted by score in descending order Value topScore = rootMoves[0].score; - int delta = std::min(topScore - rootMoves[multiPV - 1].score, PawnValue); + int delta = std::min(topScore - rootMoves[multiPV - 1].score, int(PawnValue)); int maxScore = -VALUE_INFINITE; double weakness = 120 - 2 * level; diff --git a/src/thread.h b/src/thread.h index 22fe32c3..7db7c159 100644 --- a/src/thread.h +++ b/src/thread.h @@ -56,13 +56,15 @@ class Thread { size_t pvIdx, pvLast; std::atomic nodes, tbHits, bestMoveChanges; int selDepth, nmpMinPly; - Value bestValue, optimism[COLOR_NB]; + Value bestValue; + + int optimism[COLOR_NB]; Position rootPos; StateInfo rootState; Search::RootMoves rootMoves; Depth rootDepth, completedDepth; - Value rootDelta; + int rootDelta; Value rootSimpleEval; CounterMoveHistory counterMoves; ButterflyHistory mainHistory; diff --git a/src/tune.cpp b/src/tune.cpp index 44bfa682..1dddca0c 100644 --- a/src/tune.cpp +++ b/src/tune.cpp @@ -26,10 +26,6 @@ #include "uci.h" -namespace Stockfish { -enum Value : int; -} - using std::string; namespace Stockfish { @@ -92,17 +88,6 @@ void Tune::Entry::read_option() { value = int(Options[name]); } -template<> -void Tune::Entry::init_option() { - make_option(name, value, range); -} - -template<> -void Tune::Entry::read_option() { - if (Options.count(name)) - value = Value(int(Options[name])); -} - // Instead of a variable here we have a PostUpdate function: just call it template<> void Tune::Entry::init_option() {} diff --git a/src/tune.h b/src/tune.h index 3d45e51c..17057001 100644 --- a/src/tune.h +++ b/src/tune.h @@ -27,7 +27,6 @@ #include namespace Stockfish { -enum Value : int; using Range = std::pair; // Option's min-max values using RangeFun = Range(int); @@ -101,8 +100,7 @@ class Tune { static_assert(!std::is_const_v, "Parameter cannot be const!"); - static_assert(std::is_same_v || std::is_same_v - || std::is_same_v, + static_assert(std::is_same_v || std::is_same_v, "Parameter type not supported!"); Entry(const std::string& n, T& v, const SetRange& r) : diff --git a/src/types.h b/src/types.h index 2970d1e0..ca9ef615 100644 --- a/src/types.h +++ b/src/types.h @@ -137,29 +137,33 @@ enum Bound { BOUND_EXACT = BOUND_UPPER | BOUND_LOWER }; -enum Value : int { - VALUE_ZERO = 0, - VALUE_DRAW = 0, - VALUE_NONE = 32002, - VALUE_INFINITE = 32001, +// Value is used as an alias for int16_t, this is done to differentiate between +// a search value and any other integer value. The values used in search are always +// supposed to be in the range (-VALUE_NONE, VALUE_NONE] and should not exceed this range. +using Value = int; - VALUE_MATE = 32000, - VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY, - VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY, +constexpr Value VALUE_ZERO = 0; +constexpr Value VALUE_DRAW = 0; +constexpr Value VALUE_NONE = 32002; +constexpr Value VALUE_INFINITE = 32001; - VALUE_TB = VALUE_MATE_IN_MAX_PLY - 1, - VALUE_TB_WIN_IN_MAX_PLY = VALUE_TB - MAX_PLY, - VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY, +constexpr Value VALUE_MATE = 32000; +constexpr Value VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY; +constexpr Value VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY; + +constexpr Value VALUE_TB = VALUE_MATE_IN_MAX_PLY - 1; +constexpr Value VALUE_TB_WIN_IN_MAX_PLY = VALUE_TB - MAX_PLY; +constexpr Value VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY; + +// In the code, we make the assumption that these values +// are such that non_pawn_material() can be used to uniquely +// identify the material on the board. +constexpr Value PawnValue = 208; +constexpr Value KnightValue = 781; +constexpr Value BishopValue = 825; +constexpr Value RookValue = 1276; +constexpr Value QueenValue = 2538; - // In the code, we make the assumption that these values - // are such that non_pawn_material() can be used to uniquely - // identify the material on the board. - PawnValue = 208, - KnightValue = 781, - BishopValue = 825, - RookValue = 1276, - QueenValue = 2538, -}; // clang-format off enum PieceType { @@ -280,7 +284,6 @@ struct DirtyPiece { inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \ inline T& operator/=(T& d, int i) { return d = T(int(d) / i); } -ENABLE_FULL_OPERATORS_ON(Value) ENABLE_FULL_OPERATORS_ON(Direction) ENABLE_INCR_OPERATORS_ON(PieceType)