Make from_fen return Result<Board, FenError>

This commit is contained in:
2024-05-29 20:39:38 +03:00
parent 9876fc0465
commit b471aaf109
2 changed files with 37 additions and 26 deletions

View File

@@ -2,39 +2,39 @@ use crate::board::{Board, Color, Kind, Piece};
use crate::game::{Game, State}; use crate::game::{Game, State};
use String as FenError; use String as FenError;
pub fn from_fen(fen: &str) -> Game { pub fn from_fen(fen: &str) -> Result<Game, FenError> {
let mut board = Board::empty_board();
let fen_parts: Vec<_> = fen.split_whitespace().collect(); let fen_parts: Vec<_> = fen.split_whitespace().collect();
piece_placement(fen_parts[0], &mut board); let board = piece_placement(fen_parts[0])?;
let side_to_move = side_to_move(fen_parts[1]); let side_to_move = side_to_move(fen_parts[1])?;
let castling_ability = castling_ability(fen_parts[2]); let castling_ability = castling_ability(fen_parts[2])?;
let en_passant_target_square: Result<u8, FenError> = en_passant_target_square(fen_parts[3]); let en_passant_target_square = en_passant_target_square(fen_parts[3])?;
let halfmove_clock = halfmove_clock(fen_parts[4]); let halfmove_clock = halfmove_clock(fen_parts[4])?;
let fullmove_counter = fullmove_counter(fen_parts[5]); let fullmove_counter = fullmove_counter(fen_parts[5])?;
Game { Ok(Game {
board, board,
state: State::load_state( state: State::load_state(
side_to_move.unwrap(), side_to_move,
castling_ability.unwrap(), castling_ability,
en_passant_target_square.unwrap(), en_passant_target_square,
halfmove_clock.unwrap(), halfmove_clock,
fullmove_counter.unwrap(), fullmove_counter,
), ),
} })
} }
fn piece_placement(pieces: &str, board: &mut Board) { fn piece_placement(pieces: &str) -> Result<Board, FenError> {
let mut board = Board::empty_board();
let (mut file, mut rank): (u8, u8) = (0, 7); let (mut file, mut rank): (u8, u8) = (0, 7);
for c in pieces.chars() { for c in pieces.chars() {
let square: u8 = rank * 8 + file; let square = rank * 8 + file;
let color = if c.is_ascii_lowercase() { let color = if c.is_ascii_lowercase() {
Color::Black Color::Black
} else { } else {
@@ -57,13 +57,18 @@ fn piece_placement(pieces: &str, board: &mut Board) {
rank %= n.to_digit(10).unwrap_or(0) as u8; rank %= n.to_digit(10).unwrap_or(0) as u8;
None None
} }
_ => None, _ => {
return Err(FenError::from(
"Error while parsing board piece state from FEN",
))
}
} { } {
board.set_piece(Piece::new(1 << square, kind, color)); board.set_piece(Piece::new(1 << square, kind, color));
}; };
file += 1; file += 1;
} }
Ok(board)
} }
fn side_to_move(side: &str) -> Result<Color, FenError> { fn side_to_move(side: &str) -> Result<Color, FenError> {
@@ -152,20 +157,25 @@ fn fullmove_counter(fullmove: &str) -> Result<u8, FenError> {
mod tests { mod tests {
use super::*; use super::*;
const FEN_EXAMPLE: [&str; 4] = [ const FEN_EXAMPLE: [&str; 5] = [
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1", "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
"rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2", "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2",
"rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 ", "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 ",
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR x KQkq - 0 1",
]; ];
#[test] #[test]
fn test_sqrt() -> Result<(), String> { fn test_from_fen() -> Result<(), String> {
let game = from_fen(FEN_EXAMPLE[3]); let new_game = from_fen(FEN_EXAMPLE[0])?;
println!("{}\n{}", game.board, game.state); assert_eq!(new_game, Game::new());
assert_eq!(from_fen(FEN_EXAMPLE[0]), Game::new());
Ok(()) Ok(())
} }
#[test]
#[should_panic]
fn test_fen_error() -> () {
from_fen(FEN_EXAMPLE[4]).unwrap();
}
} }

View File

@@ -2,6 +2,7 @@ use crate::{
board::{Board, Color}, board::{Board, Color},
fen::from_fen, fen::from_fen,
}; };
use String as FenError;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Game { pub struct Game {
@@ -17,7 +18,7 @@ impl Game {
} }
} }
pub fn new_from_fen(fen: &str) -> Game { pub fn new_from_fen(fen: &str) -> Result<Game, FenError> {
from_fen(fen) from_fen(fen)
} }
@@ -75,7 +76,7 @@ impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, writeln!(f,
"side_to_move: {:?}\ncastling_ability: {:b}\nen_passant_target_square: {:b}\nhalfmove_clock: {}\nfullmove_counter: {}\n", "side_to_move: {:?}\ncastling_ability: {:b}\nen_passant_target_square: {:b}\nhalfmove_clock: {}\nfullmove_counter: {}\n",
self.side_to_move, self.castling_ability, 1u64 << self.en_passant_target_square, self.halfmove_clock, self.fullmove_counter) self.side_to_move, self.castling_ability, 1_u64 << self.en_passant_target_square, self.halfmove_clock, self.fullmove_counter)
} }
} }