aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-09-04 04:57:41 +0300
committereug-vs <eugene@eug-vs.xyz>2023-09-04 04:57:41 +0300
commitcc3f6674fa1662626a95995b32890c8ddd6255a0 (patch)
tree2371993700866a01e43c9b5c83b8a34dcea2f2ae /src
parent5390756aa46b1ae2cf1e274af8f2fdc24ed8009c (diff)
downloadchessnost-cc3f6674fa1662626a95995b32890c8ddd6255a0.tar.gz
refactor: more testable UCI parse_command()
Diffstat (limited to 'src')
-rw-r--r--src/grossmeister/UCI.rs185
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> {