chessfriend/board/src/display.rs

119 lines
3 KiB
Rust

// Eryn Wells <eryn@erynwells.me>
use crate::Board;
use chessfriend_bitboard::BitBoard;
use chessfriend_core::{File, Rank, Square};
use std::fmt;
#[derive(Default)]
pub enum PieceDisplayStyle {
#[default]
Unicode,
ASCII,
}
#[must_use]
pub struct DiagramFormatter<'a> {
board: &'a Board,
piece_style: PieceDisplayStyle,
marked_squares: BitBoard,
highlighted_squares: BitBoard,
}
impl<'a> DiagramFormatter<'a> {
pub fn new(board: &'a Board) -> Self {
Self {
board,
piece_style: PieceDisplayStyle::default(),
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 fmt::Display for DiagramFormatter<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, " ╔═════════════════╗")?;
for rank in Rank::ALL.into_iter().rev() {
write!(f, "{rank} ║ ")?;
for file in File::ALL {
let square = Square::from_file_rank(file, rank);
let should_highlight = self.highlighted_squares.contains(square);
if should_highlight {
write!(f, "\x1b[7m")?;
}
if let Some(piece) = self.board.get_piece(square) {
let ch = match self.piece_style {
PieceDisplayStyle::Unicode => piece.to_unicode(),
PieceDisplayStyle::ASCII => piece.to_ascii(),
};
write!(f, "{ch}")?;
} 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, " ╚═════════════════╝")?;
write!(f, " a b c d e f g h")?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{test_board, Board};
#[test]
#[ignore]
fn empty() {
let board = test_board!(empty);
let diagram = DiagramFormatter::new(&board);
println!("{diagram}");
}
#[test]
#[ignore]
fn one_king() {
let board = test_board![Black King on H3];
let diagram = DiagramFormatter::new(&board);
println!("{diagram}");
}
#[test]
#[ignore]
fn starting() {
let board = test_board!(starting);
let diagram = DiagramFormatter::new(&board);
println!("{diagram}");
}
}