#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum Position {
N = 0x0000_0008,
NE = 0x0000_0080,
E = 0x0000_0800,
SE = 0x0000_8000,
S = 0x0008_0000,
SW = 0x0080_0000,
W = 0x0800_0000,
NW = 0x8000_0000,
}
impl Position {
pub(crate) unsafe fn from_u32_unchecked(value: u32) -> Self {
unsafe { std::mem::transmute(value) }
}
pub fn iter() -> PositionIter {
PositionIter::new()
}
}
impl From<Position> for u32 {
fn from(value: Position) -> Self {
value as u32
}
}
impl TryFrom<u32> for Position {
type Error = crate::error::Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
if (value & 0x8888_8888) != 0 && value.count_ones() == 1 {
Ok(unsafe { Position::from_u32_unchecked(value) })
} else {
Err(crate::error::Error::Position(value))
}
}
}
impl std::fmt::Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Position::*;
let s = match self {
N => "N",
NE => "NE",
E => "E",
SE => "SE",
S => "S",
SW => "SW",
W => "W",
NW => "NW",
};
write!(f, "{}", s)
}
}
#[derive(Debug)]
pub struct PositionIter {
value: u32,
}
impl PositionIter {
fn new() -> Self {
Self { value: 0x0000_0008 }
}
}
impl Iterator for PositionIter {
type Item = Position;
fn next(&mut self) -> Option<Self::Item> {
if self.value == 0 {
None
} else {
let pos = unsafe { Position::from_u32_unchecked(self.value) };
self.value <<= 4;
Some(pos)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Color {
B,
W,
}
impl Color {
pub fn opposite(self) -> Self {
use Color::*;
match self {
B => W,
W => B,
}
}
}
impl From<bool> for Color {
fn from(value: bool) -> Self {
if value { Color::B } else { Color::W }
}
}
impl From<Color> for bool {
fn from(value: Color) -> Self {
matches!(value, Color::B)
}
}
impl std::fmt::Display for Color {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Color::*;
let s = match self {
B => "Black",
W => "White",
};
write!(f, "{}", s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Action {
Put(Position, Color),
Move(Position, Position),
}
impl std::fmt::Display for Action {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Action::Put(pos, color) => write!(f, "Put({}, {})", pos, color),
Action::Move(from, to) => write!(f, "Move({}, {})", from, to),
}
}
}