WIP
This commit is contained in:
parent
d5cdf273c8
commit
091cc99cb3
42 changed files with 805 additions and 1662 deletions
|
@ -5,19 +5,29 @@ use chessfriend_board::castle::Castle;
|
|||
use chessfriend_core::{Rank, Shape, Square};
|
||||
use std::fmt;
|
||||
|
||||
/// A single player's move. In chess parlance, this is a "ply".
|
||||
/// A single player's move. In game theory parlance, this is a "ply".
|
||||
///
|
||||
/// ## TODO
|
||||
///
|
||||
/// - Rename this class `Ply`.
|
||||
///
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct Move(pub(crate) u16);
|
||||
|
||||
impl Move {
|
||||
#[must_use]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn origin_square(&self) -> Square {
|
||||
((self.0 >> 4) & 0b111111).try_into().unwrap()
|
||||
((self.0 >> 4) & 0b111_111).try_into().unwrap()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn target_square(&self) -> Square {
|
||||
(self.0 >> 10).try_into().unwrap()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn capture_square(&self) -> Option<Square> {
|
||||
if self.is_en_passant() {
|
||||
let target_square = self.target_square();
|
||||
|
@ -35,18 +45,22 @@ impl Move {
|
|||
None
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_quiet(&self) -> bool {
|
||||
self.flags() == Kind::Quiet as u16
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_double_push(&self) -> bool {
|
||||
self.flags() == Kind::DoublePush as u16
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_castle(&self) -> bool {
|
||||
self.castle().is_some()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn castle(&self) -> Option<Castle> {
|
||||
match self.flags() {
|
||||
0b0010 => Some(Castle::KingSide),
|
||||
|
@ -55,18 +69,22 @@ impl Move {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_capture(&self) -> bool {
|
||||
(self.0 & 0b0100) != 0
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_en_passant(&self) -> bool {
|
||||
self.flags() == 0b0101
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_promotion(&self) -> bool {
|
||||
(self.0 & 0b1000) != 0
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn promotion(&self) -> Option<Shape> {
|
||||
if !self.is_promotion() {
|
||||
return None;
|
||||
|
@ -80,18 +98,22 @@ impl Move {
|
|||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Move {
|
||||
#[inline]
|
||||
fn flags(&self) -> u16 {
|
||||
fn flags(self) -> u16 {
|
||||
self.0 & 0b1111
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn special(&self) -> u16 {
|
||||
fn special(self) -> u16 {
|
||||
self.0 & 0b11
|
||||
}
|
||||
}
|
||||
|
||||
fn _transfer_char(&self) -> char {
|
||||
impl Move {
|
||||
fn _transfer_char(self) -> char {
|
||||
if self.is_capture() || self.is_en_passant() {
|
||||
'x'
|
||||
} else {
|
||||
|
@ -103,22 +125,19 @@ impl Move {
|
|||
impl fmt::Display for Move {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Some(castle) = self.castle() {
|
||||
match castle {
|
||||
Castle::KingSide => return write!(f, "0-0"),
|
||||
Castle::QueenSide => return write!(f, "0-0-0"),
|
||||
}
|
||||
return match castle {
|
||||
Castle::KingSide => write!(f, "0-0"),
|
||||
Castle::QueenSide => write!(f, "0-0-0"),
|
||||
};
|
||||
}
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{}{}{}",
|
||||
self.origin_square(),
|
||||
self._transfer_char(),
|
||||
self.target_square()
|
||||
)?;
|
||||
let origin = self.origin_square();
|
||||
let target = self.target_square();
|
||||
let transfer_char = self._transfer_char();
|
||||
write!(f, "{origin}{transfer_char}{target}")?;
|
||||
|
||||
if let Some(promotion) = self.promotion() {
|
||||
write!(f, "={}", promotion)?;
|
||||
write!(f, "={promotion}")?;
|
||||
} else if self.is_en_passant() {
|
||||
write!(f, " e.p.")?;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue