1use crate::{
2 board::*,
3 finite::Empty as _,
4 position::{EnPassant, EnPassantTable},
5 square::*,
6};
7
8use super::{Id, fold};
9
10#[cfg(feature = "const-fn-standard-id")]
11#[allow(long_running_const_eval)]
13pub const STANDARD: Basis = Basis::generate_standard();
14#[cfg(not(feature = "const-fn-standard-id"))]
15include!("standard.rs");
16
17#[cfg(feature = "const-fn-polyglot-id")]
18pub const POLYGLOT: Basis = Basis::empty();
19#[cfg(not(feature = "const-fn-polyglot-id"))]
20include!("polyglot.rs");
21
22type BoardTable<T> = SquareTable<PlayerTable<RoleTable<T>>>;
23type CastleTable<T> = PlayerTable<FileTable<T>>;
24
25#[derive(Clone, Copy, Debug)]
26pub struct Basis {
27 pub board: BoardTable<Id>,
28 pub turn: PlayerTable<Id>,
29 pub castle: CastleTable<Id>,
30 pub en_passant: EnPassantTable<Id>,
31}
32
33impl Basis {
34 pub const fn empty() -> Self {
35 Self {
36 board: BoardTable::EMPTY,
37 turn: PlayerTable::EMPTY,
38 castle: CastleTable::EMPTY,
39 en_passant: EnPassantTable::EMPTY,
40 }
41 }
42
43 pub const fn generate_standard() -> Self {
44 Self {
45 board: board_table(),
46 turn: turn_table(),
47 castle: castle_table(),
48 en_passant: en_passant_table(),
49 }
50 }
51}
52
53const fn board_table() -> BoardTable<Id> {
54 let mut squares = SquareTable::empty();
55
56 finite_for!(square in Square {
57 let mut players = PlayerTable::empty();
58 finite_for!(player in Player {
59 let mut roles = RoleTable::empty();
60 finite_for!(role in Role {
61 let entry = entry_4("board", square.name(), player.name(), role.name());
62 roles.set(role, entry);
63 });
64 players.set(player, roles);
65 });
66 squares.set(square, players);
67 });
68 squares
69}
70
71const fn castle_table() -> CastleTable<Id> {
72 let mut players = PlayerTable::empty();
73 finite_for!(player in Player {
74 let mut files = FileTable::empty();
75 finite_for!(file in File {
76 let entry = entry_3("castle", player.name(), file.name());
77 files.set(file, entry);
78 });
79 players.set(player, files);
80 });
81 players
82}
83
84const fn turn_table() -> PlayerTable<Id> {
85 let mut players = PlayerTable::empty();
86 finite_for!(player in Player {
87 let entry = entry_2("turn", player.name());
88 players.set(player, entry);
89 });
90 players
91}
92
93const fn en_passant_table() -> EnPassantTable<Id> {
94 let mut squares = EnPassantTable::empty();
95 finite_for!(en_passant in EnPassant {
96 let entry = entry_2("en-passant", en_passant.name());
97 squares.set(en_passant, entry);
98 });
99 squares
100}
101
102const fn entry_2(a: &str, b: &str) -> Id {
103 Id(fold(
104 sha2_const::Sha256::new().update(a.as_bytes()).update(b":").update(b.as_bytes()).finalize(),
105 ))
106}
107
108const fn entry_3(a: &str, b: &str, c: &str) -> Id {
109 Id(fold(
110 sha2_const::Sha256::new()
111 .update(a.as_bytes())
112 .update(b":")
113 .update(b.as_bytes())
114 .update(b":")
115 .update(c.as_bytes())
116 .finalize(),
117 ))
118}
119
120const fn entry_4(a: &str, b: &str, c: &str, d: &str) -> Id {
121 Id(fold(
122 sha2_const::Sha256::new()
123 .update(a.as_bytes())
124 .update(b":")
125 .update(b.as_bytes())
126 .update(b":")
127 .update(c.as_bytes())
128 .update(b":")
129 .update(d.as_bytes())
130 .finalize(),
131 ))
132}