[board] Fix some bugs in the starting position
Turns out I was doing the starting position really wrong. In an upcoming commit, I will implement FEN output for Positions. While doing that work, I found several issues that were causing the output of the FEN formatter to return garbage. Implement a handful of unit tests to track down the errors. Rename Shape::_ascii_representation() → Shape::to_ascii. Implement to_ascii() on Piece.
This commit is contained in:
parent
84c9c43a7d
commit
829d9af52c
5 changed files with 87 additions and 42 deletions
|
@ -53,7 +53,8 @@ impl BitBoard {
|
|||
}
|
||||
|
||||
pub fn is_set(self, sq: Square) -> bool {
|
||||
!(self & &sq.into()).is_empty()
|
||||
let square_bitboard: BitBoard = sq.into();
|
||||
!(self & square_bitboard).is_empty()
|
||||
}
|
||||
|
||||
pub fn set_square(&mut self, sq: Square) {
|
||||
|
@ -341,4 +342,10 @@ mod tests {
|
|||
|
||||
assert_eq!(a, bitboard![B5, C5, G7, H3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_square() {
|
||||
assert_eq!(BitBoard::from(Square::A1), BitBoard(0b1));
|
||||
assert_eq!(BitBoard::from(Square::H8), BitBoard(1 << 63));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ impl Shape {
|
|||
PROMOTABLE_SHAPES.iter()
|
||||
}
|
||||
|
||||
fn _ascii_representation(&self) -> char {
|
||||
fn to_ascii(&self) -> char {
|
||||
match self {
|
||||
Shape::Pawn => 'P',
|
||||
Shape::Knight => 'N',
|
||||
|
@ -83,12 +83,12 @@ impl TryFrom<char> for Shape {
|
|||
|
||||
fn try_from(value: char) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
'p' => Ok(Shape::Pawn),
|
||||
'N' => Ok(Shape::Knight),
|
||||
'B' => Ok(Shape::Bishop),
|
||||
'R' => Ok(Shape::Rook),
|
||||
'Q' => Ok(Shape::Queen),
|
||||
'K' => Ok(Shape::King),
|
||||
'P' | 'p' => Ok(Shape::Pawn),
|
||||
'N' | 'n' => Ok(Shape::Knight),
|
||||
'B' | 'b' => Ok(Shape::Bishop),
|
||||
'R' | 'r' => Ok(Shape::Rook),
|
||||
'Q' | 'q' => Ok(Shape::Queen),
|
||||
'K' | 'k' => Ok(Shape::King),
|
||||
_ => Err(TryFromError),
|
||||
}
|
||||
}
|
||||
|
@ -105,13 +105,13 @@ impl TryFrom<&str> for Shape {
|
|||
|
||||
impl Into<char> for &Shape {
|
||||
fn into(self) -> char {
|
||||
self._ascii_representation()
|
||||
self.to_ascii()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<char> for Shape {
|
||||
fn into(self) -> char {
|
||||
self._ascii_representation()
|
||||
self.to_ascii()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,6 +173,10 @@ impl Piece {
|
|||
is_shape!(is_rook, Rook);
|
||||
is_shape!(is_queen, Queen);
|
||||
is_shape!(is_king, King);
|
||||
|
||||
pub fn to_ascii(&self) -> char {
|
||||
self.shape.to_ascii()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Piece {
|
||||
|
@ -193,18 +197,18 @@ impl UnicodeDisplay for Piece {
|
|||
f,
|
||||
"{}",
|
||||
match (self.color, self.shape) {
|
||||
(Color::White, Shape::Pawn) => '♟',
|
||||
(Color::White, Shape::Knight) => '♞',
|
||||
(Color::White, Shape::Bishop) => '♝',
|
||||
(Color::White, Shape::Rook) => '♜',
|
||||
(Color::White, Shape::Queen) => '♛',
|
||||
(Color::White, Shape::King) => '♚',
|
||||
(Color::Black, Shape::Pawn) => '♙',
|
||||
(Color::Black, Shape::Knight) => '♘',
|
||||
(Color::Black, Shape::Bishop) => '♗',
|
||||
(Color::Black, Shape::Rook) => '♖',
|
||||
(Color::Black, Shape::Queen) => '♕',
|
||||
(Color::Black, Shape::King) => '♔',
|
||||
(Color::Black, Shape::Pawn) => '♟',
|
||||
(Color::Black, Shape::Knight) => '♞',
|
||||
(Color::Black, Shape::Bishop) => '♝',
|
||||
(Color::Black, Shape::Rook) => '♜',
|
||||
(Color::Black, Shape::Queen) => '♛',
|
||||
(Color::Black, Shape::King) => '♚',
|
||||
(Color::White, Shape::Pawn) => '♙',
|
||||
(Color::White, Shape::Knight) => '♘',
|
||||
(Color::White, Shape::Bishop) => '♗',
|
||||
(Color::White, Shape::Rook) => '♖',
|
||||
(Color::White, Shape::Queen) => '♕',
|
||||
(Color::White, Shape::King) => '♔',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -212,7 +216,7 @@ impl UnicodeDisplay for Piece {
|
|||
|
||||
impl FENDisplay for Piece {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let ascii = self.shape()._ascii_representation();
|
||||
let ascii = self.shape().to_ascii();
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
|
|
|
@ -36,12 +36,15 @@ struct ByColorAndShape([[BitBoard; 6]; 2]);
|
|||
|
||||
impl PieceBitBoards {
|
||||
pub(super) fn new(pieces: [[BitBoard; 6]; 2]) -> Self {
|
||||
use std::ops::BitOr;
|
||||
|
||||
let white_pieces = pieces[Color::White as usize]
|
||||
.iter()
|
||||
.fold(BitBoard::empty(), std::ops::BitOr::bitor);
|
||||
let black_pieces = pieces[Color::White as usize]
|
||||
.fold(BitBoard::empty(), BitOr::bitor);
|
||||
let black_pieces = pieces[Color::Black as usize]
|
||||
.iter()
|
||||
.fold(BitBoard::empty(), std::ops::BitOr::bitor);
|
||||
.fold(BitBoard::empty(), BitOr::bitor);
|
||||
|
||||
let all_pieces = white_pieces | black_pieces;
|
||||
|
||||
Self {
|
||||
|
|
|
@ -33,22 +33,22 @@ impl Position {
|
|||
|
||||
/// Return a starting position.
|
||||
pub fn starting() -> Self {
|
||||
let white_pieces = [
|
||||
BitBoard::new(0x00FF000000000000),
|
||||
BitBoard::new(0x4200000000000000),
|
||||
BitBoard::new(0x2400000000000000),
|
||||
BitBoard::new(0x8100000000000000),
|
||||
BitBoard::new(0x1000000000000000),
|
||||
BitBoard::new(0x0800000000000000),
|
||||
let black_pieces = [
|
||||
BitBoard::new(0b0000000011111111 << 48),
|
||||
BitBoard::new(0b0100001000000000 << 48),
|
||||
BitBoard::new(0b0010010000000000 << 48),
|
||||
BitBoard::new(0b1000000100000000 << 48),
|
||||
BitBoard::new(0b0000100000000000 << 48),
|
||||
BitBoard::new(0b0001000000000000 << 48),
|
||||
];
|
||||
|
||||
let black_pieces = [
|
||||
BitBoard::new(0xFF00),
|
||||
BitBoard::new(0x0042),
|
||||
BitBoard::new(0x0024),
|
||||
BitBoard::new(0x0081),
|
||||
BitBoard::new(0x0010),
|
||||
BitBoard::new(0x0008),
|
||||
let white_pieces = [
|
||||
BitBoard::new(0b1111111100000000),
|
||||
BitBoard::new(0b0000000001000010),
|
||||
BitBoard::new(0b0000000000100100),
|
||||
BitBoard::new(0b0000000010000001),
|
||||
BitBoard::new(0b0000000000001000),
|
||||
BitBoard::new(0b0000000000010000),
|
||||
];
|
||||
|
||||
Self {
|
||||
|
@ -242,7 +242,32 @@ impl fmt::Display for Position {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{position, Castle, Color};
|
||||
use crate::{position, Castle, Color, Position, Square};
|
||||
|
||||
#[test]
|
||||
fn piece_on_square() {
|
||||
let pos = test_position![
|
||||
Black Bishop on F7,
|
||||
];
|
||||
|
||||
let piece = pos.piece_on_square(Square::F7);
|
||||
assert_eq!(piece, Some(piece!(Black Bishop on F7)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn piece_in_starting_position() {
|
||||
let pos = Position::starting();
|
||||
println!("{pos}");
|
||||
|
||||
assert_eq!(
|
||||
pos.piece_on_square(Square::H1),
|
||||
Some(piece!(White Rook on H1))
|
||||
);
|
||||
assert_eq!(
|
||||
pos.piece_on_square(Square::A8),
|
||||
Some(piece!(Black Rook on A8))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn king_is_in_check() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use crate::{r#move::Castle, Color};
|
||||
use crate::Color;
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
pub enum Direction {
|
||||
|
@ -308,6 +308,12 @@ mod tests {
|
|||
assert_eq!(sq.rank(), Rank::Four);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_index() {
|
||||
assert_eq!(Square::A1 as usize, 0);
|
||||
assert_eq!(Square::H8 as usize, 63);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_neighbors() {
|
||||
let sq = Square::E4;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue