1use crate::bitboard::*;
2use crate::constants::*;
3use crate::lineargame::*;
4use crate::piece::*;
5use crate::square::*;
6use std::io::{self, BufRead};
9
10pub struct Uci {
11 pub engine_name: String,
12 pub engine_author: String,
13 pub linear_game: LinearGame,
14}
15
16pub fn create_default_uci() -> Uci {
17 let mut uci = Uci {
18 engine_name: "rustengine".to_string(),
19 engine_author: "easychessanimations".to_string(),
20 linear_game: LinearGame::new(),
21 };
22 uci.linear_game.init(DEFAULT_VARIANT);
23 uci
24}
25
26pub fn demo() {
27 let x: Bitboard = 0xffff00000000ffff;
28
29 println!("{}", x.pretty_print_string());
30
31 let sq: Square = rank_file(RANK_3, FILE_D);
32
33 println!("square {} file {} rank {}", sq.uci(), sq.file(), sq.rank());
34
35 let fig: Figure = LANCERNE;
36
37 println!("\nfigure {} symbol {}", fig, fig.symbol());
38
39 let p: Piece = color_figure(WHITE, LANCERNE);
40
41 println!(
42 "\npiece {} fen symbol {} san symbol {} uci symbol {} san letter {}",
43 p,
44 p.fen_symbol(),
45 p.san_symbol(),
46 p.uci_symbol(),
47 p.san_letter()
48 );
49
50 let mut bb: Bitboard = sq.bitboard() | SQUARE_G6.bitboard();
51
52 loop {
53 println!("\n{}", bb.pretty_print_string());
54
55 let (sq, ok) = bb.pop_square();
56
57 if ok {
58 println!("{}", sq.uci());
59 } else {
60 println!("no square could be popped\n");
61 break;
62 }
63 }
64
65 println!(
66 "{}",
67 jump_attack(SQUARE_E4, &KNIGHT_DELTAS, SQUARE_F6.bitboard()).pretty_print_string()
68 );
69
70 println!(
71 "{}",
72 sliding_attack(SQUARE_E4, &QUEEN_DELTAS, SQUARE_G6.bitboard()).pretty_print_string()
73 );
74
75 println!("{}", BISHOP_ATTACK[SQUARE_C7].pretty_print_string());
76
77 println!("{}", KING_AREA[SQUARE_G8].pretty_print_string());
78}
79
80pub fn enum_occup_demo() {
81 let occup = BISHOP_ATTACK[SQUARE_C7];
82
83 let mut mask: usize = 0;
84
85 loop {
86 if mask < occup.variation_count() {
87 println!(
88 "{}\n{}",
89 mask,
90 translate_mask_to_occupancy(mask, occup).pretty_print_string()
91 );
92 mask += 1;
93 } else {
94 break;
95 }
96 }
97}
98
99pub fn mobility_demo() {
100 println!(
101 "{}",
102 queen_mobility(
103 SQUARE_E4,
104 MoveGenMode::All,
105 SQUARE_G6.bitboard() | SQUARE_C4.bitboard(),
106 SQUARE_D5.bitboard() | SQUARE_E7.bitboard()
107 )
108 .pretty_print_string()
109 )
110}
111
112pub fn magic_space() {
113 let tb = total_magic_space(BISHOP_MAGICS);
114
115 let sb = tb * std::mem::size_of::<Bitboard>();
116
117 println!("total bishop magic space {} bytes", sb);
118
119 let tr = total_magic_space(ROOK_MAGICS);
120
121 let sr = tr * std::mem::size_of::<Bitboard>();
122
123 println!("total rook magic space {} bytes", sr);
124
125 println!(
126 "\ngrand total magic space {} bytes = {:0.2} MiBs",
127 sb + sr,
128 (sb + sr) as f32 / 1e6
129 );
130
131 println!("magic units bishop {} rook {} total {}", tb, tr, tb + tr);
132}
133
134impl Uci {
135 pub fn execute_uci_command(&self) {
136 println!("id name {}", self.engine_name);
137 println!("id author {}\n", self.engine_author);
138 println!("uciok");
139 }
140
141 pub fn process_uci_command(&mut self, line: String) -> bool {
142 let parts: Vec<&str> = line.split(" ").collect();
143
144 let command = parts[0];
145
146 if command == "quit" || command == "q" || command == "exit" || command == "x" {
147 return false;
148 }
149
150 if command == "uci" {
151 self.execute_uci_command();
152 return true;
153 }
154
155 if command == "i" {
156 self.linear_game.print();
157 return true;
158 }
159
160 if command == "demo" {
161 let mut arg = "";
162
163 if parts.len() > 0 {
164 arg = parts[1];
165 }
166
167 match arg {
168 "occup" => enum_occup_demo(),
169 "mob" => mobility_demo(),
170 "space" => magic_space(),
171 _ => demo(),
172 }
173
174 return true;
175 }
176
177 if command == "perft" || command == "p" {
178 let depth = if command == "p" {
179 4
180 } else {
181 parts[1].parse().expect("illegal perft depth")
182 };
183 let perft_result = self.linear_game.perft(depth);
184
185 println!(
186 "node(s) {:?} , time {:.2} sec(s) , nps {} kNode(s)/sec",
187 perft_result.0, perft_result.1, perft_result.2
188 );
189 }
190
191 if command == "bb" {
192 self.linear_game.current().print_bitboards();
193
194 return true;
195 }
196
197 if command == "d" {
198 self.linear_game.pop();
199 self.linear_game.print();
200 }
201
202 match command.parse::<usize>() {
203 Ok(n) => {
204 if n > 0 {
205 self.linear_game.push_by_index(n - 1);
206 self.linear_game.print();
207 }
208 return true;
209 }
210 Err(_) => (),
211 }
212
213 true
214 }
215
216 pub fn welcome(&self, build_info: &str) {
217 println!(
218 "{} bitboard multi variant uci chess analysis engine by {} [ {} ]",
219 self.engine_name, self.engine_author, build_info
220 );
221 }
222
223 pub fn uci_loop(&mut self) {
224 let stdin = io::stdin();
225
226 for line in stdin.lock().lines() {
227 if !self.process_uci_command(line.unwrap()) {
228 break;
229 }
230 }
231 }
232}