[board] Teach DiagramFormatter how to highlight and mark squares

Add two BitBoard attributes to the struct that mark squares that should be marked
or highlighted.

Empty marked squares are shown with an asterisk (*). Marked squares with a piece
don't have any change of appearance. (Something I'm still thinking about.)

Highlighted squares are shown with the ANSI escape sequence for Reverse Video.
This commit is contained in:
Eryn Wells 2025-05-16 07:49:09 -07:00
parent 3b5b2f16a3
commit 5553bab659

View file

@ -1,19 +1,38 @@
// Eryn Wells <eryn@erynwells.me> // Eryn Wells <eryn@erynwells.me>
use crate::Board; use crate::Board;
use chessfriend_bitboard::BitBoard;
use chessfriend_core::{File, Rank, Square}; use chessfriend_core::{File, Rank, Square};
use std::fmt; use std::fmt;
#[must_use] #[must_use]
pub struct DiagramFormatter<'a>(&'a Board); pub struct DiagramFormatter<'a> {
board: &'a Board,
marked_squares: BitBoard,
highlighted_squares: BitBoard,
}
impl<'a> DiagramFormatter<'a> { impl<'a> DiagramFormatter<'a> {
pub fn new(board: &'a Board) -> Self { pub fn new(board: &'a Board) -> Self {
Self(board) Self {
board,
marked_squares: BitBoard::default(),
highlighted_squares: BitBoard::default(),
}
}
pub fn mark(mut self, bitboard: BitBoard) -> Self {
self.marked_squares = bitboard;
self
}
pub fn highlight(mut self, bitboard: BitBoard) -> Self {
self.highlighted_squares = bitboard;
self
} }
} }
impl<'a> fmt::Display for DiagramFormatter<'a> { impl fmt::Display for DiagramFormatter<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, " ╔═════════════════╗")?; writeln!(f, " ╔═════════════════╗")?;
@ -22,17 +41,35 @@ impl<'a> fmt::Display for DiagramFormatter<'a> {
for file in File::ALL { for file in File::ALL {
let square = Square::from_file_rank(file, rank); let square = Square::from_file_rank(file, rank);
match self.0.get_piece(square) {
Some(piece) => write!(f, "{piece} ")?, let should_highlight = self.highlighted_squares.contains(square);
None => write!(f, "· ")?, if should_highlight {
write!(f, "\x1b[7m")?;
} }
if let Some(piece) = self.board.get_piece(square) {
write!(f, "{piece}")?;
} else {
let ch = if self.marked_squares.contains(square) {
'*'
} else {
'·'
};
write!(f, "{ch}")?;
}
if should_highlight {
write!(f, "\x1b[0m")?;
}
write!(f, " ")?;
} }
writeln!(f, "")?; writeln!(f, "")?;
} }
writeln!(f, " ╚═════════════════╝")?; writeln!(f, " ╚═════════════════╝")?;
writeln!(f, " a b c d e f g h")?; write!(f, " a b c d e f g h")?;
Ok(()) Ok(())
} }
@ -46,24 +83,24 @@ mod tests {
#[test] #[test]
#[ignore] #[ignore]
fn empty() { fn empty() {
let pos = test_board!(empty); let board = test_board!(empty);
let diagram = DiagramFormatter(&pos); let diagram = DiagramFormatter::new(&board);
println!("{diagram}"); println!("{diagram}");
} }
#[test] #[test]
#[ignore] #[ignore]
fn one_king() { fn one_king() {
let pos = test_board![Black King on H3]; let board = test_board![Black King on H3];
let diagram = DiagramFormatter(&pos); let diagram = DiagramFormatter::new(&board);
println!("{diagram}"); println!("{diagram}");
} }
#[test] #[test]
#[ignore] #[ignore]
fn starting() { fn starting() {
let pos = test_board!(starting); let board = test_board!(starting);
let diagram = DiagramFormatter(&pos); let diagram = DiagramFormatter::new(&board);
println!("{diagram}"); println!("{diagram}");
} }
} }