commit 3b35974c0662fb2d1d5bc7bead88a5f53e0bee28
parent 3339ad957adba20630645faafc9751f114436587
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Mon, 4 Sep 2023 22:41:33 +0200
Small refactor of pv table and uci
Diffstat:
8 files changed, 70 insertions(+), 51 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
- VERSION 0.0.33
+ VERSION 0.0.34
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,7 +1,7 @@
add_executable(engine
evaluate.cpp
- engine.cpp
uci.cpp
+ engine.cpp
)
target_link_libraries(engine
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -105,17 +105,43 @@ class RTable {
const static int hashNull = 0;
};
+class PVTable {
+ public:
+ Move best(uint8_t ply = 0) { return table[0][ply]; }
+
+ void start(uint8_t ply) { length[ply] = ply; }
+ void store(Move move, uint8_t ply) {
+ table[ply][ply] = move;
+ for (uint8_t i = ply + 1; i < length[ply + 1]; i++)
+ table[ply][i] = table[ply + 1][i];
+ length[ply] = length[ply + 1];
+ }
+
+ friend std::ostream &operator<<(std::ostream &os, const PVTable &pvtable);
+
+ private:
+ Move table[MAX_PLY][MAX_PLY] = {{}};
+ uint8_t length[MAX_PLY] = {0};
+};
+
+std::ostream &operator<<(std::ostream &os, const PVTable &pvtable) {
+ for (uint8_t i = 0; i < pvtable.length[0]; i++)
+ os << pvtable.table[0][i] << " ";
+ return os;
+}
+
static const uci::Settings *settings = nullptr;
static Board board;
static TTable ttable;
static RTable rtable;
-static Move pv_table[MAX_PLY][MAX_PLY];
+
+static PVTable pvtable;
+
static Move killer[2][MAX_PLY];
static U32 history[12][64];
-static uint8_t pv_length[MAX_PLY];
static bool follow_pv;
static U64 nodes;
-static U32 ply;
+static uint8_t ply;
U32 inline move_list_score(Move move) {
const piece::Type type = board.get_square_piece_type(move.source());
@@ -143,7 +169,7 @@ std::vector<int> move_list_sort(MoveList &list, const Move best) {
if (!best_found && ply && follow_pv) {
follow_pv = false;
for (int i = 0; i < list.size(); i++) {
- if (list[i] == pv_table[0][ply]) {
+ if (list[i] == pvtable.best(ply)) {
score[i] = 20000;
follow_pv = true;
break;
@@ -188,20 +214,12 @@ void stats_move_unmake(Board ©, const Move move) {
ply--;
}
-void stats_pv_store(Move move) {
- pv_table[ply][ply] = move;
- for (int i = ply + 1; i < pv_length[ply + 1]; i++) {
- pv_table[ply][i] = pv_table[ply + 1][i];
- }
- pv_length[ply] = pv_length[ply + 1];
-}
-
int16_t quiescence(int16_t alpha, int16_t beta) {
if ((nodes & 2047) == 0) {
uci::communicate(settings);
if (settings->stopped) return 0;
}
- pv_length[ply] = ply;
+ pvtable.start(ply);
nodes++;
int score = evaluate::score_position(board);
@@ -219,7 +237,7 @@ int16_t quiescence(int16_t alpha, int16_t beta) {
if (score > alpha) {
alpha = score;
- stats_pv_store(move);
+ pvtable.store(move, ply);
if (score >= beta) return beta;
}
@@ -240,7 +258,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {
uci::communicate(settings);
if (settings->stopped) return 0;
}
- pv_length[ply] = ply;
+ pvtable.start(ply);
// && fifty >= 100
if (ply && rtable.is_repetition(board.get_hash())) return 0;
@@ -357,7 +375,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {
alpha = score;
flag = Hashe::Flag::Exact;
bestMove = move;
- stats_pv_store(move);
+ pvtable.store(move, ply);
if (score >= beta) {
ttable.write(board, ply, bestMove, beta, depth, Hashe::Flag::Beta);
@@ -404,8 +422,7 @@ Move search_position(const uci::Settings &settingsr) {
settings->stopped = false;
memset(killer, 0x00, sizeof(killer));
memset(history, 0x00, sizeof(history));
- memset(pv_table, 0x00, sizeof(pv_table));
- memset(pv_length, 0x00, sizeof(pv_length));
+ rtable = RTable();
for (uint8_t depth = 1; depth <= settings->depth; depth++) {
uci::communicate(settings);
@@ -423,11 +440,13 @@ Move search_position(const uci::Settings &settingsr) {
alpha = score - WINDOW;
beta = score + WINDOW;
- if (pv_length[0]) uci::pv_print(score, depth, nodes, pv_length, pv_table, board);
+ uci::pv_print(score, depth, nodes, pvtable);
+ if (settings->depth == 64 && uci::get_time_ms() >= (settings->stoptime + settings->starttime) / 2)
+ break;
}
settings->board = board;
- return pv_table[0][0];
+ return pvtable.best();
}
} // namespace engine
diff --git a/src/engine/engine.hpp b/src/engine/engine.hpp
@@ -9,6 +9,9 @@ namespace engine {
Move search_position(const uci::Settings &setting);
-}
+class PVTable;
+std::ostream &operator<<(std::ostream &os, const PVTable &pvtable);
+
+} // namespace engine
#endif
diff --git a/src/engine/uci.cpp b/src/engine/uci.cpp
@@ -9,19 +9,14 @@
#include "uci.hpp"
namespace uci {
+
uint32_t get_time_ms(void) {
struct timeval time;
gettimeofday(&time, NULL);
return time.tv_sec * 1000 + time.tv_usec / 1000;
}
-void move_print(const Board &board, Move move) {
- std::cout << square::to_coordinates(move.source()) << square::to_coordinates(move.target());
- if (move.is_promote()) std::cout << piece::get_code(move.promoted(), board.get_side());
-}
-
-void pv_print(int16_t score, uint8_t depth, uint64_t nodes, uint8_t pv_length[MAX_PLY],
- Move pv_table[MAX_PLY][MAX_PLY], const Board &board) {
+void pv_print(int16_t score, uint8_t depth, uint64_t nodes, const engine::PVTable &pvtable) {
if (score > -MATE_VALUE && score < -MATE_SCORE) {
std::cout << "info score mate " << -(score + MATE_VALUE) / 2 - 1;
} else if (score > MATE_SCORE && score < MATE_VALUE) {
@@ -32,12 +27,7 @@ void pv_print(int16_t score, uint8_t depth, uint64_t nodes, uint8_t pv_length[MA
std::cout << " depth " << (unsigned)depth;
std::cout << " nodes " << nodes;
- std::cout << " pv ";
- for (int i = 0; i < pv_length[0]; i++) {
- uci::move_print(board, pv_table[0][i]);
- std::cout << " ";
- }
- std::cout << "\n";
+ std::cout << " pv " << pvtable << "\n";
}
void communicate(const uci::Settings *settings) {
@@ -110,7 +100,7 @@ void loop(void) {
} else if (command == "go") {
settings.searchMoves.clear();
uint32_t wtime = 0, btime = 0, movetime = 0;
- uint16_t winc = 0, binc = 0, movestogo = 30;
+ uint16_t winc = 0, binc = 0, movestogo = 60;
while (iss >> command) {
if (command == "wtime")
@@ -162,9 +152,7 @@ void loop(void) {
if (!time) settings.infinite = true;
const Move best = engine::search_position(settings);
- std::cout << "bestmove ";
- uci::move_print(settings.board, best);
- std::cout << "\n";
+ std::cout << "bestmove " << best << '\n';
settings.newgame = false;
}
diff --git a/src/engine/uci.hpp b/src/engine/uci.hpp
@@ -7,6 +7,12 @@
#include "score.hpp"
#include "utils.hpp"
+namespace engine {
+
+class PVTable;
+
+} // namespace engine
+
namespace uci {
struct Settings {
@@ -30,12 +36,9 @@ struct Settings {
};
void loop(void);
-void pv_print(int16_t score, uint8_t depth, uint64_t nodes, uint8_t pv_length[MAX_PLY],
- Move pv_table[MAX_PLY][MAX_PLY], const Board &board);
-void move_print(const Board &board, Move move);
-void communicate(const uci::Settings *settings);
uint32_t get_time_ms(void);
+void communicate(const uci::Settings *settings);
+void pv_print(int16_t score, uint8_t depth, uint64_t nodes, const engine::PVTable &pvtable);
} // namespace uci
-
#endif
diff --git a/src/move/move.cpp b/src/move/move.cpp
@@ -93,13 +93,18 @@ bool Move::make(Board &board) const {
return 0;
}
+void Move::print(void) const {
+ std::cout << square::to_coordinates(source()) << " ";
+ std::cout << square::to_coordinates(target()) << " ";
+ std::cout << (is_promote() ? piece::get_code(promoted()) : '.') << " ";
+ std::cout << is_double() << " ";
+ std::cout << is_enpassant() << " ";
+ std::cout << is_castle();
+}
+
std::ostream &operator<<(std::ostream &os, Move move) {
- os << square::to_coordinates(move.source()) << " ";
- os << square::to_coordinates(move.target()) << " ";
- os << (move.is_promote() ? piece::get_code(move.promoted()) : '.') << " ";
- os << move.is_double() << " ";
- os << move.is_enpassant() << " ";
- os << move.is_castle();
+ std::cout << square::to_coordinates(move.source()) << square::to_coordinates(move.target());
+ if (move.is_promote()) std::cout << piece::get_code(move.promoted());
return os;
}
diff --git a/src/move/move.hpp b/src/move/move.hpp
@@ -56,6 +56,7 @@ struct Move {
bool make(Board &board) const;
friend std::ostream &operator<<(std::ostream &os, Move move);
+ void print(void) const;
private:
inline void piece_remove(Board &board, piece::Type type, color::Color color, square::Square square) const;