BenBot 1.7.5
A chess engine
Loading...
Searching...
No Matches
Engine.hpp
Go to the documentation of this file.
1/*
2 * ======================================================================================
3 *
4 * ░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░▒▓████████▓▒░
5 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
6 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
7 * ░▒▓███████▓▒░░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
8 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
9 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
10 * ░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░
11 *
12 * ======================================================================================
13 */
14
19
20#pragma once
21
22#include <array>
23#include <atomic>
24#include <filesystem>
25#include <functional>
31#include <span>
32#include <string>
33#include <string_view>
34
35namespace chess::uci {
36struct GoCommandOptions;
37} // namespace chess::uci
38
39namespace ben_bot {
40
41using chess::game::Position;
42using chess::moves::Move;
43using std::string_view;
44
45namespace uci = chess::uci;
46
50class [[nodiscard]] Engine final : public uci::EngineBase {
51public:
52 Engine() = default;
53
54 ~Engine() override = default;
55
56 Engine(const Engine&) = delete;
57 Engine& operator=(const Engine&) = delete;
58
59 Engine(Engine&&) = delete;
60 Engine& operator=(Engine&&) = delete;
61
63 void read_config_file(const std::filesystem::path& file);
64
65private:
66 [[nodiscard]] auto get_name() const -> std::string override;
67 [[nodiscard]] auto get_author() const -> string_view override { return "Ben Vining"; }
68
69 void new_game(bool firstCall) override;
70
71 void set_position(const Position& pos) override { searcher.context.set_position(pos); }
72
73 void go(const uci::GoCommandOptions& opts) override;
74
75 void abort_search() override { searcher.context.abort(); }
76
77 void ponder_hit() override { searcher.context.ponder_hit(); }
78
79 void wait() override { searcher.context.wait(); }
80
81 auto is_searching() const noexcept -> bool override { return searcher.context.in_progress(); }
82
83 void set_debug(const bool shouldDebug) override
84 {
85 debugMode.store(shouldDebug, std::memory_order::relaxed);
86 }
87
88 [[nodiscard]] auto get_options() -> std::span<uci::Option*> override { return options; }
89
90 void handle_custom_command(string_view command, string_view opts) override;
91
92 void run_perft(string_view arguments) const;
93
94 void run_bench(string_view arguments) const;
95
96 void make_null_move();
97 void color_flip();
98
99 void print_logo_and_version() const;
100 void print_help(string_view args) const;
101 void print_options() const;
102 void print_current_position(string_view arguments) const;
103
104 void set_pretty_printing(bool shouldPrettyPrint);
105
106 [[nodiscard]] auto pretty_print_move(Move move) const -> std::string;
107
108 static void print_compiler_info();
109
110 static void start_file_logger(string_view arg);
111
112 void write_config_file(string_view arg) const;
113 void read_config_file(string_view arg);
114
115 [[nodiscard]] static auto create_move_format_option() -> uci::ComboOption;
116
117 std::atomic_bool debugMode { false };
118
119 search::Thread searcher;
120
121 /* ----- UCI options ----- */
122
123 uci::IntOption ttSize {
124 "Hash",
125 1, 2048, 16,
126 "Sets the maximum transposition table size (in MB).",
127 [this](const int sizeMB) {
128 searcher.context.resize_transposition_table(static_cast<size_t>(sizeMB));
129 }
130 };
131
132 uci::Action clearTT {
133 "Clear Hash",
134 [this] { searcher.context.clear_transposition_table(); },
135 "Press to clear the transposition table."
136 };
137
138 // The engine doesn't start pondering on its own without explicitly being told to
139 // via another go command; this option is needed to inform the GUI that the engine
140 // supports pondering, and also gives the engine the opportunity to adjust its time
141 // management algorithm when pondering is enabled.
142 uci::BoolOption ponder {
143 "Ponder",
144 false,
145 "Controls whether pondering is allowed.",
146 [this](const bool shouldPonder) {
147 // the ponder flag is only ever turned on via the go options,
148 // but it can be turned off by disabling this UCI option
149 if (not shouldPonder)
150 searcher.context.set_pondering(false);
151 }
152 };
153
154 uci::IntOption threads {
155 "Threads", 1, 1, 1,
156 "Number of searcher threads (currently a dummy)."
157 };
158
159 uci::IntOption moveOverhead {
160 "Move Overhead", 0, 5000, 10,
161 "Extra overhead time subtracted from search time (in ms). Increase this if engine loses on time."
162 };
163
164 uci::StringOption logFile {
165 "Debug Log File", "<empty>",
166 "If not empty, engine I/O will be mirrored to this file.",
168 };
169
170 uci::BoolOption prettyPrintMode {
171 "Pretty Print",
172 false,
173 "When on, search output is pretty-printed instead of printed in UCI format.",
174 [this](const bool usePretty) { set_pretty_printing(usePretty); }
175 };
176
177 uci::ComboOption moveFormat { create_move_format_option() };
178
179 std::array<uci::Option*, 8uz> options {
180 &ttSize, &clearTT, &ponder, &threads, &moveOverhead, &logFile, &prettyPrintMode, &moveFormat
181 };
182
183 /* ----- Custom commands ----- */
184
185 // clang-format off
186 std::array<CustomCommand, 10uz> customCommands {
187 CustomCommand {
188 .name = "showpos",
189 .action = [this](const string_view args){ print_current_position(args); },
190 .description = "Prints the current position",
191 .argsHelp = "[utf8]"
192 },
193 CustomCommand {
194 .name = "makenull",
195 .action = CustomCommand::void_cb([this]{ make_null_move(); }),
196 .description = "Play a null move on the internal board",
197 .argsHelp = {}
198 },
199 CustomCommand {
200 .name = "flip",
201 .action = CustomCommand::void_cb([this]{ color_flip(); }),
202 .description = "Color-flip the current position",
203 .argsHelp = {}
204 },
205 CustomCommand {
206 .name = "options",
207 .action = CustomCommand::void_cb([this]{ print_options(); }),
208 .description = "Dump current UCI option values",
209 .argsHelp = {}
210 },
211 CustomCommand {
212 .name = "perft",
213 .action = [this](const string_view args) { run_perft(args); },
214 .description = "Computes perft of the current position to the given depth",
215 .argsHelp = "<N> [json]"
216 },
217 CustomCommand {
218 .name = "bench",
219 .action = [this](const string_view args){ run_bench(args); },
220 .description = "Runs a search and reports total nodes and NPS",
221 .argsHelp = "[<depth>] [<epdPath>]"
222 },
223 CustomCommand {
224 .name = "compiler",
225 .action = CustomCommand::void_cb([]{ print_compiler_info(); }),
226 .description = "Print compiler info",
227 .argsHelp = {}
228 },
229 CustomCommand {
230 .name = "writeconfig",
231 .action = [this](const string_view args) { write_config_file(args); },
232 .description = "Writes the engine's current state to a configuration file at the given path",
233 .argsHelp = "<path>"
234 },
235 CustomCommand {
236 .name = "readconfig",
237 .action = [this](const string_view args) { read_config_file(args); },
238 .description = "Loads engine state from a configuration file at the given path",
239 .argsHelp = "<path>"
240 },
241 CustomCommand {
242 .name = "help",
243 .action = [this] (const string_view args){ print_help(args); },
244 .description = "Display this text",
245 .argsHelp = "[--no-logo]"
246 }
247 };
248 // clang-format on
249};
250
251} // namespace ben_bot
void set_debug(const bool shouldDebug) override
Definition Engine.hpp:83
auto get_author() const -> string_view override
Definition Engine.hpp:67
auto is_searching() const noexcept -> bool override
Definition Engine.hpp:81
void wait() override
Definition Engine.hpp:79
void new_game(bool firstCall) override
Engine & operator=(Engine &&)=delete
auto get_name() const -> std::string override
~Engine() override=default
Engine()=default
Engine(const Engine &)=delete
Engine & operator=(const Engine &)=delete
void ponder_hit() override
Definition Engine.hpp:77
void set_position(const Position &pos) override
Definition Engine.hpp:71
auto get_options() -> std::span< uci::Option * > override
Definition Engine.hpp:88
void abort_search() override
Definition Engine.hpp:75
void read_config_file(const std::filesystem::path &file)
void go(const uci::GoCommandOptions &opts) override
Engine(Engine &&)=delete
void handle_custom_command(string_view command, string_view opts) override
auto start_file_logger(const std::filesystem::path &logFile) -> std::expected< void, std::string >
void resize_transposition_table(size_t sizeMB)
Definition Context.hpp:89
void set_pondering(const bool isPonderMode) noexcept
Definition Context.hpp:114