stellar

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

commit 478983d07da27cc277fef32f73a65f5de5631f1a
parent c36cee0f9d0031a7c068cab56947327f2a199c1e
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Mon, 28 Aug 2023 21:34:58 +0200

Restructure engine

Diffstat:
MCMakeLists.txt | 2+-
Msrc/engine/CMakeLists.txt | 8+++++++-
Msrc/engine/engine.cpp | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/engine/score.hpp | 6+++---
Dsrc/engine/transposition.cpp | 34----------------------------------
Dsrc/engine/transposition.hpp | 41-----------------------------------------
Msrc/engine/uci.cpp | 1+
Msrc/engine/uci.hpp | 1+
8 files changed, 85 insertions(+), 89 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar - VERSION 0.0.23 + VERSION 0.0.24 DESCRIPTION "Chess engine written in C" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES C CXX diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt @@ -1,6 +1,5 @@ add_executable(engine engine.cpp - transposition.cpp uci.cpp ) @@ -12,6 +11,13 @@ target_link_libraries(engine PRIVATE utils ) +stellar_target_precompile_headers(board + PRIVATE "board.hpp" + PRIVATE "move.hpp" + PRIVATE "movelist.hpp" + PRIVATE "piece.hpp" +) + set_target_properties(engine PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp @@ -10,7 +10,6 @@ #include "movelist.hpp" #include "piece.hpp" #include "score.hpp" -#include "transposition.hpp" #include "uci.hpp" #include "utils.hpp" @@ -23,8 +22,62 @@ namespace engine { +struct Hashe { + enum class Flag : uint8_t { + Exact, + Alpha, + Beta + }; + U64 key; + Move best; + uint8_t depth; + int16_t score; + Flag flag; +}; + +class TTable { + public: + static inline constexpr const uint16_t unknown = 32500; + + TTable() {} + TTable(U64 size) : table(size, {0}) {} + + void clear() { table.clear(); }; + int16_t read(const Board &board, int ply, Move *best, int16_t alpha, int16_t beta, uint8_t depth) const { + U64 hash = board.get_hash(); + const Hashe &phashe = table[hash % table.size()]; + if (phashe.key == hash) { + if (phashe.depth >= depth) { + int16_t score = phashe.score; + + if (score < -MATE_SCORE) score += ply; + if (score > MATE_SCORE) score -= ply; + + if (phashe.flag == Hashe::Flag::Exact) return score; + if ((phashe.flag == Hashe::Flag::Alpha) && (score <= alpha)) return alpha; + if ((phashe.flag == Hashe::Flag::Beta) && (score >= beta)) return beta; + } + *best = phashe.best; + } + return unknown; + } + + 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()]; + + if (score < -MATE_SCORE) score += ply; + if (score > MATE_SCORE) score -= ply; + + phashe = {hash, best, depth, score, flag}; + } + + private: + std::vector<Hashe> table; +}; + Board board; -TTable ttable(C64(0x400000)); +TTable ttable; Move pv_table[MAX_PLY][MAX_PLY]; Move killer[2][MAX_PLY]; U32 history[12][64]; @@ -130,7 +183,7 @@ void stats_pv_store(Move move) { pv_length[ply] = pv_length[ply + 1]; } -int quiescence(int alpha, int beta) { +int quiescence(int16_t alpha, int16_t beta) { pv_length[ply] = ply; nodes++; @@ -159,9 +212,9 @@ int quiescence(int alpha, int beta) { return alpha; } -int negamax(int alpha, int beta, uint8_t depth, bool null) { +int negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) { int pv_node = (beta - alpha) > 1; - HasheFlag flag = HasheFlag::Alpha; + Hashe::Flag flag = Hashe::Flag::Alpha; int futility = 0; Move bestMove; Board copy; @@ -169,7 +222,7 @@ int negamax(int alpha, int beta, uint8_t depth, bool null) { pv_length[ply] = ply; int score = ttable.read(board, ply, &bestMove, alpha, beta, depth); - if (ply && score != TTABLE_UNKNOWN && !pv_node) return score; + if (ply && score != TTable::unknown && !pv_node) return score; // && fifty >= 100 if (ply && is_repetition()) return 0; @@ -280,12 +333,12 @@ int negamax(int alpha, int beta, uint8_t depth, bool null) { } alpha = score; - flag = HasheFlag::Exact; + flag = Hashe::Flag::Exact; bestMove = move; stats_pv_store(move); if (score >= beta) { - ttable.write(board, ply, bestMove, beta, depth, HasheFlag::Beta); + ttable.write(board, ply, bestMove, beta, depth, Hashe::Flag::Beta); if (!move.is_capture()) { killer[1][ply] = killer[0][ply]; @@ -309,10 +362,20 @@ int negamax(int alpha, int beta, uint8_t depth, bool null) { } void search_position(const uci::Settings &setting) { - int alpha = -SCORE_INFINITY, beta = SCORE_INFINITY; + int16_t alpha = -SCORE_INFINITY, beta = SCORE_INFINITY; + if (setting.newgame) { + ttable = TTable(C64(0x400000)); + } + + ply = 0; nodes = 0; board = setting.board; + memset(killer, 0x00, sizeof(killer)); + memset(history, 0x00, sizeof(history)); + memset(pv_table, 0x00, sizeof(pv_table)); + memset(pv_length, 0x00, sizeof(pv_length)); + for (uint8_t depth_crnt = 1; depth_crnt <= setting.depth;) { follow_pv = 1; diff --git a/src/engine/score.hpp b/src/engine/score.hpp @@ -1,8 +1,8 @@ #ifndef STELLAR_SCORE_H #define STELLAR_SCORE_H -#define SCORE_INFINITY 50000 -#define MATE_VALUE 49000 -#define MATE_SCORE 48000 +#define SCORE_INFINITY 32000 +#define MATE_VALUE 31000 +#define MATE_SCORE 30000 #endif diff --git a/src/engine/transposition.cpp b/src/engine/transposition.cpp @@ -1,34 +0,0 @@ -#include "transposition.hpp" -#include "board.hpp" -#include "score.hpp" - -int TTable::read(const Board &board, int ply, Move *best, int alpha, int beta, uint8_t depth) const { - - U64 hash = board.get_hash(); - const Hashe &phashe = table[hash % table.size()]; - if (phashe.key == hash) { - if (phashe.depth >= depth) { - int score = phashe.score; - - if (score < -MATE_SCORE) score += ply; - if (score > MATE_SCORE) score -= ply; - - if (phashe.flag == HasheFlag::Exact) return score; - if ((phashe.flag == HasheFlag::Alpha) && (score <= alpha)) return alpha; - if ((phashe.flag == HasheFlag::Beta) && (score >= beta)) return beta; - } - *best = phashe.best; - } - return TTABLE_UNKNOWN; -} - -void TTable::write(const Board &board, int ply, Move best, int score, uint8_t depth, HasheFlag flag) { - - U64 hash = board.get_hash(); - Hashe &phashe = table[hash % table.size()]; - - if (score < -MATE_SCORE) score += ply; - if (score > MATE_SCORE) score -= ply; - - phashe = {hash, best, depth, score, flag}; -} diff --git a/src/engine/transposition.hpp b/src/engine/transposition.hpp @@ -1,41 +0,0 @@ -#ifndef STELLAR_TRANSPOSITION_H -#define STELLAR_TRANSPOSITION_H - -#include "move.hpp" -#include "utils.hpp" - -#include <vector> - -#define TTABLE_UNKNOWN 100000 - -#define T TTable - -enum class HasheFlag : uint8_t { - Exact, - Alpha, - Beta -}; - -typedef struct Hashe Hashe; -struct Hashe { - U64 key; - Move best; - uint8_t depth; - int score; - HasheFlag flag; -}; - -class TTable { - public: - TTable(U64 size) : table(size, {0}) {} - - void clear() { table.clear(); }; - int read(const Board &board, int ply, Move *best, int alpha, int beta, uint8_t depth) const; - void write(const Board &board, int ply, Move best, int score, uint8_t depth, HasheFlag flag); - - private: - std::vector<Hashe> table; -}; - -#undef T -#endif diff --git a/src/engine/uci.cpp b/src/engine/uci.cpp @@ -101,6 +101,7 @@ void loop(void) { } } engine::search_position(settings); + settings.newgame = false; } } } diff --git a/src/engine/uci.hpp b/src/engine/uci.hpp @@ -22,6 +22,7 @@ struct Settings { bool debug = false; bool mate = false; bool infinite = false; + bool newgame = true; }; void loop(void);