aboutsummaryrefslogtreecommitdiff
path: root/src/board.rs
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-01-21 03:33:55 +0300
committereug-vs <eugene@eug-vs.xyz>2023-01-21 03:33:55 +0300
commitd788e73ea5240f72d3ca64a5ce2bad5026643ebd (patch)
tree13cb05b7afa7600511ad082c70bcccc92bd2db3c /src/board.rs
parent9d9ded06303a810f9abd604d7b16825f8840f79a (diff)
downloadchessnost-d788e73ea5240f72d3ca64a5ce2bad5026643ebd.tar.gz
feat: implement FEN parsing
Diffstat (limited to 'src/board.rs')
-rw-r--r--src/board.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/board.rs b/src/board.rs
index c190c52..991820a 100644
--- a/src/board.rs
+++ b/src/board.rs
@@ -1,3 +1,117 @@
+use crate::bitboard::Bitboard;
+
+#[derive(Debug)]
+pub struct Board {
+ pub pieces: [Bitboard; 12],
+}
+
+
+enum PieceTypes {
+ Pawn,
+ PawnBlack,
+ Knight,
+ KnightBlack,
+ Bishop,
+ BishopBlack,
+ Rook,
+ RookBlack,
+ Queen,
+ QueenBlack,
+ King,
+ KingBlack,
+}
+
+
+const PIECE_CHARS: [&str; 12] = [
+ "♟︎", "♙",
+ "♞", "♘",
+ "♝", "♗",
+ "♜", "♖",
+ "♛", "♕",
+ "♚", "♔",
+];
+
+
+impl Board {
+ #[allow(non_snake_case)]
+ pub fn from_FEN(fen: String) -> Self {
+ let mut pieces = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let mut rank = 7;
+ let mut file = 0i32;
+
+ for character in fen.chars() {
+ let index = rank * 8 + file;
+ let position = 1 << index.clamp(0, 63);
+
+ if character.is_numeric() {
+ let digit = match character.to_digit(10) {
+ None => todo!("What to do here?"),
+ Some(digit) => digit,
+ };
+ if digit > 0 && digit <= 8 {
+ file += digit as i32;
+ }
+ } else {
+ match character {
+ 'P' => pieces[PieceTypes::Pawn as usize] |= position,
+ 'N' => pieces[PieceTypes::Knight as usize] |= position,
+ 'B' => pieces[PieceTypes::Bishop as usize] |= position,
+ 'R' => pieces[PieceTypes::Rook as usize] |= position,
+ 'Q' => pieces[PieceTypes::Queen as usize] |= position,
+ 'K' => pieces[PieceTypes::King as usize] |= position,
+ 'p' => pieces[PieceTypes::PawnBlack as usize] |= position,
+ 'n' => pieces[PieceTypes::KnightBlack as usize] |= position,
+ 'b' => pieces[PieceTypes::BishopBlack as usize] |= position,
+ 'r' => pieces[PieceTypes::RookBlack as usize] |= position,
+ 'q' => pieces[PieceTypes::QueenBlack as usize] |= position,
+ 'k' => pieces[PieceTypes::KingBlack as usize] |= position,
+ '/' => {
+ rank -= 1;
+ file = -1; // So it becomes 0
+ },
+ ' ' => { break }, // TODO: break for now, parse everything else later
+ '-' => {}, // TODO
+ 'w' => {}, // TODO
+ _ => todo!("Unexpected character!"),
+ }
+ file += 1;
+ }
+ }
+
+ Self { pieces }
+ }
+
+ pub fn print(&self) {
+ println!();
+ for rank in (0..8).rev() {
+ print!("{}|", rank + 1);
+ for file in 0..8 {
+ let index = rank * 8 + file;
+ let position: Bitboard = 1 << index;
+ let mut found = false;
+ for (piec_type, piece_bitboard) in self.pieces.iter().enumerate() {
+ if (piece_bitboard & position) > 0 {
+ found = true;
+ print!("{} ", PIECE_CHARS[piec_type]);
+ }
+ }
+ if !found {
+ print!(". ");
+ }
+ }
+ println!();
+ }
+ println!(" a b c d e f g h");
+ }
+}
+
+
+enum Color {
+ White,
+ Black,
+}
+
/// Aliases to board square indexes
#[allow(dead_code)]
enum Square {
@@ -14,6 +128,7 @@ enum Square {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::bitboard;
#[test]
fn test_square_enum() {
@@ -21,4 +136,29 @@ mod tests {
assert_eq!(Square::F1 as u8, 5);
assert_eq!(Square::H8 as u8, 63);
}
+
+ #[test]
+ fn test_from_fen() {
+ let fen = String::from("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
+ let board = Board::from_FEN(fen);
+
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::Pawn as usize]), 8);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::Knight as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::Bishop as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::Rook as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::Queen as usize]), 1);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::King as usize]), 1);
+
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::PawnBlack as usize]), 8);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::KnightBlack as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::BishopBlack as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::RookBlack as usize]), 2);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::QueenBlack as usize]), 1);
+ assert_eq!(bitboard::pop_count(board.pieces[PieceTypes::KingBlack as usize]), 1);
+
+ assert_eq!(bitboard::bitscan(board.pieces[PieceTypes::King as usize]), Square::E1 as u8);
+ assert_eq!(bitboard::bitscan(board.pieces[PieceTypes::QueenBlack as usize]), Square::D8 as u8);
+
+ board.print();
+ }
}