chess_move_gen/
castling_rights.rs1use crate::castle::*;
2use crate::side::Side;
3use std::fmt;
4
5type Internal = u8;
6
7#[derive(PartialEq, Copy, Clone)]
9pub struct CastlingRights(pub Internal);
10
11pub const WHITE_QS: CastlingRights = CastlingRights(1);
12pub const BLACK_QS: CastlingRights = CastlingRights(2);
13pub const WHITE_KS: CastlingRights = CastlingRights(4);
14pub const BLACK_KS: CastlingRights = CastlingRights(8);
15
16pub const NO_RIGHTS: CastlingRights = CastlingRights(0);
17pub const ALL_RIGHTS: CastlingRights = CastlingRights(1 | 2 | 4 | 8);
18pub const WHITE_RIGHTS: CastlingRights = CastlingRights(1 | 4);
19
20const CASTLING_RIGHTS_CHARS: [char; 4] = ['Q', 'q', 'K', 'k'];
21
22impl CastlingRights {
23 pub fn to_usize(self) -> usize {
24 self.0 as usize
25 }
26
27 pub fn has(self, right: CastlingRights) -> bool {
28 self.0 & right.0 != 0
29 }
30
31 #[allow(dead_code)]
32 pub fn add(&mut self, castle: Castle, side: Side) {
33 self.0 |= CastlingRights::from(castle, side).0
34 }
35
36 pub fn set(&mut self, rights: CastlingRights) {
37 self.0 |= rights.0;
38 }
39
40 pub fn clear_side(&mut self, side: Side) {
41 let rights = WHITE_RIGHTS.0 << side.raw();
42 self.0 &= !rights;
43 }
44
45 pub fn clear(&mut self, rights: CastlingRights) {
46 self.0 &= !rights.0;
47 }
48
49 #[allow(dead_code)]
50 pub fn side_can(self, side: Side) -> bool {
51 let rights = WHITE_RIGHTS.0 << side.raw();
52 self.0 & rights != 0
53 }
54
55 pub fn any(self) -> bool {
56 self.0 != 0
57 }
58
59 pub fn from(castle: Castle, side: Side) -> CastlingRights {
60 CastlingRights(1 << (castle.to_usize() * 2 + side.0))
61 }
62
63 pub fn parse(chr: char) -> Result<CastlingRights, String> {
64 for (i, &c) in CASTLING_RIGHTS_CHARS.iter().enumerate() {
65 if c == chr {
66 return Ok(CastlingRights(1 << i));
67 }
68 }
69 Err(format!("Invalid castle: {}", chr))
70 }
71}
72
73impl fmt::Display for CastlingRights {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 let mut string = String::new();
76
77 if !self.any() {
78 return write!(f, "-");
79 }
80
81 for (i, &c) in CASTLING_RIGHTS_CHARS.iter().enumerate() {
82 let right = CastlingRights(1 << i);
83 if self.has(right) {
84 string.push(c);
85 }
86 }
87
88 write!(f, "{}", string)
89 }
90}
91
92impl fmt::Debug for CastlingRights {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 let mut string = String::new();
95
96 if !self.any() {
97 return write!(f, "-");
98 }
99
100 for (i, &c) in CASTLING_RIGHTS_CHARS.iter().enumerate() {
101 let right = CastlingRights(1 << i);
102 if self.has(right) {
103 string.push(c);
104 }
105 }
106
107 write!(f, "{}", string)
108 }
109}
110
111#[cfg(test)]
112mod test {
113 use super::*;
114 use crate::side::*;
115
116 #[test]
117 fn can_1() {
118 let rights = WHITE_QS;
119 assert_eq!(rights.has(WHITE_QS), true);
120 assert_eq!(rights.has(BLACK_QS), false);
121 assert_eq!(rights.has(WHITE_KS), false);
122 assert_eq!(rights.has(BLACK_KS), false);
123 }
124
125 #[test]
126 fn can_2() {
127 let rights = BLACK_QS;
128 assert_eq!(rights.has(WHITE_QS), false);
129 assert_eq!(rights.has(BLACK_QS), true);
130 assert_eq!(rights.has(WHITE_KS), false);
131 assert_eq!(rights.has(BLACK_KS), false);
132 }
133
134 #[test]
135 fn can_3() {
136 let rights = WHITE_KS;
137 assert_eq!(rights.has(WHITE_QS), false);
138 assert_eq!(rights.has(BLACK_QS), false);
139 assert_eq!(rights.has(WHITE_KS), true);
140 assert_eq!(rights.has(BLACK_KS), false);
141 }
142
143 #[test]
144 fn can_4() {
145 let rights = BLACK_KS;
146 assert_eq!(rights.has(WHITE_QS), false);
147 assert_eq!(rights.has(BLACK_QS), false);
148 assert_eq!(rights.has(WHITE_KS), false);
149 assert_eq!(rights.has(BLACK_KS), true);
150 }
151
152 #[test]
153 fn can_5() {
154 let mut rights = BLACK_KS;
155 rights.add(QUEEN_SIDE, WHITE);
156 assert_eq!(rights.has(WHITE_QS), true);
157 assert_eq!(rights.has(BLACK_QS), false);
158 assert_eq!(rights.has(WHITE_KS), false);
159 assert_eq!(rights.has(BLACK_KS), true);
160 }
161
162 #[test]
163 fn can_6() {
164 assert_eq!(NO_RIGHTS.has(WHITE_QS), false);
165 assert_eq!(NO_RIGHTS.has(BLACK_QS), false);
166 assert_eq!(NO_RIGHTS.has(WHITE_KS), false);
167 assert_eq!(NO_RIGHTS.has(BLACK_KS), false);
168 }
169
170 #[test]
171 fn can_7() {
172 assert_eq!(ALL_RIGHTS.has(WHITE_QS), true);
173 assert_eq!(ALL_RIGHTS.has(BLACK_QS), true);
174 assert_eq!(ALL_RIGHTS.has(WHITE_KS), true);
175 assert_eq!(ALL_RIGHTS.has(BLACK_KS), true);
176 }
177
178 #[test]
179 fn side_can_1() {
180 let rights = BLACK_KS;
181
182 assert_eq!(rights.side_can(WHITE), false);
183 assert_eq!(rights.side_can(BLACK), true);
184 }
185
186 #[test]
187 fn side_can_2() {
188 let mut rights = WHITE_KS;
189 rights.add(QUEEN_SIDE, WHITE);
190
191 assert_eq!(rights.side_can(WHITE), true);
192 assert_eq!(rights.side_can(BLACK), false);
193
194 assert_eq!(NO_RIGHTS.side_can(WHITE), false);
195 assert_eq!(NO_RIGHTS.side_can(BLACK), false);
196
197 assert_eq!(ALL_RIGHTS.side_can(WHITE), true);
198 assert_eq!(ALL_RIGHTS.side_can(BLACK), true);
199 }
200
201 #[test]
202 fn any() {
203 assert_eq!(CastlingRights::from(KING_SIDE, WHITE).any(), true);
204 assert_eq!(NO_RIGHTS.any(), false);
205 }
206
207 #[test]
208 fn char_1() {
209 assert_eq!(WHITE_QS.to_string(), "Q");
210 }
211
212 #[test]
213 fn char_2() {
214 assert_eq!(BLACK_QS.to_string(), "q");
215 }
216
217 #[test]
218 fn char_3() {
219 assert_eq!(WHITE_KS.to_string(), "K");
220 }
221
222 #[test]
223 fn char_4() {
224 assert_eq!(BLACK_KS.to_string(), "k");
225 }
226}