diff --git a/src/chess/board.rs b/src/chess/board.rs index db18626..398bd67 100644 --- a/src/chess/board.rs +++ b/src/chess/board.rs @@ -73,7 +73,7 @@ pub struct Board { // | 0;7 | 1;7 | 2;7 | 3;7 | 4;7 | 5;7 | 6;7 | 7;7 | // |-----------------------------------------------| // Chess board repesented in code -// + // NOTE: capture left/right is implemented relative to color // TODO: make this a doc comment @@ -241,39 +241,135 @@ impl Board { /// Use position impl Board { - pub fn get_moves(&mut self) -> Vec { + pub fn position_init(&mut self) -> &mut Self { + let check = self.check_init(); + self.mut_ref_position().ref_set_check(check); + let castl_possibilities = self.castling_possibilities_init(); + trace!("{self:?}"); + self.mut_ref_position().ref_set_castle_possibilities(castl_possibilities); + let moves = self.valid_moves_init(); + // self.mut_ref_position().ref_set_moves(moves); + self + } + + fn check_init(&mut self) -> Option { + let whites_turn = self.ref_whites_turn(); + trace!("{whites_turn}"); + let attacker = self.threatened_by(self.king_pos(*whites_turn)); + match attacker.len() { + 0 => None, + 1 => Some(false), + _ => Some(true), + } + } + + fn castling_possibilities_init(&mut self) -> [[bool; 2]; 2] { + let fields = if *self.mut_ref_whites_turn() { + if self.mut_ref_rows()[7][4] != Some(Piece::new(true, PieceVariant::King)) { + return [[false; 2]; 2] + } + [[5, 6], [2, 3]] + } else { + if self.mut_ref_rows()[0][4] != Some(Piece::new(false, PieceVariant::King)) { + return [[false; 2]; 2] + } + [[1, 2], [5, 6]] + }; + let mut castle_possibilities = [[false; 2]; 2]; + + let y = match self.mut_ref_whites_turn() { + true => 7, + false => 0, + }; + for (i, side) in fields.iter().enumerate() { + for (j, field) in side.iter().enumerate() { + if self.used(Square::new(*field as u8, y)) || self.threatened(Square::new(*field as u8, y)) { + castle_possibilities[i][j] = false; + break; + } + } + } + castle_possibilities + } + + fn valid_moves_init(&mut self) -> Vec { + let mut moves: Vec = vec![]; if self.ref_position().ref_check().is_some() { if self.ref_position().ref_check().unwrap() { let king_pos = self.king_pos(self.whites_turn); - self.mut_ref_position().ref_set_moves(MoveVariant::king_move(king_pos)); + moves.append(&mut MoveVariant::king_move(king_pos)); + for i in 0..moves.len() { + if self.used(moves[i].to()) || self.threatened(moves[i].to()) { + moves.remove(i); + } + } } else { todo!("take, block or king move"); } } - todo!("finish"); + + if moves.is_empty() { + todo!("Any other move") + } + moves + } +} + + +impl Board { + pub fn used(&self, square: Square) -> bool { + self.ref_rows()[square.x() as usize][square.y() as usize].is_some() } - // INFO: solution 1 => reverse Change - // solution 2 => loops - pub fn rc_threatened(&self, square: Square) -> bool { + pub fn threatened(&self, square: Square) -> bool { let mut changes; - let mut to_move; + let to_move = self.whites_turn; for variant in MoveVariant::iter() { - to_move = self.whites_turn; changes = MoveVariant::variant_move(variant.borrow()); - for change in changes { + for mut change in changes { + change = change.reverse(); + if square.x() as i8 + change.ref_x() < 0 || square.x() as i8 + change.ref_x() > 7 || + square.y() as i8 + change.ref_y() < 0 || square.y() as i8 + change.ref_y() > 7 { + continue; + } + trace!("{:?}:{:?} => {}:{:?}", {square.x() as i8 + change.ref_x()}, {square.y() as i8 + change.ref_y()}, {if to_move {"w".to_string()} else {"b".to_string()}}, variant); if self.ref_rows() - [(square.clone().x() as i8 + change.ref_x()) as usize] - [(square.clone().y() as i8 + change.ref_y()) as usize] == - Some(Piece::new(to_move, variant.as_piece_variant())) { - return true; + [(square.x() as i8 + change.ref_x()) as usize] + [(square.y() as i8 + change.ref_y()) as usize] == + Some(Piece::new(to_move, variant.as_piece_variant())) + { + return true } } } false } - pub fn threatened_by(&self, _square: Square) -> Square { - todo!(); + pub fn threatened_by(&self, square: Square) -> Vec { + let mut changes; + let to_move = self.whites_turn; + let mut attacker = vec![]; + for variant in MoveVariant::iter() { + changes = MoveVariant::variant_move(variant.borrow()); + for mut change in changes { + change = change.reverse(); + if square.x() as i8 + change.ref_x() < 0 || square.x() as i8 + change.ref_x() > 7 || + square.y() as i8 + change.ref_y() < 0 || square.y() as i8 + change.ref_y() > 7 { + continue; + } + trace!("{:?}:{:?} => {}:{:?}", {square.x() as i8 + change.ref_x()}, {square.y() as i8 + change.ref_y()}, {if to_move {"w".to_string()} else {"b".to_string()}}, variant); + if self.ref_rows() + [(square.x() as i8 + change.ref_x()) as usize] + [(square.y() as i8 + change.ref_y()) as usize] == + Some(Piece::new(to_move, variant.as_piece_variant())) { + trace!("matched: {:?}:{:?}", {square.x() as i8 + change.ref_x()}, {square.y() as i8 + change.ref_y()}); + attacker.push(Square::new( + (square.x() as i8 + change.ref_x()) as u8, + (square.y() as i8 + change.ref_y()) as u8, + )); + } + } + } + attacker } } diff --git a/src/chess/moves.rs b/src/chess/moves.rs index 701cb8e..2e668be 100644 --- a/src/chess/moves.rs +++ b/src/chess/moves.rs @@ -3,7 +3,7 @@ use super::{piece::PieceVariant, square::Square}; #[cfg(feature = "custom_pieces")] use serde_derive::Deserialize; -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct Move { from: Square, to: Square, @@ -70,17 +70,23 @@ impl Change { } impl Change { - pub fn reverse(&mut self) -> &Self { + pub fn ref_reverse(&mut self) -> &Self { let x = *self.ref_x(); self.set_x(-x); let y = self.ref_y(); self.set_y(-y) } + + pub fn reverse(mut self) -> Self { + self.set_x(-self.x); + self.set_y(-self.y); + self + } } -#[derive(strum_macros::EnumIter)] +#[derive(strum_macros::EnumIter, Debug)] pub enum MoveVariant { King, KingCastle, @@ -122,7 +128,7 @@ impl MoveVariant { pub fn variant_move(&self) -> Vec { match self { Self::King => Self::vec_king(), - Self::KingCastle => todo!(), + Self::KingCastle => vec![], Self::Queen => Self::vec_queen(), Self::Rook => Self::vec_rook(), Self::Bishop => Self::vec_bishop(), diff --git a/src/chess/piece.rs b/src/chess/piece.rs index 71790bb..b9df470 100644 --- a/src/chess/piece.rs +++ b/src/chess/piece.rs @@ -2,7 +2,7 @@ #[cfg(feature = "custom_pieces")] use serde_derive::Deserialize; -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone, Copy)] pub enum PieceVariant { King, Queen, diff --git a/src/chess/square.rs b/src/chess/square.rs index 4e95255..8f785b4 100644 --- a/src/chess/square.rs +++ b/src/chess/square.rs @@ -2,7 +2,7 @@ use log::{debug, trace}; use super::moves::Change; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Square { x: u8, y: u8, @@ -25,6 +25,16 @@ impl Square { )) } } + + pub fn add_change(&self, change: &Change) -> Option { + let x = self.x as i8 + change.ref_x(); + let y = self.y as i8 + change.ref_y(); + if !(0..7).contains(&x) || !(0..7).contains(&y) { + None + } else { + Some(Square::new(x as u8, y as u8)) + } + } } impl Square { @@ -41,15 +51,3 @@ impl Square { &self.y } } - -impl Square { - pub fn add_change(&self, change: &Change) -> Option { - let x = self.x as i8 + change.ref_x(); - let y = self.y as i8 + change.ref_y(); - if !(0..7).contains(&x) || !(0..7).contains(&y) { - None - } else { - Some(Square::new(x as u8, y as u8)) - } - } -} diff --git a/src/main.rs b/src/main.rs index 20ebfc0..b49cd46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,13 @@ fn main() { let config = get_config().unwrap_or_else(||panic!("")); trace!("{:?}", config); - let board = Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1".to_string()); - trace!("{:?}", board); + let mut board = Board::from_fen( + // "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1".to_string() // start + "2r2q1k/5pp1/4p1N1/8/1bp5/5P1R/6P1/2R4K b - - 0 1".to_string() // double-check + ); + + let moves = board + .position_init() + .ref_position() + .ref_moves(); }