stellar

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

commit644090d7e796c3e13c7595700830ddcad8836754
parent0218a1559240963bdc53c7157b1cb16cfa4878f0
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateWed, 20 Mar 2024 18:51:51 +0000

Improve transposition table, add stats info

Diffstat:
MCMakeLists.txt|+-
Msrc/engine/CMakeLists.txt|++++
Msrc/engine/engine.cpp|++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/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++;