diff --git a/src/board.rs b/src/board.rs index 31893c1..60b4db2 100644 --- a/src/board.rs +++ b/src/board.rs @@ -121,7 +121,7 @@ impl Board { pieces, all_occupancies, enemy_occupancies, - self.state, + self.state.get_en_passant_target_square(), color, ), Kind::Knight => knight_pseudo_moves(pieces, own_occupancies), diff --git a/src/fen.rs b/src/fen.rs index 9428f98..aa6f292 100644 --- a/src/fen.rs +++ b/src/fen.rs @@ -101,7 +101,7 @@ fn castling_ability(castling: &str) -> Result { use std::collections::HashMap; -fn en_passant_target_square(square: &str) -> Result { +fn en_passant_target_square(square: &str) -> Result, FenError> { let mut sqr = square.chars(); let mut files: HashMap = HashMap::new(); @@ -120,14 +120,15 @@ fn en_passant_target_square(square: &str) -> Result { match sqr.next() { Some(file) if files.contains_key(&file) => match sqr.next() { - Some(rank) if ranks.contains_key(&rank) => Ok(ranks.get(&rank).expect("Invalid rank") - * 8 - + files.get(&file).expect("Invalid file")), + Some(rank) if ranks.contains_key(&rank) => Ok(Some( + ranks.get(&rank).expect("Invalid rank") * 8 + + files.get(&file).expect("Invalid file"), + )), Some(_) | None => Err(FenError::from( "Not a valid rank (3 or 6) for an en passant target square", )), }, - Some('-') => Ok(0), + Some('-') => Ok(None), Some(_) | None => Err(FenError::from("Not a file (a..h) or dash (-) character")), } } diff --git a/src/game.rs b/src/game.rs index 78284ab..e069ac6 100644 --- a/src/game.rs +++ b/src/game.rs @@ -35,7 +35,7 @@ impl Default for Game { pub struct State { side_to_move: Color, castling_ability: u8, - en_passant_target_square: u8, + en_passant_target_square: Option, halfmove_clock: u8, fullmove_counter: u8, } @@ -45,7 +45,7 @@ impl State { Self { side_to_move: Color::White, castling_ability: 0b1111, - en_passant_target_square: 0, + en_passant_target_square: None, halfmove_clock: 0, fullmove_counter: 1, } @@ -54,7 +54,7 @@ impl State { pub const fn load_state( side_to_move: Color, castling_ability: u8, - en_passant_target_square: u8, + en_passant_target_square: Option, halfmove_clock: u8, fullmove_counter: u8, ) -> Self { @@ -67,7 +67,7 @@ impl State { } } - pub const fn get_en_passant_target_square(&self) -> u8 { + pub const fn get_en_passant_target_square(&self) -> Option { self.en_passant_target_square } } @@ -78,7 +78,7 @@ impl fmt::Display for State { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "side_to_move: {:?}\ncastling_ability: {:b}\nen_passant_target_square: {:b}\nhalfmove_clock: {}\nfullmove_counter: {}\n", - self.side_to_move, self.castling_ability, 1_u64 << self.en_passant_target_square, self.halfmove_clock, self.fullmove_counter) + self.side_to_move, self.castling_ability, 1_u64 << self.en_passant_target_square.unwrap_or(0), self.halfmove_clock, self.fullmove_counter) } } diff --git a/src/movegen.rs b/src/movegen.rs index 4760655..5e83c17 100644 --- a/src/movegen.rs +++ b/src/movegen.rs @@ -3,7 +3,6 @@ use crate::attack::{ get_rook_attacks, }; use crate::board::Color; -use crate::game::State; use u64 as Bitboard; const NOT_A_FILE: Bitboard = 0xfefefefefefefefe; @@ -27,17 +26,25 @@ pub fn pawn_pseudo_moves( pawns: Bitboard, all_occupancies: Bitboard, enemy_occupancies: Bitboard, - state: State, + en_passant_square: Option, color: Color, ) -> Vec { let mut moves: Vec = vec![]; match color { Color::White => { moves.extend(white_pawn_quiet_moves(pawns, all_occupancies)); - moves.extend(white_pawn_capture_moves(pawns, enemy_occupancies, state)); + moves.extend(white_pawn_capture_moves( + pawns, + enemy_occupancies, + en_passant_square, + )); } Color::Black => { - moves.extend(black_pawn_capture_moves(pawns, enemy_occupancies, state)); + moves.extend(black_pawn_capture_moves( + pawns, + enemy_occupancies, + en_passant_square, + )); moves.extend(black_pawn_quiet_moves(pawns, all_occupancies)); } } @@ -91,7 +98,7 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { fn white_pawn_capture_moves( pawns: Bitboard, enemy_occupancies: Bitboard, - state: State, + en_passant_square: Option, ) -> Vec { let mut moves: Vec = vec![]; let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_H_FILE); @@ -110,19 +117,18 @@ fn white_pawn_capture_moves( w_pawns_capture_west &= w_pawns_capture_west - 1; } - let epts = state.get_en_passant_target_square(); - if epts != 0 { - let attacked_from = get_pawn_attacks(epts as usize, Color::Black); + if let Some(en_passant_square) = en_passant_square { + let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::Black); let result = attacked_from & pawns; - moves.push(Move::new(result.trailing_zeros(), epts as u32)); - } + moves.push(Move::new(result.trailing_zeros(), en_passant_square as u32)); + }; moves } fn black_pawn_capture_moves( pawns: Bitboard, enemy_occupancies: Bitboard, - state: State, + en_passant_square: Option, ) -> Vec { let mut moves: Vec = vec![]; let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_H_FILE); @@ -142,12 +148,11 @@ fn black_pawn_capture_moves( b_pawns_capture_west &= b_pawns_capture_west - 1; } - let epts = state.get_en_passant_target_square(); - if epts != 0 { - let attacked_from = get_pawn_attacks(epts as usize, Color::White); + if let Some(en_passant_square) = en_passant_square { + let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::White); let result = attacked_from & pawns; - moves.push(Move::new(result.trailing_zeros(), epts as u32)); - } + moves.push(Move::new(result.trailing_zeros(), en_passant_square as u32)); + }; moves } @@ -190,7 +195,6 @@ pub fn bishop_pseudo_moves( bishops &= bishops - 1; } moves - // moves arkoudaki se agapo polu! to gataki sou } pub fn rook_pseudo_moves(