[board] Remove BoardSide enum; use Castle everywhere

Move Castle to a castle module inside the move module.
Implement into_index() on Castle to turn it into a usize.
This commit is contained in:
Eryn Wells 2024-01-21 10:38:50 -08:00
parent 21b5266789
commit fa1c6b452e
8 changed files with 95 additions and 63 deletions

View file

@ -14,7 +14,7 @@ mod square;
pub use piece::{Color, Piece}; pub use piece::{Color, Piece};
pub use position::{Position, PositionBuilder}; pub use position::{Position, PositionBuilder};
pub use r#move::{MakeMoveError, Move, MoveBuilder}; pub use r#move::{Castle, MakeMoveError, Move, MoveBuilder};
pub use square::{File, Rank, Square}; pub use square::{File, Rank, Square};
pub(crate) use bitboard::BitBoard; pub(crate) use bitboard::BitBoard;

View file

@ -2,12 +2,12 @@
use crate::{ use crate::{
piece::{Piece, PlacedPiece, Shape}, piece::{Piece, PlacedPiece, Shape},
position::BoardSide,
square::Rank, square::Rank,
Square, Square,
}; };
use std::fmt; use std::fmt;
pub use castle::Castle;
pub(crate) use move_formatter::AlgebraicMoveFormatter; pub(crate) use move_formatter::AlgebraicMoveFormatter;
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@ -18,18 +18,81 @@ pub enum MakeMoveError {
IllegalCastle, IllegalCastle,
} }
#[repr(u16)] mod castle {
#[derive(Copy, Clone, Debug, Eq, PartialEq)] use crate::{Color, Square};
pub enum Castle {
KingSide = 0b10,
QueenSide = 0b11,
}
impl From<BoardSide> for Castle { #[repr(u16)]
fn from(value: BoardSide) -> Self { #[derive(Copy, Clone, Debug, Eq, PartialEq)]
match value { pub enum Castle {
BoardSide::King => Castle::KingSide, KingSide = 0b10,
BoardSide::Queen => Castle::QueenSide, QueenSide = 0b11,
}
pub(crate) struct Squares {
pub king: Square,
pub rook: Square,
}
impl Castle {
const STARTING_SQUARES: [[Squares; 2]; 2] = [
[
Squares {
king: Square::E1,
rook: Square::H1,
},
Squares {
king: Square::E1,
rook: Square::A1,
},
],
[
Squares {
king: Square::E8,
rook: Square::H8,
},
Squares {
king: Square::E8,
rook: Square::A8,
},
],
];
const TARGET_SQUARES: [[Squares; 2]; 2] = [
[
Squares {
king: Square::G1,
rook: Square::F1,
},
Squares {
king: Square::C1,
rook: Square::D1,
},
],
[
Squares {
king: Square::G8,
rook: Square::F8,
},
Squares {
king: Square::C8,
rook: Square::D8,
},
],
];
pub(crate) fn starting_squares(&self, color: Color) -> &'static Squares {
&Castle::STARTING_SQUARES[color as usize][self.into_index()]
}
pub(crate) fn target_squares(&self, color: Color) -> &'static Squares {
&Castle::TARGET_SQUARES[color as usize][self.into_index()]
}
pub(crate) fn into_index(&self) -> usize {
match self {
Castle::KingSide => 0,
Castle::QueenSide => 1,
}
} }
} }
} }

View file

@ -176,12 +176,14 @@ impl<'p> Builder<'p, ValidatedMove> {
} => { } => {
let mut pieces = self.position.piece_bitboards().clone(); let mut pieces = self.position.piece_bitboards().clone();
let target_squares = castle.target_squares(player);
let king_from: BitBoard = king.square().into(); let king_from: BitBoard = king.square().into();
let king_to: BitBoard = Square::king_castle_target(player, castle).into(); let king_to: BitBoard = target_squares.king.into();
*pieces.bitboard_for_piece_mut(king.piece()) ^= king_from | king_to; *pieces.bitboard_for_piece_mut(king.piece()) ^= king_from | king_to;
let rook_from: BitBoard = rook.square().into(); let rook_from: BitBoard = rook.square().into();
let rook_to: BitBoard = Square::rook_castle_target(player, castle).into(); let rook_to: BitBoard = target_squares.rook.into();
*pieces.bitboard_for_piece_mut(rook.piece()) ^= rook_from | rook_to; *pieces.bitboard_for_piece_mut(rook.piece()) ^= rook_from | rook_to;
*pieces.bitboard_for_color_mut(player) &= *pieces.bitboard_for_color_mut(player) &=

View file

@ -3,7 +3,7 @@
use crate::{ use crate::{
bitboard::BitBoardBuilder, bitboard::BitBoardBuilder,
piece::{PlacedPiece, Shape}, piece::{PlacedPiece, Shape},
position::{flags::Flags, piece_sets::PieceBitBoards, BoardSide}, position::{flags::Flags, piece_sets::PieceBitBoards},
r#move::Castle, r#move::Castle,
square::{Direction, Rank}, square::{Direction, Rank},
BitBoard, Color, MakeMoveError, Move, Piece, Position, Square, BitBoard, Color, MakeMoveError, Move, Piece, Position, Square,
@ -64,22 +64,19 @@ impl Builder {
impl Default for Builder { impl Default for Builder {
fn default() -> Self { fn default() -> Self {
let white_king_square = Square::king_starting_square(Color::White);
let black_king_square = Square::king_starting_square(Color::Black);
let pieces = BTreeMap::from_iter([ let pieces = BTreeMap::from_iter([
( (white_king_square, piece!(White King)),
Square::KING_STARTING_SQUARES[Color::White as usize], (black_king_square, piece!(Black King)),
piece!(White King),
),
(
Square::KING_STARTING_SQUARES[Color::Black as usize],
piece!(Black King),
),
]); ]);
Self { Self {
player_to_move: Color::White, player_to_move: Color::White,
flags: Flags::default(), flags: Flags::default(),
pieces: pieces, pieces: pieces,
kings: Square::KING_STARTING_SQUARES, kings: [white_king_square, black_king_square],
} }
} }
} }

View file

@ -1,6 +1,5 @@
// Eryn Wells <eryn@erynwells.me> // Eryn Wells <eryn@erynwells.me>
use super::position::BoardSide;
use crate::{r#move::Castle, Color}; use crate::{r#move::Castle, Color};
use std::fmt; use std::fmt;
@ -9,9 +8,8 @@ pub(super) struct Flags(u8);
impl Flags { impl Flags {
#[inline] #[inline]
pub(super) fn player_has_right_to_castle_flag_offset(color: Color, castle: Castle) -> u8 { pub(super) fn player_has_right_to_castle_flag_offset(color: Color, castle: Castle) -> usize {
let board_side: BoardSide = castle.into(); ((color as usize) << 1) + castle.into_index()
((color as u8) << 1) + board_side as u8
} }
pub(super) fn player_has_right_to_castle(&self, color: Color, castle: Castle) -> bool { pub(super) fn player_has_right_to_castle(&self, color: Color, castle: Castle) -> bool {

View file

@ -11,5 +11,3 @@ pub use builders::{MoveBuilder, PositionBuilder};
pub use diagram_formatter::DiagramFormatter; pub use diagram_formatter::DiagramFormatter;
pub use pieces::Pieces; pub use pieces::Pieces;
pub use position::Position; pub use position::Position;
pub(crate) use position::BoardSide;

View file

@ -11,23 +11,6 @@ use crate::{
}; };
use std::{cell::OnceCell, fmt}; use std::{cell::OnceCell, fmt};
/// A lateral side of the board relative to the player. Kingside is the side the
/// player's king starts on. Queenside is the side of the board the player's
/// queen starts on.
pub(crate) enum BoardSide {
King = 0,
Queen = 1,
}
impl From<Castle> for BoardSide {
fn from(value: Castle) -> Self {
match value {
Castle::KingSide => BoardSide::King,
Castle::QueenSide => BoardSide::Queen,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Position { pub struct Position {
color_to_move: Color, color_to_move: Color,

View file

@ -1,6 +1,6 @@
// Eryn Wells <eryn@erynwells.me> // Eryn Wells <eryn@erynwells.me>
use crate::{position::BoardSide, r#move::Castle, Color}; use crate::{r#move::Castle, Color};
use std::{fmt, str::FromStr}; use std::{fmt, str::FromStr};
pub enum Direction { pub enum Direction {
@ -156,25 +156,16 @@ impl Square {
} }
impl Square { impl Square {
pub(crate) const KING_STARTING_SQUARES: [Square; 2] = [Square::E1, Square::E8]; const KING_STARTING_SQUARES: [Square; 2] = [Square::E1, Square::E8];
pub(crate) const KING_CASTLE_TARGET_SQUARES: [[Square; 2]; 2] =
[[Square::G1, Square::C1], [Square::G8, Square::C8]]; pub fn king_starting_square(color: Color) -> Square {
pub(crate) const ROOK_CASTLE_TARGET_SQUARES: [[Square; 2]; 2] = Square::KING_STARTING_SQUARES[color as usize]
[[Square::F1, Square::D1], [Square::F8, Square::D8]]; }
pub fn from_algebraic_str(s: &str) -> Result<Square, ParseSquareError> { pub fn from_algebraic_str(s: &str) -> Result<Square, ParseSquareError> {
s.parse() s.parse()
} }
pub fn king_castle_target(player: Color, castle: Castle) -> Square {
let board_side: BoardSide = castle.into();
Self::KING_CASTLE_TARGET_SQUARES[player as usize][board_side as usize]
}
pub fn rook_castle_target(player: Color, castle: Castle) -> Square {
let board_side: BoardSide = castle.into();
Self::ROOK_CASTLE_TARGET_SQUARES[player as usize][board_side as usize]
}
pub fn neighbor(self, direction: Direction) -> Option<Square> { pub fn neighbor(self, direction: Direction) -> Option<Square> {
match direction { match direction {
Direction::North => Square::try_index(self as usize + 8), Direction::North => Square::try_index(self as usize + 8),