1use super::*;
2
3use std::io::{self, BufRead};
4use std::mem;
5use std::str;
6
7
8use scoped_threadpool::Scope;
9
10use core::color::Color;
11use core::mv::Move;
12use util::MutRef;
13
14const WHITE: usize = Color::White as usize;
15const BLACK: usize = Color::Black as usize;
16
17macro_rules! name { () => { "Hexe" } }
18
19macro_rules! authors { () => { "Nikolai Vazquez" } }
20
21macro_rules! id {
22 ($mac:ident) => {
23 concat!("id ", stringify!($mac), " ", $mac!())
24 }
25}
26
27struct Limits {
28 ponder: bool,
29 infinite: bool,
30 moves_to_go: u32,
31 time: [u32; 2],
32 inc: [u32; 2],
33 depth: u32,
34 nodes: u32,
35 mate: u32,
36 move_time: u32,
37}
38
39impl Default for Limits {
40 fn default() -> Limits {
41 unsafe { mem::zeroed() }
43 }
44}
45
46type UciIter<'a> = str::SplitWhitespace<'a>;
47
48pub struct Uci<'a>(MutRef<'a, Engine>);
52
53impl<'a> From<&'a mut Engine> for Uci<'a> {
54 #[inline]
55 fn from(engine: &'a mut Engine) -> Uci<'a> {
56 Uci(MutRef::Borrowed(engine))
57 }
58}
59
60impl<'a> From<Box<Engine>> for Uci<'a> {
61 #[inline]
62 fn from(engine: Box<Engine>) -> Uci<'a> {
63 Uci(MutRef::Owned(engine))
64 }
65}
66
67impl<'a> Default for Uci<'a> {
68 fn default() -> Uci<'a> {
69 Uci(MutRef::Owned(Box::default()))
70 }
71}
72
73impl<'a> Uci<'a> {
74 #[inline]
76 pub fn engine(&self) -> &Engine { &self.0 }
77
78 #[inline]
81 pub fn engine_mut(&mut self) -> &mut Engine { &mut self.0 }
82
83 pub fn start(&mut self) {
99 let Engine { ref mut pool, ref mut engine } = *self.0;
100 pool.scoped(|scope| {
101 let stdin = io::stdin();
102 let lines = stdin.lock()
103 .lines()
104 .filter_map(Result::ok);
105 for line in lines {
106 if !engine.run_uci_line(scope, &line) {
107 break;
108 }
109 }
110 });
111 }
112
113 pub fn start_with<I>(&mut self, commands: I)
130 where I: IntoIterator,
131 I::Item: AsRef<str>,
132 {
133 let Engine { ref mut pool, ref mut engine } = *self.0;
134 pool.scoped(|scope| {
135 for line in commands {
136 engine.run_uci(scope, line.as_ref());
137 }
138 });
139 }
140
141 #[inline]
143 pub fn run(&mut self, command: &str) {
144 let Engine { ref mut pool, ref mut engine } = *self.0;
145 pool.scoped(|scope| {
146 engine.run_uci(scope, command);
147 });
148 }
149}
150
151macro_rules! unknown_command {
152 ($cmd:expr) => { println!("Unknown command: {}", $cmd) }
153}
154
155impl EngineInner {
156 fn run_uci(&mut self, scope: &Scope, command: &str) {
157 if command.is_empty() {
158 unknown_command!(command);
159 } else {
160 for line in command.lines() {
161 if !self.run_uci_line(scope, line) {
162 break;
163 }
164 }
165 }
166 }
167
168 fn run_uci_line(&mut self, scope: &Scope, line: &str) -> bool {
169 let mut split = line.split_whitespace();
170 match split.next().unwrap_or("") {
171 "quit" => return false,
172 "uci" => self.cmd_uci(),
173 "stop" => self.cmd_stop(),
174 "ponderhit" => self.cmd_ponder_hit(),
175 "position" => self.cmd_position(split),
176 "setoption" => self.cmd_set_option(split),
177 "ucinewgame" => self.cmd_new_game(),
178 "go" => self.cmd_go(split),
179 "isready" => println!("readyok"),
180 _ => unknown_command!(line),
181 }
182 true
183 }
184
185 fn cmd_uci(&self) {
186 println!(id!(name));
187 println!(id!(authors));
188 self.options.report();
189 println!("uciok");
190 }
191
192 fn cmd_stop(&mut self) {
193
194 }
195
196 fn cmd_ponder_hit(&mut self) {
197
198 }
199
200 fn cmd_position(&mut self, _: UciIter) {
201
202 }
203
204 fn cmd_set_option(&mut self, mut iter: UciIter) {
205 iter.next(); let mut name = String::new();
208 let mut value = String::new();
209
210 while let Some(next) = iter.next() {
211 if next == "value" {
212 break;
213 }
214 if !name.is_empty() {
215 name.push(' ');
216 }
217 name.push_str(next);
218 }
219
220 for next in iter {
221 if !value.is_empty() {
222 value.push(' ');
223 }
224 value.push_str(next);
225 }
226
227 if !self.options.set(&name, &value) {
228 println!("No such option: {}", name);
229 }
230 }
231
232 fn cmd_new_game(&mut self) {
233
234 }
235
236 fn cmd_go(&mut self, mut iter: UciIter) {
237 let mut limits = Limits::default();
238 let mut moves = Vec::<Move>::new();
239
240 macro_rules! update {
241 ($val:expr) => {
242 if let Some(Ok(val)) = iter.next().map(str::parse) {
243 $val = val
244 }
245 }
246 }
247
248 while let Some(next) = iter.next() {
249 match next {
250 "searchmoves" => while let Some(m) = iter.next() {
251 if let Some(mv) = self.cmd_read_move(m) {
252 moves.push(mv);
253 }
254 },
255 "ponder" => limits.ponder = true,
256 "infinite" => limits.infinite = true,
257 "wtime" => update!(limits.time[WHITE]),
258 "btime" => update!(limits.time[BLACK]),
259 "winc" => update!(limits.inc[WHITE]),
260 "binc" => update!(limits.inc[BLACK]),
261 "movestogo" => update!(limits.moves_to_go),
262 "depth" => update!(limits.depth),
263 "nodes" => update!(limits.nodes),
264 "mate" => update!(limits.mate),
265 "movetime" => update!(limits.move_time),
266 _ => continue,
267 }
268 }
269
270 self.cmd_start_thinking(&limits, &moves);
271 }
272
273 fn cmd_read_move(&self, s: &str) -> Option<Move> {
274 None
275 }
276
277 fn cmd_start_thinking(&mut self, limits: &Limits, moves: &[Move]) {
278
279 }
280}