diff --git a/src/board/mod.rs b/src/board/mod.rs index ad91192..da449df 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -13,6 +13,9 @@ pub use direction::*; pub mod file; pub use file::*; +pub mod piece; +pub use piece::*; + pub mod rank; pub use rank::*; diff --git a/src/board/piece.rs b/src/board/piece.rs new file mode 100644 index 0000000..58f989a --- /dev/null +++ b/src/board/piece.rs @@ -0,0 +1,72 @@ +/// An enum representing the type of a piece. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Piece { + King, + Queen, + Rook, + Bishop, + Knight, + Pawn, +} + +impl Piece { + /// The number of [Piece] variants. + pub const NUM_VARIANTS: usize = 6; + + const ALL: [Self; Self::NUM_VARIANTS] = [ + Self::King, + Self::Queen, + Self::Rook, + Self::Bishop, + Self::Knight, + Self::Pawn, + ]; + + /// Iterate over all piece types. + pub fn iter() -> impl Iterator { + Self::ALL.iter().cloned() + } + + /// Convert from a piece index into a [Piece] type. + #[inline(always)] + pub fn from_index(index: usize) -> Self { + assert!(index < Self::NUM_VARIANTS); + // SAFETY: we know the value is in-bounds + unsafe { Self::from_index_unchecked(index) } + } + + /// Convert from a piece index into a [Piece] type, no bounds checking. + /// + /// # Safety + /// + /// Should only be called with values that can be output by [Piece::index()]. + #[inline(always)] + pub unsafe fn from_index_unchecked(index: usize) -> Self { + std::mem::transmute(index as u8) + } + + /// Return the index of a given [Piece]. + #[inline(always)] + pub fn index(self) -> usize { + self as usize + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn from_index() { + assert_eq!(Piece::from_index(0), Piece::King); + assert_eq!(Piece::from_index(1), Piece::Queen); + assert_eq!(Piece::from_index(5), Piece::Pawn); + } + + #[test] + fn index() { + assert_eq!(Piece::King.index(), 0); + assert_eq!(Piece::Queen.index(), 1); + assert_eq!(Piece::Pawn.index(), 5); + } +}