use crate::board::*;
use crate::position::*;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UciMove {
pub from: Square,
pub to: Square,
pub promotion: Option<Role>,
}
impl UciMove {
#[inline]
pub fn to_move<'l>(self, position: &'l Position) -> Result<Move<'l>, InvalidUciMove> {
let Self {
from,
to,
promotion,
} = self;
position
.check_move(from, to, promotion)
.ok_or(InvalidUciMove::Illegal)
}
#[inline]
pub fn from_ascii(s: &[u8]) -> Option<Self> {
match s {
[a, b, c, d, s @ ..] => Some(Self {
from: Square::from_coords(File::from_ascii(*a)?, Rank::from_ascii(*b)?),
to: Square::from_coords(File::from_ascii(*c)?, Rank::from_ascii(*d)?),
promotion: match s {
[] => None,
[c] => Some(Role::from_ascii(*c)?),
_ => return None,
},
}),
_ => None,
}
}
}
impl core::fmt::Display for UciMove {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}{}", self.from, self.to)?;
if let Some(promotion) = self.promotion {
write!(f, "{}", promotion.to_char_lowercase())?;
}
Ok(())
}
}
impl core::fmt::Debug for UciMove {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "{self}")
}
}
impl core::str::FromStr for UciMove {
type Err = ParseUciMoveError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_ascii(s.as_bytes()).ok_or(ParseUciMoveError)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ParseUciMoveError;
impl core::fmt::Display for ParseUciMoveError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("invalid UCI notation")
}
}
impl core::error::Error for ParseUciMoveError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum InvalidUciMove {
Illegal,
}
impl core::fmt::Display for InvalidUciMove {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("illegal UCI move")
}
}
impl core::error::Error for InvalidUciMove {}