montyformat/
chess.rs

1pub mod attacks;
2pub mod consts;
3pub mod frc;
4pub mod moves;
5pub mod position;
6
7pub const STARTPOS: &str = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
8
9pub use attacks::Attacks;
10pub use consts::{Flag, Piece, Right, Side};
11pub use frc::Castling;
12pub use moves::Move;
13pub use position::Position;
14
15#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
16pub enum GameState {
17    #[default]
18    Ongoing,
19    Lost(u8),
20    Draw,
21    Won(u8),
22}
23
24impl From<GameState> for u16 {
25    fn from(value: GameState) -> Self {
26        match value {
27            GameState::Ongoing => 0,
28            GameState::Draw => 1 << 8,
29            GameState::Lost(x) => (2 << 8) ^ u16::from(x),
30            GameState::Won(x) => (3 << 8) ^ u16::from(x),
31        }
32    }
33}
34
35impl From<u16> for GameState {
36    fn from(value: u16) -> Self {
37        let discr = value >> 8;
38        let x = value as u8;
39
40        match discr {
41            0 => GameState::Ongoing,
42            1 => GameState::Draw,
43            2 => GameState::Lost(x),
44            3 => GameState::Won(x),
45            _ => unreachable!(),
46        }
47    }
48}
49
50impl std::fmt::Display for GameState {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            GameState::Ongoing => write!(f, "O"),
54            GameState::Lost(n) => write!(f, "L{n}"),
55            GameState::Won(n) => write!(f, "W{n}"),
56            GameState::Draw => write!(f, "D"),
57        }
58    }
59}
60
61pub fn perft<const REPORT: bool>(pos: &Position, castling: &Castling, depth: u8) -> u64 {
62    if depth == 1 {
63        let mut count = 0;
64        pos.map_legal_moves(castling, |_| count += 1);
65        return count;
66    }
67
68    let mut count = 0;
69
70    pos.map_legal_moves(castling, |mov| {
71        let mut new = *pos;
72        new.make(mov, castling);
73
74        let sub_count = perft::<false>(&new, castling, depth - 1);
75
76        if REPORT {
77            println!("{}: {sub_count}", mov.to_uci(castling));
78        }
79
80        count += sub_count;
81    });
82
83    count
84}