diff options
author | eug-vs <eugene@eug-vs.xyz> | 2023-09-04 04:57:41 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2023-09-04 04:57:41 +0300 |
commit | cc3f6674fa1662626a95995b32890c8ddd6255a0 (patch) | |
tree | 2371993700866a01e43c9b5c83b8a34dcea2f2ae | |
parent | 5390756aa46b1ae2cf1e274af8f2fdc24ed8009c (diff) | |
download | chessnost-cc3f6674fa1662626a95995b32890c8ddd6255a0.tar.gz |
refactor: more testable UCI parse_command()
-rw-r--r-- | src/grossmeister/UCI.rs | 185 |
1 files changed, 98 insertions, 87 deletions
diff --git a/src/grossmeister/UCI.rs b/src/grossmeister/UCI.rs index 2351b2f..50af980 100644 --- a/src/grossmeister/UCI.rs +++ b/src/grossmeister/UCI.rs @@ -14,103 +14,114 @@ impl Grossmeister { loop { let mut cmd = String::new(); stdin().read_line(&mut cmd).unwrap(); - let mut tokens = cmd.trim().split(' '); - - if let Some(token) = tokens.next() { - match token { - "uci" => { - println!("id name {}", NAME); - println!("id author {}", AUTHOR); - println!("uciok"); - } - "debug" => { - if let Some(token) = tokens.next() { - match token { - "on" => self.debug = true, - "off" => self.debug = false, - _ => { - panic!("Wrong option to debug: {}. CMD: {}", token, cmd); - }, - } - }; - } - "isready" => { - println!("readyok"); - } - "setoption" => { - todo!() - } - "ucinewgame" => { - *self = Self::default() - } - "position" => { - match tokens.next() { - Some("startpos") => { - self.board = Board::new(); - } - Some("fen") => { - let fen = (0..6).filter_map(|_| tokens.next()).collect::<Vec<_>>().join(" "); - self.board = Board::from_FEN(fen.to_string()); - } - _ => panic!("Expected position"), + let tokens = cmd.trim().split(' '); + if !self.parse_command(tokens, &mut search_handle) { + break + } + } + } + + pub fn parse_command(&mut self, mut tokens: Split<char>, search_handle: &mut Option<JoinHandle<Self>>) -> bool { + if let Some(token) = tokens.next() { + match token { + "uci" => { + println!("id name {}", NAME); + println!("id author {}", AUTHOR); + println!("uciok"); + } + "debug" => { + if let Some(token) = tokens.next() { + match token { + "on" => self.debug = true, + "off" => self.debug = false, + _ => panic!("Wrong option to debug: {}", token), } - if let Some("moves") = tokens.next() { - for token in tokens.by_ref() { - let input_move = Move::from_notation(token.chars()); - let moves = self.board.generate_pseudolegal_moves(); - if let Some(mov) = moves - .iter() - .find(|m| { - let promo_matches = match input_move.kind { - MoveKind::Promotion(piece) => match m.kind { - MoveKind::Promotion(another_piece) => piece.without_color() == another_piece.without_color(), - _ => false - }, - _ => true, - }; - promo_matches && m.source == input_move.source && m.target == input_move.target - }) { - self.board.make_move(*mov); - } else { - panic!("Illegal move: {}", input_move); - } - } + }; + } + "isready" => { + println!("readyok"); + } + "setoption" => { + todo!() + } + "ucinewgame" => { + *self = Self::default() + } + "position" => { + match tokens.next() { + Some("startpos") => { + self.board = Board::new(); + } + Some("fen") => { + let fen = (0..6).filter_map(|_| tokens.next()).collect::<Vec<_>>().join(" "); + self.board = Board::from_FEN(fen); } + _ => panic!("Expected position"), } - "go" => { - // Before we go, let's join to the latest search - if let Some(hand) = search_handle.take() { - let better_self = hand.join().unwrap(); - self.transposition_table = better_self.transposition_table; + if let Some("moves") = tokens.next() { + for token in tokens.by_ref() { + let input_move = Move::from_notation(token.chars()); + let moves = self.board.generate_pseudolegal_moves(); + if let Some(mov) = moves + .iter() + .find(|m| { + let promo_matches = match input_move.kind { + MoveKind::Promotion(piece) => match m.kind { + MoveKind::Promotion(another_piece) => piece.without_color() == another_piece.without_color(), + _ => false + }, + _ => true, + }; + promo_matches && m.source == input_move.source && m.target == input_move.target + }) { + self.board.make_move(*mov); + let repeated = self.board.positions.iter().filter(|&&p| p == self.board.hash).count(); + if self.board.hash == 13465997660506371065 { + self.board.print(); + dbg!(mov, repeated, self.board.hash, self.board.ply); + } + } else { + panic!("Illegal move: {}", input_move); + } } - - search_handle = Some(self.parse_go(tokens, false)); } - "stop" => { - self.should_halt.store(true, std::sync::atomic::Ordering::SeqCst); + } + "go" => { + // Before we go, let's join to the latest search + if let Some(hand) = search_handle.take() { + let better_self = hand.join().unwrap(); + self.transposition_table = better_self.transposition_table; } - "ponderhit" => { - // Since we were pondering without any scheduled halting previously, - // in case of ponderhit we need to schedule a new halting based on clock - // TODO: isn't the color flipped here? Might lead to time management bugs - let color = self.board.color(); - let duration = (self.board.clock.time[color as usize] + self.board.clock.increment[color as usize]) / 20; - let halt_scheduled = self.schedule_halt(duration); - - // Join to the current pondering search - if let Some(hand) = search_handle.take() { - let better_self = hand.join().unwrap(); - halt_scheduled.store(false, Ordering::SeqCst); // Cancel scheduled halting - self.transposition_table = better_self.transposition_table; - } else { - panic!("Search thread not found!"); - } + + *search_handle = Some(self.parse_go(tokens, false)); + } + "stop" => { + self.should_halt.store(true, std::sync::atomic::Ordering::SeqCst); + } + "ponderhit" => { + // Since we were pondering without any scheduled halting previously, + // in case of ponderhit we need to schedule a new halting based on clock + // TODO: isn't the color flipped here? Might lead to time management bugs + let color = self.board.color(); + let duration = (self.board.clock.time[color as usize] + self.board.clock.increment[color as usize]) / 20; + let halt_scheduled = self.schedule_halt(duration); + + // Join to the current pondering search + if let Some(hand) = search_handle.take() { + let better_self = hand.join().unwrap(); + halt_scheduled.store(false, Ordering::SeqCst); // Cancel scheduled halting + self.transposition_table = better_self.transposition_table; + } else { + panic!("Search thread not found!"); } - "quit" => break, - _ => {}, } + "quit" => return false, + // Non-UCI debug commands + "print" => self.board.print(), + _ => {}, } } + true } fn parse_go(&mut self, mut tokens: Split<char>, ponder: bool) -> JoinHandle<Self> { |