diff --git a/rs/src/ui.rs b/rs/src/ui.rs index 0b926b5..187700a 100644 --- a/rs/src/ui.rs +++ b/rs/src/ui.rs @@ -25,17 +25,47 @@ impl std::fmt::Display for board::Piece { } } +trait GridAxisIO: std::fmt::Display +where + Self: GridAxis, +{ + const ALL_CHARS: [char; 8]; + fn parse(c: char) -> Result { + let index = Self::ALL_CHARS.iter().position(|p| p == &c).ok_or(())?; + Ok(Self::ALL_VALUES[index].clone()) + } +} + +impl GridAxisIO for board::Rank { + const ALL_CHARS: [char; 8] = ['1', '2', '3', '4', '5', '6', '7', '8']; +} + impl std::fmt::Display for board::Rank { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - const ALL_CHARS: [char; 8] = ['1', '2', '3', '4', '5', '6', '7', '8']; - write!(f, "{}", ALL_CHARS[self.get_index() as usize]) + write!(f, "{}", Self::ALL_CHARS[self.get_index() as usize]) } } +impl GridAxisIO for board::File { + const ALL_CHARS: [char; 8] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; +} + impl std::fmt::Display for board::File { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - const ALL_CHARS: [char; 8] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; - write!(f, "{}", ALL_CHARS[self.get_index() as usize]) + write!(f, "{}", Self::ALL_CHARS[self.get_index() as usize]) + } +} + +impl board::Position { + fn parse(s: &str) -> Result { + let mut chars = s.chars(); + let file = board::File::parse(chars.next().ok_or(())?)?; + let rank = board::Rank::parse(chars.next().ok_or(())?)?; + if chars.next().is_none() { + Ok(board::Position::new(rank, file)) + } else { + Err(()) + } } } @@ -74,6 +104,22 @@ impl Ui { Ok(result) } } + fn get_moves(&self, args: &[&str]) -> Result { + if args.len() != 1 { + return Err("get_moves takes 1 arg".to_owned()); + }; + let position = board::Position::parse(args[0]) + .map_err(|_| format!("Error parsing position {}", args[0]))?; + match self.board.get_legal_moves(&position) { + None => { + let error = format!("No moves possible from {}", position); + Err(error) + } + Some(positions) => { + Ok(positions.iter().map(|pos| format!("{}", pos)).collect()) + } + } + } fn handle_command(&mut self, s: &str) -> Result { let mut cmd = s.split(','); // There will be at least an empty string => otherwise panic @@ -81,6 +127,7 @@ impl Ui { let args: Vec<&str> = cmd.collect(); match cmd_type { "get_state" => self.get_state(&args), + "get_moves" => self.get_moves(&args), "" => Err("No command given".to_owned()), _ => Err("Invalid command".to_owned()), }