Make en_passant_square an Option<u8>

This commit is contained in:
2024-06-09 15:54:41 +03:00
parent 880df665d5
commit 1f7cbbe577
4 changed files with 33 additions and 28 deletions

View File

@@ -121,7 +121,7 @@ impl Board {
pieces, pieces,
all_occupancies, all_occupancies,
enemy_occupancies, enemy_occupancies,
self.state, self.state.get_en_passant_target_square(),
color, color,
), ),
Kind::Knight => knight_pseudo_moves(pieces, own_occupancies), Kind::Knight => knight_pseudo_moves(pieces, own_occupancies),

View File

@@ -101,7 +101,7 @@ fn castling_ability(castling: &str) -> Result<u8, FenError> {
use std::collections::HashMap; use std::collections::HashMap;
fn en_passant_target_square(square: &str) -> Result<u8, FenError> { fn en_passant_target_square(square: &str) -> Result<Option<u8>, FenError> {
let mut sqr = square.chars(); let mut sqr = square.chars();
let mut files: HashMap<char, u8> = HashMap::new(); let mut files: HashMap<char, u8> = HashMap::new();
@@ -120,14 +120,15 @@ fn en_passant_target_square(square: &str) -> Result<u8, FenError> {
match sqr.next() { match sqr.next() {
Some(file) if files.contains_key(&file) => 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") Some(rank) if ranks.contains_key(&rank) => Ok(Some(
* 8 ranks.get(&rank).expect("Invalid rank") * 8
+ files.get(&file).expect("Invalid file")), + files.get(&file).expect("Invalid file"),
)),
Some(_) | None => Err(FenError::from( Some(_) | None => Err(FenError::from(
"Not a valid rank (3 or 6) for an en passant target square", "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")), Some(_) | None => Err(FenError::from("Not a file (a..h) or dash (-) character")),
} }
} }

View File

@@ -35,7 +35,7 @@ impl Default for Game {
pub struct State { pub struct State {
side_to_move: Color, side_to_move: Color,
castling_ability: u8, castling_ability: u8,
en_passant_target_square: u8, en_passant_target_square: Option<u8>,
halfmove_clock: u8, halfmove_clock: u8,
fullmove_counter: u8, fullmove_counter: u8,
} }
@@ -45,7 +45,7 @@ impl State {
Self { Self {
side_to_move: Color::White, side_to_move: Color::White,
castling_ability: 0b1111, castling_ability: 0b1111,
en_passant_target_square: 0, en_passant_target_square: None,
halfmove_clock: 0, halfmove_clock: 0,
fullmove_counter: 1, fullmove_counter: 1,
} }
@@ -54,7 +54,7 @@ impl State {
pub const fn load_state( pub const fn load_state(
side_to_move: Color, side_to_move: Color,
castling_ability: u8, castling_ability: u8,
en_passant_target_square: u8, en_passant_target_square: Option<u8>,
halfmove_clock: u8, halfmove_clock: u8,
fullmove_counter: u8, fullmove_counter: u8,
) -> Self { ) -> 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<u8> {
self.en_passant_target_square self.en_passant_target_square
} }
} }
@@ -78,7 +78,7 @@ impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, writeln!(f,
"side_to_move: {:?}\ncastling_ability: {:b}\nen_passant_target_square: {:b}\nhalfmove_clock: {}\nfullmove_counter: {}\n", "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)
} }
} }

View File

@@ -3,7 +3,6 @@ use crate::attack::{
get_rook_attacks, get_rook_attacks,
}; };
use crate::board::Color; use crate::board::Color;
use crate::game::State;
use u64 as Bitboard; use u64 as Bitboard;
const NOT_A_FILE: Bitboard = 0xfefefefefefefefe; const NOT_A_FILE: Bitboard = 0xfefefefefefefefe;
@@ -27,17 +26,25 @@ pub fn pawn_pseudo_moves(
pawns: Bitboard, pawns: Bitboard,
all_occupancies: Bitboard, all_occupancies: Bitboard,
enemy_occupancies: Bitboard, enemy_occupancies: Bitboard,
state: State, en_passant_square: Option<u8>,
color: Color, color: Color,
) -> Vec<Move> { ) -> Vec<Move> {
let mut moves: Vec<Move> = vec![]; let mut moves: Vec<Move> = vec![];
match color { match color {
Color::White => { Color::White => {
moves.extend(white_pawn_quiet_moves(pawns, all_occupancies)); 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 => { 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)); moves.extend(black_pawn_quiet_moves(pawns, all_occupancies));
} }
} }
@@ -91,7 +98,7 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
fn white_pawn_capture_moves( fn white_pawn_capture_moves(
pawns: Bitboard, pawns: Bitboard,
enemy_occupancies: Bitboard, enemy_occupancies: Bitboard,
state: State, en_passant_square: Option<u8>,
) -> Vec<Move> { ) -> Vec<Move> {
let mut moves: Vec<Move> = vec![]; let mut moves: Vec<Move> = vec![];
let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_H_FILE); 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; w_pawns_capture_west &= w_pawns_capture_west - 1;
} }
let epts = state.get_en_passant_target_square(); if let Some(en_passant_square) = en_passant_square {
if epts != 0 { let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::Black);
let attacked_from = get_pawn_attacks(epts as usize, Color::Black);
let result = attacked_from & pawns; 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 moves
} }
fn black_pawn_capture_moves( fn black_pawn_capture_moves(
pawns: Bitboard, pawns: Bitboard,
enemy_occupancies: Bitboard, enemy_occupancies: Bitboard,
state: State, en_passant_square: Option<u8>,
) -> Vec<Move> { ) -> Vec<Move> {
let mut moves: Vec<Move> = vec![]; let mut moves: Vec<Move> = vec![];
let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_H_FILE); 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; b_pawns_capture_west &= b_pawns_capture_west - 1;
} }
let epts = state.get_en_passant_target_square(); if let Some(en_passant_square) = en_passant_square {
if epts != 0 { let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::White);
let attacked_from = get_pawn_attacks(epts as usize, Color::White);
let result = attacked_from & pawns; 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 moves
} }
@@ -190,7 +195,6 @@ pub fn bishop_pseudo_moves(
bishops &= bishops - 1; bishops &= bishops - 1;
} }
moves moves
// moves arkoudaki se agapo polu! to gataki sou
} }
pub fn rook_pseudo_moves( pub fn rook_pseudo_moves(