From 1776448917e49b922a762d2d08c00a3f3be10205 Mon Sep 17 00:00:00 2001 From: Disservin Date: Fri, 13 Dec 2024 17:00:05 +0100 Subject: [PATCH 01/26] Move Embedded Net Data out of Anon Namespace fixes https://github.com/official-stockfish/Stockfish/issues/5714 closes https://github.com/official-stockfish/Stockfish/pull/5715 No functional change --- src/nnue/network.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nnue/network.cpp b/src/nnue/network.cpp index 0a4452f66..01cf2516d 100644 --- a/src/nnue/network.cpp +++ b/src/nnue/network.cpp @@ -38,7 +38,6 @@ #include "nnue_common.h" #include "nnue_misc.h" -namespace { // Macro to embed the default efficiently updatable neural network (NNUE) file // data in the engine binary (using incbin.h, by Dale Weiler). // This macro invocation will declare the following three variables @@ -58,6 +57,8 @@ const unsigned char* const gEmbeddedNNUESmallEnd = &gEmbeddedNNUESmallData[1 const unsigned int gEmbeddedNNUESmallSize = 1; #endif +namespace { + struct EmbeddedNNUE { EmbeddedNNUE(const unsigned char* embeddedData, const unsigned char* embeddedEnd, From e770b55f7f25d1aa4ce3d80f511868dc86d6b6d9 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Fri, 13 Dec 2024 11:45:11 -0800 Subject: [PATCH 02/26] Remove Extraneous Parenthesis No longer needed after https://github.com/official-stockfish/Stockfish/pull/5667. closes https://github.com/official-stockfish/Stockfish/pull/5717 No functional change --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 9a0a9d046..36c0b8c03 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -538,7 +538,7 @@ Value Search::Worker::search( // Dive into quiescence search when the depth reaches zero if (depth <= 0) - return qsearch(pos, ss, alpha, beta); + return qsearch < PvNode ? PV : NonPV > (pos, ss, alpha, beta); // Limit the depth if extensions made it too large depth = std::min(depth, MAX_PLY - 1); @@ -1714,7 +1714,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) const { int reductionScale = reductions[d] * reductions[mn]; - return (reductionScale + 1304 - delta * 814 / rootDelta) + (!i && reductionScale > 1423) * 1135; + return reductionScale - delta * 814 / rootDelta + (!i && reductionScale > 1423) * 1135 + 1304; } // elapsed() returns the time elapsed since the search started. If the From ba145332c9f0b8126bd940ec5afbc7769ef43174 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Fri, 13 Dec 2024 13:45:54 -0800 Subject: [PATCH 03/26] Remove time reduction for recaptures Passed simplification STC LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 54016 W: 14098 L: 13902 D: 26016 Ptnml(0-2): 165, 5797, 14919, 5931, 196 https://tests.stockfishchess.org/tests/view/6758a90486d5ee47d954201e Passed simplification LTC LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 296940 W: 75631 L: 75689 D: 145620 Ptnml(0-2): 145, 28928, 90384, 28866, 147 https://tests.stockfishchess.org/tests/view/6758df7a86d5ee47d9542091 closes https://github.com/official-stockfish/Stockfish/pull/5719 Bench: 1148169 --- src/engine.cpp | 8 -------- src/engine.h | 3 --- src/search.cpp | 3 +-- src/search.h | 1 - 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 85c840993..30ad6ba0f 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -58,7 +58,6 @@ Engine::Engine(std::optional path) : NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::EmbeddedNNUEType::BIG), NN::NetworkSmall({EvalFileDefaultNameSmall, "None", ""}, NN::EmbeddedNNUEType::SMALL))) { pos.set(StartFEN, false, &states->back()); - capSq = SQ_NONE; options["Debug Log File"] << Option("", [](const Option& o) { start_logger(o); @@ -125,7 +124,6 @@ std::uint64_t Engine::perft(const std::string& fen, Depth depth, bool isChess960 void Engine::go(Search::LimitsType& limits) { assert(limits.perft == 0); verify_networks(); - limits.capSq = capSq; threads.start_thinking(options, pos, states, limits); } @@ -168,7 +166,6 @@ void Engine::set_position(const std::string& fen, const std::vector states = StateListPtr(new std::deque(1)); pos.set(fen, options["UCI_Chess960"], &states->back()); - capSq = SQ_NONE; for (const auto& move : moves) { auto m = UCIEngine::to_move(pos, move); @@ -178,11 +175,6 @@ void Engine::set_position(const std::string& fen, const std::vector states->emplace_back(); pos.do_move(m, states->back()); - - capSq = SQ_NONE; - DirtyPiece& dp = states->back().dirtyPiece; - if (dp.dirty_num > 1 && dp.to[1] == SQ_NONE) - capSq = m.to_sq(); } } diff --git a/src/engine.h b/src/engine.h index 257826935..2d17fb31d 100644 --- a/src/engine.h +++ b/src/engine.h @@ -39,8 +39,6 @@ namespace Stockfish { -enum Square : int; - class Engine { public: using InfoShort = Search::InfoShort; @@ -116,7 +114,6 @@ class Engine { Position pos; StateListPtr states; - Square capSq; OptionsMap options; ThreadPool threads; diff --git a/src/search.cpp b/src/search.cpp index 36c0b8c03..f42ecf711 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -453,10 +453,9 @@ void Search::Worker::iterative_deepening() { timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.495 : 0.687; double reduction = (1.48 + mainThread->previousTimeReduction) / (2.17 * timeReduction); double bestMoveInstability = 1 + 1.88 * totBestMoveChanges / threads.size(); - double recapture = limits.capSq == rootMoves[0].pv[0].to_sq() ? 0.955 : 1.005; double totalTime = - mainThread->tm.optimum() * fallingEval * reduction * bestMoveInstability * recapture; + mainThread->tm.optimum() * fallingEval * reduction * bestMoveInstability; // Cap used time in case of a single legal move for a better viewer experience if (rootMoves.size() == 1) diff --git a/src/search.h b/src/search.h index e9a7943d1..c65267a1d 100644 --- a/src/search.h +++ b/src/search.h @@ -126,7 +126,6 @@ struct LimitsType { int movestogo, depth, mate, perft, infinite; uint64_t nodes; bool ponderMode; - Square capSq; }; From 77ec878ffa5b33e796c01d8331d07d05838212ae Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sun, 15 Dec 2024 01:35:15 -0800 Subject: [PATCH 04/26] Prevent out of bounds access of dbg info arrays closes https://github.com/official-stockfish/Stockfish/pull/5721 No functional change --- src/misc.cpp | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index 10c86b7a6..7db8bd59e 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -18,7 +18,9 @@ #include "misc.h" +#include #include +#include #include #include #include @@ -287,7 +289,10 @@ template struct DebugInfo { std::atomic data[N] = {0}; - constexpr std::atomic& operator[](int index) { return data[index]; } + [[nodiscard]] constexpr std::atomic& operator[](size_t index) { + assert(index < N); + return data[index]; + } }; struct DebugExtremes: public DebugInfo<3> { @@ -297,54 +302,54 @@ struct DebugExtremes: public DebugInfo<3> { } }; -DebugInfo<2> hit[MaxDebugSlots]; -DebugInfo<2> mean[MaxDebugSlots]; -DebugInfo<3> stdev[MaxDebugSlots]; -DebugInfo<6> correl[MaxDebugSlots]; -DebugExtremes extremes[MaxDebugSlots]; +std::array, MaxDebugSlots> hit; +std::array, MaxDebugSlots> mean; +std::array, MaxDebugSlots> stdev; +std::array, MaxDebugSlots> correl; +std::array extremes; } // namespace void dbg_hit_on(bool cond, int slot) { - ++hit[slot][0]; + ++hit.at(slot)[0]; if (cond) - ++hit[slot][1]; + ++hit.at(slot)[1]; } void dbg_mean_of(int64_t value, int slot) { - ++mean[slot][0]; - mean[slot][1] += value; + ++mean.at(slot)[0]; + mean.at(slot)[1] += value; } void dbg_stdev_of(int64_t value, int slot) { - ++stdev[slot][0]; - stdev[slot][1] += value; - stdev[slot][2] += value * value; + ++stdev.at(slot)[0]; + stdev.at(slot)[1] += value; + stdev.at(slot)[2] += value * value; } void dbg_extremes_of(int64_t value, int slot) { - ++extremes[slot][0]; + ++extremes.at(slot)[0]; - int64_t current_max = extremes[slot][1].load(); - while (current_max < value && !extremes[slot][1].compare_exchange_weak(current_max, value)) + int64_t current_max = extremes.at(slot)[1].load(); + while (current_max < value && !extremes.at(slot)[1].compare_exchange_weak(current_max, value)) {} - int64_t current_min = extremes[slot][2].load(); - while (current_min > value && !extremes[slot][2].compare_exchange_weak(current_min, value)) + int64_t current_min = extremes.at(slot)[2].load(); + while (current_min > value && !extremes.at(slot)[2].compare_exchange_weak(current_min, value)) {} } void dbg_correl_of(int64_t value1, int64_t value2, int slot) { - ++correl[slot][0]; - correl[slot][1] += value1; - correl[slot][2] += value1 * value1; - correl[slot][3] += value2; - correl[slot][4] += value2 * value2; - correl[slot][5] += value1 * value2; + ++correl.at(slot)[0]; + correl.at(slot)[1] += value1; + correl.at(slot)[2] += value1 * value1; + correl.at(slot)[3] += value2; + correl.at(slot)[4] += value2 * value2; + correl.at(slot)[5] += value1 * value2; } void dbg_print() { From 2dc47e4345a7a13421e66b88168a13bd8d6bf1bf Mon Sep 17 00:00:00 2001 From: Disservin Date: Sun, 15 Dec 2024 13:52:20 +0100 Subject: [PATCH 05/26] Cleanup Evaluate Calls Makes code a bit easier to read as well. closes https://github.com/official-stockfish/Stockfish/pull/5722 No functional change --- src/search.cpp | 30 ++++++++++++------------------ src/search.h | 2 ++ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index f42ecf711..4bebd9850 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -60,7 +60,6 @@ void syzygy_extend_pv(const OptionsMap& options, Stockfish::Search::RootMove& rootMove, Value& v); -using Eval::evaluate; using namespace Search; namespace { @@ -592,10 +591,8 @@ Value Search::Worker::search( // Step 2. Check for aborted search and immediate draw if (threads.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !ss->inCheck) - ? evaluate(networks[numaAccessToken], pos, refreshTable, - thisThread->optimism[us]) - : value_draw(thisThread->nodes); + return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) + : value_draw(thisThread->nodes); // Step 3. Mate distance pruning. Even if we mate at the next move our score // would be at best mate_in(ss->ply + 1), but if alpha is already bigger because @@ -732,8 +729,7 @@ Value Search::Worker::search( // Never assume anything about values stored in TT unadjustedStaticEval = ttData.eval; if (!is_valid(unadjustedStaticEval)) - unadjustedStaticEval = - evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]); + unadjustedStaticEval = evaluate(pos); else if (PvNode) Eval::NNUE::hint_common_parent_position(pos, networks[numaAccessToken], refreshTable); @@ -747,9 +743,8 @@ Value Search::Worker::search( } else { - unadjustedStaticEval = - evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]); - ss->staticEval = eval = + unadjustedStaticEval = evaluate(pos); + ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); // Static evaluation is saved as it was before adjustment by correction history @@ -1510,9 +1505,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) // Step 2. Check for an immediate draw or maximum ply reached if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !ss->inCheck) - ? evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]) - : VALUE_DRAW; + return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : VALUE_DRAW; assert(0 <= ss->ply && ss->ply < MAX_PLY); @@ -1542,8 +1535,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) // Never assume anything about values stored in TT unadjustedStaticEval = ttData.eval; if (!is_valid(unadjustedStaticEval)) - unadjustedStaticEval = - evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]); + unadjustedStaticEval = evaluate(pos); ss->staticEval = bestValue = to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); @@ -1556,9 +1548,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) { // In case of null move search, use previous static eval with opposite sign unadjustedStaticEval = - (ss - 1)->currentMove != Move::null() - ? evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]) - : -(ss - 1)->staticEval; + (ss - 1)->currentMove != Move::null() ? evaluate(pos) : -(ss - 1)->staticEval; ss->staticEval = bestValue = to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); } @@ -1730,6 +1720,10 @@ TimePoint Search::Worker::elapsed() const { TimePoint Search::Worker::elapsed_time() const { return main_manager()->tm.elapsed_time(); } +Value Search::Worker::evaluate(const Position& pos) { + return Eval::evaluate(networks[numaAccessToken], pos, refreshTable, + optimism[pos.side_to_move()]); +} namespace { // Adjusts a mate or TB score from "plies to mate from the root" to diff --git a/src/search.h b/src/search.h index c65267a1d..945c66c1c 100644 --- a/src/search.h +++ b/src/search.h @@ -313,6 +313,8 @@ class Worker { TimePoint elapsed() const; TimePoint elapsed_time() const; + Value evaluate(const Position&); + LimitsType limits; size_t pvIdx, pvLast; From 6075e787d05e609bd5e0c64acb0f5eb1dc623dde Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Mon, 16 Dec 2024 13:35:15 -0800 Subject: [PATCH 06/26] Add CI test with glibcxx assertions enabled Re: https://github.com/official-stockfish/Stockfish/pull/5721#pullrequestreview-2504542601 closes https://github.com/official-stockfish/Stockfish/pull/5723 No functional change --- .github/workflows/sanitizers.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sanitizers.yml b/.github/workflows/sanitizers.yml index 946a81cec..950435f30 100644 --- a/.github/workflows/sanitizers.yml +++ b/.github/workflows/sanitizers.yml @@ -21,19 +21,28 @@ jobs: sanitizers: - name: Run with thread sanitizer make_option: sanitize=thread + cxx_extra_flags: "" instrumented_option: sanitizer-thread - name: Run with UB sanitizer make_option: sanitize=undefined + cxx_extra_flags: "" instrumented_option: sanitizer-undefined - name: Run under valgrind make_option: "" + cxx_extra_flags: "" instrumented_option: valgrind - name: Run under valgrind-thread make_option: "" + cxx_extra_flags: "" instrumented_option: valgrind-thread - name: Run non-instrumented make_option: "" + cxx_extra_flags: "" instrumented_option: none + - name: Run with glibcxx assertions + make_option: "" + cxx_extra_flags: -D_GLIBCXX_ASSERTIONS + instrumented_option: non defaults: run: working-directory: src @@ -72,7 +81,7 @@ jobs: - name: ${{ matrix.sanitizers.name }} run: | - export CXXFLAGS="-O1 -fno-inline" + export CXXFLAGS="-O1 -fno-inline ${{ matrix.sanitizers.cxx_extra_flags }}" make clean make -j4 ARCH=x86-64-sse41-popcnt ${{ matrix.sanitizers.make_option }} debug=yes optimize=no build > /dev/null python3 ../tests/instrumented.py --${{ matrix.sanitizers.instrumented_option }} ./stockfish From a04b07265ff5ce8ea27bd4ecb761a56341399bde Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Wed, 18 Dec 2024 14:32:48 +0300 Subject: [PATCH 07/26] Make reductionScale smoother Making the second part of the formula smoother, changing it to a linear function, increasing steadily as reductionScale increases and at the same time, it should be a little bit simpler, therefore the simplification bounds. Passed STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 83040 W: 21493 L: 21322 D: 40225 Ptnml(0-2): 252, 9848, 21209, 9899, 312 https://tests.stockfishchess.org/tests/view/6762145486d5ee47d9543242 Passed LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 230124 W: 58485 L: 58478 D: 113161 Ptnml(0-2): 175, 25620, 63484, 25589, 194 https://tests.stockfishchess.org/tests/view/6762d4ef86d5ee47d9543367 closes https://github.com/official-stockfish/Stockfish/pull/5725 Bench: 1204658 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 4bebd9850..02d7b6777 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1703,7 +1703,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) Depth Search::Worker::reduction(bool i, Depth d, int mn, int delta) const { int reductionScale = reductions[d] * reductions[mn]; - return reductionScale - delta * 814 / rootDelta + (!i && reductionScale > 1423) * 1135 + 1304; + return reductionScale - delta * 814 / rootDelta + !i * reductionScale / 3 + 1304; } // elapsed() returns the time elapsed since the search started. If the From e7e78aa09e190ea0fd7fed6fcff97d98c0cf5b5f Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sat, 14 Dec 2024 15:13:32 -0800 Subject: [PATCH 08/26] Adjust LMR with correction history A positive constant increase in base reduction is applied to counter the decrease in average reduction from this tweak. Passed STC: LLR: 2.98 (-2.94,2.94) <0.00,2.00> Total: 109216 W: 28415 L: 27989 D: 52812 Ptnml(0-2): 310, 12848, 27911, 13184, 355 https://tests.stockfishchess.org/tests/view/6760bb0e86d5ee47d9542f26 Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 66918 W: 17073 L: 16694 D: 33151 Ptnml(0-2): 33, 7175, 18666, 7550, 35 https://tests.stockfishchess.org/tests/view/6761e10f86d5ee47d95431fa closes https://github.com/official-stockfish/Stockfish/pull/5727 Bench: 1294909 --- src/search.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 02d7b6777..f184a3539 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -77,9 +77,7 @@ constexpr int futility_move_count(bool improving, Depth depth) { return (3 + depth * depth) / (2 - improving); } -// Add correctionHistory value to raw staticEval and guarantee evaluation -// does not hit the tablebase range. -Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos, Stack* ss) { +int correction_value(const Worker& w, const Position& pos, Stack* ss) { const Color us = pos.side_to_move(); const auto m = (ss - 1)->currentMove; const auto pcv = w.pawnCorrectionHistory[us][pawn_structure_index(pos)]; @@ -87,15 +85,17 @@ Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos, St const auto micv = w.minorPieceCorrectionHistory[us][minor_piece_index(pos)]; const auto wnpcv = w.nonPawnCorrectionHistory[WHITE][us][non_pawn_index(pos)]; const auto bnpcv = w.nonPawnCorrectionHistory[BLACK][us][non_pawn_index(pos)]; - int cntcv = 1; + const auto cntcv = + m.is_ok() ? (*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()] + : 0; - if (m.is_ok()) - cntcv = int((*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()]); + return (6384 * pcv + 3583 * macv + 6492 * micv + 6725 * (wnpcv + bnpcv) + 5880 * cntcv); +} - const auto cv = - (6384 * pcv + 3583 * macv + 6492 * micv + 6725 * (wnpcv + bnpcv) + cntcv * 5880) / 131072; - v += cv; - return std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); +// Add correctionHistory value to raw staticEval and guarantee evaluation +// does not hit the tablebase range. +Value to_corrected_static_eval(Value v, const int cv) { + return std::clamp(v + cv / 131072, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); } // History and stats update bonus, based on depth @@ -709,7 +709,8 @@ Value Search::Worker::search( } // Step 6. Static evaluation of the position - Value unadjustedStaticEval = VALUE_NONE; + Value unadjustedStaticEval = VALUE_NONE; + const auto correctionValue = correction_value(*thisThread, pos, ss); if (ss->inCheck) { // Skip early pruning when in check @@ -733,8 +734,7 @@ Value Search::Worker::search( else if (PvNode) Eval::NNUE::hint_common_parent_position(pos, networks[numaAccessToken], refreshTable); - ss->staticEval = eval = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, correctionValue); // ttValue can be used as a better position evaluation (~7 Elo) if (is_valid(ttData.value) @@ -744,8 +744,7 @@ Value Search::Worker::search( else { unadjustedStaticEval = evaluate(pos); - ss->staticEval = eval = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, correctionValue); // Static evaluation is saved as it was before adjustment by correction history ttWriter.write(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_UNSEARCHED, Move::none(), @@ -1155,6 +1154,10 @@ moves_loop: // When in check, search starts here // These reduction adjustments have no proven non-linear scaling + r += 330; + + r -= std::min(std::abs(correctionValue) / 32768, 2048); + // Increase reduction for cut nodes (~4 Elo) if (cutNode) r += 2518 - (ttData.depth >= depth && ss->ttPv) * 991; @@ -1525,7 +1528,8 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) return ttData.value; // Step 4. Static evaluation of the position - Value unadjustedStaticEval = VALUE_NONE; + Value unadjustedStaticEval = VALUE_NONE; + const auto correctionValue = correction_value(*thisThread, pos, ss); if (ss->inCheck) bestValue = futilityBase = -VALUE_INFINITE; else @@ -1537,7 +1541,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) if (!is_valid(unadjustedStaticEval)) unadjustedStaticEval = evaluate(pos); ss->staticEval = bestValue = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + to_corrected_static_eval(unadjustedStaticEval, correctionValue); // ttValue can be used as a better position evaluation (~13 Elo) if (is_valid(ttData.value) && !is_decisive(ttData.value) @@ -1550,7 +1554,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) unadjustedStaticEval = (ss - 1)->currentMove != Move::null() ? evaluate(pos) : -(ss - 1)->staticEval; ss->staticEval = bestValue = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + to_corrected_static_eval(unadjustedStaticEval, correctionValue); } // Stand pat. Return immediately if static value is at least beta From 4bc2a24245faa8ea8b3b8a80d03bd7436ac154a2 Mon Sep 17 00:00:00 2001 From: Disservin Date: Wed, 18 Dec 2024 19:47:56 +0100 Subject: [PATCH 09/26] Workaround for clang-format bug closes https://github.com/official-stockfish/Stockfish/pull/5728 No functional change --- src/search.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index f184a3539..1f19c74db 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -536,7 +536,10 @@ Value Search::Worker::search( // Dive into quiescence search when the depth reaches zero if (depth <= 0) - return qsearch < PvNode ? PV : NonPV > (pos, ss, alpha, beta); + { + constexpr auto nt = PvNode ? PV : NonPV; + return qsearch(pos, ss, alpha, beta); + } // Limit the depth if extensions made it too large depth = std::min(depth, MAX_PLY - 1); From 79261bec593267a79a4af9bfb08b2ee848f67dfa Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Thu, 19 Dec 2024 01:14:40 +0300 Subject: [PATCH 10/26] Simplify away reductions adjustment for multithreaded search Seem to no longer bring measurable benefit. Passed STC SMP simplification: https://tests.stockfishchess.org/tests/view/6753561a86d5ee47d954151f LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 38000 W: 9864 L: 9656 D: 18480 Ptnml(0-2): 53, 4177, 10320, 4409, 41 Passed LTC SMP simplification: https://tests.stockfishchess.org/tests/view/6753d75f86d5ee47d9541669 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 258674 W: 66314 L: 66335 D: 126025 Ptnml(0-2): 77, 26957, 75303, 26910, 90 Passed 16 threads LTC simplification: https://tests.stockfishchess.org/tests/view/675a066286d5ee47d9542296 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 221804 W: 56950 L: 56936 D: 107918 Ptnml(0-2): 34, 21491, 67839, 21503, 35 closes https://github.com/official-stockfish/Stockfish/pull/5729 Bench: 1294909 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 1f19c74db..192b837c9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -519,7 +519,7 @@ void Search::Worker::clear() { h->fill(-427); for (size_t i = 1; i < reductions.size(); ++i) - reductions[i] = int((19.43 + std::log(size_t(options["Threads"])) / 2) * std::log(i)); + reductions[i] = int(19.43 * std::log(i)); refreshTable.clear(networks[numaAccessToken]); } From f656fdfa9a4566f9d5d7ffe86f8390a53e518b3c Mon Sep 17 00:00:00 2001 From: mstembera Date: Thu, 19 Dec 2024 15:08:16 -0800 Subject: [PATCH 11/26] Simplify Zobrist keys for captures The Zobrist keys for NO_PIECE are 0 so no need to special case captures. Also the TranspositionTable reference passed to do_null_move() can be const. STC Simplification: https://tests.stockfishchess.org/tests/view/6764a79a86d5ee47d9544005 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 114240 W: 29654 L: 29523 D: 55063 Ptnml(0-2): 329, 12360, 31620, 12473, 338 closes https://github.com/official-stockfish/Stockfish/pull/5731 No functional change --- src/position.cpp | 7 ++----- src/position.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 1b1c0269f..2bc0aa650 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1012,7 +1012,7 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ // Used to do a "null move": it flips // the side to move without executing any move on the board. -void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) { +void Position::do_null_move(StateInfo& newSt, const TranspositionTable& tt) { assert(!checkers()); assert(&newSt != st); @@ -1071,10 +1071,7 @@ Key Position::key_after(Move m) const { Piece captured = piece_on(to); Key k = st->key ^ Zobrist::side; - if (captured) - k ^= Zobrist::psq[captured][to]; - - k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; + k ^= Zobrist::psq[captured][to] ^ Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; return (captured || type_of(pc) == PAWN) ? k : adjust_key50(k); } diff --git a/src/position.h b/src/position.h index 888612da7..a339471d2 100644 --- a/src/position.h +++ b/src/position.h @@ -143,7 +143,7 @@ class Position { void do_move(Move m, StateInfo& newSt); void do_move(Move m, StateInfo& newSt, bool givesCheck); void undo_move(Move m); - void do_null_move(StateInfo& newSt, TranspositionTable& tt); + void do_null_move(StateInfo& newSt, const TranspositionTable& tt); void undo_null_move(); // Static Exchange Evaluation From 03e4cde729bdd357afc1e0ecb40e9e7780ada978 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Mon, 23 Dec 2024 16:12:29 +0300 Subject: [PATCH 12/26] Allow Pv nodes at certain conditions to spawn zero window searches deeper than default In current case it's allowed if there is no best move. Passed STC: https://tests.stockfishchess.org/tests/view/67640fd586d5ee47d9543d5a LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 392480 W: 102038 L: 101192 D: 189250 Ptnml(0-2): 1303, 46287, 100253, 47055, 1342 Passed LTC: https://tests.stockfishchess.org/tests/view/67671a4686d5ee47d9544476 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 128616 W: 32941 L: 32433 D: 63242 Ptnml(0-2): 84, 13997, 35634, 14513, 80 closes https://github.com/official-stockfish/Stockfish/pull/5733 Bench: 1095871 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 192b837c9..1fe89c4ac 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1198,7 +1198,7 @@ moves_loop: // When in check, search starts here // beyond the first move depth. // To prevent problems when the max value is less than the min value, // std::clamp has been replaced by a more robust implementation. - Depth d = std::max(1, std::min(newDepth - r / 1024, newDepth + !allNode)); + Depth d = std::max(1, std::min(newDepth - r / 1024, newDepth + !allNode + (PvNode && !bestMove))); value = -search(pos, ss + 1, -(alpha + 1), -alpha, d, true); From 78b57339394b284ee5d1fe32e5c2c285f80df550 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sat, 21 Dec 2024 12:06:35 -0800 Subject: [PATCH 13/26] Simplify post-lmr conthist bonus Passed Non-regression STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 49184 W: 12735 L: 12528 D: 23921 Ptnml(0-2): 134, 5746, 12647, 5909, 156 https://tests.stockfishchess.org/tests/view/6765cd2e86d5ee47d954420e Passed Non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 177270 W: 45227 L: 45166 D: 86877 Ptnml(0-2): 132, 19498, 49302, 19583, 120 https://tests.stockfishchess.org/tests/view/676721fd86d5ee47d9544489 closes https://github.com/official-stockfish/Stockfish/pull/5734 Bench: 1042099 --- src/search.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 1fe89c4ac..44394c1d6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1198,7 +1198,8 @@ moves_loop: // When in check, search starts here // beyond the first move depth. // To prevent problems when the max value is less than the min value, // std::clamp has been replaced by a more robust implementation. - Depth d = std::max(1, std::min(newDepth - r / 1024, newDepth + !allNode + (PvNode && !bestMove))); + Depth d = std::max( + 1, std::min(newDepth - r / 1024, newDepth + !allNode + (PvNode && !bestMove))); value = -search(pos, ss + 1, -(alpha + 1), -alpha, d, true); @@ -1216,8 +1217,8 @@ moves_loop: // When in check, search starts here value = -search(pos, ss + 1, -(alpha + 1), -alpha, newDepth, !cutNode); // Post LMR continuation history updates (~1 Elo) - int bonus = (value >= beta) * stat_bonus(newDepth); - update_continuation_histories(ss, movedPiece, move.to_sq(), bonus * 1427 / 1024); + int bonus = (value >= beta) * 2048; + update_continuation_histories(ss, movedPiece, move.to_sq(), bonus); } } From 5cf6f991771d4260517d28812bfaef192c42ac97 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sun, 29 Dec 2024 09:32:29 -0800 Subject: [PATCH 14/26] Remove some incorrectly marked const qualifiers closes https://github.com/official-stockfish/Stockfish/pull/5744 No functional change --- src/nnue/network.cpp | 2 +- src/nnue/nnue_feature_transformer.h | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/nnue/network.cpp b/src/nnue/network.cpp index 01cf2516d..9191148bb 100644 --- a/src/nnue/network.cpp +++ b/src/nnue/network.cpp @@ -101,7 +101,7 @@ bool read_parameters(std::istream& stream, T& reference) { // Write evaluation function parameters template -bool write_parameters(std::ostream& stream, const T& reference) { +bool write_parameters(std::ostream& stream, T& reference) { write_little_endian(stream, T::get_hash_value()); return reference.write_parameters(stream); diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index fa180678d..556a114af 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -256,21 +256,20 @@ class FeatureTransformer { #endif } - void permute_weights([[maybe_unused]] void (*order_fn)(uint64_t*)) const { + void permute_weights([[maybe_unused]] void (*order_fn)(uint64_t*)) { #if defined(USE_AVX2) #if defined(USE_AVX512) constexpr IndexType di = 16; #else constexpr IndexType di = 8; #endif - uint64_t* b = reinterpret_cast(const_cast(&biases[0])); + uint64_t* b = reinterpret_cast(&biases[0]); for (IndexType i = 0; i < HalfDimensions * sizeof(BiasType) / sizeof(uint64_t); i += di) order_fn(&b[i]); for (IndexType j = 0; j < InputDimensions; ++j) { - uint64_t* w = - reinterpret_cast(const_cast(&weights[j * HalfDimensions])); + uint64_t* w = reinterpret_cast(&weights[j * HalfDimensions]); for (IndexType i = 0; i < HalfDimensions * sizeof(WeightType) / sizeof(uint64_t); i += di) order_fn(&w[i]); @@ -278,17 +277,16 @@ class FeatureTransformer { #endif } - inline void scale_weights(bool read) const { + inline void scale_weights(bool read) { for (IndexType j = 0; j < InputDimensions; ++j) { - WeightType* w = const_cast(&weights[j * HalfDimensions]); + WeightType* w = &weights[j * HalfDimensions]; for (IndexType i = 0; i < HalfDimensions; ++i) w[i] = read ? w[i] * 2 : w[i] / 2; } - BiasType* b = const_cast(biases); for (IndexType i = 0; i < HalfDimensions; ++i) - b[i] = read ? b[i] * 2 : b[i] / 2; + biases[i] = read ? biases[i] * 2 : biases[i] / 2; } // Read network parameters @@ -304,7 +302,7 @@ class FeatureTransformer { } // Write network parameters - bool write_parameters(std::ostream& stream) const { + bool write_parameters(std::ostream& stream) { permute_weights(order_packs); scale_weights(false); From 00da3ff4637ea982c5ca3a2a07393d3be6aaba90 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Mon, 30 Dec 2024 23:00:03 -0800 Subject: [PATCH 15/26] Cleanup stats entry Prevents potential issue caused by publicly inheriting from STL container types closes https://github.com/official-stockfish/Stockfish/pull/5746 No functional change --- src/history.h | 58 +++++++++++++++++++++++++++++++++++------------- src/movepick.cpp | 1 - 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/history.h b/src/history.h index 17ab3481c..2ec2b7911 100644 --- a/src/history.h +++ b/src/history.h @@ -76,9 +76,12 @@ class StatsEntry { T entry; public: - void operator=(const T& v) { entry = v; } - T* operator&() { return &entry; } - T* operator->() { return &entry; } + StatsEntry& operator=(const T& v) { + entry = v; + return *this; + } + T* operator&() { return &entry; } + T* operator->() { return &entry; } operator const T&() const { return entry; } void operator<<(int bonus) { @@ -92,28 +95,53 @@ class StatsEntry { } }; +template +struct StatsHelper; + // Stats is a generic N-dimensional array used to store various statistics. // The first template parameter T is the base type of the array, and the second // template parameter D limits the range of updates in [-D, D] when we update // values with the << operator, while the last parameters (Size and Sizes) // encode the dimensions of the array. -template -struct Stats: public std::array, Size> { - using stats = Stats; +template +class Stats { + using child_type = typename StatsHelper::child_type; + using array_type = std::array; + array_type data; + + public: + using size_type = typename array_type::size_type; + + auto& operator[](size_type index) { return data[index]; } + const auto& operator[](size_type index) const { return data[index]; } + + auto begin() { return data.begin(); } + auto end() { return data.end(); } + auto begin() const { return data.cbegin(); } + auto end() const { return data.cend(); } + auto cbegin() const { return data.cbegin(); } + auto cend() const { return data.cend(); } void fill(const T& v) { - - // For standard-layout 'this' points to the first struct member - assert(std::is_standard_layout_v); - - using entry = StatsEntry; - entry* p = reinterpret_cast(this); - std::fill(p, p + sizeof(*this) / sizeof(entry), v); + for (auto& ele : data) + { + if constexpr (sizeof...(Sizes) == 0) + ele = v; + else + ele.fill(v); + } } }; -template -struct Stats: public std::array, Size> {}; +template +struct StatsHelper { + using child_type = Stats; +}; + +template +struct StatsHelper { + using child_type = StatsEntry; +}; // In stats table, D=0 means that the template parameter is not used enum StatsParams { diff --git a/src/movepick.cpp b/src/movepick.cpp index 96f031717..540024b7d 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -18,7 +18,6 @@ #include "movepick.h" -#include #include #include From 5488dd2f91226f73d93ab8f892d4aaa9b2582eed Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Tue, 31 Dec 2024 22:28:16 -0800 Subject: [PATCH 16/26] Update Copyright Year closes https://github.com/official-stockfish/Stockfish/pull/5747 No functional change --- src/Makefile | 2 +- src/benchmark.cpp | 2 +- src/benchmark.h | 2 +- src/bitboard.cpp | 2 +- src/bitboard.h | 2 +- src/engine.cpp | 2 +- src/engine.h | 2 +- src/evaluate.cpp | 2 +- src/evaluate.h | 2 +- src/history.h | 2 +- src/main.cpp | 2 +- src/memory.cpp | 2 +- src/memory.h | 2 +- src/misc.cpp | 2 +- src/misc.h | 2 +- src/movegen.cpp | 2 +- src/movegen.h | 2 +- src/movepick.cpp | 2 +- src/movepick.h | 2 +- src/nnue/features/half_ka_v2_hm.cpp | 2 +- src/nnue/features/half_ka_v2_hm.h | 2 +- src/nnue/layers/affine_transform.h | 2 +- src/nnue/layers/affine_transform_sparse_input.h | 2 +- src/nnue/layers/clipped_relu.h | 2 +- src/nnue/layers/simd.h | 2 +- src/nnue/layers/sqr_clipped_relu.h | 2 +- src/nnue/network.cpp | 2 +- src/nnue/network.h | 2 +- src/nnue/nnue_accumulator.h | 2 +- src/nnue/nnue_architecture.h | 2 +- src/nnue/nnue_common.h | 2 +- src/nnue/nnue_feature_transformer.h | 2 +- src/nnue/nnue_misc.cpp | 2 +- src/nnue/nnue_misc.h | 2 +- src/numa.h | 2 +- src/perft.h | 2 +- src/position.cpp | 2 +- src/position.h | 2 +- src/score.cpp | 2 +- src/score.h | 2 +- src/search.cpp | 2 +- src/search.h | 2 +- src/syzygy/tbprobe.cpp | 2 +- src/syzygy/tbprobe.h | 2 +- src/thread.cpp | 2 +- src/thread.h | 2 +- src/thread_win32_osx.h | 2 +- src/timeman.cpp | 2 +- src/timeman.h | 2 +- src/tt.cpp | 2 +- src/tt.h | 2 +- src/tune.cpp | 2 +- src/tune.h | 2 +- src/types.h | 2 +- src/uci.cpp | 2 +- src/uci.h | 2 +- src/ucioption.cpp | 2 +- src/ucioption.h | 2 +- 58 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/Makefile b/src/Makefile index e7f8ce556..39cfce8bf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ # Stockfish, a UCI chess playing engine derived from Glaurung 2.1 -# Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) +# Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) # # Stockfish is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 35ad3c180..a9f70f10d 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/benchmark.h b/src/benchmark.h index eb3a52d89..d6bdc275d 100644 --- a/src/benchmark.h +++ b/src/benchmark.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/bitboard.cpp b/src/bitboard.cpp index deda6da2a..8798c5701 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/bitboard.h b/src/bitboard.h index c4bf18b53..6f9cca0bd 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/engine.cpp b/src/engine.cpp index 30ad6ba0f..d835fc8e4 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/engine.h b/src/engine.h index 2d17fb31d..d26844f4c 100644 --- a/src/engine.h +++ b/src/engine.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/evaluate.cpp b/src/evaluate.cpp index bc86a7420..9a523ae44 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/evaluate.h b/src/evaluate.h index 4604321d3..aad358321 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/history.h b/src/history.h index 2ec2b7911..edf7fdc67 100644 --- a/src/history.h +++ b/src/history.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/main.cpp b/src/main.cpp index a6a3d1c4e..e262f3875 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/memory.cpp b/src/memory.cpp index 47c901b4e..92cb650f2 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/memory.h b/src/memory.h index eaf0261aa..4dc232878 100644 --- a/src/memory.h +++ b/src/memory.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/misc.cpp b/src/misc.cpp index 7db8bd59e..06a8c624a 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/misc.h b/src/misc.h index 21093769b..48c49bafb 100644 --- a/src/misc.h +++ b/src/misc.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/movegen.cpp b/src/movegen.cpp index 69b8fe6ae..8653a828f 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/movegen.h b/src/movegen.h index f067f8808..7c6cceb7c 100644 --- a/src/movegen.h +++ b/src/movegen.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/movepick.cpp b/src/movepick.cpp index 540024b7d..4c5cc11de 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/movepick.h b/src/movepick.h index ab4e832fd..71078bdcf 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/features/half_ka_v2_hm.cpp b/src/nnue/features/half_ka_v2_hm.cpp index 71782a7b7..5bb0296e2 100644 --- a/src/nnue/features/half_ka_v2_hm.cpp +++ b/src/nnue/features/half_ka_v2_hm.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/features/half_ka_v2_hm.h b/src/nnue/features/half_ka_v2_hm.h index 963497047..ca940c54e 100644 --- a/src/nnue/features/half_ka_v2_hm.h +++ b/src/nnue/features/half_ka_v2_hm.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 59a6149f0..f5c640fb9 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/layers/affine_transform_sparse_input.h b/src/nnue/layers/affine_transform_sparse_input.h index 0ac557aba..cbeb507f0 100644 --- a/src/nnue/layers/affine_transform_sparse_input.h +++ b/src/nnue/layers/affine_transform_sparse_input.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/layers/clipped_relu.h b/src/nnue/layers/clipped_relu.h index 2ee378ad8..2ad5a86a1 100644 --- a/src/nnue/layers/clipped_relu.h +++ b/src/nnue/layers/clipped_relu.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/layers/simd.h b/src/nnue/layers/simd.h index 55cb7df14..70ca68a0c 100644 --- a/src/nnue/layers/simd.h +++ b/src/nnue/layers/simd.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/layers/sqr_clipped_relu.h b/src/nnue/layers/sqr_clipped_relu.h index 9c20df9d6..d14f1e0ab 100644 --- a/src/nnue/layers/sqr_clipped_relu.h +++ b/src/nnue/layers/sqr_clipped_relu.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/network.cpp b/src/nnue/network.cpp index 9191148bb..b96625a79 100644 --- a/src/nnue/network.cpp +++ b/src/nnue/network.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/network.h b/src/nnue/network.h index 95253595a..f99fa1182 100644 --- a/src/nnue/network.h +++ b/src/nnue/network.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_accumulator.h b/src/nnue/nnue_accumulator.h index b92901e4a..0d3d94135 100644 --- a/src/nnue/nnue_accumulator.h +++ b/src/nnue/nnue_accumulator.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index 7f73f87fd..0c9f097dc 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_common.h b/src/nnue/nnue_common.h index 4bc3408f1..f21a8dec7 100644 --- a/src/nnue/nnue_common.h +++ b/src/nnue/nnue_common.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 556a114af..6192cd51e 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_misc.cpp b/src/nnue/nnue_misc.cpp index a2bece21d..1e2690503 100644 --- a/src/nnue/nnue_misc.cpp +++ b/src/nnue/nnue_misc.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nnue/nnue_misc.h b/src/nnue/nnue_misc.h index 27a93f884..a7647f846 100644 --- a/src/nnue/nnue_misc.h +++ b/src/nnue/nnue_misc.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/numa.h b/src/numa.h index 1063721e3..5cadbc726 100644 --- a/src/numa.h +++ b/src/numa.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/perft.h b/src/perft.h index e907742da..f0d38ab72 100644 --- a/src/perft.h +++ b/src/perft.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/position.cpp b/src/position.cpp index 2bc0aa650..60b7d7d3f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/position.h b/src/position.h index a339471d2..7dc83f251 100644 --- a/src/position.h +++ b/src/position.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/score.cpp b/src/score.cpp index 179796d20..561bc23c4 100644 --- a/src/score.cpp +++ b/src/score.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/score.h b/src/score.h index 2eb40f7e0..eda90af35 100644 --- a/src/score.h +++ b/src/score.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/search.cpp b/src/search.cpp index 44394c1d6..2453679ec 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/search.h b/src/search.h index 945c66c1c..dee759410 100644 --- a/src/search.h +++ b/src/search.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 9b24e700b..120e64885 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index 75a185857..c34338fe3 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/thread.cpp b/src/thread.cpp index 5f73771ef..43ba7d9c0 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/thread.h b/src/thread.h index 43e2e1423..912d44335 100644 --- a/src/thread.h +++ b/src/thread.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/thread_win32_osx.h b/src/thread_win32_osx.h index 1d9a834f6..fb4b2ec97 100644 --- a/src/thread_win32_osx.h +++ b/src/thread_win32_osx.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/timeman.cpp b/src/timeman.cpp index 9de70fdc6..d0b0d0a94 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/timeman.h b/src/timeman.h index 10207a8a7..e8602bb7c 100644 --- a/src/timeman.h +++ b/src/timeman.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tt.cpp b/src/tt.cpp index 75689562d..50f5ca45a 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tt.h b/src/tt.h index e7bb5c452..f0936fd28 100644 --- a/src/tt.h +++ b/src/tt.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tune.cpp b/src/tune.cpp index dfcd34689..aff96c8cb 100644 --- a/src/tune.cpp +++ b/src/tune.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tune.h b/src/tune.h index ed4738cdc..4dab6bf45 100644 --- a/src/tune.h +++ b/src/tune.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/types.h b/src/types.h index 564446011..6465dfd6b 100644 --- a/src/types.h +++ b/src/types.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/uci.cpp b/src/uci.cpp index 8388cad8c..4b8e8b7f5 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/uci.h b/src/uci.h index 6adf74cb8..5c1c07f7b 100644 --- a/src/uci.h +++ b/src/uci.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 455803cfe..56cf41edc 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/ucioption.h b/src/ucioption.h index a47cc98de..c9f6787d3 100644 --- a/src/ucioption.h +++ b/src/ucioption.h @@ -1,6 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 1611b9c940f784619d6cbf01ff8b1b3ab28405a4 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Thu, 2 Jan 2025 14:58:53 -0500 Subject: [PATCH 17/26] Corrplexity for futility pruning Add corrhist-based term to futility margin Inspired by a recent patch of Shawn Xu, this tweak increases the margin over beta needed to futility prune based on the correction history, with an offset. Passed STC LLR: 2.97 (-2.94,2.94) <0.00,2.00> Total: 545504 W: 141957 L: 140885 D: 262662 Ptnml(0-2): 1829, 64226, 139551, 65336, 1810 https://tests.stockfishchess.org/tests/view/67634a8386d5ee47d95439db Passed LTC LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 125994 W: 32199 L: 31695 D: 62100 Ptnml(0-2): 97, 13742, 34798, 14280, 80 https://tests.stockfishchess.org/tests/view/6765cf9986d5ee47d9544217 closes https://github.com/official-stockfish/Stockfish/pull/5748 Bench: 999324 --- src/search.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/search.cpp b/src/search.cpp index 2453679ec..f53c116c8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -787,6 +787,7 @@ Value Search::Worker::search( if (!ss->ttPv && depth < 14 && eval - futility_margin(depth, cutNode && !ss->ttHit, improving, opponentWorsening) - (ss - 1)->statScore / 290 + + (ss->staticEval == eval) * (40 - std::abs(correctionValue) / 131072) >= beta && eval >= beta && (!ttData.move || ttCapture) && !is_loss(beta) && !is_win(eval)) return beta + (eval - beta) / 3; From c76c1793615b17b97dd504f8c81c1ff2c63c232a Mon Sep 17 00:00:00 2001 From: Daniel Monroe <39802758+Ergodice@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:18:09 -0800 Subject: [PATCH 18/26] Remove non-functional std::min() closes https://github.com/official-stockfish/Stockfish/pull/5749 No functional change --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index f53c116c8..d6748c769 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1160,7 +1160,7 @@ moves_loop: // When in check, search starts here r += 330; - r -= std::min(std::abs(correctionValue) / 32768, 2048); + r -= std::abs(correctionValue) / 32768; // Increase reduction for cut nodes (~4 Elo) if (cutNode) From 7858f9dfdcc26fc4f1bf2fc0975803c5fcee2968 Mon Sep 17 00:00:00 2001 From: sscg13 Date: Fri, 27 Dec 2024 12:15:10 +0800 Subject: [PATCH 19/26] Use same pawn value in both nets when doing material scaling of eval Passed Non-regression STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 221312 W: 57291 L: 57274 D: 106747 Ptnml(0-2): 760, 26152, 56841, 26117, 786 https://tests.stockfishchess.org/tests/view/676e2a101a2f267f20548453 Passed Non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 176808 W: 45084 L: 45023 D: 86701 Ptnml(0-2): 112, 19418, 49286, 19473, 115 https://tests.stockfishchess.org/tests/view/676f424d1a2f267f2054857f closes https://github.com/official-stockfish/Stockfish/pull/5741 Bench: 1121800 --- AUTHORS | 1 + src/evaluate.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index ddc53ec02..f6468c561 100644 --- a/AUTHORS +++ b/AUTHORS @@ -47,6 +47,7 @@ Bryan Cross (crossbr) candirufish Carlos Esparza Sánchez (ces42) Chess13234 +Chris Bao (sscg13) Chris Cain (ceebo) Ciekce clefrks diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 9a523ae44..4fce86e3a 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -78,7 +78,7 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks, optimism += optimism * nnueComplexity / 468; nnue -= nnue * nnueComplexity / (smallNet ? 20233 : 17879); - int material = (smallNet ? 553 : 532) * pos.count() + pos.non_pawn_material(); + int material = 535 * pos.count() + pos.non_pawn_material(); int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777; // Damp down the evaluation linearly when shuffling From d1a1ff4f17e91d77856f10f7e0f79b6d56e8179c Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sat, 14 Dec 2024 15:02:06 -0800 Subject: [PATCH 20/26] Simplify Razoring Passed Non-regression STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 95584 W: 24906 L: 24750 D: 45928 Ptnml(0-2): 285, 11227, 24632, 11343, 305 https://tests.stockfishchess.org/tests/view/675e0ed286d5ee47d95429ee Passed Non-regression LTC: LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 191292 W: 48637 L: 48589 D: 94066 Ptnml(0-2): 97, 21061, 53276, 21121, 91 https://tests.stockfishchess.org/tests/view/675f08c686d5ee47d9542be3 closes https://github.com/official-stockfish/Stockfish/pull/5724 Bench: 1286274 --- src/search.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index d6748c769..226506616 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -775,12 +775,9 @@ Value Search::Worker::search( // Step 7. Razoring (~1 Elo) // If eval is really low, check with qsearch if we can exceed alpha. If the // search suggests we cannot exceed alpha, return a speculative fail low. - if (eval < alpha - 469 - 307 * depth * depth) - { - value = qsearch(pos, ss, alpha - 1, alpha); - if (value < alpha && !is_decisive(value)) - return value; - } + // For PvNodes, we must have a guard against mates being returned. + if (!PvNode && eval < alpha - 469 - 307 * depth * depth) + return qsearch(pos, ss, alpha - 1, alpha); // Step 8. Futility pruning: child node (~40 Elo) // The depth condition is important for mate finding. From c47e6fcf84fecda5973cebeeb766aba43ac3cda3 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Thu, 26 Dec 2024 23:11:41 -0800 Subject: [PATCH 21/26] Small cleanup of nnue_feature_transformer.h Passed Non-regression STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 285760 W: 73716 L: 73768 D: 138276 Ptnml(0-2): 777, 30775, 79851, 30677, 800 https://tests.stockfishchess.org/tests/view/676f78681a2f267f205485aa closes https://github.com/official-stockfish/Stockfish/pull/5745 No functional change --- src/nnue/nnue_feature_transformer.h | 227 ++++++++++++++-------------- 1 file changed, 116 insertions(+), 111 deletions(-) diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 6192cd51e..b047f62c4 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -146,10 +146,10 @@ using psqt_vec_t = int32x4_t; #endif +// Compute optimal SIMD register count for feature transformer accumulation. +template +class SIMDTiling { #ifdef VECTOR - - // Compute optimal SIMD register count for feature transformer accumulation. - // We use __m* types as template arguments, which causes GCC to emit warnings // about losing some attribute information. This is irrelevant to us as we // only take their size, so the following pragma are harmless. @@ -158,33 +158,47 @@ using psqt_vec_t = int32x4_t; #pragma GCC diagnostic ignored "-Wignored-attributes" #endif -template -static constexpr int BestRegisterCount() { - #define RegisterSize sizeof(SIMDRegisterType) - #define LaneSize sizeof(LaneType) + template + static constexpr int BestRegisterCount() { + constexpr std::size_t RegisterSize = sizeof(SIMDRegisterType); + constexpr std::size_t LaneSize = sizeof(LaneType); - static_assert(RegisterSize >= LaneSize); - static_assert(MaxRegisters <= NumRegistersSIMD); - static_assert(MaxRegisters > 0); - static_assert(NumRegistersSIMD > 0); - static_assert(RegisterSize % LaneSize == 0); - static_assert((NumLanes * LaneSize) % RegisterSize == 0); + static_assert(RegisterSize >= LaneSize); + static_assert(MaxRegisters <= NumRegistersSIMD); + static_assert(MaxRegisters > 0); + static_assert(NumRegistersSIMD > 0); + static_assert(RegisterSize % LaneSize == 0); + static_assert((NumLanes * LaneSize) % RegisterSize == 0); - const int ideal = (NumLanes * LaneSize) / RegisterSize; - if (ideal <= MaxRegisters) - return ideal; + const int ideal = (NumLanes * LaneSize) / RegisterSize; + if (ideal <= MaxRegisters) + return ideal; - // Look for the largest divisor of the ideal register count that is smaller than MaxRegisters - for (int divisor = MaxRegisters; divisor > 1; --divisor) - if (ideal % divisor == 0) - return divisor; + // Look for the largest divisor of the ideal register count that is smaller than MaxRegisters + for (int divisor = MaxRegisters; divisor > 1; --divisor) + if (ideal % divisor == 0) + return divisor; + + return 1; + } - return 1; -} #if defined(__GNUC__) #pragma GCC diagnostic pop #endif + + public: + static constexpr int NumRegs = + BestRegisterCount(); + static constexpr int NumPsqtRegs = + BestRegisterCount(); + + static constexpr IndexType TileHeight = NumRegs * sizeof(vec_t) / 2; + static constexpr IndexType PsqtTileHeight = NumPsqtRegs * sizeof(psqt_vec_t) / 4; + + static_assert(HalfDimensions % TileHeight == 0, "TileHeight must divide HalfDimensions"); + static_assert(PSQTBuckets % PsqtTileHeight == 0, "PsqtTileHeight must divide PSQTBuckets"); #endif +}; // Input feature converter @@ -196,17 +210,7 @@ class FeatureTransformer { static constexpr IndexType HalfDimensions = TransformedFeatureDimensions; private: -#ifdef VECTOR - static constexpr int NumRegs = - BestRegisterCount(); - static constexpr int NumPsqtRegs = - BestRegisterCount(); - - static constexpr IndexType TileHeight = NumRegs * sizeof(vec_t) / 2; - static constexpr IndexType PsqtTileHeight = NumPsqtRegs * sizeof(psqt_vec_t) / 4; - static_assert(HalfDimensions % TileHeight == 0, "TileHeight must divide HalfDimensions"); - static_assert(PSQTBuckets % PsqtTileHeight == 0, "PsqtTileHeight must divide PSQTBuckets"); -#endif + using Tiling = SIMDTiling; public: // Output type @@ -478,8 +482,8 @@ class FeatureTransformer { #ifdef VECTOR // Gcc-10.2 unnecessarily spills AVX2 registers if this array // is defined in the VECTOR code below, once in each branch. - vec_t acc[NumRegs]; - psqt_vec_t psqt[NumPsqtRegs]; + vec_t acc[Tiling::NumRegs]; + psqt_vec_t psqt[Tiling::NumPsqtRegs]; #endif const Square ksq = pos.square(Perspective); @@ -504,14 +508,14 @@ class FeatureTransformer { #ifdef VECTOR if ((removed.size() == 1 || removed.size() == 2) && added.size() == 1) { - auto accIn = + auto* accIn = reinterpret_cast(&(computed->*accPtr).accumulation[Perspective][0]); - auto accOut = reinterpret_cast(&(next->*accPtr).accumulation[Perspective][0]); + auto* accOut = reinterpret_cast(&(next->*accPtr).accumulation[Perspective][0]); const IndexType offsetR0 = HalfDimensions * removed[0]; - auto columnR0 = reinterpret_cast(&weights[offsetR0]); + auto* columnR0 = reinterpret_cast(&weights[offsetR0]); const IndexType offsetA = HalfDimensions * added[0]; - auto columnA = reinterpret_cast(&weights[offsetA]); + auto* columnA = reinterpret_cast(&weights[offsetA]); if (removed.size() == 1) { @@ -521,22 +525,22 @@ class FeatureTransformer { else { const IndexType offsetR1 = HalfDimensions * removed[1]; - auto columnR1 = reinterpret_cast(&weights[offsetR1]); + auto* columnR1 = reinterpret_cast(&weights[offsetR1]); for (IndexType i = 0; i < HalfDimensions * sizeof(WeightType) / sizeof(vec_t); ++i) accOut[i] = vec_sub_16(vec_add_16(accIn[i], columnA[i]), vec_add_16(columnR0[i], columnR1[i])); } - auto accPsqtIn = reinterpret_cast( + auto* accPsqtIn = reinterpret_cast( &(computed->*accPtr).psqtAccumulation[Perspective][0]); - auto accPsqtOut = + auto* accPsqtOut = reinterpret_cast(&(next->*accPtr).psqtAccumulation[Perspective][0]); const IndexType offsetPsqtR0 = PSQTBuckets * removed[0]; - auto columnPsqtR0 = reinterpret_cast(&psqtWeights[offsetPsqtR0]); + auto* columnPsqtR0 = reinterpret_cast(&psqtWeights[offsetPsqtR0]); const IndexType offsetPsqtA = PSQTBuckets * added[0]; - auto columnPsqtA = reinterpret_cast(&psqtWeights[offsetPsqtA]); + auto* columnPsqtA = reinterpret_cast(&psqtWeights[offsetPsqtA]); if (removed.size() == 1) { @@ -548,7 +552,8 @@ class FeatureTransformer { else { const IndexType offsetPsqtR1 = PSQTBuckets * removed[1]; - auto columnPsqtR1 = reinterpret_cast(&psqtWeights[offsetPsqtR1]); + auto* columnPsqtR1 = + reinterpret_cast(&psqtWeights[offsetPsqtR1]); for (std::size_t i = 0; i < PSQTBuckets * sizeof(PSQTWeightType) / sizeof(psqt_vec_t); ++i) @@ -559,69 +564,69 @@ class FeatureTransformer { } else { - for (IndexType i = 0; i < HalfDimensions / TileHeight; ++i) + for (IndexType i = 0; i < HalfDimensions / Tiling::TileHeight; ++i) { // Load accumulator - auto accTileIn = reinterpret_cast( - &(computed->*accPtr).accumulation[Perspective][i * TileHeight]); - for (IndexType j = 0; j < NumRegs; ++j) + auto* accTileIn = reinterpret_cast( + &(computed->*accPtr).accumulation[Perspective][i * Tiling::TileHeight]); + for (IndexType j = 0; j < Tiling::NumRegs; ++j) acc[j] = vec_load(&accTileIn[j]); // Difference calculation for the deactivated features for (const auto index : removed) { - const IndexType offset = HalfDimensions * index + i * TileHeight; - auto column = reinterpret_cast(&weights[offset]); - for (IndexType j = 0; j < NumRegs; ++j) + const IndexType offset = HalfDimensions * index + i * Tiling::TileHeight; + auto* column = reinterpret_cast(&weights[offset]); + for (IndexType j = 0; j < Tiling::NumRegs; ++j) acc[j] = vec_sub_16(acc[j], column[j]); } // Difference calculation for the activated features for (const auto index : added) { - const IndexType offset = HalfDimensions * index + i * TileHeight; - auto column = reinterpret_cast(&weights[offset]); - for (IndexType j = 0; j < NumRegs; ++j) + const IndexType offset = HalfDimensions * index + i * Tiling::TileHeight; + auto* column = reinterpret_cast(&weights[offset]); + for (IndexType j = 0; j < Tiling::NumRegs; ++j) acc[j] = vec_add_16(acc[j], column[j]); } // Store accumulator - auto accTileOut = reinterpret_cast( - &(next->*accPtr).accumulation[Perspective][i * TileHeight]); - for (IndexType j = 0; j < NumRegs; ++j) + auto* accTileOut = reinterpret_cast( + &(next->*accPtr).accumulation[Perspective][i * Tiling::TileHeight]); + for (IndexType j = 0; j < Tiling::NumRegs; ++j) vec_store(&accTileOut[j], acc[j]); } - for (IndexType i = 0; i < PSQTBuckets / PsqtTileHeight; ++i) + for (IndexType i = 0; i < PSQTBuckets / Tiling::PsqtTileHeight; ++i) { // Load accumulator - auto accTilePsqtIn = reinterpret_cast( - &(computed->*accPtr).psqtAccumulation[Perspective][i * PsqtTileHeight]); - for (std::size_t j = 0; j < NumPsqtRegs; ++j) + auto* accTilePsqtIn = reinterpret_cast( + &(computed->*accPtr).psqtAccumulation[Perspective][i * Tiling::PsqtTileHeight]); + for (std::size_t j = 0; j < Tiling::NumPsqtRegs; ++j) psqt[j] = vec_load_psqt(&accTilePsqtIn[j]); // Difference calculation for the deactivated features for (const auto index : removed) { - const IndexType offset = PSQTBuckets * index + i * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t j = 0; j < NumPsqtRegs; ++j) + const IndexType offset = PSQTBuckets * index + i * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&psqtWeights[offset]); + for (std::size_t j = 0; j < Tiling::NumPsqtRegs; ++j) psqt[j] = vec_sub_psqt_32(psqt[j], columnPsqt[j]); } // Difference calculation for the activated features for (const auto index : added) { - const IndexType offset = PSQTBuckets * index + i * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t j = 0; j < NumPsqtRegs; ++j) + const IndexType offset = PSQTBuckets * index + i * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&psqtWeights[offset]); + for (std::size_t j = 0; j < Tiling::NumPsqtRegs; ++j) psqt[j] = vec_add_psqt_32(psqt[j], columnPsqt[j]); } // Store accumulator - auto accTilePsqtOut = reinterpret_cast( - &(next->*accPtr).psqtAccumulation[Perspective][i * PsqtTileHeight]); - for (std::size_t j = 0; j < NumPsqtRegs; ++j) + auto* accTilePsqtOut = reinterpret_cast( + &(next->*accPtr).psqtAccumulation[Perspective][i * Tiling::PsqtTileHeight]); + for (std::size_t j = 0; j < Tiling::NumPsqtRegs; ++j) vec_store_psqt(&accTilePsqtOut[j], psqt[j]); } } @@ -700,88 +705,88 @@ class FeatureTransformer { accumulator.computed[Perspective] = true; #ifdef VECTOR - vec_t acc[NumRegs]; - psqt_vec_t psqt[NumPsqtRegs]; + vec_t acc[Tiling::NumRegs]; + psqt_vec_t psqt[Tiling::NumPsqtRegs]; - for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) + for (IndexType j = 0; j < HalfDimensions / Tiling::TileHeight; ++j) { - auto accTile = - reinterpret_cast(&accumulator.accumulation[Perspective][j * TileHeight]); - auto entryTile = reinterpret_cast(&entry.accumulation[j * TileHeight]); + auto* accTile = reinterpret_cast( + &accumulator.accumulation[Perspective][j * Tiling::TileHeight]); + auto* entryTile = reinterpret_cast(&entry.accumulation[j * Tiling::TileHeight]); - for (IndexType k = 0; k < NumRegs; ++k) + for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = entryTile[k]; - int i = 0; - for (; i < int(std::min(removed.size(), added.size())); ++i) + std::size_t i = 0; + for (; i < std::min(removed.size(), added.size()); ++i) { IndexType indexR = removed[i]; - const IndexType offsetR = HalfDimensions * indexR + j * TileHeight; - auto columnR = reinterpret_cast(&weights[offsetR]); + const IndexType offsetR = HalfDimensions * indexR + j * Tiling::TileHeight; + auto* columnR = reinterpret_cast(&weights[offsetR]); IndexType indexA = added[i]; - const IndexType offsetA = HalfDimensions * indexA + j * TileHeight; - auto columnA = reinterpret_cast(&weights[offsetA]); + const IndexType offsetA = HalfDimensions * indexA + j * Tiling::TileHeight; + auto* columnA = reinterpret_cast(&weights[offsetA]); - for (unsigned k = 0; k < NumRegs; ++k) + for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_add_16(acc[k], vec_sub_16(columnA[k], columnR[k])); } - for (; i < int(removed.size()); ++i) + for (; i < removed.size(); ++i) { IndexType index = removed[i]; - const IndexType offset = HalfDimensions * index + j * TileHeight; - auto column = reinterpret_cast(&weights[offset]); + const IndexType offset = HalfDimensions * index + j * Tiling::TileHeight; + auto* column = reinterpret_cast(&weights[offset]); - for (unsigned k = 0; k < NumRegs; ++k) + for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_sub_16(acc[k], column[k]); } - for (; i < int(added.size()); ++i) + for (; i < added.size(); ++i) { IndexType index = added[i]; - const IndexType offset = HalfDimensions * index + j * TileHeight; - auto column = reinterpret_cast(&weights[offset]); + const IndexType offset = HalfDimensions * index + j * Tiling::TileHeight; + auto* column = reinterpret_cast(&weights[offset]); - for (unsigned k = 0; k < NumRegs; ++k) + for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_add_16(acc[k], column[k]); } - for (IndexType k = 0; k < NumRegs; k++) + for (IndexType k = 0; k < Tiling::NumRegs; k++) vec_store(&entryTile[k], acc[k]); - for (IndexType k = 0; k < NumRegs; k++) + for (IndexType k = 0; k < Tiling::NumRegs; k++) vec_store(&accTile[k], acc[k]); } - for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j) + for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) { - auto accTilePsqt = reinterpret_cast( - &accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); - auto entryTilePsqt = - reinterpret_cast(&entry.psqtAccumulation[j * PsqtTileHeight]); + auto* accTilePsqt = reinterpret_cast( + &accumulator.psqtAccumulation[Perspective][j * Tiling::PsqtTileHeight]); + auto* entryTilePsqt = + reinterpret_cast(&entry.psqtAccumulation[j * Tiling::PsqtTileHeight]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) + for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = entryTilePsqt[k]; - for (int i = 0; i < int(removed.size()); ++i) + for (std::size_t i = 0; i < removed.size(); ++i) { IndexType index = removed[i]; - const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); + const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) + for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]); } - for (int i = 0; i < int(added.size()); ++i) + for (std::size_t i = 0; i < added.size(); ++i) { IndexType index = added[i]; - const IndexType offset = PSQTBuckets * index + j * PsqtTileHeight; - auto columnPsqt = reinterpret_cast(&psqtWeights[offset]); + const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&psqtWeights[offset]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) + for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]); } - for (std::size_t k = 0; k < NumPsqtRegs; ++k) + for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) vec_store_psqt(&entryTilePsqt[k], psqt[k]); - for (std::size_t k = 0; k < NumPsqtRegs; ++k) + for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) vec_store_psqt(&accTilePsqt[k], psqt[k]); } From 5370c3035e17a163376d83c49e7c927174e587a7 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sun, 5 Jan 2025 17:11:22 -0800 Subject: [PATCH 22/26] Refactor Stats Array * Limit use of `StatsEntry` wrapper to arithmetic types * Generalize `Stats` to `MultiArray` by discarding the template parameter `D` * Allow `MultiArray::fill` to take any type assignable to element type * Remove now-unused operator overloads on `StatsEntry` closes https://github.com/official-stockfish/Stockfish/pull/5750 No functional change --- src/history.h | 97 ++++++++++++++---------------------------------- src/misc.h | 87 +++++++++++++++++++++++++++++++++++++++++++ src/movepick.cpp | 1 + src/search.cpp | 4 +- 4 files changed, 117 insertions(+), 72 deletions(-) diff --git a/src/history.h b/src/history.h index edf7fdc67..15095cd0b 100644 --- a/src/history.h +++ b/src/history.h @@ -28,6 +28,7 @@ #include #include // IWYU pragma: keep +#include "misc.h" #include "position.h" namespace Stockfish { @@ -66,13 +67,17 @@ inline int non_pawn_index(const Position& pos) { return pos.non_pawn_key(c) & (CORRECTION_HISTORY_SIZE - 1); } -// StatsEntry stores the stat table value. It is usually a number but could -// be a move or even a nested history. We use a class instead of a naked value -// to directly call history update operator<<() on the entry so to use stats -// tables at caller sites as simple multi-dim arrays. +// StatsEntry is the container of various numerical statistics. We use a class +// instead of a naked value to directly call history update operator<<() on +// the entry. The first template parameter T is the base type of the array, +// and the second template parameter D limits the range of updates in [-D, D] +// when we update values with the << operator template class StatsEntry { + static_assert(std::is_arithmetic::value, "Not an arithmetic type"); + static_assert(D <= std::numeric_limits::max(), "D overflows T"); + T entry; public: @@ -80,13 +85,9 @@ class StatsEntry { entry = v; return *this; } - T* operator&() { return &entry; } - T* operator->() { return &entry; } operator const T&() const { return entry; } void operator<<(int bonus) { - static_assert(D <= std::numeric_limits::max(), "D overflows T"); - // Make sure that bonus is in range [-D, D] int clampedBonus = std::clamp(bonus, -D, D); entry += clampedBonus - entry * std::abs(clampedBonus) / D; @@ -95,87 +96,39 @@ class StatsEntry { } }; -template -struct StatsHelper; - -// Stats is a generic N-dimensional array used to store various statistics. -// The first template parameter T is the base type of the array, and the second -// template parameter D limits the range of updates in [-D, D] when we update -// values with the << operator, while the last parameters (Size and Sizes) -// encode the dimensions of the array. -template -class Stats { - using child_type = typename StatsHelper::child_type; - using array_type = std::array; - array_type data; - - public: - using size_type = typename array_type::size_type; - - auto& operator[](size_type index) { return data[index]; } - const auto& operator[](size_type index) const { return data[index]; } - - auto begin() { return data.begin(); } - auto end() { return data.end(); } - auto begin() const { return data.cbegin(); } - auto end() const { return data.cend(); } - auto cbegin() const { return data.cbegin(); } - auto cend() const { return data.cend(); } - - void fill(const T& v) { - for (auto& ele : data) - { - if constexpr (sizeof...(Sizes) == 0) - ele = v; - else - ele.fill(v); - } - } -}; - -template -struct StatsHelper { - using child_type = Stats; -}; - -template -struct StatsHelper { - using child_type = StatsEntry; -}; - -// In stats table, D=0 means that the template parameter is not used -enum StatsParams { - NOT_USED = 0 -}; enum StatsType { NoCaptures, Captures }; +template +using Stats = MultiArray, Sizes...>; + // ButterflyHistory records how often quiet moves have been successful or unsuccessful // during the current search, and is used for reduction and move ordering decisions. // It uses 2 tables (one for each color) indexed by the move's from and to squares, // see https://www.chessprogramming.org/Butterfly_Boards (~11 elo) -using ButterflyHistory = Stats; +using ButterflyHistory = Stats; // LowPlyHistory is adressed by play and move's from and to squares, used // to improve move ordering near the root -using LowPlyHistory = Stats; +using LowPlyHistory = + Stats; // CapturePieceToHistory is addressed by a move's [piece][to][captured piece type] -using CapturePieceToHistory = Stats; +using CapturePieceToHistory = Stats; // PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to] -using PieceToHistory = Stats; +using PieceToHistory = Stats; // ContinuationHistory is the combined history of a given pair of moves, usually // the current one given a previous one. The nested history table is based on // PieceToHistory instead of ButterflyBoards. // (~63 elo) -using ContinuationHistory = Stats; +using ContinuationHistory = MultiArray; // PawnHistory is addressed by the pawn structure and a move's [piece][to] -using PawnHistory = Stats; +using PawnHistory = Stats; // Correction histories record differences between the static evaluation of // positions and their search score. It is used to improve the static evaluation @@ -190,23 +143,27 @@ enum CorrHistType { Continuation, // Combined history of move pairs }; +namespace Detail { + template struct CorrHistTypedef { - using type = Stats; + using type = Stats; }; template<> struct CorrHistTypedef { - using type = Stats; + using type = Stats; }; template<> struct CorrHistTypedef { - using type = Stats::type, NOT_USED, PIECE_NB, SQUARE_NB>; + using type = MultiArray::type, PIECE_NB, SQUARE_NB>; }; +} + template -using CorrectionHistory = typename CorrHistTypedef::type; +using CorrectionHistory = typename Detail::CorrHistTypedef::type; } // namespace Stockfish diff --git a/src/misc.h b/src/misc.h index 48c49bafb..81c7b17fe 100644 --- a/src/misc.h +++ b/src/misc.h @@ -20,6 +20,7 @@ #define MISC_H_INCLUDED #include +#include #include #include #include @@ -142,6 +143,92 @@ class ValueList { }; +template +class MultiArray; + +namespace Detail { + +template +struct MultiArrayHelper { + using ChildType = MultiArray; +}; + +template +struct MultiArrayHelper { + using ChildType = T; +}; + +} + +// MultiArray is a generic N-dimensional array. +// The template parameters (Size and Sizes) encode the dimensions of the array. +template +class MultiArray { + using ChildType = typename Detail::MultiArrayHelper::ChildType; + using ArrayType = std::array; + ArrayType data_; + + public: + using value_type = typename ArrayType::value_type; + using size_type = typename ArrayType::size_type; + using difference_type = typename ArrayType::difference_type; + using reference = typename ArrayType::reference; + using const_reference = typename ArrayType::const_reference; + using pointer = typename ArrayType::pointer; + using const_pointer = typename ArrayType::const_pointer; + using iterator = typename ArrayType::iterator; + using const_iterator = typename ArrayType::const_iterator; + using reverse_iterator = typename ArrayType::reverse_iterator; + using const_reverse_iterator = typename ArrayType::const_reverse_iterator; + + constexpr auto& at(size_type index) noexcept { return data_.at(index); } + constexpr const auto& at(size_type index) const noexcept { return data_.at(index); } + + constexpr auto& operator[](size_type index) noexcept { return data_[index]; } + constexpr const auto& operator[](size_type index) const noexcept { return data_[index]; } + + constexpr auto& front() noexcept { return data_.front(); } + constexpr const auto& front() const noexcept { return data_.front(); } + constexpr auto& back() noexcept { return data_.back(); } + constexpr const auto& back() const noexcept { return data_.back(); } + + auto* data() { return data_.data(); } + const auto* data() const { return data_.data(); } + + constexpr auto begin() noexcept { return data_.begin(); } + constexpr auto end() noexcept { return data_.end(); } + constexpr auto begin() const noexcept { return data_.begin(); } + constexpr auto end() const noexcept { return data_.end(); } + constexpr auto cbegin() const noexcept { return data_.cbegin(); } + constexpr auto cend() const noexcept { return data_.cend(); } + + constexpr auto rbegin() noexcept { return data_.rbegin(); } + constexpr auto rend() noexcept { return data_.rend(); } + constexpr auto rbegin() const noexcept { return data_.rbegin(); } + constexpr auto rend() const noexcept { return data_.rend(); } + constexpr auto crbegin() const noexcept { return data_.crbegin(); } + constexpr auto crend() const noexcept { return data_.crend(); } + + constexpr bool empty() const noexcept { return data_.empty(); } + constexpr size_type size() const noexcept { return data_.size(); } + constexpr size_type max_size() const noexcept { return data_.max_size(); } + + template + void fill(const U& v) { + static_assert(std::is_assignable_v, "Cannot assign fill value to entry type"); + for (auto& ele : data_) + { + if constexpr (sizeof...(Sizes) == 0) + ele = v; + else + ele.fill(v); + } + } + + constexpr void swap(MultiArray& other) noexcept { data_.swap(other.data_); } +}; + + // xorshift64star Pseudo-Random Number Generator // This class is based on original code written and dedicated // to the public domain by Sebastiano Vigna (2014). diff --git a/src/movepick.cpp b/src/movepick.cpp index 4c5cc11de..844861694 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -22,6 +22,7 @@ #include #include "bitboard.h" +#include "misc.h" #include "position.h" namespace Stockfish { diff --git a/src/search.cpp b/src/search.cpp index 226506616..d937c399a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -510,13 +510,13 @@ void Search::Worker::clear() { for (auto& to : continuationCorrectionHistory) for (auto& h : to) - h->fill(0); + h.fill(0); for (bool inCheck : {false, true}) for (StatsType c : {NoCaptures, Captures}) for (auto& to : continuationHistory[inCheck][c]) for (auto& h : to) - h->fill(-427); + h.fill(-427); for (size_t i = 1; i < reductions.size(); ++i) reductions[i] = int(19.43 * std::log(i)); From 403a5e100b006b46d3b4001ae9a3ef53ad1b7558 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Tue, 31 Dec 2024 21:14:16 -0800 Subject: [PATCH 23/26] Simplify Fail-Low Bonus Passed Non-regression STC: LLR: 2.92 (-2.94,2.94) <-1.75,0.25> Total: 66592 W: 17426 L: 17239 D: 31927 Ptnml(0-2): 208, 7812, 17109, 7919, 248 https://tests.stockfishchess.org/tests/view/6774e1711a2f267f20548b22 Passed Non-regression LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 179616 W: 45764 L: 45706 D: 88146 Ptnml(0-2): 125, 19665, 50162, 19739, 117 https://tests.stockfishchess.org/tests/view/677590531a2f267f20548b82 closes https://github.com/official-stockfish/Stockfish/pull/5751 Bench: 1310158 --- src/search.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index d937c399a..42a7bb971 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1408,10 +1408,6 @@ moves_loop: // When in check, search starts here << stat_bonus(depth) * 2; } - // Bonus when search fails low and there is a TT move - else if (ttData.move && !allNode) - thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) * 287 / 1024; - if (PvNode) bestValue = std::min(bestValue, maxValue); From c88a5b395021a0020b417faf897e8ad3b71512e7 Mon Sep 17 00:00:00 2001 From: pb00067 Date: Tue, 7 Jan 2025 10:06:03 +0100 Subject: [PATCH 24/26] Simplify away hint for common parent position at probcut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since it's introduction at probcut step the nnue network has changed substantially and now it no longer seems useful. Passed non-regression test at STC https://tests.stockfishchess.org/tests/view/675fe27986d5ee47d9542d86 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 118656 W: 30732 L: 30609 D: 57315 Ptnml(0-2): 319, 12767, 33049, 12858, 335 N.B.: It may be useful to reintroduce it here at probcut if we know that a node that was cut away previously now has to be explored. Exploring new ground will deliver no tt-hits so in this case the hint for common parent position might be useful. No functional change --- src/search.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 42a7bb971..4a72a4162 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -911,8 +911,6 @@ Value Search::Worker::search( return is_decisive(value) ? value : value - (probCutBeta - beta); } } - - Eval::NNUE::hint_common_parent_position(pos, networks[numaAccessToken], refreshTable); } moves_loop: // When in check, search starts here From d49fd9090bc3668638f5686cb0ae39bdadc342cf Mon Sep 17 00:00:00 2001 From: Maxim Masiutin Date: Tue, 7 Jan 2025 15:30:05 +0200 Subject: [PATCH 25/26] Add .gitattributes for script LE closes https://github.com/official-stockfish/Stockfish/pull/5753 No functional change --- scripts/.gitattributes | 1 + tests/.gitattributes | 1 + 2 files changed, 2 insertions(+) create mode 100644 scripts/.gitattributes create mode 100644 tests/.gitattributes diff --git a/scripts/.gitattributes b/scripts/.gitattributes new file mode 100644 index 000000000..dfdb8b771 --- /dev/null +++ b/scripts/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf diff --git a/tests/.gitattributes b/tests/.gitattributes new file mode 100644 index 000000000..dfdb8b771 --- /dev/null +++ b/tests/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf From ea71a088435d4f1e51433c0a321f2afdff7814b1 Mon Sep 17 00:00:00 2001 From: Disservin Date: Tue, 7 Jan 2025 21:16:12 +0100 Subject: [PATCH 26/26] Improve Instrumented Python Testing Script For betting debugging and earlier stop in case of termination, like in https://github.com/official-stockfish/Stockfish/pull/5754#issuecomment-2576120357 closes https://github.com/official-stockfish/Stockfish/pull/5755 No functional change --- tests/testing.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/testing.py b/tests/testing.py index d51ca89ac..bc1f6b15b 100644 --- a/tests/testing.py +++ b/tests/testing.py @@ -150,6 +150,7 @@ class MiniTestFramework: self.failed_test_suites = 0 self.passed_tests = 0 self.failed_tests = 0 + self.stop_on_failure = True def has_failed(self) -> bool: return self.failed_test_suites > 0 @@ -167,6 +168,9 @@ class MiniTestFramework: self.failed_test_suites += 1 else: self.passed_test_suites += 1 + except Exception as e: + self.failed_test_suites += 1 + print(f"\n{RED_COLOR}Error: {e}{RESET_COLOR}") finally: os.chdir(original_cwd) @@ -226,6 +230,10 @@ class MiniTestFramework: if isinstance(e, AssertionError): self.__handle_assertion_error(t0, method) + if self.stop_on_failure: + self.__print_buffer_output(buffer) + raise e + fails += 1 finally: self.__print_buffer_output(buffer) @@ -286,6 +294,11 @@ class Stockfish: self.start() + def _check_process_alive(self): + if not self.process or self.process.poll() is not None: + print("\n".join(self.output)) + raise RuntimeError("Stockfish process has terminated") + def start(self): if self.cli: self.process = subprocess.run( @@ -314,6 +327,8 @@ class Stockfish: if not self.process: raise RuntimeError("Stockfish process is not started") + self._check_process_alive() + self.process.stdin.write(command + "\n") self.process.stdin.flush() @@ -355,6 +370,7 @@ class Stockfish: raise RuntimeError("Stockfish process is not started") while True: + self._check_process_alive() line = self.process.stdout.readline().strip() self.output.append(line)