From 02e7d7e984bbfc2a0e8406cfc9ad13be7b26d714 Mon Sep 17 00:00:00 2001 From: Pavel Lutskov Date: Sun, 5 Dec 2021 11:54:15 +0100 Subject: [PATCH] Split board-related stuff into board.rs --- rs/src/board.rs | 235 +++++++++++++++++++++++++++++++++++++++++++++++ rs/src/main.rs | 238 +++--------------------------------------------- 2 files changed, 248 insertions(+), 225 deletions(-) create mode 100644 rs/src/board.rs diff --git a/rs/src/board.rs b/rs/src/board.rs new file mode 100644 index 0000000..dbd5181 --- /dev/null +++ b/rs/src/board.rs @@ -0,0 +1,235 @@ +#[derive(Clone)] +enum Color { + Black, + White, +} + +impl Color { + fn get_home_rank(&self) -> Rank { + match self { + Color::Black => Rank::_8, + Color::White => Rank::_1, + } + } + fn get_pawn_rank(&self) -> Rank { + match self { + Color::Black => Rank::_7, + Color::White => Rank::_2, + } + } + fn get_direction(&self) -> i8 { + match self { + Color::Black => -1, + Color::White => 1, + } + } +} + +#[derive(Clone)] +pub struct Position { + rank: Rank, + file: File, +} + +impl Position { + pub fn new(rank: Rank, file: File) -> Position { + Position { + rank, + file, + } + } + fn delta(&self, delta_rank_file: (i8, i8)) -> Result { + let (delta_rank, delta_file) = delta_rank_file; + Ok(Position::new( + self.rank.delta(delta_rank)?, + self.file.delta(delta_file)?, + )) + } +} + +#[derive(PartialEq, Clone, Copy)] +pub enum Rank { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, +} + +#[derive(PartialEq, Clone, Copy)] +pub enum File { + A, + B, + C, + D, + E, + F, + G, + H, +} + +trait GridAxis +where + Self: Sized, + Self: Clone, +{ + const ALL_VALUES: [Self; 8]; + fn new(index: u8) -> Result { + return Ok( + Self::ALL_VALUES[Self::validate_index(index)? as usize].clone() + ); + } + fn validate_index(index: u8) -> Result { + if index as usize >= Self::ALL_VALUES.len() { + Err(()) + } else { + Ok(index) + } + } + fn get_index(&self) -> u8; + fn delta(&self, delta: i8) -> Result { + let highest = Self::ALL_VALUES.len() as i8 - 1; + if delta > highest + || delta < -highest + || (delta < 0 && self.get_index() < delta.abs() as u8) + || (delta > 0 && self.get_index() + delta as u8 > highest as u8) + { + Err(()) + } else { + Self::new(((self.get_index() as i8) + delta) as u8) + } + } +} + +impl GridAxis for Rank { + const ALL_VALUES: [Rank; 8] = [ + Rank::_1, + Rank::_2, + Rank::_3, + Rank::_4, + Rank::_5, + Rank::_6, + Rank::_7, + Rank::_8, + ]; + fn get_index(&self) -> u8 { + *self as u8 + } +} + +impl GridAxis for File { + const ALL_VALUES: [File; 8] = [ + File::A, + File::B, + File::C, + File::D, + File::E, + File::F, + File::G, + File::H, + ]; + fn get_index(&self) -> u8 { + *self as u8 + } +} + +#[derive(Clone)] +pub enum PieceType { + Pawn, +} + +impl PieceType { + fn initial_setup(&self) -> Vec { + match &self { + PieceType::Pawn => [Color::Black, Color::White] + .iter() + .flat_map(|color| { + File::ALL_VALUES.iter().map(|&file| Piece { + piece_type: self.clone(), + position: Position::new(color.get_pawn_rank(), file), + color: color.clone(), + }) + }) + .collect(), + } + } +} + +pub struct Piece { + position: Position, + color: Color, + piece_type: PieceType, +} + +trait Movement { + fn get_moves(&self) -> Vec; + fn get_captures(&self) -> Vec; +} + +impl Piece { + fn get_moves(&self) -> Vec { + let deltas = match self.piece_type { + PieceType::Pawn => self._pawn_get_move_deltas(), + }; + self.deltas_to_valid_positions(&deltas) + } + fn get_captures(&self) -> Vec { + let deltas = match self.piece_type { + PieceType::Pawn => self._pawn_get_capture_deltas(), + }; + self.deltas_to_valid_positions(&deltas) + } + fn deltas_to_valid_positions( + &self, + deltas: &Vec<(i8, i8)>, + ) -> Vec { + deltas + .iter() + .filter_map(|&delta_rank_file| { + self.position.delta(delta_rank_file).ok() + }) + .collect() + } + fn _pawn_get_move_deltas(&self) -> Vec<(i8, i8)> { + let direction = self.color.get_direction(); + if self.position.rank == self.color.get_pawn_rank() { + vec![(1 * direction, 0), (2 * direction, 0)] + } else { + vec![(1 * direction, 0)] + } + } + fn _pawn_get_capture_deltas(&self) -> Vec<(i8, i8)> { + let direction = self.color.get_direction(); + vec![(1 * direction, 1), (1 * direction, -1)] + } +} + +pub struct Board { + state: [[Option; File::ALL_VALUES.len()]; Rank::ALL_VALUES.len()], +} + +impl Board { + pub fn get_at(&self, position: &Position) -> &Option { + &self.state[position.rank.get_index() as usize] + [position.file.get_index() as usize] + } + fn set_at(&mut self, position: &Position, mut piece: Piece) { + piece.position = position.clone(); + self.state[position.rank.get_index() as usize] + [position.file.get_index() as usize] = Some(piece); + } + pub fn new() -> Board { + let mut board = Board { + state: Default::default(), + }; + for piece_type in &[PieceType::Pawn] { + for piece in piece_type.initial_setup() { + board.set_at(&piece.position.clone(), piece); + } + } + board + } +} diff --git a/rs/src/main.rs b/rs/src/main.rs index 413af52..9155a7c 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -1,229 +1,17 @@ -#[derive(Clone)] -enum Color { - Black, - White, -} +mod board; -impl Color { - fn get_home_rank(&self) -> Rank { - match self { - Color::Black => Rank::_8, - Color::White => Rank::_1, - } - } - fn get_pawn_rank(&self) -> Rank { - match self { - Color::Black => Rank::_7, - Color::White => Rank::_2, - } - } - fn get_direction(&self) -> i8 { - match self { - Color::Black => -1, - Color::White => 1, - } - } -} - -#[derive(Clone)] -struct Position { - rank: Rank, - file: File, -} - -impl Position { - fn delta(&self, delta_rank_file: (i8, i8)) -> Result { - let (delta_rank, delta_file) = delta_rank_file; - Ok(Position { - rank: self.rank.delta(delta_rank)?, - file: self.file.delta(delta_file)?, - }) - } -} - -#[derive(PartialEq, Clone, Copy)] -enum Rank { - _1, - _2, - _3, - _4, - _5, - _6, - _7, - _8, -} - -#[derive(PartialEq, Clone, Copy)] -enum File { - A, - B, - C, - D, - E, - F, - G, - H, -} - -trait GridAxis -where - Self: Sized, - Self: Clone, -{ - const ALL_VALUES: [Self; 8]; - fn new(index: u8) -> Result { - return Ok( - Self::ALL_VALUES[Self::validate_index(index)? as usize].clone() - ); - } - fn validate_index(index: u8) -> Result { - if index as usize >= Self::ALL_VALUES.len() { - Err(()) - } else { - Ok(index) - } - } - fn get_index(&self) -> u8; - fn delta(&self, delta: i8) -> Result { - let highest = Self::ALL_VALUES.len() as i8 - 1; - if delta > highest - || delta < -highest - || (delta < 0 && self.get_index() < delta.abs() as u8) - || (delta > 0 && self.get_index() + delta as u8 > highest as u8) +fn main() { + println!( + "{}", + match board::Board::new() + .get_at(&board::Position::new(board::Rank::_2, board::File::A)) { - Err(()) - } else { - Ok(Self::new(((self.get_index() as i8) + delta) as u8)?) + Some(piece) => "Some", + None => "None", } - } + ); + // reset -> (ok/fail) + // get_state -> (ok/fail),state + // get_moves,position,[state] -> (ok/fail),position[] + // make_move,[move],[state] -> (ok/fail),state } - -impl GridAxis for Rank { - const ALL_VALUES: [Rank; 8] = [ - Rank::_1, - Rank::_2, - Rank::_3, - Rank::_4, - Rank::_5, - Rank::_6, - Rank::_7, - Rank::_8, - ]; - fn get_index(&self) -> u8 { - *self as u8 - } -} - -impl GridAxis for File { - const ALL_VALUES: [File; 8] = [ - File::A, - File::B, - File::C, - File::D, - File::E, - File::F, - File::G, - File::H, - ]; - fn get_index(&self) -> u8 { - *self as u8 - } -} - -#[derive(Clone)] -enum PieceType { - Pawn, -} - -impl PieceType { - fn initial_setup(&self) -> Vec { - match &self { - PieceType::Pawn => [Color::Black, Color::White] - .iter() - .flat_map(|color| { - File::ALL_VALUES.iter().map(|&file| Piece { - piece_type: self.clone(), - position: Position { - rank: color.get_pawn_rank(), - file, - }, - color: color.clone(), - }) - }) - .collect(), - } - } -} - -struct Piece { - position: Position, - color: Color, - piece_type: PieceType, -} - -trait Movement { - fn get_moves(&self) -> Vec; - fn get_captures(&self) -> Vec; -} - -impl Piece { - fn get_moves(&self) -> Vec { - let deltas = match self.piece_type { - PieceType::Pawn => self._pawn_get_move_deltas(), - }; - self.deltas_to_valid_positions(&deltas) - } - fn get_captures(&self) -> Vec { - let deltas = match self.piece_type { - PieceType::Pawn => self._pawn_get_capture_deltas(), - }; - self.deltas_to_valid_positions(&deltas) - } - fn deltas_to_valid_positions( - &self, - deltas: &Vec<(i8, i8)>, - ) -> Vec { - deltas - .iter() - .filter_map(|&delta_rank_file| { - self.position.delta(delta_rank_file).ok() - }) - .collect() - } - fn _pawn_get_move_deltas(&self) -> Vec<(i8, i8)> { - let direction = self.color.get_direction(); - if self.position.rank == self.color.get_pawn_rank() { - vec![(1 * direction, 0), (2 * direction, 0)] - } else { - vec![(1 * direction, 0)] - } - } - fn _pawn_get_capture_deltas(&self) -> Vec<(i8, i8)> { - let direction = self.color.get_direction(); - vec![(1 * direction, 1), (1 * direction, -1)] - } -} - -struct Board { - state: [[Option; File::ALL_VALUES.len()]; Rank::ALL_VALUES.len()], -} - -impl Board { - fn set_at(&mut self, position: &Position, piece: Piece) { - self.state[position.rank.get_index() as usize] - [position.file.get_index() as usize] = Some(piece); - } - fn new() -> Board { - let mut board = Board { - state: Default::default(), - }; - for piece_type in &[PieceType::Pawn] { - for piece in piece_type.initial_setup() { - board.set_at(&piece.position.clone(), piece); - } - } - board - } -} - -fn main() {}