stellar

UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit 644090d7e796c3e13c7595700830ddcad8836754
parent 0218a1559240963bdc53c7157b1cb16cfa4878f0
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Wed, 20 Mar 2024 18:51:51 +0000

Improve transposition table, add stats info

Diffstat:
M CMakeLists.txt | + -
M src/engine/CMakeLists.txt | ++++
M src/engine/engine.cpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ------
M src/perft/perft.cpp | +

4 files changed, 74 insertions(+), 7 deletions(-)


diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar
VERSION 1.3.8
VERSION 1.3.9
DESCRIPTION "Chess engine written in C++" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES CXX

diff --git a/ src/engine/CMakeLists.txt b/ src/engine/CMakeLists.txt

@@ -4,6 +4,10 @@ add_executable(engine uci.cpp )
option(STELLAR_STATS "Provide stats for analysis" OFF)
if(STELLAR_STATS)
add_definitions(-DUSE_STATS)
endif()
target_link_libraries(engine PRIVATE Stellar_version

diff --git a/ src/engine/engine.cpp b/ src/engine/engine.cpp

@@ -45,10 +45,44 @@ template <U64 size> class TTable_internal { public: static inline constexpr const int16_t unknown = 32500;
static void clear() { memset(table.data(), 0x00, size * sizeof(Hashe)); };
static void clear() {
memset(table.data(), 0x00, size * sizeof(Hashe));
#ifdef USE_STATS
accessed = 0, rewrite = 0, miss = 0;
#endif
};
#ifdef USE_STATS
static void print() {
std::cout << "Transposition table: " << std::endl;
std::cout << "\tSize: " << size << " entries (" << sizeof(Hashe) << "B per entry)" << std::endl;
std::cout << "\tSize: " << std::fixed << std::setprecision(2)
<< (double)size * sizeof(Hashe) / (1 << 20) << "MB" << std::endl;
std::cout << "\tReads: " << accessed << std::endl;
std::cout << "\tMisses: " << miss << "(" << (double)miss / accessed << "%)" << std::endl;
std::cout << "\tRewrite: " << rewrite << std::endl;
std::cout << "\tUsed " << (double)used() / size << "%" << std::endl;
}
static U64 used() {
U64 res = 0;
for (int i = 0; i < size; i++) {
if (table[i].key) res++;
}
return res;
}
#endif
static int16_t read(const Board &board, int ply, Move *best, int16_t alpha, int16_t beta, uint8_t depth) { U64 hash = board.get_hash();
const Hashe &phashe = table[hash % table.size()];
const Hashe &phashe = table[hash % size];
#ifdef USE_STATS
accessed++;
#endif
if (phashe.key == hash) { if (phashe.depth >= depth) { int16_t score = phashe.score;

@@ -62,26 +96,54 @@ template <U64 size> class TTable_internal { } *best = phashe.best; }
#ifdef USE_STATS
else {
miss++;
}
#endif
return unknown; } static void write(const Board &board, int ply, Move best, int16_t score, uint8_t depth, Hashe::Flag flag) { U64 hash = board.get_hash();
Hashe &phashe = table[hash % table.size()];
Hashe &phashe = table[hash % size];
if (score < -MATE_SCORE) score += ply; if (score > MATE_SCORE) score -= ply;
if (phashe.key == hash) {
if (phashe.depth > depth) return;
}
#ifdef USE_STATS
else {
rewrite++;
}
#endif
phashe = {hash, best, depth, score, flag}; } private: static std::array<Hashe, size> table;
#ifdef USE_STATS
static U64 accessed, rewrite, miss;
#endif
}; template <U64 size> std::array<Hashe, size> TTable_internal<size>::table;
#ifdef USE_STATS
template <U64 size> U64 TTable_internal<size>::accessed = 0;
template <U64 size> U64 TTable_internal<size>::rewrite = 0;
template <U64 size> U64 TTable_internal<size>::miss = 0;
#endif
using TTable = TTable_internal<C64(0x2000023)>;
TTable ttable;
class PVTable { public: Move best(uint8_t ply = 0) { return table[0][ply]; }

@@ -107,9 +169,6 @@ std::ostream &operator<<(std::ostream &os, const PVTable &pvtable) { return os; }
using TTable = TTable_internal<C64(0x2FB4377)>;
TTable ttable;
static const uci::Settings *settings = nullptr; static Board board; static repetition::Table rtable;

@@ -476,5 +535,8 @@ int main() { attack::init(); zobrist::init(); uci::loop();
#ifdef USE_STATS
engine::ttable.print();
#endif
return 0; }

diff --git a/ src/perft/perft.cpp b/ src/perft/perft.cpp

@@ -82,6 +82,7 @@ class Perft { void score(const Board &board, Move move) { local.node++;
std::cout << std::setw(16) << std::hex << board.get_hash() << std::endl;
#ifdef USE_FULL_COUNT if (board.is_check()) local.check++; if (move.is_capture()) local.capture++;