[board] Implement move_formatter::AlgebraicMoveFormatter

This commit is contained in:
Eryn Wells 2024-01-11 08:33:58 -08:00
parent caef0af244
commit 094131822c

View file

@ -58,4 +58,153 @@ impl Move {
&& self.to && self.to
== Square::KING_CASTLE_TARGET_SQUARES[color as usize][BoardSide::Queen as usize] == Square::KING_CASTLE_TARGET_SQUARES[color as usize][BoardSide::Queen as usize]
} }
pub fn is_capture(&self) -> bool {
self.capturing.is_some()
}
pub fn is_promotion(&self) -> bool {
self.promoting_to.is_some()
}
}
mod move_formatter {
use super::Move;
use crate::{piece::Shape, Position};
use std::fmt;
enum Style {
Short,
Long,
}
pub(crate) struct AlgebraicMoveFormatter<'m> {
r#move: &'m Move,
style: Style,
}
impl<'pos, 'm> AlgebraicMoveFormatter<'m> {
pub(crate) fn new(mv: &'m Move) -> AlgebraicMoveFormatter<'m> {
AlgebraicMoveFormatter {
r#move: mv,
style: Style::Short,
}
}
fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
fn fmt_kingside_castle(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0-0")
}
fn fmt_queenside_castle(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0-0-0")
}
fn fmt_short(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unimplemented!()
}
fn fmt_long(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// TODO: Figure out how to write the short algebraic form, where a
// disambiguating coordiate is specified when two of the same piece
// cam move to the same square.
// TODO: Write better pawn moves.
let mv = self.r#move;
let shape = mv.piece.shape();
if shape != Shape::Pawn {
write!(f, "{}", shape)?;
}
write!(
f,
"{}{}{}",
mv.from,
if mv.is_capture() { 'x' } else { '-' },
mv.to,
)?;
if let Some(promoting_to) = mv.promoting_to {
write!(f, "={}", promoting_to)?;
}
// TODO: Write check (+) and checkmate (#) symbols
Ok(())
}
}
impl<'pos, 'mv> fmt::Display for AlgebraicMoveFormatter<'mv> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.r#move.is_kingside_castle() {
return self.fmt_kingside_castle(f);
} else if self.r#move.is_queenside_castle() {
return self.fmt_queenside_castle(f);
}
match self.style {
Style::Short => self.fmt_short(f),
Style::Long => self.fmt_long(f),
}
}
}
#[cfg(test)]
mod tests {
use super::{AlgebraicMoveFormatter, Style};
macro_rules! chess_move {
($color:ident $shape:ident $from_square:ident - $to_square:ident) => {
crate::Move::new(
crate::piece::Piece::new(crate::piece::Color::$color, crate::piece::Shape::$shape),
crate::Square::$from_square,
crate::Square::$to_square,
)
};
($color:ident $shape:ident $from_square:ident x $to_square:ident, $captured_color:ident $captured_shape:ident) => {
chess_move!($color $shape $from_square - $to_square)
.capturing(crate::piece::PlacedPiece::new(
crate::piece::Piece::new(
crate::piece::Color::$captured_color,
crate::piece::Shape::$captured_shape,
),
crate::Square::$to_square,
))
};
}
macro_rules! test_algebraic_formatter {
($test_name:ident, $style:ident, $color:ident $shape:ident $from_square:ident x $to_square:ident, $captured_color:ident $captured_shape:ident, $output:expr) => {
#[test]
fn $test_name() {
let mv = chess_move!(
$color $shape $from_square x $to_square,
$captured_color $captured_shape
);
let formatter = AlgebraicMoveFormatter::new(&mv).style(Style::$style);
assert_eq!(format!("{}", formatter), $output);
}
};
($test_name:ident, $style:ident, $color:ident $shape:ident $from_square:ident - $to_square:ident, $output:expr) => {
#[test]
fn $test_name() {
let mv = chess_move!($color $shape $from_square-$to_square);
let formatter = AlgebraicMoveFormatter::new(&mv).style(Style::$style);
assert_eq!(format!("{}", formatter), $output);
}
};
}
test_algebraic_formatter!(long_pawn_move, Long, White Pawn E4 - E5, "e4-e5");
test_algebraic_formatter!(long_bishop_move, Long, White Bishop A4 - D7, "Ba4-d7");
test_algebraic_formatter!(long_bishop_capture, Long, White Bishop A2 x E6, Black Knight, "Ba2xe6");
}
} }