tanton/core/
mono_traits.rs

1//! Traits and Dummy Types defined for various Enum types. Shouldn't be used in place
2//! of their enum representations.
3//!
4//! This modules only use is to allow for compile-time mono-morphization of
5//! functions / methods, where each method created can be optimized further.
6//!
7//! We are awaiting the stabilization of `const fn` and constant generics to remove these traits.
8
9use super::bitboard::BitBoard;
10use super::sq::SQ;
11use super::{GenTypes, PieceType, Player};
12
13/// Defines a Player Trait, allowing for specific functions in relation
14/// to a certain player.
15///
16/// These shouldn't be used in place of `Player`, as they are only used for
17/// compile-time optimizations of certain functions.
18pub trait PlayerTrait {
19    /// Return the current `Player`.
20    fn player() -> Player;
21
22    /// Return the opposing `Player`.
23    fn opp_player() -> Player;
24
25    /// Returns the index of the player
26    fn player_idx() -> usize;
27
28    /// Given a `SQ`, return a square that is down relative to the current player.
29    fn down(sq: SQ) -> SQ;
30
31    /// Given a `SQ`, return a square that is up relative to the current player.
32    fn up(sq: SQ) -> SQ;
33
34    /// Given a `SQ`, return a square that is left relative to the current player.
35    fn left(sq: SQ) -> SQ;
36
37    /// Given a `SQ`, return a square that is right relative to the current player.
38    fn right(sq: SQ) -> SQ;
39
40    /// Given a `SQ`, return a square that is down-left relative to the current player.
41    fn down_left(sq: SQ) -> SQ;
42
43    /// Given a `SQ`, return a square that is down-right relative to the current player.
44    fn down_right(sq: SQ) -> SQ;
45
46    /// Given a `SQ`, return a square that is up-right relative to the current player.
47    fn up_left(sq: SQ) -> SQ;
48
49    /// Given a `SQ`, return a square that is up-right relative to the current player.
50    fn up_right(sq: SQ) -> SQ;
51
52    /// Return the same BitBoard shifted "down" relative to the current player.
53    fn shift_down(bb: BitBoard) -> BitBoard;
54
55    /// Return the same BitBoard shifted "up" relative to the current player.
56    fn shift_up(bb: BitBoard) -> BitBoard;
57
58    /// Return the same BitBoard shifted "left" relative to the current player. Does not
59    /// include the left-most file in the result.
60    fn shift_left(bb: BitBoard) -> BitBoard;
61
62    /// Return the same BitBoard shifted "right" relative to the current player. Does not
63    /// include the left-most file in the result.
64    fn shift_right(bb: BitBoard) -> BitBoard;
65
66    /// Return the same BitBoard shifted "left" and "down" relative to the current player.
67    /// Does not include the left-most file in the result.
68    fn shift_down_left(bb: BitBoard) -> BitBoard;
69
70    /// Return the same BitBoard shifted "right" and "down" relative to the current player.
71    /// Does not include the right-most file in the result.
72    fn shift_down_right(bb: BitBoard) -> BitBoard;
73
74    /// Return the same BitBoard shifted "left" and "up" relative to the current player.
75    /// Does not include the left-most file in the result.
76    fn shift_up_left(bb: BitBoard) -> BitBoard;
77
78    /// Return the same BitBoard shifted "right" and "up" relative to the current player.
79    /// Does not include the right-most file in the result.
80    fn shift_up_right(bb: BitBoard) -> BitBoard;
81}
82
83/// Dummy type to represent a `Player::White` which implements `PlayerTrait`.
84pub struct WhiteType {}
85
86/// Dummy type to represent a `Player::Black` which implements `PlayerTrait`.
87pub struct BlackType {}
88
89impl PlayerTrait for WhiteType {
90    #[inline(always)]
91    fn player() -> Player {
92        Player::White
93    }
94    #[inline(always)]
95    fn opp_player() -> Player {
96        Player::Black
97    }
98
99    #[inline(always)]
100    fn player_idx() -> usize {
101        Player::White as usize
102    }
103
104    #[inline(always)]
105    fn down(sq: SQ) -> SQ {
106        sq - SQ(8)
107    }
108
109    #[inline(always)]
110    fn up(sq: SQ) -> SQ {
111        sq + SQ(8)
112    }
113
114    #[inline(always)]
115    fn left(sq: SQ) -> SQ {
116        sq - SQ(1)
117    }
118
119    #[inline(always)]
120    fn right(sq: SQ) -> SQ {
121        sq + SQ(1)
122    }
123
124    #[inline(always)]
125    fn down_left(sq: SQ) -> SQ {
126        sq - SQ(9)
127    }
128
129    #[inline(always)]
130    fn down_right(sq: SQ) -> SQ {
131        sq - SQ(7)
132    }
133
134    #[inline(always)]
135    fn up_left(sq: SQ) -> SQ {
136        sq + SQ(7)
137    }
138
139    #[inline(always)]
140    fn up_right(sq: SQ) -> SQ {
141        sq + SQ(9)
142    }
143
144    #[inline(always)]
145    fn shift_down(bb: BitBoard) -> BitBoard {
146        bb >> 8
147    }
148
149    #[inline(always)]
150    fn shift_up(bb: BitBoard) -> BitBoard {
151        bb << 8
152    }
153
154    #[inline(always)]
155    fn shift_left(bb: BitBoard) -> BitBoard {
156        (bb & !BitBoard::FILE_A) >> 1
157    }
158
159    #[inline(always)]
160    fn shift_right(bb: BitBoard) -> BitBoard {
161        (bb & !BitBoard::FILE_H) << 1
162    }
163
164    #[inline(always)]
165    fn shift_down_left(bb: BitBoard) -> BitBoard {
166        (bb & !BitBoard::FILE_A) >> 9
167    }
168
169    #[inline(always)]
170    fn shift_down_right(bb: BitBoard) -> BitBoard {
171        (bb & !BitBoard::FILE_H) >> 7
172    }
173
174    #[inline(always)]
175    fn shift_up_left(bb: BitBoard) -> BitBoard {
176        (bb & !BitBoard::FILE_A) << 7
177    }
178
179    #[inline(always)]
180    fn shift_up_right(bb: BitBoard) -> BitBoard {
181        (bb & !BitBoard::FILE_H) << 9
182    }
183}
184
185impl PlayerTrait for BlackType {
186    #[inline(always)]
187    fn player() -> Player {
188        Player::Black
189    }
190
191    #[inline(always)]
192    fn opp_player() -> Player {
193        Player::White
194    }
195
196    #[inline(always)]
197    fn player_idx() -> usize {
198        Player::Black as usize
199    }
200
201    #[inline(always)]
202    fn down(sq: SQ) -> SQ {
203        sq + SQ(8)
204    }
205
206    #[inline(always)]
207    fn up(sq: SQ) -> SQ {
208        sq - SQ(8)
209    }
210
211    #[inline(always)]
212    fn left(sq: SQ) -> SQ {
213        sq + SQ(1)
214    }
215
216    #[inline(always)]
217    fn right(sq: SQ) -> SQ {
218        sq - SQ(1)
219    }
220
221    #[inline(always)]
222    fn down_left(sq: SQ) -> SQ {
223        sq + SQ(9)
224    }
225
226    #[inline(always)]
227    fn down_right(sq: SQ) -> SQ {
228        sq + SQ(7)
229    }
230
231    #[inline(always)]
232    fn up_left(sq: SQ) -> SQ {
233        sq - SQ(7)
234    }
235
236    #[inline(always)]
237    fn up_right(sq: SQ) -> SQ {
238        sq - SQ(9)
239    }
240
241    #[inline(always)]
242    fn shift_down(bb: BitBoard) -> BitBoard {
243        bb << (8)
244    }
245
246    #[inline(always)]
247    fn shift_up(bb: BitBoard) -> BitBoard {
248        bb >> (8)
249    }
250
251    #[inline(always)]
252    fn shift_left(bb: BitBoard) -> BitBoard {
253        (bb & !BitBoard::FILE_H) << (1)
254    }
255
256    #[inline(always)]
257    fn shift_right(bb: BitBoard) -> BitBoard {
258        (bb & !BitBoard::FILE_A) >> (1)
259    }
260
261    #[inline(always)]
262    fn shift_down_left(bb: BitBoard) -> BitBoard {
263        (bb & !BitBoard::FILE_H) << (9)
264    }
265
266    #[inline(always)]
267    fn shift_down_right(bb: BitBoard) -> BitBoard {
268        (bb & !BitBoard::FILE_A) << (7)
269    }
270
271    #[inline(always)]
272    fn shift_up_left(bb: BitBoard) -> BitBoard {
273        (bb & !BitBoard::FILE_H) >> (7)
274    }
275
276    #[inline(always)]
277    fn shift_up_right(bb: BitBoard) -> BitBoard {
278        (bb & !BitBoard::FILE_A) >> (9)
279    }
280}
281
282/// A `GenTypeTrait` allows for specific functions in relation
283/// to a certain type of move generation.
284///
285/// Alike `PlayerTrait`, `GenTypeTrait` is only used for compile-time
286/// optimization through mono-morphism. This trait isn't intended to be used
287/// elsewhere.
288pub trait GenTypeTrait {
289    /// Returns the `GenType`.
290    fn gen_type() -> GenTypes;
291}
292
293/// Dummy type to represent a `GenTypes::All` which implements `GenTypeTrait`.
294pub struct AllGenType {}
295/// Dummy type to represent a `GenTypes::Captures` which implements `GenTypeTrait`.
296pub struct CapturesGenType {}
297/// Dummy type to represent a `GenTypes::Quiets` which implements `GenTypeTrait`.
298pub struct QuietsGenType {}
299/// Dummy type to represent a `GenTypes::QuietChecks` which implements `GenTypeTrait`.
300pub struct QuietChecksGenType {}
301/// Dummy type to represent a `GenTypes::Evasions` which implements `GenTypeTrait`.
302pub struct EvasionsGenType {}
303/// Dummy type to represent a `GenTypes::NonEvasions` which implements `GenTypeTrait`.
304pub struct NonEvasionsGenType {}
305
306impl GenTypeTrait for AllGenType {
307    #[inline(always)]
308    fn gen_type() -> GenTypes {
309        GenTypes::All
310    }
311}
312
313impl GenTypeTrait for CapturesGenType {
314    #[inline(always)]
315    fn gen_type() -> GenTypes {
316        GenTypes::Captures
317    }
318}
319
320impl GenTypeTrait for QuietsGenType {
321    #[inline(always)]
322    fn gen_type() -> GenTypes {
323        GenTypes::Quiets
324    }
325}
326
327impl GenTypeTrait for QuietChecksGenType {
328    #[inline(always)]
329    fn gen_type() -> GenTypes {
330        GenTypes::QuietChecks
331    }
332}
333
334impl GenTypeTrait for EvasionsGenType {
335    #[inline(always)]
336    fn gen_type() -> GenTypes {
337        GenTypes::Evasions
338    }
339}
340
341impl GenTypeTrait for NonEvasionsGenType {
342    #[inline(always)]
343    fn gen_type() -> GenTypes {
344        GenTypes::NonEvasions
345    }
346}
347
348/// A `PieceTrait` allows for specific functions in relation
349/// to the type of move.
350///
351/// Alike `PlayerTrait` and `GenTypeTrait`, `PieceTrait` is only used for compile-time
352/// optimization through mono-morphism. This trait isn't intended to be used
353/// elsewhere.
354pub trait PieceTrait {
355    /// Returns the `Piece` of an object.
356    fn piece_type() -> PieceType;
357}
358
359// Returns the next `PieceTrait` for the PieceTrait.
360//
361// Pawn   -> KnightType
362// Knight -> BishopType
363// Bishop -> RookType
364// Rook   -> QueenType
365// Queen  -> KingType
366// King   -> KingType
367//pub(crate) fn incr_pt<P: PieceTrait>(p: P) -> impl PieceTrait {
368//    match <P as PieceTrait>::piece_type() {
369//        PieceType::P => PawnType{},
370//        PieceType::N => KnightType{},
371//        PieceType::B => BishopType{},
372//        PieceType::R => QueenType{},
373//        PieceType::Q => KingType{},
374//        PieceType::K => KingType{},
375//    }
376//}
377
378/// Dummy type to represent a `Piece::P` which implements `PieceTrait`.
379pub struct PawnType {}
380/// Dummy type to represent a `Piece::N` which implements `PieceTrait`.
381pub struct KnightType {}
382/// Dummy type to represent a `Piece::B` which implements `PieceTrait`.
383pub struct BishopType {}
384/// Dummy type to represent a `Piece::R` which implements `PieceTrait`.
385pub struct RookType {}
386/// Dummy type to represent a `Piece::Q` which implements `PieceTrait`.
387pub struct QueenType {}
388/// Dummy type to represent a `Piece::K` which implements `PieceTrait`.
389pub struct KingType {}
390
391impl PieceTrait for PawnType {
392    #[inline(always)]
393    fn piece_type() -> PieceType {
394        PieceType::P
395    }
396}
397
398impl PawnType {
399    #[inline(always)]
400    fn incr() -> impl PieceTrait {
401        KnightType {}
402    }
403}
404
405impl PieceTrait for KnightType {
406    #[inline(always)]
407    fn piece_type() -> PieceType {
408        PieceType::N
409    }
410}
411
412impl KnightType {
413    #[inline(always)]
414    fn incr() -> impl PieceTrait {
415        BishopType {}
416    }
417}
418
419impl PieceTrait for BishopType {
420    #[inline(always)]
421    fn piece_type() -> PieceType {
422        PieceType::B
423    }
424}
425
426impl BishopType {
427    #[inline(always)]
428    fn incr() -> impl PieceTrait {
429        RookType {}
430    }
431}
432
433impl PieceTrait for RookType {
434    #[inline(always)]
435    fn piece_type() -> PieceType {
436        PieceType::R
437    }
438}
439
440impl RookType {
441    #[inline(always)]
442    fn incr() -> impl PieceTrait {
443        QueenType {}
444    }
445}
446
447impl PieceTrait for QueenType {
448    #[inline(always)]
449    fn piece_type() -> PieceType {
450        PieceType::Q
451    }
452}
453
454impl QueenType {
455    #[inline(always)]
456    fn incr() -> impl PieceTrait {
457        KingType {}
458    }
459}
460
461impl PieceTrait for KingType {
462    #[inline(always)]
463    fn piece_type() -> PieceType {
464        PieceType::K
465    }
466}
467
468impl KingType {
469    #[inline(always)]
470    fn incr() -> impl PieceTrait {
471        KingType {}
472    }
473}