mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Merge commit 'ea71a088435d4f1e51433c0a321f2afdff7814b1' into cluster
This is the last commit before there are more conflicts.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -47,6 +47,7 @@ Bryan Cross (crossbr)
|
||||
candirufish
|
||||
Carlos Esparza Sánchez (ces42)
|
||||
Chess13234
|
||||
Chris Bao (sscg13)
|
||||
Chris Cain (ceebo)
|
||||
Ciekce
|
||||
clefrks
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.sh text eol=lf
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-9
@@ -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
|
||||
@@ -58,7 +58,6 @@ Engine::Engine(std::optional<std::string> 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<std::string>
|
||||
states = StateListPtr(new std::deque<StateInfo>(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<std::string>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -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
|
||||
@@ -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;
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -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<PAWN>() + pos.non_pawn_material();
|
||||
int material = 535 * pos.count<PAWN>() + pos.non_pawn_material();
|
||||
int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777;
|
||||
|
||||
// Damp down the evaluation linearly when shuffling
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+32
-47
@@ -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
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <limits>
|
||||
#include <type_traits> // IWYU pragma: keep
|
||||
|
||||
#include "misc.h"
|
||||
#include "position.h"
|
||||
|
||||
namespace Stockfish {
|
||||
@@ -66,24 +67,27 @@ 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<typename T, int D>
|
||||
class StatsEntry {
|
||||
|
||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
|
||||
|
||||
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;
|
||||
}
|
||||
operator const T&() const { return entry; }
|
||||
|
||||
void operator<<(int bonus) {
|
||||
static_assert(D <= std::numeric_limits<T>::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;
|
||||
@@ -92,62 +96,39 @@ class StatsEntry {
|
||||
}
|
||||
};
|
||||
|
||||
// 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<typename T, int D, int Size, int... Sizes>
|
||||
struct Stats: public std::array<Stats<T, D, Sizes...>, Size> {
|
||||
using stats = Stats<T, D, Size, Sizes...>;
|
||||
|
||||
void fill(const T& v) {
|
||||
|
||||
// For standard-layout 'this' points to the first struct member
|
||||
assert(std::is_standard_layout_v<stats>);
|
||||
|
||||
using entry = StatsEntry<T, D>;
|
||||
entry* p = reinterpret_cast<entry*>(this);
|
||||
std::fill(p, p + sizeof(*this) / sizeof(entry), v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int D, int Size>
|
||||
struct Stats<T, D, Size>: public std::array<StatsEntry<T, D>, Size> {};
|
||||
|
||||
// In stats table, D=0 means that the template parameter is not used
|
||||
enum StatsParams {
|
||||
NOT_USED = 0
|
||||
};
|
||||
enum StatsType {
|
||||
NoCaptures,
|
||||
Captures
|
||||
};
|
||||
|
||||
template<typename T, int D, std::size_t... Sizes>
|
||||
using Stats = MultiArray<StatsEntry<T, D>, 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<int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)>;
|
||||
using ButterflyHistory = Stats<std::int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)>;
|
||||
|
||||
// LowPlyHistory is adressed by play and move's from and to squares, used
|
||||
// to improve move ordering near the root
|
||||
using LowPlyHistory = Stats<int16_t, 7183, LOW_PLY_HISTORY_SIZE, int(SQUARE_NB) * int(SQUARE_NB)>;
|
||||
using LowPlyHistory =
|
||||
Stats<std::int16_t, 7183, LOW_PLY_HISTORY_SIZE, int(SQUARE_NB) * int(SQUARE_NB)>;
|
||||
|
||||
// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
|
||||
using CapturePieceToHistory = Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
|
||||
using CapturePieceToHistory = Stats<std::int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
|
||||
|
||||
// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
|
||||
using PieceToHistory = Stats<int16_t, 30000, PIECE_NB, SQUARE_NB>;
|
||||
using PieceToHistory = Stats<std::int16_t, 30000, PIECE_NB, SQUARE_NB>;
|
||||
|
||||
// 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<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB>;
|
||||
using ContinuationHistory = MultiArray<PieceToHistory, PIECE_NB, SQUARE_NB>;
|
||||
|
||||
// PawnHistory is addressed by the pawn structure and a move's [piece][to]
|
||||
using PawnHistory = Stats<int16_t, 8192, PAWN_HISTORY_SIZE, PIECE_NB, SQUARE_NB>;
|
||||
using PawnHistory = Stats<std::int16_t, 8192, PAWN_HISTORY_SIZE, PIECE_NB, SQUARE_NB>;
|
||||
|
||||
// Correction histories record differences between the static evaluation of
|
||||
// positions and their search score. It is used to improve the static evaluation
|
||||
@@ -162,23 +143,27 @@ enum CorrHistType {
|
||||
Continuation, // Combined history of move pairs
|
||||
};
|
||||
|
||||
namespace Detail {
|
||||
|
||||
template<CorrHistType _>
|
||||
struct CorrHistTypedef {
|
||||
using type = Stats<int16_t, CORRECTION_HISTORY_LIMIT, COLOR_NB, CORRECTION_HISTORY_SIZE>;
|
||||
using type = Stats<std::int16_t, CORRECTION_HISTORY_LIMIT, COLOR_NB, CORRECTION_HISTORY_SIZE>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CorrHistTypedef<PieceTo> {
|
||||
using type = Stats<int16_t, CORRECTION_HISTORY_LIMIT, PIECE_NB, SQUARE_NB>;
|
||||
using type = Stats<std::int16_t, CORRECTION_HISTORY_LIMIT, PIECE_NB, SQUARE_NB>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CorrHistTypedef<Continuation> {
|
||||
using type = Stats<CorrHistTypedef<PieceTo>::type, NOT_USED, PIECE_NB, SQUARE_NB>;
|
||||
using type = MultiArray<CorrHistTypedef<PieceTo>::type, PIECE_NB, SQUARE_NB>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<CorrHistType T>
|
||||
using CorrectionHistory = typename CorrHistTypedef<T>::type;
|
||||
using CorrectionHistory = typename Detail::CorrHistTypedef<T>::type;
|
||||
|
||||
} // namespace Stockfish
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+30
-25
@@ -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
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
@@ -287,7 +289,10 @@ template<size_t N>
|
||||
struct DebugInfo {
|
||||
std::atomic<int64_t> data[N] = {0};
|
||||
|
||||
constexpr std::atomic<int64_t>& operator[](int index) { return data[index]; }
|
||||
[[nodiscard]] constexpr std::atomic<int64_t>& 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<DebugInfo<2>, MaxDebugSlots> hit;
|
||||
std::array<DebugInfo<2>, MaxDebugSlots> mean;
|
||||
std::array<DebugInfo<3>, MaxDebugSlots> stdev;
|
||||
std::array<DebugInfo<6>, MaxDebugSlots> correl;
|
||||
std::array<DebugExtremes, MaxDebugSlots> 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() {
|
||||
|
||||
+88
-1
@@ -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
|
||||
@@ -20,6 +20,7 @@
|
||||
#define MISC_H_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
@@ -142,6 +143,92 @@ class ValueList {
|
||||
};
|
||||
|
||||
|
||||
template<typename T, std::size_t Size, std::size_t... Sizes>
|
||||
class MultiArray;
|
||||
|
||||
namespace Detail {
|
||||
|
||||
template<typename T, std::size_t Size, std::size_t... Sizes>
|
||||
struct MultiArrayHelper {
|
||||
using ChildType = MultiArray<T, Sizes...>;
|
||||
};
|
||||
|
||||
template<typename T, std::size_t Size>
|
||||
struct MultiArrayHelper<T, Size> {
|
||||
using ChildType = T;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// MultiArray is a generic N-dimensional array.
|
||||
// The template parameters (Size and Sizes) encode the dimensions of the array.
|
||||
template<typename T, std::size_t Size, std::size_t... Sizes>
|
||||
class MultiArray {
|
||||
using ChildType = typename Detail::MultiArrayHelper<T, Size, Sizes...>::ChildType;
|
||||
using ArrayType = std::array<ChildType, Size>;
|
||||
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<typename U>
|
||||
void fill(const U& v) {
|
||||
static_assert(std::is_assignable_v<T, U>, "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<T, Size, Sizes...>& 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).
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
#include "movepick.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include "bitboard.h"
|
||||
#include "misc.h"
|
||||
#include "position.h"
|
||||
|
||||
namespace Stockfish {
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -39,7 +39,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
|
||||
@@ -59,6 +58,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,
|
||||
@@ -101,7 +102,7 @@ bool read_parameters(std::istream& stream, T& reference) {
|
||||
|
||||
// Write evaluation function parameters
|
||||
template<typename T>
|
||||
bool write_parameters(std::ostream& stream, const T& reference) {
|
||||
bool write_parameters(std::ostream& stream, T& reference) {
|
||||
|
||||
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
|
||||
return reference.write_parameters(stream);
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+110
-107
@@ -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
|
||||
@@ -144,10 +144,10 @@ using psqt_vec_t = int32x4_t;
|
||||
#endif
|
||||
|
||||
|
||||
// Compute optimal SIMD register count for feature transformer accumulation.
|
||||
template<IndexType TransformedFeatureWidth, IndexType HalfDimensions>
|
||||
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.
|
||||
@@ -156,10 +156,10 @@ using psqt_vec_t = int32x4_t;
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
|
||||
template<typename SIMDRegisterType, typename LaneType, int NumLanes, int MaxRegisters>
|
||||
static constexpr int BestRegisterCount() {
|
||||
#define RegisterSize sizeof(SIMDRegisterType)
|
||||
#define LaneSize sizeof(LaneType)
|
||||
template<typename SIMDRegisterType, typename LaneType, int NumLanes, int MaxRegisters>
|
||||
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);
|
||||
@@ -178,11 +178,25 @@ static constexpr int BestRegisterCount() {
|
||||
return divisor;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
static constexpr int NumRegs =
|
||||
BestRegisterCount<vec_t, WeightType, TransformedFeatureWidth, NumRegistersSIMD>();
|
||||
static constexpr int NumPsqtRegs =
|
||||
BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>();
|
||||
|
||||
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
|
||||
@@ -194,17 +208,7 @@ class FeatureTransformer {
|
||||
static constexpr IndexType HalfDimensions = TransformedFeatureDimensions;
|
||||
|
||||
private:
|
||||
#ifdef VECTOR
|
||||
static constexpr int NumRegs =
|
||||
BestRegisterCount<vec_t, WeightType, TransformedFeatureDimensions, NumRegistersSIMD>();
|
||||
static constexpr int NumPsqtRegs =
|
||||
BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>();
|
||||
|
||||
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<TransformedFeatureDimensions, HalfDimensions>;
|
||||
|
||||
public:
|
||||
// Output type
|
||||
@@ -254,21 +258,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<uint64_t*>(const_cast<BiasType*>(&biases[0]));
|
||||
uint64_t* b = reinterpret_cast<uint64_t*>(&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<uint64_t*>(const_cast<WeightType*>(&weights[j * HalfDimensions]));
|
||||
uint64_t* w = reinterpret_cast<uint64_t*>(&weights[j * HalfDimensions]);
|
||||
for (IndexType i = 0; i < HalfDimensions * sizeof(WeightType) / sizeof(uint64_t);
|
||||
i += di)
|
||||
order_fn(&w[i]);
|
||||
@@ -276,17 +279,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<WeightType*>(&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<BiasType*>(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
|
||||
@@ -302,7 +304,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);
|
||||
@@ -478,8 +480,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<KING>(Perspective);
|
||||
@@ -504,14 +506,14 @@ class FeatureTransformer {
|
||||
#ifdef VECTOR
|
||||
if ((removed.size() == 1 || removed.size() == 2) && added.size() == 1)
|
||||
{
|
||||
auto accIn =
|
||||
auto* accIn =
|
||||
reinterpret_cast<const vec_t*>(&(computed->*accPtr).accumulation[Perspective][0]);
|
||||
auto accOut = reinterpret_cast<vec_t*>(&(next->*accPtr).accumulation[Perspective][0]);
|
||||
auto* accOut = reinterpret_cast<vec_t*>(&(next->*accPtr).accumulation[Perspective][0]);
|
||||
|
||||
const IndexType offsetR0 = HalfDimensions * removed[0];
|
||||
auto columnR0 = reinterpret_cast<const vec_t*>(&weights[offsetR0]);
|
||||
auto* columnR0 = reinterpret_cast<const vec_t*>(&weights[offsetR0]);
|
||||
const IndexType offsetA = HalfDimensions * added[0];
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
auto* columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
|
||||
if (removed.size() == 1)
|
||||
{
|
||||
@@ -521,22 +523,22 @@ class FeatureTransformer {
|
||||
else
|
||||
{
|
||||
const IndexType offsetR1 = HalfDimensions * removed[1];
|
||||
auto columnR1 = reinterpret_cast<const vec_t*>(&weights[offsetR1]);
|
||||
auto* columnR1 = reinterpret_cast<const vec_t*>(&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<const psqt_vec_t*>(
|
||||
auto* accPsqtIn = reinterpret_cast<const psqt_vec_t*>(
|
||||
&(computed->*accPtr).psqtAccumulation[Perspective][0]);
|
||||
auto accPsqtOut =
|
||||
auto* accPsqtOut =
|
||||
reinterpret_cast<psqt_vec_t*>(&(next->*accPtr).psqtAccumulation[Perspective][0]);
|
||||
|
||||
const IndexType offsetPsqtR0 = PSQTBuckets * removed[0];
|
||||
auto columnPsqtR0 = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtR0]);
|
||||
auto* columnPsqtR0 = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtR0]);
|
||||
const IndexType offsetPsqtA = PSQTBuckets * added[0];
|
||||
auto columnPsqtA = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtA]);
|
||||
auto* columnPsqtA = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtA]);
|
||||
|
||||
if (removed.size() == 1)
|
||||
{
|
||||
@@ -548,7 +550,8 @@ class FeatureTransformer {
|
||||
else
|
||||
{
|
||||
const IndexType offsetPsqtR1 = PSQTBuckets * removed[1];
|
||||
auto columnPsqtR1 = reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtR1]);
|
||||
auto* columnPsqtR1 =
|
||||
reinterpret_cast<const psqt_vec_t*>(&psqtWeights[offsetPsqtR1]);
|
||||
|
||||
for (std::size_t i = 0;
|
||||
i < PSQTBuckets * sizeof(PSQTWeightType) / sizeof(psqt_vec_t); ++i)
|
||||
@@ -559,69 +562,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<const vec_t*>(
|
||||
&(computed->*accPtr).accumulation[Perspective][i * TileHeight]);
|
||||
for (IndexType j = 0; j < NumRegs; ++j)
|
||||
auto* accTileIn = reinterpret_cast<const vec_t*>(
|
||||
&(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<const vec_t*>(&weights[offset]);
|
||||
for (IndexType j = 0; j < NumRegs; ++j)
|
||||
const IndexType offset = HalfDimensions * index + i * Tiling::TileHeight;
|
||||
auto* column = reinterpret_cast<const vec_t*>(&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<const vec_t*>(&weights[offset]);
|
||||
for (IndexType j = 0; j < NumRegs; ++j)
|
||||
const IndexType offset = HalfDimensions * index + i * Tiling::TileHeight;
|
||||
auto* column = reinterpret_cast<const vec_t*>(&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<vec_t*>(
|
||||
&(next->*accPtr).accumulation[Perspective][i * TileHeight]);
|
||||
for (IndexType j = 0; j < NumRegs; ++j)
|
||||
auto* accTileOut = reinterpret_cast<vec_t*>(
|
||||
&(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<const psqt_vec_t*>(
|
||||
&(computed->*accPtr).psqtAccumulation[Perspective][i * PsqtTileHeight]);
|
||||
for (std::size_t j = 0; j < NumPsqtRegs; ++j)
|
||||
auto* accTilePsqtIn = reinterpret_cast<const psqt_vec_t*>(
|
||||
&(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<const psqt_vec_t*>(&psqtWeights[offset]);
|
||||
for (std::size_t j = 0; j < NumPsqtRegs; ++j)
|
||||
const IndexType offset = PSQTBuckets * index + i * Tiling::PsqtTileHeight;
|
||||
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(&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<const psqt_vec_t*>(&psqtWeights[offset]);
|
||||
for (std::size_t j = 0; j < NumPsqtRegs; ++j)
|
||||
const IndexType offset = PSQTBuckets * index + i * Tiling::PsqtTileHeight;
|
||||
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(&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<psqt_vec_t*>(
|
||||
&(next->*accPtr).psqtAccumulation[Perspective][i * PsqtTileHeight]);
|
||||
for (std::size_t j = 0; j < NumPsqtRegs; ++j)
|
||||
auto* accTilePsqtOut = reinterpret_cast<psqt_vec_t*>(
|
||||
&(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 +703,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<vec_t*>(&accumulator.accumulation[Perspective][j * TileHeight]);
|
||||
auto entryTile = reinterpret_cast<vec_t*>(&entry.accumulation[j * TileHeight]);
|
||||
auto* accTile = reinterpret_cast<vec_t*>(
|
||||
&accumulator.accumulation[Perspective][j * Tiling::TileHeight]);
|
||||
auto* entryTile = reinterpret_cast<vec_t*>(&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<const vec_t*>(&weights[offsetR]);
|
||||
const IndexType offsetR = HalfDimensions * indexR + j * Tiling::TileHeight;
|
||||
auto* columnR = reinterpret_cast<const vec_t*>(&weights[offsetR]);
|
||||
IndexType indexA = added[i];
|
||||
const IndexType offsetA = HalfDimensions * indexA + j * TileHeight;
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
const IndexType offsetA = HalfDimensions * indexA + j * Tiling::TileHeight;
|
||||
auto* columnA = reinterpret_cast<const vec_t*>(&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<const vec_t*>(&weights[offset]);
|
||||
const IndexType offset = HalfDimensions * index + j * Tiling::TileHeight;
|
||||
auto* column = reinterpret_cast<const vec_t*>(&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<const vec_t*>(&weights[offset]);
|
||||
const IndexType offset = HalfDimensions * index + j * Tiling::TileHeight;
|
||||
auto* column = reinterpret_cast<const vec_t*>(&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<psqt_vec_t*>(
|
||||
&accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]);
|
||||
auto entryTilePsqt =
|
||||
reinterpret_cast<psqt_vec_t*>(&entry.psqtAccumulation[j * PsqtTileHeight]);
|
||||
auto* accTilePsqt = reinterpret_cast<psqt_vec_t*>(
|
||||
&accumulator.psqtAccumulation[Perspective][j * Tiling::PsqtTileHeight]);
|
||||
auto* entryTilePsqt =
|
||||
reinterpret_cast<psqt_vec_t*>(&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<const psqt_vec_t*>(&psqtWeights[offset]);
|
||||
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
|
||||
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(&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<const psqt_vec_t*>(&psqtWeights[offset]);
|
||||
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
|
||||
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(&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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+3
-6
@@ -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
|
||||
@@ -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<true>(k);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+48
-55
@@ -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
|
||||
@@ -61,7 +61,6 @@ void syzygy_extend_pv(const OptionsMap& options,
|
||||
Stockfish::Search::RootMove& rootMove,
|
||||
Value& v);
|
||||
|
||||
using Eval::evaluate;
|
||||
using namespace Search;
|
||||
|
||||
namespace {
|
||||
@@ -79,9 +78,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<Correction>(pos)];
|
||||
@@ -89,15 +86,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<WHITE>(pos)];
|
||||
const auto bnpcv = w.nonPawnCorrectionHistory[BLACK][us][non_pawn_index<BLACK>(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
|
||||
@@ -501,10 +500,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)
|
||||
@@ -560,16 +558,16 @@ 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(size_t(options["Threads"])) / 2) * std::log(i));
|
||||
reductions[i] = int(19.43 * std::log(i));
|
||||
|
||||
refreshTable.clear(networks[numaAccessToken]);
|
||||
}
|
||||
@@ -586,7 +584,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<nt>(pos, ss, alpha, beta);
|
||||
}
|
||||
|
||||
// Limit the depth if extensions made it too large
|
||||
depth = std::min(depth, MAX_PLY - 1);
|
||||
@@ -641,9 +642,7 @@ 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])
|
||||
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
|
||||
@@ -763,6 +762,7 @@ Value Search::Worker::search(
|
||||
|
||||
// Step 6. Static evaluation of the position
|
||||
Value unadjustedStaticEval = VALUE_NONE;
|
||||
const auto correctionValue = correction_value(*thisThread, pos, ss);
|
||||
if (ss->inCheck)
|
||||
{
|
||||
// Skip early pruning when in check
|
||||
@@ -782,13 +782,11 @@ 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);
|
||||
|
||||
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)
|
||||
@@ -797,10 +795,8 @@ Value Search::Worker::search(
|
||||
}
|
||||
else
|
||||
{
|
||||
unadjustedStaticEval =
|
||||
evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]);
|
||||
ss->staticEval = eval =
|
||||
to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss);
|
||||
unadjustedStaticEval = evaluate(pos);
|
||||
ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, correctionValue);
|
||||
|
||||
// Static evaluation is saved as it was before adjustment by correction history
|
||||
Distributed::save(tt, threads, thisThread, ttWriter, posKey, VALUE_NONE, ss->ttPv,
|
||||
@@ -829,18 +825,16 @@ 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<NonPV>(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<NonPV>(pos, ss, alpha - 1, alpha);
|
||||
|
||||
// Step 8. Futility pruning: child node (~40 Elo)
|
||||
// The depth condition is important for mate finding.
|
||||
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;
|
||||
@@ -968,8 +962,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
|
||||
@@ -1212,6 +1204,10 @@ moves_loop: // When in check, search starts here
|
||||
|
||||
// These reduction adjustments have no proven non-linear scaling
|
||||
|
||||
r += 330;
|
||||
|
||||
r -= std::abs(correctionValue) / 32768;
|
||||
|
||||
// Increase reduction for cut nodes (~4 Elo)
|
||||
if (cutNode)
|
||||
r += 2518 - (ttData.depth >= depth && ss->ttPv) * 991;
|
||||
@@ -1249,7 +1245,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));
|
||||
Depth d = std::max(
|
||||
1, std::min(newDepth - r / 1024, newDepth + !allNode + (PvNode && !bestMove)));
|
||||
|
||||
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha, d, true);
|
||||
|
||||
@@ -1267,8 +1264,8 @@ moves_loop: // When in check, search starts here
|
||||
value = -search<NonPV>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1460,10 +1457,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);
|
||||
|
||||
@@ -1563,9 +1556,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);
|
||||
|
||||
@@ -1586,6 +1577,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta)
|
||||
|
||||
// Step 4. Static evaluation of the position
|
||||
Value unadjustedStaticEval = VALUE_NONE;
|
||||
const auto correctionValue = correction_value(*thisThread, pos, ss);
|
||||
if (ss->inCheck)
|
||||
bestValue = futilityBase = -VALUE_INFINITE;
|
||||
else
|
||||
@@ -1595,10 +1587,9 @@ 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);
|
||||
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)
|
||||
@@ -1609,11 +1600,9 @@ 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);
|
||||
to_corrected_static_eval(unadjustedStaticEval, correctionValue);
|
||||
}
|
||||
|
||||
// Stand pat. Return immediately if static value is at least beta
|
||||
@@ -1768,7 +1757,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 / 3 + 1304;
|
||||
}
|
||||
|
||||
// elapsed() returns the time elapsed since the search started. If the
|
||||
@@ -1785,6 +1774,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
|
||||
|
||||
+3
-2
@@ -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
|
||||
@@ -130,7 +130,6 @@ struct LimitsType {
|
||||
int movestogo, depth, mate, perft, infinite;
|
||||
uint64_t nodes;
|
||||
bool ponderMode;
|
||||
Square capSq;
|
||||
};
|
||||
|
||||
|
||||
@@ -348,6 +347,8 @@ class Worker {
|
||||
TimePoint elapsed() const;
|
||||
TimePoint elapsed_time() const;
|
||||
|
||||
Value evaluate(const Position&);
|
||||
|
||||
LimitsType limits;
|
||||
|
||||
size_t pvIdx, pvLast;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.sh text eol=lf
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user