cleanroom implementation of a chess engine. doesn't work :)

add more structure for movemaking

+65 -11
+65 -11
src/lib.rs
··· 38 38 file: usize, 39 39 } 40 40 41 - struct Board { 41 + pub struct Board { 42 42 white: Vec<LocatedPiece>, 43 43 black: Vec<LocatedPiece>, 44 44 white_to_move: bool, 45 45 } 46 46 47 47 impl Board { 48 - fn new() -> Self { 48 + pub fn new() -> Self { 49 49 let white_pawns = (0..8) 50 50 .map(|file| LocatedPiece { 51 51 piece: Piece::Pawn, ··· 100 100 .sum::<i32>(); 101 101 white_value - black_value 102 102 } 103 - fn make_move(&mut self, algebra: &str) { 104 - let (mover, non_mover) = if self.white_to_move { 105 - (&mut self.white, &mut self.black) 106 - } else { 107 - (&mut self.black, &mut self.white) 108 - }; 103 + pub fn make_move(&mut self, algebra: &str) { 104 + let (mover, non_mover) = self.movers_or_not(); 109 105 if algebra == "O-O" || algebra == "0-0" { 110 106 mover 111 107 .iter_mut() ··· 134 130 while let Some(ch) = iter.next() { 135 131 if let Some(piece) = Piece::from_char(ch) { 136 132 move_segments.push(MoveSegment::Piece(piece)); 137 - } else if let Some(file) = ch.to_digit(10) { 138 - move_segments.push(MoveSegment::File(file as usize)); 133 + } else if let Some(rank) = ch.to_digit(10) { 134 + move_segments.push(MoveSegment::File(rank as usize)); 139 135 } else if ch >= 'a' && ch <= 'h' { 140 - move_segments.push(MoveSegment::Rank(ch as usize)); 136 + move_segments.push(MoveSegment::File(ch as usize - 'a' as usize)); 141 137 } else if ch == 'x' { 142 138 move_segments.push(MoveSegment::Captures) 143 139 } else if ch == '=' ··· 147 143 move_segments.push(MoveSegment::Promotion(piece)); 148 144 } 149 145 } 146 + if move_segments.len() == 2 147 + && let MoveSegment::File(file) = move_segments[0] 148 + && let MoveSegment::Rank(rank) = move_segments[1] 149 + { 150 + self.move_unambiguous(Piece::Pawn, None, None, rank, file); 151 + } 150 152 } 153 + } 154 + fn move_unambiguous( 155 + &mut self, 156 + piece: Piece, 157 + source_rank: Option<usize>, 158 + source_file: Option<usize>, 159 + dest_rank: usize, 160 + dest_file: usize, 161 + ) { 162 + let piece_to_move = (if self.white_to_move { 163 + &mut self.white 164 + } else { 165 + &mut self.black 166 + }) 167 + .iter_mut() 168 + .filter(|lp| lp.piece == piece) 169 + .filter(|lp| { 170 + source_rank.is_none_or(|rank| rank == lp.rank) 171 + && source_file.is_none_or(|file| file == lp.file) 172 + }) 173 + .find(|lp| self.valid_moves(lp).contains((dest_file, dest_rank))) 174 + .unwrap(); 175 + 176 + self.capture_if_possible(dest_file, dest_rank); 177 + piece_to_move.rank = dest_rank; 178 + piece_to_move.file = dest_file; 179 + } 180 + fn valid_moves(&self, lp: LocatedPiece) -> Vec<(usize, usize)> { 181 + let mut moves = vec![];j 182 + match lp.piece { 183 + Piece::Pawn => ,//todo: en passant (requires a list of moves to keep track of whether the previous 184 + //move was one that is en passantable?) 185 + Piece::Knight => todo!(), 186 + Piece::Bishop => todo!(), 187 + Piece::Rook => todo!(), 188 + Piece::Queen => todo!(), 189 + Piece::King => todo!(), 190 + } 191 + moves.retain(|(file, rank)| !self.mover_is_in_check(file, rank)); 192 + moves 193 + } 194 + fn movers_or_not(&mut self) -> (&mut Vec<LocatedPiece>, &mut Vec<LocatedPiece>) { 195 + if self.white_to_move { 196 + (&mut self.white, &mut self.black) 197 + } else { 198 + (&mut self.black, &mut self.white) 199 + } 200 + } 201 + fn capture_if_possible(&mut self, file: usize, rank: usize) { 202 + self.movers_or_not() 203 + .1 204 + .retain(|lp| lp.rank != rank && lp.file != file) 151 205 } 152 206 } 153 207