diff --git a/src/board/color.rs b/src/board/color.rs new file mode 100644 index 0000000..ada896d --- /dev/null +++ b/src/board/color.rs @@ -0,0 +1,106 @@ +use super::Rank; + +/// An enum representing the color of a player. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Color { + White, + Black, +} + +impl Color { + /// Convert from a file index into a [Color] type. + #[inline(always)] + pub fn from_index(index: usize) -> Self { + assert!(index < 2); + // SAFETY: we know the value is in-bounds + unsafe { Self::from_index_unchecked(index) } + } + + /// Convert from a file index into a [Color] type, no bounds checking. + /// + /// # Safety + /// + /// Should only be called with values that can be output by [Color::index()]. + #[inline(always)] + pub unsafe fn from_index_unchecked(index: usize) -> Self { + std::mem::transmute(index as u8) + } + + /// Return the index of a given [Color]. + #[inline(always)] + pub fn index(self) -> usize { + self as usize + } + + /// Return the first [Rank] for pieces of the given [Color], where its pieces start. + #[inline(always)] + pub fn first_rank(self) -> Rank { + match self { + Self::White => Rank::First, + Self::Black => Rank::Eighth, + } + } + + /// Return the second [Rank] for pieces of the given [Color], where its pawns start. + #[inline(always)] + pub fn second_rank(self) -> Rank { + match self { + Self::White => Rank::Second, + Self::Black => Rank::Seventh, + } + } + + /// Return the fourth [Rank] for pieces of the given [Color], where its pawns move to after a + /// two-square move. + #[inline(always)] + pub fn fourth_rank(self) -> Rank { + match self { + Self::White => Rank::Fourth, + Self::Black => Rank::Fifth, + } + } + + /// Return the seventh [Rank] for pieces of the given [Color], which is the rank before a pawn + /// gets promoted. + #[inline(always)] + pub fn seventh_rank(self) -> Rank { + match self { + Self::White => Rank::Seventh, + Self::Black => Rank::Second, + } + } +} + +impl std::ops::Not for Color { + type Output = Color; + + fn not(self) -> Self::Output { + match self { + Self::White => Self::Black, + Self::Black => Self::White, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn from_index() { + assert_eq!(Color::from_index(0), Color::White); + assert_eq!(Color::from_index(1), Color::Black); + } + + #[test] + fn index() { + assert_eq!(Color::White.index(), 0); + assert_eq!(Color::Black.index(), 1); + } + + #[test] + fn not() { + assert_eq!(!Color::White, Color::Black); + assert_eq!(!Color::Black, Color::White); + } +} diff --git a/src/board/mod.rs b/src/board/mod.rs index ea3c69e..6a29cbe 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -1,6 +1,9 @@ pub mod bitboard; pub use bitboard::*; +pub mod color; +pub use color::*; + pub mod direction; pub use direction::*;