[board] Implement move_formatter::AlgebraicMoveFormatter
This commit is contained in:
parent
caef0af244
commit
094131822c
1 changed files with 149 additions and 0 deletions
|
@ -58,4 +58,153 @@ impl Move {
|
|||
&& self.to
|
||||
== 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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue