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}