1use super::*;
2
3pub mod description {
4 pub const ENGINE_NAME: &str = "Timecat";
5 pub const ENGINE_AUTHOR: &str = "Gourab Ghosh";
6 pub const ENGINE_VERSION: &str = env!("CARGO_PKG_VERSION");
7}
8
9pub mod types {
10 use super::*;
11
12 pub type Ply = usize;
13 pub type Depth = i8;
14 pub type Score = i16;
15 pub type MoveWeight = i32;
16 pub type NumMoves = u16;
17 pub type Spin = u128;
18 pub type Engine = CustomEngine<SearchController, Evaluator>;
19
20 #[cfg(feature = "colored")]
21 pub type ColoredStringFunction = fn(colored::ColoredString) -> colored::ColoredString;
22 #[cfg(not(feature = "colored"))]
23 pub type ColoredStringFunction = fn(String) -> String;
24
25 pub type Result<T> = std::result::Result<T, TimecatError>;
26}
27
28pub mod bitboard_and_square {
29 use super::*;
30 use File::*;
31
32 pub const NUM_SQUARES: usize = 64;
33
34 macro_rules! generate_bitboard_and_square_constants {
35 (@bb_squares $(($file:expr, $rank:expr)),+ $(,)?) => {
36 paste! {
37 $(
38 pub const [<BB_$file$rank>]: BitBoard = BitBoard::new(1 << (8 * ($rank - 1) + $file as usize));
39 )*
40 pub static ALL_SQUARES: [Square; NUM_SQUARES] = [$( Square::[<$file$rank>] ), *];
41 pub static BB_SQUARES: [BitBoard; NUM_SQUARES] = [$( [<BB_$file$rank>] ), *];
42 pub static SQUARES_VERTICAL_MIRROR: [Square; NUM_SQUARES] = [$( [<$file$rank>].vertical_mirror() ), *];
43 pub static SQUARES_HORIZONTAL_MIRROR: [Square; NUM_SQUARES] = [$( [<$file$rank>].horizontal_mirror() ), *];
44 pub static SQUARES_ROTATED: [Square; NUM_SQUARES] = [$( [<$file$rank>].rotate() ), *];
45 }
46 };
47
48 (@bb_ranks_and_files $(($file:expr, $rank:expr)),+ $(,)?) => {
49 paste! {
50 $(
51 pub const [<BB_RANK_$rank>]: BitBoard = unsafe { Rank::from_int($rank - 1) }.to_bitboard();
52 pub const [<BB_FILE_$file>]: BitBoard = $file.to_bitboard();
53 )*
54 pub static BB_RANKS: [BitBoard; NUM_RANKS] = [$( [<BB_RANK_$rank>] ), *];
55 pub static BB_FILES: [BitBoard; NUM_FILES] = [$( [<BB_FILE_$file>] ), *];
56 }
57 };
58 }
59
60 #[rustfmt::skip]
61 generate_bitboard_and_square_constants!(
62 @bb_squares
63 (A, 1), (B, 1), (C, 1), (D, 1), (E, 1), (F, 1), (G, 1), (H, 1),
64 (A, 2), (B, 2), (C, 2), (D, 2), (E, 2), (F, 2), (G, 2), (H, 2),
65 (A, 3), (B, 3), (C, 3), (D, 3), (E, 3), (F, 3), (G, 3), (H, 3),
66 (A, 4), (B, 4), (C, 4), (D, 4), (E, 4), (F, 4), (G, 4), (H, 4),
67 (A, 5), (B, 5), (C, 5), (D, 5), (E, 5), (F, 5), (G, 5), (H, 5),
68 (A, 6), (B, 6), (C, 6), (D, 6), (E, 6), (F, 6), (G, 6), (H, 6),
69 (A, 7), (B, 7), (C, 7), (D, 7), (E, 7), (F, 7), (G, 7), (H, 7),
70 (A, 8), (B, 8), (C, 8), (D, 8), (E, 8), (F, 8), (G, 8), (H, 8),
71 );
72 generate_bitboard_and_square_constants!(
73 @bb_ranks_and_files
74 (A, 1), (B, 2), (C, 3), (D, 4), (E, 5), (F, 6), (G, 7), (H, 8),
75 );
76
77 pub static BB_ADJACENT_FILES: [BitBoard; 8] = [
78 BitBoard::new(144680345676153346),
79 BitBoard::new(361700864190383365),
80 BitBoard::new(723401728380766730),
81 BitBoard::new(1446803456761533460),
82 BitBoard::new(2893606913523066920),
83 BitBoard::new(5787213827046133840),
84 BitBoard::new(11574427654092267680),
85 BitBoard::new(4629771061636907072),
86 ];
87
88 pub const BB_CORNERS: BitBoard = BitBoard::new(
89 BB_A1.into_inner() ^ BB_H1.into_inner() ^ BB_A8.into_inner() ^ BB_H8.into_inner(),
90 );
91 pub const BB_CENTER: BitBoard = BitBoard::new(
92 BB_D4.into_inner() ^ BB_E4.into_inner() ^ BB_D5.into_inner() ^ BB_E5.into_inner(),
93 );
94 pub const BB_EDGES: BitBoard = BitBoard::new(
95 BB_RANK_1.into_inner()
96 | BB_RANK_8.into_inner()
97 | BB_FILE_A.into_inner()
98 | BB_FILE_H.into_inner(),
99 );
100
101 pub const BB_LIGHT_SQUARES: BitBoard = BitBoard::new(0x55aa_55aa_55aa_55aa);
102 pub const BB_DARK_SQUARES: BitBoard = BitBoard::new(0xaa55_aa55_aa55_aa55);
103
104 pub const BB_BACKRANKS: BitBoard =
105 BitBoard::new(BB_RANK_1.into_inner() ^ BB_RANK_8.into_inner());
106
107 pub const BB_UPPER_HALF_BOARD: BitBoard = BitBoard::new(0xFFFFFFFF00000000);
108 pub const BB_LOWER_HALF_BOARD: BitBoard = BitBoard::new(0x00000000FFFFFFFF);
109 pub const BB_LEFT_HALF_BOARD: BitBoard = BitBoard::new(0xF0F0F0F0F0F0F0F0);
110 pub const BB_RIGHT_HALF_BOARD: BitBoard = BitBoard::new(0x0F0F0F0F0F0F0F0F);
111
112 pub const CENTER_SQUARES_BB: BitBoard = BitBoard::new(0x0000001818000000);
113 pub const PSEUDO_CENTER_SQUARES_BB: BitBoard = BitBoard::new(0x00003C24243C0000);
114
115 pub static BOARD_QUARTER_MASKS: [BitBoard; 4] = [
116 BitBoard::new(0x0f0f_0f0f_0000_0000),
117 BitBoard::new(0xf0f0_f0f0_0000_0000),
118 BitBoard::new(0x0000_0000_0f0f_0f0f),
119 BitBoard::new(0x0000_0000_f0f0_f0f0),
120 ];
121
122 pub const DIAGONAL_RAY: BitBoard = BitBoard::new(0x8040201008040201);
123 pub const ANTI_DIAGONAL_RAY: BitBoard = DIAGONAL_RAY.flip_horizontal();
124
125 pub static UPPER_BOARD_MASK: [[BitBoard; 8]; 2] = [
126 [
127 BitBoard::new(0x0000_0000_0000_0000),
128 BitBoard::new(0x0000_0000_0000_00ff),
129 BitBoard::new(0x0000_0000_0000_ffff),
130 BitBoard::new(0x0000_0000_00ff_ffff),
131 BitBoard::new(0x0000_0000_ffff_ffff),
132 BitBoard::new(0x0000_00ff_ffff_ffff),
133 BitBoard::new(0x0000_ffff_ffff_ffff),
134 BitBoard::new(0x00ff_ffff_ffff_ffff),
135 ],
136 [
137 BitBoard::new(0xffff_ffff_ffff_ff00),
138 BitBoard::new(0xffff_ffff_ffff_0000),
139 BitBoard::new(0xffff_ffff_ff00_0000),
140 BitBoard::new(0xffff_ffff_0000_0000),
141 BitBoard::new(0xffff_ff00_0000_0000),
142 BitBoard::new(0xffff_0000_0000_0000),
143 BitBoard::new(0xff00_0000_0000_0000),
144 BitBoard::new(0x0000_0000_0000_0000),
145 ],
146 ];
147}
148
149pub mod board {
150 pub const EMPTY_SPACE_SYMBOL: &str = " ";
151 pub const EMPTY_SPACE_UNICODE_SYMBOL: &str = " ";
152 pub const WHITE_PIECE_UNICODE_SYMBOLS: [&str; 6] = ["♙", "♘", "♗", "♖", "♕", "♔"];
153 pub const BLACK_PIECE_UNICODE_SYMBOLS: [&str; 6] = ["♟", "♞", "♝", "♜", "♛", "♚"];
154 pub const MAX_MOVES_PER_POSITION: usize = 250;
155}
156
157pub mod fen {
158 pub const EMPTY_POSITION_FEN: &str = "8/8/8/8/8/8/8/8 w - - 0 1";
159 pub const STARTING_POSITION_FEN: &str =
160 "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
161}
162
163pub mod strings {
164 use super::*;
165
166 macro_rules! generate_constants {
167 ($constant_name:ident, [$( $func_name:ident ), *]) => {
168 #[cfg(feature = "colored")]
169 pub static $constant_name: &[ColoredStringFunction] = &[$( colored::Colorize::$func_name ), *];
170 #[cfg(not(feature = "colored"))]
171 pub static $constant_name: &[ColoredStringFunction] = &[];
172 };
173 }
174
175 generate_constants!(WHITE_PIECES_STYLE, [white, bold]);
176 generate_constants!(BLACK_PIECES_STYLE, [purple, bold]);
177 generate_constants!(BITBOARD_OCCUPIED_SQUARE_STYLE, [white, bold]);
178 generate_constants!(BOARD_SKELETON_STYLE, [green]);
179 generate_constants!(BOARD_LABEL_STYLE, [red, bold]);
180 generate_constants!(INFO_MESSAGE_STYLE, [bright_cyan, bold]);
181 generate_constants!(CHECK_STYLE, [on_bright_red]);
182 generate_constants!(CHECKERS_STYLE, [bright_red, bold]);
183 generate_constants!(CHECKMATE_SCORE_STYLE, [bright_red, bold]);
184 generate_constants!(PERFT_MOVE_STYLE, [green, bold]);
185 generate_constants!(PERFT_COUNT_STYLE, []);
186 generate_constants!(INPUT_MESSAGE_STYLE, [blue, bold]);
187 generate_constants!(SUCCESS_MESSAGE_STYLE, [green, bold]);
188 generate_constants!(ERROR_MESSAGE_STYLE, [red, bold]);
189 generate_constants!(LAST_MOVE_HIGHLIGHT_STYLE, [on_bright_black]);
190 generate_constants!(WARNING_MESSAGE_STYLE, [bright_yellow, bold]);
191
192 pub const STRINGIFY_NONE: &str = "UNKNOWN";
193}
194
195pub mod evaluate {
196 use super::*;
197
198 pub const ENDGAME_PIECE_THRESHOLD: u32 = 12;
199 pub const CACHE_TABLE_SIZE: CacheTableSize = CacheTableSize::Exact(16);
200 pub const DRAW_SCORE: Score = PAWN_VALUE / 2;
201 pub const CHECKMATE_SCORE: Score = 25_000;
202 pub const CHECKMATE_THRESHOLD: Score = CHECKMATE_SCORE - MAX_PLY as Score - 1;
203 pub const INFINITY: Score = CHECKMATE_SCORE + 4 * MAX_PLY as Score;
204 pub const PAWN_VALUE: Score = 100;
205 pub const MAX_PLY: usize = 255;
206 pub const INITIAL_MATERIAL_SCORE_ABS: Score = 16 * PAWN_VALUE
207 + 4 * (Knight.evaluate() + Bishop.evaluate() + Rook.evaluate())
208 + 2 * Queen.evaluate();
209 pub const MAX_MATERIAL_SCORE: Score = INITIAL_MATERIAL_SCORE_ABS / 2;
210 pub const WINNING_SCORE_THRESHOLD: Score = 15 * PAWN_VALUE;
211}
212
213pub mod cache_table {
214 use super::*;
215
216 pub const DEFAULT_HASH: NonZeroU64 = NonZeroU64::new(1).unwrap();
217}
218
219pub mod engine {
220 use super::*;
221
222 pub const NUM_KILLER_MOVES: usize = 3;
223
224 pub const DISABLE_ALL_PRUNINGS: bool = false;
225
226 pub const NULL_MOVE_MIN_DEPTH: Depth = 2;
227 pub const NULL_MOVE_MIN_REDUCTION: Depth = 2;
228 pub const NULL_MOVE_DEPTH_DIVIDER: Depth = 4;
229
230 pub const FULL_DEPTH_SEARCH_LMR: usize = 4;
231 pub const REDUCTION_LIMIT_LMR: Depth = 3;
232 pub const LMR_BASE_REDUCTION: f64 = 0.75;
233 pub const LMR_MOVE_DIVIDER: f64 = 2.25;
234
235 pub const ASPIRATION_WINDOW_CUTOFF: Score = PAWN_VALUE / 2;
236
237 pub const FOLLOW_PV: bool = true;
238 pub const PRINT_MOVE_INFO_DURATION_THRESHOLD: Duration = Duration::from_millis(1000);
239
240 pub const NUM_BEST_ROOT_MOVES_TO_SEARCH_FIRST: usize = 3;
241
242 #[rustfmt::skip]
243 pub static MVV_LVA: [[MoveWeight; 6]; 6] = [
244 [105, 205, 305, 405, 505, 605],
245 [104, 204, 304, 404, 504, 604],
246 [103, 203, 303, 403, 503, 603],
247 [102, 202, 302, 402, 502, 602],
248 [101, 201, 301, 401, 501, 601],
249 [100, 200, 300, 400, 500, 600],
250 ];
251}
252
253pub mod binary {
254 use super::*;
255
256 pub const DEFAULT_SELFPLAY_COMMAND: SearchConfig =
257 SearchConfig::from_go_command(GoCommand::from_millis(3000));
258}
259
260pub mod io {
261 use super::*;
262
263 pub const COMMUNICATION_CHECK_INTERVAL: Duration = Duration::from_millis(1);
264}
265
266pub mod atomic {
267 pub const MEMORY_ORDERING: std::sync::atomic::Ordering = std::sync::atomic::Ordering::Relaxed;
268}
269
270pub mod color {
271 use super::*;
272
273 pub const NUM_COLORS: usize = 2;
274 pub static ALL_COLORS: [Color; NUM_COLORS] = [Black, White];
275}
276
277pub mod piece {
278 use super::*;
279
280 pub const NUM_PIECE_TYPES: usize = 6;
281 pub static ALL_PIECE_TYPES: [PieceType; NUM_PIECE_TYPES] =
282 [Pawn, Knight, Bishop, Rook, Queen, King];
283 pub static ALL_PIECES: [Piece; NUM_PIECE_TYPES * NUM_COLORS] = [
284 WhitePawn,
285 WhiteKnight,
286 WhiteBishop,
287 WhiteRook,
288 WhiteQueen,
289 WhiteKing,
290 BlackPawn,
291 BlackKnight,
292 BlackBishop,
293 BlackRook,
294 BlackQueen,
295 BlackKing,
296 ];
297 pub const NUM_PROMOTION_PIECES: usize = 4;
298 pub static PROMOTION_PIECES: [PieceType; NUM_PROMOTION_PIECES] = [Queen, Knight, Rook, Bishop];
299}
300
301pub mod ranks {
302 use super::*;
303
304 pub const NUM_RANKS: usize = 8;
305 pub static ALL_RANKS: [Rank; NUM_RANKS] = [
306 Rank::First,
307 Rank::Second,
308 Rank::Third,
309 Rank::Fourth,
310 Rank::Fifth,
311 Rank::Sixth,
312 Rank::Seventh,
313 Rank::Eighth,
314 ];
315}
316
317pub mod files {
318 use super::*;
319
320 pub const NUM_FILES: usize = 8;
321 pub static ALL_FILES: [File; NUM_FILES] = [
322 File::A,
323 File::B,
324 File::C,
325 File::D,
326 File::E,
327 File::F,
328 File::G,
329 File::H,
330 ];
331}
332
333pub mod default_parameters {
334 use super::*;
335
336 pub const TIMECAT_DEFAULTS: TimecatDefaults = TimecatDefaults {
337 #[cfg(feature = "colored")]
338 colored: true,
339 console_mode: cfg!(feature = "debug"),
340 t_table_size: CacheTableSize::Exact(16),
341 long_algebraic_notation: false,
342 num_threads: NonZeroUsize::new(1).unwrap(),
343 move_overhead: Duration::from_millis(10),
344 use_own_book: false,
345 book_path: None,
346 inbuilt_book_bytes: None,
347 debug_mode: true,
348 chess960_mode: false,
349 };
350}