use crate::Color;
use core::fmt;
#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Debug, Hash)]
pub enum PieceType {
Pawn,
Knight,
Bishop,
Rook,
Queen,
King,
}
impl fmt::Display for PieceType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Pawn => write!(f, "Pawn"),
Self::Knight => write!(f, "Knight"),
Self::Bishop => write!(f, "Bishop"),
Self::Rook => write!(f, "Rook"),
Self::Queen => write!(f, "Queen"),
Self::King => write!(f, "King"),
}
}
}
impl PieceType {
pub const PAWN: usize = 0;
pub const KNIGHT: usize = 1;
pub const BISHOP: usize = 2;
pub const ROOK: usize = 3;
pub const QUEEN: usize = 4;
pub const KING: usize = 5;
#[inline(always)]
pub const unsafe fn from_index_unchecked(index: u8) -> Self {
unsafe { core::mem::transmute(index) }
}
#[inline(always)]
pub const fn to_char(&self) -> char {
match self {
Self::Pawn => 'P',
Self::Knight => 'N',
Self::Bishop => 'B',
Self::Rook => 'R',
Self::Queen => 'Q',
Self::King => 'K',
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[repr(u8)]
pub enum Piece {
WP,
WN,
WB,
WR,
WQ,
WK,
BP,
BN,
BB,
BR,
BQ,
BK,
}
impl fmt::Display for Piece {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.to_char())
}
}
impl TryFrom<char> for Piece {
type Error = &'static str;
fn try_from(c: char) -> Result<Self, Self::Error> {
match c {
'P' => Ok(Piece::WP),
'N' => Ok(Piece::WN),
'B' => Ok(Piece::WB),
'R' => Ok(Piece::WR),
'Q' => Ok(Piece::WQ),
'K' => Ok(Piece::WK),
'p' => Ok(Piece::BP),
'n' => Ok(Piece::BN),
'b' => Ok(Piece::BB),
'r' => Ok(Piece::BR),
'q' => Ok(Piece::BQ),
'k' => Ok(Piece::BK),
_ => Err("Invalid piece character"),
}
}
}
pub(crate) const PROM_PIECES: [[Piece; 4]; 2] = [
[Piece::WN, Piece::WB, Piece::WR, Piece::WQ],
[Piece::BN, Piece::BB, Piece::BR, Piece::BQ],
];
impl Piece {
pub const COUNT: usize = 6;
pub const NUM_PIECES: usize = 12;
#[inline(always)]
pub const fn new(piece_type: PieceType, color: Color) -> Self {
let index: u8 = color as u8 * 6 + piece_type as u8;
unsafe { core::mem::transmute(index) }
}
#[inline(always)]
pub const fn piece_index(self) -> usize {
(self as u8 % 6) as usize
}
#[inline(always)]
pub const fn to_index(self) -> usize {
self as usize
}
#[inline(always)]
pub const fn from_index(index: usize) -> Option<Self> {
if index < 12 {
Some(unsafe { core::mem::transmute::<u8, Piece>(index as u8 & 15) })
} else {
None
}
}
#[inline(always)]
pub const fn color(self) -> Color {
if (self as u8) < 6 {
Color::White
} else {
Color::Black
}
}
#[inline(always)]
pub const fn piece_type(self) -> PieceType {
let index: u8 = self as u8 % 6;
unsafe { PieceType::from_index_unchecked(index) }
}
#[inline(always)]
pub const fn to_char(&self) -> char {
match self {
Self::WP => 'P',
Self::WN => 'N',
Self::WB => 'B',
Self::WR => 'R',
Self::WQ => 'Q',
Self::WK => 'K',
Self::BP => 'p',
Self::BN => 'n',
Self::BB => 'b',
Self::BR => 'r',
Self::BQ => 'q',
Self::BK => 'k',
}
}
}