Minor cleanups June 2026

In the spirit of previous such PRs, this PR proposes a collection of nonfunctional changes.

I am happy to incorporate changes from other devs, and revert some of the proposed changes if the maintainers ask me to.

Apart from trivial changes, the proposed changes so far include:

* A requested edit to `AUTHORS` and a resorting of all entries, following DIN 5007 for the treatment of any special characters.
* Exclude the two recent integer type renaming commits from git blame.
* Tightening of some static asserts in `history.h` to avoid overflows. (Note that rounding errors for floating point types could lead to the assert in `operator<<` triggering at run-time.)
* Re-instate the 0.5s maximal thinking time in case of a single legal move and reword the comment to make it clear that it should not be tuned.
* ~~A small refactoring of the network loading code thanks to @dubslow.~~
* A refactoring of the "dtz is dtm" code, also thanks to @dubslow.

closes https://github.com/official-stockfish/Stockfish/pull/6928

No functional change
This commit is contained in:
Robert Nurnberg
2026-07-10 20:12:38 +02:00
committed by Joost VandeVondele
parent eca43a97ef
commit 48a9118251
23 changed files with 87 additions and 182 deletions
+5 -1
View File
@@ -4,4 +4,8 @@
# Post commit formatting fixes
0fca5605fa2e5e7240fde5e1aae50952b2612231
08ed4c90db31959521b7ef3186c026edd1e90307
08ed4c90db31959521b7ef3186c026edd1e90307
# Ignore commits related to integer type renamings
dd3e1c4a50fd358c8bf8051c9ef73219669ff6c0
6e4e03fd282d5e1cba514197bf1ef326c990f0d2
+12 -12
View File
@@ -12,8 +12,8 @@ Hisayori Noda (nodchip)
# All other authors of Stockfish code (in alphabetical order)
87flowers
Aditya (absimaldata)
Adrian Ladoni (AdrianGHUB15)
Adrian Petrescu (apetresc)
Adrian (AdrianGHUB15)
Ahmed Kerimov (wcdbmv)
Ajith Chandy Jose (ajithcj)
AK-Khan02
@@ -63,11 +63,11 @@ Cody Ho (aesrentai)
CSTENTOR
Dale Weiler (graphitemaster)
Dalton Hanaway (dhanaway)
Dan Schmidt (dfannius)
Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic)
Daniel Monroe (daniel-monroe)
Daniel Samek (DanSamek)
Dan Schmidt (dfannius)
Dariusz Orzechowski (dorzechowski)
David (dav1312)
David Zar
@@ -92,9 +92,9 @@ Fanael Linithien (Fanael)
fanon
Fauzi Akram Dabat (fauzi2)
Felix Wittmann
gamander
Gabriele Lombardo (gabe)
Gahtan Nahdi
gamander
Gary Heckman (gheckman)
George Sobala (gsobala)
gguliash
@@ -105,8 +105,8 @@ Gontran Lemaire (gonlem)
Goodkov Vasiliy Aleksandrovich (goodkov)
Gregor Cramer
GuardianRM
Guy Vreuls (gvreuls)
Günther Demetz (pb00067, pb00068)
Guy Vreuls (gvreuls)
Henri Wiechers
Hiraoka Takuya (HiraokaTakuya)
homoSapiensSapiens
@@ -119,8 +119,8 @@ Jan Ondruš (hxim)
Jared Kish (Kurtbusch, kurt22i)
Jarrod Torriero (DU-jdto)
Jasper Shovelton (Beanie496)
Jean-Francois Romang (jromang)
Jean Gauthier (OuaisBla)
Jean-Francois Romang (jromang)
Jekaa
Jerry Donald Watson (jerrydonaldwatson)
jjoshua2
@@ -128,10 +128,10 @@ Jonathan Buladas Dumale (SFisGOD)
Jonathan Calovski (Mysseno)
Jonathan McDermid (jonathanmcdermid)
Joost VandeVondele (vondele)
Jörg Oster (joergoster)
Joseph Ellis (jhellis3)
Joseph R. Prostko
Jost Triller (tsoj)
Jörg Oster (joergoster)
Julian Willemer (NightlyKing)
jundery
Justin Blanchard (UncombedCoconut)
@@ -189,8 +189,8 @@ Muzhen J (XInTheDark)
Mafanwei
Nathan Rugg (nmrugg)
Nguyen Pham (nguyenpham)
Nicklas Persson (NicklasPersson)
Nick Pelling (nickpelling)
Nicklas Persson (NicklasPersson)
Nicolas Duhamel (nikloskoda)
Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
@@ -198,11 +198,11 @@ Norman Schmidt (FireFather)
notruck
Nour Berakdar (Nonlinear)
Ofek Shochat (OfekShochat, ghostway)
Ondrej Mosnáček (WOnder93)
Ömer Faruk Tutkun (OmerFarukTutkun)
Ondřej Mišina (AndrovT)
Ondrej Mosnáček (WOnder93)
Onur Zungur (zungur)
Oskar Werkelin Ahlin
Ömer Faruk Tutkun (OmerFarukTutkun)
Pablo Vazquez
Panthee
Pascal Romaret
@@ -224,13 +224,13 @@ Richard Lloyd (Richard-Lloyd)
Robert Nürnberg (robertnurnberg)
Rodrigo Exterckötter Tjäder
Rodrigo Roim (roim)
Ronald de Man (syzygy1, syzygy)
Ron Britvich (Britvich)
Ronald de Man (syzygy1, syzygy)
rqs
Rui Coelho (ruicoelhopedro)
rustam-cpp
Ryan Lefkowitz (rlefko)
Ryan Hirsch
Ryan Lefkowitz (rlefko)
Ryan Schmitt
Ryan Takker
Sami Kiminki (skiminki)
@@ -262,9 +262,9 @@ Timothy Herchen (anematode)
Ting-Hsuan Huang (fffelix-huang)
tobi437a
Tobias Steinmann
Tomasz Sobczyk (Sopel97)
Tom Truscott
Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97)
Tony Wang (TonyCongqianWang)
Torsten Franz (torfranz, tfranzer)
Torsten Hellwig (Torom)
+2 -3
View File
@@ -70,7 +70,7 @@ static void init_magics(Magic magics[][2]) {
// Sliding attacks within a rank, indexed by the slider's file and the
// 8-bit rank occupancy, yielding the 8-bit attack set on that rank
[[maybe_unused]] constexpr auto RankAttacks = []() {
constexpr auto RankAttacks = []() {
std::array<std::array<u8, 256>, FILE_NB> table{};
for (int file = 0; file < 8; ++file)
for (int occ = 0; occ < 256; ++occ)
@@ -117,8 +117,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) {
m.attacks = s == SQ_A1 ? table : magics[s - 1][pt - BISHOP].attacks + size;
size = 0;
Bitboard b = 0;
[[maybe_unused]] Bitboard prevSliding = -1;
Bitboard b = 0;
do
{
occupancy[size] = b;
+5 -5
View File
@@ -102,10 +102,10 @@ struct alignas(32) DualMagic {
//
// When using hyperbola quintessence, file, diagonal and antidiagonal attacks
// can use a byte reversal rather than a full bit reversal (because all squares
// reside in different bytes). Rank atttacks cannot. Thus, for rank attacks
// reside in different bytes). Rank attacks cannot. Thus, for rank attacks
// only, we use a compact lookup table indexed by the 8 bits of the rank's occupancy.
std::pair<Bitboard, Bitboard> both_attacks_bb(Bitboard occupied) const {
// Byteswap within 64-bit elements
// Byteswap within 128-bit elements
const auto bswap = [](__m256i v) {
return _mm256_shuffle_epi8(v, _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
@@ -270,7 +270,7 @@ inline Bitboard attacks_bb(Square s, Color c = COLOR_NB) {
// Returns the attacks by the given piece
// assuming the board is occupied according to the passed Bitboard.
// Sliding piece attacks do not continue passed an occupied square.
// Sliding piece attacks do not continue past an occupied square.
template<PieceType Pt>
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
@@ -306,7 +306,7 @@ inline Bitboard attacks_bb(Square s, Bitboard occupied) {
// Returns the attacks by the given piece
// assuming the board is occupied according to the passed Bitboard.
// Sliding piece attacks do not continue passed an occupied square.
// Sliding piece attacks do not continue past an occupied square.
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
assert(pt != PAWN && is_ok(s));
@@ -318,7 +318,7 @@ inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
case ROOK :
return attacks_bb<ROOK>(s, occupied);
case QUEEN :
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
return attacks_bb<QUEEN>(s, occupied);
default :
return PseudoAttacks[pt][s];
}
+1 -1
View File
@@ -485,7 +485,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) {
float totalTime = 0;
for (const auto& game : BenchmarkPositions)
for (usize i = 0; i < game.size(); ++i)
totalTime += float(getCorrectedTime(i + 1));
totalTime += float(getCorrectedTime(int(i + 1)));
float timeScaleFactor = static_cast<float>(desiredTimeS * 1000) / totalTime;
+1 -8
View File
@@ -23,7 +23,6 @@
namespace Stockfish {
u8 PopCnt16[1 << 16];
u8 SquareDistance[SQUARE_NB][SQUARE_NB];
// Returns an ASCII representation of a bitboard suitable
// to be printed to standard output. Useful for debugging.
@@ -46,16 +45,10 @@ std::string Bitboards::pretty(Bitboard b) {
return s;
}
// Initializes various bitboard tables. It is called at
// startup and relies on global objects to be already zero-initialized.
// Initializes the popcount table at startup.
void Bitboards::init() {
for (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = u8(std::bitset<16>(i).count());
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
}
} // namespace Stockfish
-25
View File
@@ -21,9 +21,7 @@
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include "types.h"
@@ -66,7 +64,6 @@ constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
extern u8 PopCnt16[1 << 16];
extern u8 SquareDistance[SQUARE_NB][SQUARE_NB];
constexpr Bitboard square_bb(Square s) {
assert(is_ok(s));
@@ -133,30 +130,8 @@ constexpr Bitboard pawn_single_push_bb(Color c, Bitboard b) {
return c == WHITE ? shift<NORTH>(b) : shift<SOUTH>(b);
}
// distance() functions return the distance between x and y, defined as the
// number of steps for a king in x to reach y.
template<typename T1 = Square>
inline int distance(Square x, Square y);
template<>
inline int distance<File>(Square x, Square y) {
return std::abs(file_of(x) - file_of(y));
}
template<>
inline int distance<Rank>(Square x, Square y) {
return std::abs(rank_of(x) - rank_of(y));
}
template<>
inline int distance<Square>(Square x, Square y) {
return SquareDistance[x][y];
}
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
constexpr int constexpr_popcount(Bitboard b) {
b = b - ((b >> 1) & 0x5555555555555555ULL);
b = (b & 0x3333333333333333ULL) + ((b >> 2) & 0x3333333333333333ULL);
+1 -1
View File
@@ -164,7 +164,7 @@ void Engine::search_clear() {
tt.clear(threads);
threads.clear();
// @TODO wont work with multiple instances
// TODO: does not work with multiple instances
Tablebases::init(options["SyzygyPath"]); // Free mapped files
}
+4 -1
View File
@@ -54,7 +54,10 @@ static_assert((CORRHIST_BASE_SIZE & (CORRHIST_BASE_SIZE - 1)) == 0,
// when we update values with the << operator
template<typename T, int D, bool Shared = false>
struct StatsEntry {
static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type");
static_assert(std::is_integral_v<T> && std::is_signed_v<T>, "Not a signed integer type");
static_assert(D > 0 && D <= std::numeric_limits<T>::max()
&& D <= std::numeric_limits<int>::max() / D,
"D can lead to overflows");
private:
std::conditional_t<Shared, RelaxedAtomic<T>, T> entry;
+1 -1
View File
@@ -190,7 +190,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceTo
// Assigns a numerical value to each move in a list, used for sorting.
// Captures are ordered by Most Valuable Victim (MVV), preferring captures
// with a good history. Quiets moves are ordered using the history tables.
// with a good history. Quiet moves are ordered using the history tables.
template<GenType Type>
ExtMove* MovePicker::score(const MoveList<Type>& ml) {
+1 -1
View File
@@ -256,10 +256,10 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos,
{
Piece attacker = make_piece(c, pt);
Bitboard bb = pos.pieces(c, pt);
Bitboard targets = pt == KNIGHT || pt == QUEEN ? queenTargets : minorSliderTargets;
while (bb)
{
Square from = pop_lsb(bb);
Bitboard targets = pt == KNIGHT || pt == QUEEN ? queenTargets : minorSliderTargets;
Bitboard attacks = Attacks::attacks_bb(pt, from, occupied) & targets;
while (attacks)
{
+1 -1
View File
@@ -109,7 +109,7 @@ class Network {
};
} // namespace Stockfish
} // namespace Stockfish::Eval::NNUE
template<>
struct std::hash<Stockfish::Eval::NNUE::Network> {
+2 -2
View File
@@ -73,8 +73,8 @@ struct NetworkArchitecture {
hashValue ^= TransformedFeatureDimensions * 2;
hashValue = decltype(fc_0)::get_hash_value(hashValue);
// TODO: considerincluding hash value of ac_sqr_0 in the overall hash value.
// For now omitted on purpose because hash value is not written by trainer yet
// TODO: consider including hash value of ac_sqr_0 in the overall hash value.
// For now omitted on purpose because hash value is not written by trainer (yet)
hashValue = decltype(ac_0)::get_hash_value(hashValue);
hashValue = decltype(fc_1)::get_hash_value(hashValue);
hashValue = decltype(ac_1)::get_hash_value(hashValue);
+1 -1
View File
@@ -252,7 +252,7 @@ class FeatureTransformer {
// means our pairwise product is zero. If we perform packus and
// remove the lower-side clip for the second element, then our
// product before packus will be negative, and is zeroed on pack.
// The two operation produce equivalent results, but the second
// The two operations produce equivalent results, but the second
// one (using packus) saves one max operation per pair.
// But here we run into a problem: mullo does not preserve the
+4 -3
View File
@@ -42,7 +42,7 @@ struct NNZInfo {
indices[i] = {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23,
8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31};
for (u16& m : indices[i])
m += i * Dimensions / 8;
m += u16(i * Dimensions / 8);
}
return indices;
}();
@@ -85,9 +85,10 @@ struct NNZInfo {
count += popcount(nnzMask);
indices = _mm512_add_epi16(indices, increment);
#else
const __m512i increment = _mm512_set1_epi32(16);
for (auto neurons : {neurons1, neurons2})
{
const __m512i increment = _mm512_set1_epi32(16);
// Get a bitmask and gather non zero indices
const __mmask16 nnzMask = _mm512_test_epi32_mask(neurons, neurons);
const __m512i nnzV = _mm512_maskz_compress_epi32(nnzMask, indices);
@@ -162,6 +163,6 @@ struct NNZInfo {
NNZCursor make_cursor(bool perspective) { return {*this, perspective}; }
#endif
};
} // namespace Stockfish
} // namespace Stockfish::Eval::NNUE
#endif
+4 -63
View File
@@ -59,9 +59,7 @@ namespace Stockfish::Eval::NNUE::SIMD {
#ifdef USE_AVX512
using vec_t = __m512i;
using vec_i8_t = __m256i;
using vec128_t = __m128i;
using psqt_vec_t = __m256i;
using vec_uint_t = __m512i;
#define vec_load(a) _mm512_load_si512(a)
#define vec_store(a, b) _mm512_store_si512(a, b)
#define vec_convert_8_16(a) _mm512_cvtepi8_epi16(a)
@@ -81,24 +79,15 @@ using vec_uint_t = __m512i;
#define vec_sub_psqt_32(a, b) _mm256_sub_epi32(a, b)
#define vec_zero_psqt() _mm256_setzero_si256()
#ifdef USE_SSSE3
#define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512())
#endif
#define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512())
#define vec128_zero _mm_setzero_si128()
#define vec128_set_16(a) _mm_set1_epi16(a)
#define vec128_load(a) _mm_load_si128(a)
#define vec128_storeu(a, b) _mm_storeu_si128(a, b)
#define vec128_add(a, b) _mm_add_epi16(a, b)
#define NumRegistersSIMD 16
#define MaxChunkSize 64
#elif USE_AVX2
using vec_t = __m256i;
using vec_i8_t = __m128i;
using vec128_t = __m128i;
using psqt_vec_t = __m256i;
using vec_uint_t = __m256i;
#define vec_load(a) _mm256_load_si256(a)
#define vec_store(a, b) _mm256_store_si256(a, b)
#define vec_convert_8_16(a) _mm256_cvtepi8_epi16(a)
@@ -118,31 +107,16 @@ using vec_uint_t = __m256i;
#define vec_sub_psqt_32(a, b) _mm256_sub_epi32(a, b)
#define vec_zero_psqt() _mm256_setzero_si256()
#ifdef USE_SSSE3
#if defined(USE_VNNI) && !defined(USE_AVXVNNI)
#define vec_nnz(a) _mm256_cmpgt_epi32_mask(a, _mm256_setzero_si256())
#else
#define vec_nnz(a) \
_mm256_movemask_ps( \
_mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256())))
#endif
#endif
#define vec128_zero _mm_setzero_si128()
#define vec128_set_16(a) _mm_set1_epi16(a)
#define vec128_load(a) _mm_load_si128(a)
#define vec128_storeu(a, b) _mm_storeu_si128(a, b)
#define vec128_add(a, b) _mm_add_epi16(a, b)
#define vec_nnz(a) \
_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256())))
#define NumRegistersSIMD 12
#define MaxChunkSize 32
#elif USE_SSE2
using vec_t = __m128i;
using vec_i8_t = u64; // for the correct size -- will be loaded into an xmm reg
using vec128_t = __m128i;
using vec_i8_t = u64;
using psqt_vec_t = __m128i;
using vec_uint_t = __m128i;
#define vec_load(a) (*(a))
#define vec_store(a, b) *(a) = (b)
#define vec_add_16(a, b) _mm_add_epi16(a, b)
@@ -186,12 +160,6 @@ inline __m128i vec_convert_8_16(u64 x) {
}
#endif
#define vec128_zero _mm_setzero_si128()
#define vec128_set_16(a) _mm_set1_epi16(a)
#define vec128_load(a) _mm_load_si128(a)
#define vec128_storeu(a, b) _mm_storeu_si128(a, b)
#define vec128_add(a, b) _mm_add_epi16(a, b)
#define NumRegistersSIMD (Is64Bit ? 12 : 6)
#define MaxChunkSize 16
@@ -205,8 +173,6 @@ using vec_i32x4_t __attribute__((may_alias)) = int32x4_t;
using vec_t __attribute__((may_alias)) = int16x8_t;
using vec_i8_t __attribute__((may_alias)) = int8x16_t;
using psqt_vec_t __attribute__((may_alias)) = int32x4_t;
using vec128_t __attribute__((may_alias)) = uint16x8_t;
using vec_uint_t __attribute__((may_alias)) = uint32x4_t;
#define vec_load(a) (*(a))
#define vec_store(a, b) *(a) = (b)
#define vec_add_16(a, b) vaddq_s16(a, b)
@@ -224,15 +190,6 @@ using vec_uint_t __attribute__((may_alias)) = uint32x4_t;
#define vec_sub_psqt_32(a, b) vsubq_s32(a, b)
#define vec_zero_psqt() psqt_vec_t{0}
static constexpr u32 Mask[4] = {1, 2, 4, 8};
#define vec_nnz(a) \
vaddvq_u32(vandq_u32(vtstq_u32((uint32x4_t) a, (uint32x4_t) a), vld1q_u32(Mask)))
#define vec128_zero vdupq_n_u16(0)
#define vec128_set_16(a) vdupq_n_u16(a)
#define vec128_load(a) vld1q_u16(reinterpret_cast<const u16*>(a))
#define vec128_storeu(a, b) vst1q_u16(reinterpret_cast<u16*>(a), b)
#define vec128_add(a, b) vaddq_u16(a, b)
#define NumRegistersSIMD 16
#define MaxChunkSize 16
@@ -245,9 +202,7 @@ inline int16x8_t vsubw_high_s8(int16x8_t a, int8x16_t b) { return vsubw_s8(a, vg
#elif USE_LASX
using vec_t = __m256i;
using vec_i8_t = __m128i;
using vec128_t = __m128i;
using psqt_vec_t = __m256i;
using vec_uint_t = __m256i;
inline __m256i lasx_load256(const __m256i* a) {
return __lasx_xvld(reinterpret_cast<const void*>(a), 0);
@@ -293,12 +248,6 @@ inline __m256i lasx_packus_32(__m256i a, __m256i b) {
#define vec_mulhi_8 __lasx_xvmuh_bu
#define vec_srli_8 __lasx_xvsrli_b
#define vec128_zero __lsx_vldi(0)
#define vec128_set_16(a) __lsx_vreplgr2vr_h(a)
#define vec128_load(a) (*(a))
#define vec128_storeu(a, b) *(a) = (b)
#define vec128_add(a, b) __lsx_vadd_h(a, b)
#define NumRegistersSIMD 24
#define MaxChunkSize 32
@@ -328,9 +277,7 @@ inline int lasx_vec_nnz(__m256i a) {
#elif USE_LSX
using vec_t = __m128i;
using vec_i8_t = u64;
using vec128_t = __m128i;
using psqt_vec_t = __m128i;
using vec_uint_t = __m128i;
inline __m128i lsx_packus_16(__m128i a, __m128i b) {
#if defined(__clang__) && defined(__has_builtin) && __has_builtin(__builtin_lsx_vssrani_bu_h)
@@ -381,12 +328,6 @@ inline __m128i vec_convert_8_16(u64 x) {
#define vec_mulhi_8 __lsx_vmuh_bu
#define vec_srli_8 __lsx_vsrli_b
#define vec128_zero __lsx_vldi(0)
#define vec128_set_16(a) __lsx_vreplgr2vr_h(a)
#define vec128_load(a) (*(a))
#define vec128_storeu(a, b) *(a) = (b)
#define vec128_add(a, b) __lsx_vadd_h(a, b)
#define NumRegistersSIMD 24
#define MaxChunkSize 16
+7 -13
View File
@@ -113,8 +113,8 @@ inline int H1(Key h) { return h & 0x1fff; }
inline int H2(Key h) { return (h >> 16) & 0x1fff; }
// Cuckoo tables with Zobrist hashes of valid reversible moves, and the moves themselves
std::array<Key, 8192> cuckoo;
std::array<Move, 8192> cuckooMove;
static std::array<Key, 8192> cuckoo;
static std::array<Move, 8192> cuckooMove;
// Initializes at startup the various arrays used to compute hash keys
void Position::init() {
@@ -305,7 +305,7 @@ Position::set(const string& fenStr, bool isChess960, StateInfo* si) {
// if an inner rook is associated with the castling right, the castling tag is
// replaced by the file letter of the involved rook, as for the Shredder-FEN.
//
// NOTE: Due to the prevalnce of incorrect (or missing) castling rights the
// NOTE: Due to the prevalence of incorrect (or missing) castling rights the
// validation is less strict. However, incorrect castling rights are still sanitized.
int num_castling_rights = 0;
for (;;)
@@ -421,7 +421,7 @@ Position::set(const string& fenStr, bool isChess960, StateInfo* si) {
ss >> std::skipws >> st->rule50 >> gamePly;
// Normally values larger than 99 would be pointless but we do support ignoring 50 move rule for TB purposes.
// Limit at 2**15 as it's used multiplicativly with position evaluation during search.
// Limit at 2**15 as it's used multiplicatively with position evaluation during search.
if (st->rule50 < 0 || st->rule50 > 32767)
return PositionSetError("Unsupported position. Rule50 counter out of range.");
@@ -1636,21 +1636,16 @@ bool Position::material_key_is_ok() const { return compute_material_key() == st-
// This is meant to be helpful when debugging.
bool Position::pos_is_ok() const {
constexpr bool Fast = false; // fast or full check?
if ((sideToMove != WHITE && sideToMove != BLACK) || piece_on(square<KING>(WHITE)) != W_KING
|| piece_on(square<KING>(BLACK)) != B_KING
|| (ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6))
assert(0 && "pos_is_ok: Default");
if (Fast)
return true;
if (pieceCount[W_KING] != 1 || pieceCount[B_KING] != 1
if (count<KING>(WHITE) != 1 || count<KING>(BLACK) != 1
|| attackers_to_exist(square<KING>(~sideToMove), pieces(), sideToMove))
assert(0 && "pos_is_ok: Kings");
if ((pieces(PAWN) & (Rank1BB | Rank8BB)) || pieceCount[W_PAWN] > 8 || pieceCount[B_PAWN] > 8)
if ((pieces(PAWN) & (Rank1BB | Rank8BB)) || count<PAWN>(WHITE) > 8 || count<PAWN>(BLACK) > 8)
assert(0 && "pos_is_ok: Pawns");
@@ -1679,7 +1674,6 @@ bool Position::pos_is_ok() const {
if (p1 != p2 && (pieces(p1) & pieces(p2)))
assert(0 && "pos_is_ok: Bitboards");
for (Piece pc : Pieces)
if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc)))
|| pieceCount[pc] != std::count(board.begin(), board.end(), pc))
@@ -1691,7 +1685,7 @@ bool Position::pos_is_ok() const {
if (!can_castle(cr))
continue;
if (piece_on(castlingRookSquare[cr]) != make_piece(c, ROOK)
if (piece_on(castling_rook_square(cr)) != make_piece(c, ROOK)
|| castlingRightsMask[castlingRookSquare[cr]] != cr
|| (castlingRightsMask[square<KING>(c)] & cr) != cr)
assert(0 && "pos_is_ok: Castling");
+6
View File
@@ -177,6 +177,7 @@ class Position {
int rule50_count() const;
Value non_pawn_material(Color c) const;
Value non_pawn_material() const;
bool dtz_is_dtm() const; // Pawnless && (3-men || 4-men-minors-only)
// Position consistency check, for debugging
bool pos_is_ok() const;
@@ -344,6 +345,11 @@ inline int Position::rule50_count() const { return st->rule50; }
inline bool Position::is_chess960() const { return chess960; }
inline bool Position::dtz_is_dtm() const {
return !count<PAWN>()
&& (count<ALL_PIECES>() == 3 || (count<ALL_PIECES>() == 4 && !pieces(QUEEN, ROOK)));
}
inline bool Position::capture(Move m) const {
assert(m.is_ok());
+16 -15
View File
@@ -146,6 +146,8 @@ void update_all_stats(const Position& pos,
Move ttMove,
bool PvNode);
// Detect shuffling moves in order to limit search explosions
// Added in #6447 as non-regression, and so its parameters should not be tuned
bool is_shuffling(Move move, Stack* const ss, const Position& pos) {
if (pos.capture_stage(move) || pos.rule50_count() < 10)
return false;
@@ -249,9 +251,9 @@ void Search::Worker::start_searching() {
// Send PV info if it has changed since last output in iterative_deepening().
if (!uciPvSent || bestThread != this)
main_manager()->pv(*bestThread, threads, tt, bestThread->rootDepth);
main_manager()->output_pv(*bestThread, threads, tt, bestThread->rootDepth);
// In rare cases, pv() may change the ponder move through syzygy_extend_pv().
// In rare cases, output_pv() may change the ponder move through syzygy_extend_pv().
std::string ponder;
if (bestThread->rootMoves[0].pv.size() > 1)
ponder = UCIEngine::move(bestThread->rootMoves[0].pv[1], rootPos.is_chess960());
@@ -347,8 +349,7 @@ bool Search::Worker::iterative_deepening() {
rootMoves[i].previousScoreExact = i < multiPV;
}
usize pvFirst = 0;
pvLast = 0;
usize pvFirst = pvLast = 0;
if (!threads.increaseDepth)
searchAgainCounter++;
@@ -411,7 +412,7 @@ bool Search::Worker::iterative_deepening() {
// at nodes > 10M (rather than depth N, which can be reached quickly)
if (mainThread && multiPV == 1 && (bestValue <= alpha || bestValue >= beta)
&& nodes > NODES_LIMIT_OUTPUT)
main_manager()->pv(*this, threads, tt, rootDepth);
main_manager()->output_pv(*this, threads, tt, rootDepth);
// In case of failing low/high increase aspiration window and re-search,
// otherwise exit the loop.
@@ -491,7 +492,7 @@ bool Search::Worker::iterative_deepening() {
if (mainThread && !threads.stop && (pvIdx + 1 == multiPV || nodes > NODES_LIMIT_OUTPUT))
{
main_manager()->pv(*this, threads, tt, rootDepth);
main_manager()->output_pv(*this, threads, tt, rootDepth);
uciPvSent = (pvIdx + 1 == multiPV);
}
@@ -587,9 +588,9 @@ bool Search::Worker::iterative_deepening() {
double totalTime = mainThread->tm.optimum() * fallingEval * reduction
* bestMoveInstability * highBestMoveEffort;
// Cap used time in case of a single legal move for a better viewer experience
if (rootMoves.size() == 1)
totalTime = std::min(561.7, totalTime);
// Cap used time to 0.5s for a better viewer experience
totalTime = std::min(500.0, totalTime);
auto elapsedTime = elapsed();
@@ -700,7 +701,7 @@ void Search::Worker::clear() {
// Main search function for both PV and non-PV nodes
template<NodeType nodeType>
Value Search::Worker::search(
Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) {
Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, const bool cutNode) {
constexpr bool PvNode = nodeType != NonPV;
constexpr bool rootNode = nodeType == Root;
@@ -1917,7 +1918,7 @@ void update_all_stats(const Position& pos,
if (!PvNode)
// Important: don't remove the cast to a 64-bit number else the multiplication
// can overflow on 32-bit platforms which would change the bench signature
bonus += bonus * u64(quietsSearched.size() + capturesSearched.size()) / 256;
bonus += int(bonus * u64(quietsSearched.size() + capturesSearched.size()) / 256);
if (!pos.capture_stage(bestMove))
{
@@ -2175,7 +2176,7 @@ void syzygy_extend_pv(const OptionsMap& options,
// Finding a draw in this function is an exceptional case, that cannot happen when rule50 is false or
// during engine game play, since we have a winning score, and play correctly
// with TB support. However, it can be that a position is draw due to the 50 move
// rule if it has been been reached on the board with a non-optimal 50 move counter
// rule if it has been reached on the board with a non-optimal 50 move counter
// (e.g. 8/8/6k1/3B4/3K4/4N3/8/8 w - - 54 106 ) which TB with dtz counter rounding
// cannot always correctly rank. See also
// https://github.com/official-stockfish/Stockfish/issues/5175#issuecomment-2058893495
@@ -2196,10 +2197,10 @@ void syzygy_extend_pv(const OptionsMap& options,
<< sync_endl;
}
void SearchManager::pv(Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth) {
void SearchManager::output_pv(Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth) {
const auto nodes = threads.nodes_searched();
auto& rootMoves = worker.rootMoves;
+6 -5
View File
@@ -282,10 +282,10 @@ class SearchManager: public ISearchManager {
void check_time(Search::Worker& worker) override;
void pv(Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth);
void output_pv(Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth);
Stockfish::TimeManagement tm;
double originalTimeAdjust;
@@ -353,7 +353,8 @@ class Worker {
// This is the main search function, for both PV and non-PV nodes
template<NodeType nodeType>
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
Value
search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, const bool cutNode);
// Quiescence search function, which is called by the main search
template<NodeType nodeType>
-5
View File
@@ -40,11 +40,6 @@
#include "shm_linux.h"
#endif
#if defined(__ANDROID__)
#include <limits.h>
#define SF_MAX_SEM_NAME_LEN NAME_MAX
#endif
#include "types.h"
#include "memory.h"
+2 -6
View File
@@ -1802,14 +1802,10 @@ Config Tablebases::rank_root_moves(const OptionsMap& options,
config.probeDepth = 0;
}
if (config.cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
if (config.cardinality >= pos.count<ALL_PIECES>() && !pos.can_castle(ANY_CASTLING))
{
// Use DTZ to rank the moves if checkmate is the only zeroing move
rankDTZ =
rankDTZ
|| (!pos.pieces(PAWN)
&& (popcount(pos.pieces()) == 3
|| (popcount(pos.pieces()) == 4 && !(pos.pieces(QUEEN) | pos.pieces(ROOK)))));
rankDTZ = rankDTZ || pos.dtz_is_dtm();
// Rank moves using DTZ tables, bail out if time_abort flags zeitnot
config.rootInTB =
+5 -9
View File
@@ -58,7 +58,7 @@
// _WIN32 Building on Windows (any)
// _WIN64 Building on Windows 64 bit
// Enforce minimum GCC version
// Enforce minimum GCC version
#if defined(__GNUC__) && !defined(__clang__) \
&& (__GNUC__ < 9 || (__GNUC__ == 9 && __GNUC_MINOR__ < 3))
#error "Stockfish requires GCC 9.3 or later for correct compilation"
@@ -190,6 +190,10 @@ constexpr bool is_mated(Value value) {
constexpr bool is_mate_or_mated(Value value) { return is_mate(value) || is_mated(value); }
constexpr Value mate_in(int ply) { return VALUE_MATE - ply; }
constexpr Value mated_in(int ply) { return -VALUE_MATE + ply; }
// In the code, we make the assumption that these values
// are such that non_pawn_material() can be used to uniquely
// identify the material on the board.
@@ -377,10 +381,6 @@ constexpr CastlingRights operator&(Color c, CastlingRights cr) {
return CastlingRights((c == WHITE ? WHITE_CASTLING : BLACK_CASTLING) & cr);
}
constexpr Value mate_in(int ply) { return VALUE_MATE - ply; }
constexpr Value mated_in(int ply) { return -VALUE_MATE + ply; }
constexpr Square make_square(File f, Rank r) { return Square((r << 3) + f); }
constexpr Piece make_piece(Color c, PieceType pt) { return Piece((c << 3) + pt); }
@@ -454,10 +454,6 @@ class Move {
return Square(data & 0x3F);
}
// Same as to_sq() but without assertion, for branchless code paths
// where the result is masked/ignored when move is not ok
constexpr Square to_sq_unchecked() const { return Square(data & 0x3F); }
constexpr MoveType type_of() const { return MoveType(data & (3 << 14)); }
constexpr PieceType promotion_type() const { return PieceType(((data >> 12) & 3) + KNIGHT); }