use std::fmt::{self, Display};
use std::ops::{Index, IndexMut};
use crate::boardrepr::PieceSets;
use crate::coretypes::{
Color, Piece, PieceKind, Square, SquareIndexable, NUM_FILES, NUM_RANKS, NUM_SQUARES,
};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Mailbox {
board: [Option<Piece>; Self::SIZE],
}
impl Mailbox {
pub const FILES: usize = NUM_FILES;
pub const RANKS: usize = NUM_RANKS;
pub const SIZE: usize = NUM_SQUARES;
pub fn new() -> Self {
Mailbox {
board: [None; Mailbox::SIZE],
}
}
pub fn start_position() -> Self {
use Color::*;
use PieceKind::*;
use Square::*;
let mut mb = Self::new();
mb[A1] = Some(Piece::new(White, Rook));
mb[B1] = Some(Piece::new(White, Knight));
mb[C1] = Some(Piece::new(White, Bishop));
mb[D1] = Some(Piece::new(White, Queen));
mb[E1] = Some(Piece::new(White, King));
mb[F1] = Some(Piece::new(White, Bishop));
mb[G1] = Some(Piece::new(White, Knight));
mb[H1] = Some(Piece::new(White, Rook));
for square in [A2, B2, C2, D2, E2, F2, G2, H2] {
mb[square] = Some(Piece::new(White, Pawn));
}
mb[A8] = Some(Piece::new(Black, Rook));
mb[B8] = Some(Piece::new(Black, Knight));
mb[C8] = Some(Piece::new(Black, Bishop));
mb[D8] = Some(Piece::new(Black, Queen));
mb[E8] = Some(Piece::new(Black, King));
mb[F8] = Some(Piece::new(Black, Bishop));
mb[G8] = Some(Piece::new(Black, Knight));
mb[H8] = Some(Piece::new(Black, Rook));
for square in [A7, B7, C7, D7, E7, F7, G7, H7] {
mb[square] = Some(Piece::new(Black, Pawn));
}
mb
}
pub fn board(&self) -> &[Option<Piece>; Self::SIZE] {
&self.board
}
pub fn pretty(&self) -> String {
const RANK_SEP: &'static str = "+---+---+---+---+---+---+---+---+\n";
let mut pretty = String::with_capacity(626);
pretty.push_str(RANK_SEP);
for rank in (0..Self::RANKS).rev() {
pretty.push_str("| ");
for file in 0..Self::FILES {
pretty.push(match self[rank * Self::RANKS + file] {
Some(piece) => char::from(piece),
None => ' ',
});
pretty.push_str(" | ");
}
pretty.push_str(&(rank + 1).to_string());
pretty.push('\n');
pretty.push_str(RANK_SEP);
}
pretty.push_str(" a b c d e f g h\n");
pretty
}
}
impl Index<usize> for Mailbox {
type Output = Option<Piece>;
fn index(&self, idx: usize) -> &Self::Output {
&self.board[idx]
}
}
impl IndexMut<usize> for Mailbox {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.board[idx]
}
}
impl<I: SquareIndexable> Index<I> for Mailbox {
type Output = Option<Piece>;
fn index(&self, idx: I) -> &Self::Output {
&self.board[idx.idx()]
}
}
impl<I: SquareIndexable> IndexMut<I> for Mailbox {
fn index_mut(&mut self, idx: I) -> &mut Self::Output {
&mut self.board[idx.idx()]
}
}
impl From<&PieceSets> for Mailbox {
fn from(pieces: &PieceSets) -> Mailbox {
let mut mb = Mailbox::new();
for color in Color::iter() {
for piece_kind in PieceKind::iter() {
let piece = Piece::new(color, piece_kind);
pieces[&piece]
.into_iter()
.for_each(|square| mb[square] = Some(piece));
}
}
mb
}
}
impl Default for Mailbox {
fn default() -> Self {
Mailbox::start_position()
}
}
impl Display for Mailbox {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.pretty())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_start_position_mailbox() {
let mb = Mailbox::start_position();
println!("{}", mb.pretty().len());
println!("{}", mb);
}
}