From b471aaf109057de9b16fbfd93d026f9a716eaca2 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Wed, 29 May 2024 20:39:38 +0300 Subject: [PATCH] Make from_fen return Result --- src/fen.rs | 58 +++++++++++++++++++++++++++++++---------------------- src/game.rs | 5 +++-- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/fen.rs b/src/fen.rs index b2d1237..f8d345b 100644 --- a/src/fen.rs +++ b/src/fen.rs @@ -2,39 +2,39 @@ use crate::board::{Board, Color, Kind, Piece}; use crate::game::{Game, State}; use String as FenError; -pub fn from_fen(fen: &str) -> Game { - let mut board = Board::empty_board(); +pub fn from_fen(fen: &str) -> Result { 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 = 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, state: State::load_state( - side_to_move.unwrap(), - castling_ability.unwrap(), - en_passant_target_square.unwrap(), - halfmove_clock.unwrap(), - fullmove_counter.unwrap(), + side_to_move, + castling_ability, + en_passant_target_square, + halfmove_clock, + fullmove_counter, ), - } + }) } -fn piece_placement(pieces: &str, board: &mut Board) { +fn piece_placement(pieces: &str) -> Result { + let mut board = Board::empty_board(); let (mut file, mut rank): (u8, u8) = (0, 7); for c in pieces.chars() { - let square: u8 = rank * 8 + file; + let square = rank * 8 + file; let color = if c.is_ascii_lowercase() { Color::Black } else { @@ -57,13 +57,18 @@ fn piece_placement(pieces: &str, board: &mut Board) { rank %= n.to_digit(10).unwrap_or(0) as u8; None } - _ => None, + _ => { + return Err(FenError::from( + "Error while parsing board piece state from FEN", + )) + } } { board.set_piece(Piece::new(1 << square, kind, color)); }; file += 1; } + Ok(board) } fn side_to_move(side: &str) -> Result { @@ -152,20 +157,25 @@ fn fullmove_counter(fullmove: &str) -> Result { mod tests { 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/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/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 ", + "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR x KQkq - 0 1", ]; #[test] - fn test_sqrt() -> Result<(), String> { - let game = from_fen(FEN_EXAMPLE[3]); - println!("{}\n{}", game.board, game.state); - - assert_eq!(from_fen(FEN_EXAMPLE[0]), Game::new()); + fn test_from_fen() -> Result<(), String> { + let new_game = from_fen(FEN_EXAMPLE[0])?; + assert_eq!(new_game, Game::new()); Ok(()) } + + #[test] + #[should_panic] + fn test_fen_error() -> () { + from_fen(FEN_EXAMPLE[4]).unwrap(); + } } diff --git a/src/game.rs b/src/game.rs index a2e1f32..9ecf425 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2,6 +2,7 @@ use crate::{ board::{Board, Color}, fen::from_fen, }; +use String as FenError; #[derive(Debug, PartialEq)] 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 { from_fen(fen) } @@ -75,7 +76,7 @@ impl fmt::Display for State { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "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) } }