use core::fmt;
use core::mem::transmute;
use core::str::FromStr;
use crate::{BitBoard, Color, File, Rank, SquareDocs};
SquareDocs! {
A1, B1, C1, D1, E1, F1, G1, H1,
A2, B2, C2, D2, E2, F2, G2, H2,
A3, B3, C3, D3, E3, F3, G3, H3,
A4, B4, C4, D4, E4, F4, G4, H4,
A5, B5, C5, D5, E5, F5, G5, H5,
A6, B6, C6, D6, E6, F6, G6, H6,
A7, B7, C7, D7, E7, F7, G7, H7,
A8, B8, C8, D8, E8, F8, G8, H8
}
impl FromStr for Square {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() != 2 {
return Err("Invalid Square!");
};
let index: usize = Self::SQUARE_NAMES
.iter()
.position(|&tgt| tgt == s)
.ok_or("Invalid Square Name!")?;
Ok(Square::from_index(index))
}
}
impl fmt::Display for Square {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", Self::SQUARE_NAMES[*self as usize])?;
Ok(())
}
}
impl Square {
pub const NUM_SQUARES: usize = 64;
#[inline(always)]
pub const fn from_file_rank(file: File, rank: Rank) -> Self {
let index: u8 = ((rank as u8) << 3) ^ (file as u8);
unsafe { transmute(index & 63) }
}
#[inline(always)]
pub const fn from_index(index: usize) -> Self {
unsafe { transmute(index as u8 & 63) }
}
#[inline(always)]
pub const fn to_index(self) -> usize {
self as usize
}
#[inline(always)]
pub const fn to_bitboard(self) -> BitBoard {
BitBoard(1u64 << self.to_index())
}
#[inline(always)]
pub const fn rank(self) -> Rank {
unsafe { transmute((self as u8 >> 3) & 7) }
}
#[inline(always)]
pub const fn file(self) -> File {
unsafe { transmute(self as u8 & 7) }
}
#[inline(always)]
pub const fn down(self) -> Self {
unsafe { transmute((self as u8).wrapping_sub(8) & 63) }
}
#[inline(always)]
pub const fn up(self) -> Self {
unsafe { transmute((self as u8 + 8) & 63) }
}
#[inline(always)]
pub const fn left(self) -> Self {
unsafe { transmute((self as u8).wrapping_sub(1) & 63) }
}
#[inline(always)]
pub const fn right(self) -> Self {
unsafe { transmute((self as u8 + 1) & 63) }
}
#[inline(always)]
pub const fn forward(self, color: Color) -> Self {
match color {
Color::White => self.up(),
Color::Black => self.down(),
}
}
#[inline(always)]
pub const fn backward(self, color: Color) -> Self {
match color {
Color::White => self.down(),
Color::Black => self.up(),
}
}
#[inline(always)]
pub const fn right_color(self, color: Color) -> Self {
match color {
Color::White => self.right(),
Color::Black => self.left(),
}
}
#[inline(always)]
pub const fn left_color(self, color: Color) -> Self {
match color {
Color::White => self.left(),
Color::Black => self.right(),
}
}
#[inline]
pub fn to_str(&self) -> &'static str {
Self::SQUARE_NAMES[*self as usize]
}
const SQUARE_NAMES: [&'static str; Self::NUM_SQUARES] = [
"a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "a2", "b2", "c2", "d2", "e2", "f2", "g2",
"h2", "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", "a4", "b4", "c4", "d4", "e4", "f4",
"g4", "h4", "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", "a6", "b6", "c6", "d6", "e6",
"f6", "g6", "h6", "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", "a8", "b8", "c8", "d8",
"e8", "f8", "g8", "h8",
];
}