hokmah_uci/
square.rs

1#![allow(dead_code)]
2
3#[derive(Clone, Copy)]
4pub struct Square(pub u8);
5
6pub const A1: &Square = &Square(0);
7pub const B1: &Square = &Square(1);
8pub const C1: &Square = &Square(2);
9pub const D1: &Square = &Square(3);
10pub const E1: &Square = &Square(4);
11pub const F1: &Square = &Square(5);
12pub const G1: &Square = &Square(6);
13pub const H1: &Square = &Square(7);
14pub const A2: &Square = &Square(8);
15pub const B2: &Square = &Square(9);
16pub const C2: &Square = &Square(10);
17pub const D2: &Square = &Square(11);
18pub const E2: &Square = &Square(12);
19pub const F2: &Square = &Square(13);
20pub const G2: &Square = &Square(14);
21pub const H2: &Square = &Square(15);
22pub const A3: &Square = &Square(16);
23pub const B3: &Square = &Square(17);
24pub const C3: &Square = &Square(18);
25pub const D3: &Square = &Square(19);
26pub const E3: &Square = &Square(20);
27pub const F3: &Square = &Square(21);
28pub const G3: &Square = &Square(22);
29pub const H3: &Square = &Square(23);
30pub const A4: &Square = &Square(24);
31pub const B4: &Square = &Square(25);
32pub const C4: &Square = &Square(26);
33pub const D4: &Square = &Square(27);
34pub const E4: &Square = &Square(28);
35pub const F4: &Square = &Square(29);
36pub const G4: &Square = &Square(30);
37pub const H4: &Square = &Square(31);
38pub const A5: &Square = &Square(32);
39pub const B5: &Square = &Square(33);
40pub const C5: &Square = &Square(34);
41pub const D5: &Square = &Square(35);
42pub const E5: &Square = &Square(36);
43pub const F5: &Square = &Square(37);
44pub const G5: &Square = &Square(38);
45pub const H5: &Square = &Square(39);
46pub const A6: &Square = &Square(40);
47pub const B6: &Square = &Square(41);
48pub const C6: &Square = &Square(42);
49pub const D6: &Square = &Square(43);
50pub const E6: &Square = &Square(44);
51pub const F6: &Square = &Square(45);
52pub const G6: &Square = &Square(46);
53pub const H6: &Square = &Square(47);
54pub const A7: &Square = &Square(48);
55pub const B7: &Square = &Square(49);
56pub const C7: &Square = &Square(50);
57pub const D7: &Square = &Square(51);
58pub const E7: &Square = &Square(52);
59pub const F7: &Square = &Square(53);
60pub const G7: &Square = &Square(54);
61pub const H7: &Square = &Square(55);
62pub const A8: &Square = &Square(56);
63pub const B8: &Square = &Square(57);
64pub const C8: &Square = &Square(58);
65pub const D8: &Square = &Square(59);
66pub const E8: &Square = &Square(60);
67pub const F8: &Square = &Square(61);
68pub const G8: &Square = &Square(62);
69pub const H8: &Square = &Square(63);
70
71#[derive(Debug)]
72pub struct InputError;
73
74impl std::fmt::Display for InputError {
75    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76        write!(f, "invalid square")
77    }
78}
79
80impl Square {
81    pub fn from_string(s: &str) -> Result<Self, InputError> {
82        if s.len() == 2 {
83            let (file, rank) = s.split_at(1);
84            let sq: u8 = match file {
85                "a" => 0,
86                "b" => 1,
87                "c" => 2,
88                "d" => 3,
89                "e" => 4,
90                "f" => 5,
91                "g" => 6,
92                "h" => 7,
93                _ => return Err(InputError),
94            } + match rank {
95                "1" => 0,
96                "2" => 8,
97                "3" => 16,
98                "4" => 24,
99                "5" => 32,
100                "6" => 40,
101                "7" => 48,
102                "8" => 56,
103                _ => return Err(InputError),
104            };
105            Ok(Self(sq))
106        } else {
107            Err(InputError)
108        }
109    }
110
111    pub fn from_bitboard(bitboard: u64) -> Self {
112        for i in 0..64u8 {
113            let sq = Square(i);
114            if sq.test(bitboard) {
115                return sq
116            }
117        }
118        panic!("bitboard empty {}", bitboard);
119    }
120
121    pub fn rank(&self) -> u8 {
122        return self.0 / 8
123    }
124
125    pub fn file(&self) -> u8 {
126        return self.0 % 8
127    }
128
129    pub fn north(&self, cnt: u8) -> Option<Self> {
130        if cnt > 7 {
131            return None
132        }
133        if self.rank() > (7 - cnt) {
134            None
135        } else {
136            Some(Self(self.0 + 8 * cnt))
137        }
138    }
139
140    pub fn east(&self, cnt: u8) -> Option<Self> {
141        if cnt > 7 {
142            return None
143        }
144        if self.file() > (7 - cnt) {
145            None
146        } else {
147            Some(Self(self.0 + cnt))
148        }
149    }
150
151    pub fn west(&self, cnt: u8) -> Option<Self> {
152        if cnt > 7 {
153            return None
154        }
155        if self.file() < cnt {
156            None
157        } else {
158            Some(Self(self.0 - cnt))
159        }
160    }
161
162    pub fn south(&self, cnt: u8) -> Option<Self> {
163        if cnt > 7 {
164            return None
165        }
166        if self.rank() < cnt {
167            None
168        } else {
169            Some(Self(self.0 - 8 * cnt))
170        }
171    }
172
173    pub fn north_east(&self, cnt: u8) -> Option<Self> {
174        self.north(cnt)?.east(cnt)
175    }
176
177    pub fn north_west(&self, cnt: u8) -> Option<Self> {
178        self.north(cnt)?.west(cnt)
179    }
180
181    pub fn south_east(&self, cnt: u8) -> Option<Self> {
182        self.south(cnt)?.east(cnt)
183    }
184
185    pub fn south_west(&self, cnt: u8) -> Option<Self> {
186        self.south(cnt)?.west(cnt)
187    }
188
189    pub fn test(&self, bitboard: u64) -> bool {
190        bitboard & self.tester() > 0
191    }
192
193    pub fn tester(&self) -> u64 {
194        1 << (63 - self.0)
195    }
196}
197
198impl std::fmt::Display for Square {
199    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
200        let file = match self.file() {
201            0 => "a",
202            1 => "b",
203            2 => "c",
204            3 => "d",
205            4 => "e",
206            5 => "f",
207            6 => "g",
208            _ => "h",
209        };
210        let rank = self.rank() + 1;
211        write!(f, "{}{}", file, rank)
212    }
213}
214
215impl PartialEq for Square {
216    fn eq(&self, other: &Self) -> bool {
217        self.0 == other.0
218    }
219}
220
221#[cfg(test)]
222mod tests {
223    use crate::square::*;
224
225    #[test]
226    fn it_parses_e4() {
227        let sq = Square::from_string("e4").unwrap();
228        assert_eq!(sq.0, E4.0);
229    }
230}