fast_tak/
ptn.rs

1use takparse::{Move, ParseMoveError};
2
3use crate::{reserves::Reserves, Game, GameResult, PlayError};
4
5impl<const N: usize, const HALF_KOMI: i8> Game<N, HALF_KOMI>
6where
7    Reserves<N>: Default,
8{
9    /// Creates a default game and plays the supplied moves.
10    ///
11    /// # Errors
12    ///
13    /// If a move is invalid or the game is over when trying to
14    /// play a move, a [`PlayError`] is returned.
15    pub fn from_moves(moves: &[Move]) -> Result<Self, PlayError> {
16        let mut game = Self::default();
17        for mov in moves {
18            if game.result() != GameResult::Ongoing {
19                return Err(PlayError::GameOver);
20            }
21            game.play(*mov)?;
22        }
23        Ok(game)
24    }
25
26    /// Creates a default game and plays all the
27    /// moves after parsing them.
28    ///
29    /// # Panics
30    ///
31    /// Panics if there is an error in parsing or if any
32    /// move is invalid during play.
33    #[must_use]
34    pub fn from_ptn_moves(moves: &[&str]) -> Self {
35        let moves = ptn_to_moves(moves).unwrap();
36        Self::from_moves(&moves).unwrap()
37    }
38}
39
40pub fn ptn_to_moves(moves: &[&str]) -> Result<Box<[Move]>, ParseMoveError> {
41    moves.iter().map(|mov| mov.parse()).collect()
42}
43
44#[cfg(test)]
45mod tests {
46    use crate::{ptn::ptn_to_moves, Game, PlayError};
47
48    #[test]
49    fn game_ends() {
50        let moves = ptn_to_moves(&[
51            "a1", "e5", "a3", "b1", "c3", "c1", "e3", "d1", "d3", "e1", "b5",
52        ])
53        .unwrap();
54        assert_eq!(Game::<5, 0>::from_moves(&moves), Err(PlayError::GameOver));
55    }
56}