[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 {
|
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) {
|
pub fn set_square(&mut self, sq: Square) {
|
||||||
|
@ -341,4 +342,10 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(a, bitboard![B5, C5, G7, H3]);
|
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()
|
PROMOTABLE_SHAPES.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _ascii_representation(&self) -> char {
|
fn to_ascii(&self) -> char {
|
||||||
match self {
|
match self {
|
||||||
Shape::Pawn => 'P',
|
Shape::Pawn => 'P',
|
||||||
Shape::Knight => 'N',
|
Shape::Knight => 'N',
|
||||||
|
@ -83,12 +83,12 @@ impl TryFrom<char> for Shape {
|
||||||
|
|
||||||
fn try_from(value: char) -> Result<Self, Self::Error> {
|
fn try_from(value: char) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
'p' => Ok(Shape::Pawn),
|
'P' | 'p' => Ok(Shape::Pawn),
|
||||||
'N' => Ok(Shape::Knight),
|
'N' | 'n' => Ok(Shape::Knight),
|
||||||
'B' => Ok(Shape::Bishop),
|
'B' | 'b' => Ok(Shape::Bishop),
|
||||||
'R' => Ok(Shape::Rook),
|
'R' | 'r' => Ok(Shape::Rook),
|
||||||
'Q' => Ok(Shape::Queen),
|
'Q' | 'q' => Ok(Shape::Queen),
|
||||||
'K' => Ok(Shape::King),
|
'K' | 'k' => Ok(Shape::King),
|
||||||
_ => Err(TryFromError),
|
_ => Err(TryFromError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,13 +105,13 @@ impl TryFrom<&str> for Shape {
|
||||||
|
|
||||||
impl Into<char> for &Shape {
|
impl Into<char> for &Shape {
|
||||||
fn into(self) -> char {
|
fn into(self) -> char {
|
||||||
self._ascii_representation()
|
self.to_ascii()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<char> for Shape {
|
impl Into<char> for Shape {
|
||||||
fn into(self) -> char {
|
fn into(self) -> char {
|
||||||
self._ascii_representation()
|
self.to_ascii()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +173,10 @@ impl Piece {
|
||||||
is_shape!(is_rook, Rook);
|
is_shape!(is_rook, Rook);
|
||||||
is_shape!(is_queen, Queen);
|
is_shape!(is_queen, Queen);
|
||||||
is_shape!(is_king, King);
|
is_shape!(is_king, King);
|
||||||
|
|
||||||
|
pub fn to_ascii(&self) -> char {
|
||||||
|
self.shape.to_ascii()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Piece {
|
impl fmt::Display for Piece {
|
||||||
|
@ -193,18 +197,18 @@ impl UnicodeDisplay for Piece {
|
||||||
f,
|
f,
|
||||||
"{}",
|
"{}",
|
||||||
match (self.color, self.shape) {
|
match (self.color, self.shape) {
|
||||||
(Color::White, Shape::Pawn) => '♟',
|
(Color::Black, Shape::Pawn) => '♟',
|
||||||
(Color::White, Shape::Knight) => '♞',
|
(Color::Black, Shape::Knight) => '♞',
|
||||||
(Color::White, Shape::Bishop) => '♝',
|
(Color::Black, Shape::Bishop) => '♝',
|
||||||
(Color::White, Shape::Rook) => '♜',
|
(Color::Black, Shape::Rook) => '♜',
|
||||||
(Color::White, Shape::Queen) => '♛',
|
(Color::Black, Shape::Queen) => '♛',
|
||||||
(Color::White, Shape::King) => '♚',
|
(Color::Black, Shape::King) => '♚',
|
||||||
(Color::Black, Shape::Pawn) => '♙',
|
(Color::White, Shape::Pawn) => '♙',
|
||||||
(Color::Black, Shape::Knight) => '♘',
|
(Color::White, Shape::Knight) => '♘',
|
||||||
(Color::Black, Shape::Bishop) => '♗',
|
(Color::White, Shape::Bishop) => '♗',
|
||||||
(Color::Black, Shape::Rook) => '♖',
|
(Color::White, Shape::Rook) => '♖',
|
||||||
(Color::Black, Shape::Queen) => '♕',
|
(Color::White, Shape::Queen) => '♕',
|
||||||
(Color::Black, Shape::King) => '♔',
|
(Color::White, Shape::King) => '♔',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +216,7 @@ impl UnicodeDisplay for Piece {
|
||||||
|
|
||||||
impl FENDisplay for Piece {
|
impl FENDisplay for Piece {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let ascii = self.shape()._ascii_representation();
|
let ascii = self.shape().to_ascii();
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}",
|
"{}",
|
||||||
|
|
|
@ -36,12 +36,15 @@ struct ByColorAndShape([[BitBoard; 6]; 2]);
|
||||||
|
|
||||||
impl PieceBitBoards {
|
impl PieceBitBoards {
|
||||||
pub(super) fn new(pieces: [[BitBoard; 6]; 2]) -> Self {
|
pub(super) fn new(pieces: [[BitBoard; 6]; 2]) -> Self {
|
||||||
|
use std::ops::BitOr;
|
||||||
|
|
||||||
let white_pieces = pieces[Color::White as usize]
|
let white_pieces = pieces[Color::White as usize]
|
||||||
.iter()
|
.iter()
|
||||||
.fold(BitBoard::empty(), std::ops::BitOr::bitor);
|
.fold(BitBoard::empty(), BitOr::bitor);
|
||||||
let black_pieces = pieces[Color::White as usize]
|
let black_pieces = pieces[Color::Black as usize]
|
||||||
.iter()
|
.iter()
|
||||||
.fold(BitBoard::empty(), std::ops::BitOr::bitor);
|
.fold(BitBoard::empty(), BitOr::bitor);
|
||||||
|
|
||||||
let all_pieces = white_pieces | black_pieces;
|
let all_pieces = white_pieces | black_pieces;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -33,22 +33,22 @@ impl Position {
|
||||||
|
|
||||||
/// Return a starting position.
|
/// Return a starting position.
|
||||||
pub fn starting() -> Self {
|
pub fn starting() -> Self {
|
||||||
let white_pieces = [
|
let black_pieces = [
|
||||||
BitBoard::new(0x00FF000000000000),
|
BitBoard::new(0b0000000011111111 << 48),
|
||||||
BitBoard::new(0x4200000000000000),
|
BitBoard::new(0b0100001000000000 << 48),
|
||||||
BitBoard::new(0x2400000000000000),
|
BitBoard::new(0b0010010000000000 << 48),
|
||||||
BitBoard::new(0x8100000000000000),
|
BitBoard::new(0b1000000100000000 << 48),
|
||||||
BitBoard::new(0x1000000000000000),
|
BitBoard::new(0b0000100000000000 << 48),
|
||||||
BitBoard::new(0x0800000000000000),
|
BitBoard::new(0b0001000000000000 << 48),
|
||||||
];
|
];
|
||||||
|
|
||||||
let black_pieces = [
|
let white_pieces = [
|
||||||
BitBoard::new(0xFF00),
|
BitBoard::new(0b1111111100000000),
|
||||||
BitBoard::new(0x0042),
|
BitBoard::new(0b0000000001000010),
|
||||||
BitBoard::new(0x0024),
|
BitBoard::new(0b0000000000100100),
|
||||||
BitBoard::new(0x0081),
|
BitBoard::new(0b0000000010000001),
|
||||||
BitBoard::new(0x0010),
|
BitBoard::new(0b0000000000001000),
|
||||||
BitBoard::new(0x0008),
|
BitBoard::new(0b0000000000010000),
|
||||||
];
|
];
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -242,7 +242,32 @@ impl fmt::Display for Position {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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]
|
#[test]
|
||||||
fn king_is_in_check() {
|
fn king_is_in_check() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use crate::{r#move::Castle, Color};
|
use crate::Color;
|
||||||
use std::{fmt, str::FromStr};
|
use std::{fmt, str::FromStr};
|
||||||
|
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
|
@ -308,6 +308,12 @@ mod tests {
|
||||||
assert_eq!(sq.rank(), Rank::Four);
|
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]
|
#[test]
|
||||||
fn valid_neighbors() {
|
fn valid_neighbors() {
|
||||||
let sq = Square::E4;
|
let sq = Square::E4;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue