Skip to main content

giga_chess/engine/
attack_table.rs

1use crate::engine::magic_numbers::magic_hash;
2use crate::game::bit_board::BitBoard;
3use crate::game::color::Color;
4use crate::game::square::Square;
5
6const BISHOP_MAGICS: [u64; 64] = [
7    0x0106004105020080,
8    0x0010002A00081020,
9    0x2800208400404020,
10    0x0148400441014000,
11    0x0420221208840110,
12    0x02204C204103B408,
13    0x1080540200600884,
14    0x8501021404100400,
15    0x0025228110004010,
16    0x0200D48002044048,
17    0x0004004200810004,
18    0x8042088040800008,
19    0x0010040020000000,
20    0x0000428244208800,
21    0x0080222404000811,
22    0x80082011A0100068,
23    0x0120000982004208,
24    0x0246A60100400CD0,
25    0x2411400A01020008,
26    0x04804802000B0000,
27    0x0000080080844000,
28    0x00811220010C0202,
29    0x002200080C010811,
30    0x0000004022081A00,
31    0x0800044841803050,
32    0x200402088400800B,
33    0x4002020801800126,
34    0x0200081000820500,
35    0x40028C000820D022,
36    0x00A2500418407800,
37    0x0000114000080110,
38    0x040901C002043004,
39    0x8026118400001490,
40    0x11A1100080021004,
41    0x00020042C2004010,
42    0x8204300800440501,
43    0x18040AC004018080,
44    0x6182801310025200,
45    0x000021004880900C,
46    0x1010210007120010,
47    0xA405840101005800,
48    0x2950118025200442,
49    0x000684E218000020,
50    0x0004502020010022,
51    0x0041AC001308040C,
52    0x000103080A000824,
53    0x0020100200800520,
54    0x2008804446040802,
55    0x0011219800088001,
56    0x0000408010814088,
57    0x08830B4040202040,
58    0x0004325080400401,
59    0x0000100020240008,
60    0x0000019200250000,
61    0x0604078200881040,
62    0x4028180444120000,
63    0x8000010128088C70,
64    0x0360004004811050,
65    0x00B5280044100C04,
66    0x00020010020C2001,
67    0x0100200128010819,
68    0x4803120C41100090,
69    0x0042004192008008,
70    0x0006861020210069,
71];
72
73const ROOK_MAGICS: [u64; 64] = [
74    0x0080002040001084,
75    0x00092030804082C0,
76    0x0020040008202002,
77    0x0020040820200200,
78    0x0100100408400A23,
79    0x0020088C00030200,
80    0x4288008003000200,
81    0x0080012100044080,
82    0x1090280040008000,
83    0x0500060840242004,
84    0x14004A0220002800,
85    0x2100A00204401000,
86    0x0211201101200426,
87    0x40008022800CDC00,
88    0x4204015002088401,
89    0x0065000100012E42,
90    0x0080100804004140,
91    0x2860040804008022,
92    0x0A20300450061100,
93    0x0002002080140420,
94    0x1210282802010514,
95    0x1220048000C10142,
96    0x0020202002508A00,
97    0x0C42208021904101,
98    0x1080400080056082,
99    0x0188000804210108,
100    0x0010200040040801,
101    0x86000A0C10003912,
102    0x0000011120040A08,
103    0x0000009A02005280,
104    0x1000040488080940,
105    0x4000041002006008,
106    0x0008001048022424,
107    0x0000A60426004000,
108    0x00A8600808010260,
109    0x2090015080080300,
110    0x0004020100080C60,
111    0x002004022D004010,
112    0x8003000100400082,
113    0x0A00100020100940,
114    0x000400C006100800,
115    0x001AA00422122560,
116    0x602020104C015000,
117    0x0844180802001000,
118    0x1044BC0100202002,
119    0x0C01280402810002,
120    0xC284011031D04200,
121    0x1210110143200406,
122    0x1209012580413100,
123    0x8780300104201004,
124    0xAA002806020E0008,
125    0x0001900080023002,
126    0x0808050018002424,
127    0x0001042401088020,
128    0x0040020030E30080,
129    0x000001140880A200,
130    0x000107A040800015,
131    0x0040800820110043,
132    0x001028800A00C222,
133    0x0002000410480802,
134    0x0148704800040213,
135    0x1800040100008801,
136    0x0064063008058114,
137    0x18400034840101C2,
138];
139
140#[derive(Debug)]
141pub struct AttackTable {
142    pawn_masks: [[BitBoard; 64]; 2],
143    pawn_attacks: [[BitBoard; 64]; 2],
144    knight_attacks: [BitBoard; 64],
145    king_attacks: [BitBoard; 64],
146    bishop_masks: [BitBoard; 64],
147    rook_masks: [BitBoard; 64],
148    bishop_blocks: [BitBoard; 64],
149    rook_blocks: [BitBoard; 64],
150    bishop_attacks: Vec<Vec<BitBoard>>,
151    rook_attacks: Vec<Vec<BitBoard>>,
152}
153
154impl Default for AttackTable {
155    fn default() -> Self {
156        Self::build()
157    }
158}
159
160impl AttackTable {
161    pub fn build() -> Self {
162        Self {
163            pawn_masks: build_pawn_masks(),
164            pawn_attacks: build_pawn_attacks(),
165            knight_attacks: build_knight_attacks(),
166            king_attacks: build_king_attacks(),
167            bishop_masks: build_bishop_masks(),
168            rook_masks: build_rook_masks(),
169            bishop_blocks: build_bishop_blocks(),
170            rook_blocks: build_rook_blocks(),
171            bishop_attacks: build_bishop_attacks(),
172            rook_attacks: build_rook_attacks(),
173        }
174    }
175
176    pub fn get_pawn_mask(&self, square: u8, color: Color) -> BitBoard {
177        self.pawn_masks[color as usize][square as usize]
178    }
179
180    pub fn get_pawn_attacks(&self, square: u8, color: Color) -> BitBoard {
181        self.pawn_attacks[color as usize][square as usize]
182    }
183
184    pub fn get_pawn_king_attack(&self, square: u8, color: Color) -> BitBoard {
185        self.pawn_attacks[color.opposite() as usize][square as usize]
186    }
187
188    pub fn get_knight_attacks(&self, square: u8) -> BitBoard {
189        self.knight_attacks[square as usize]
190    }
191
192    pub fn get_king_attacks(&self, square: u8) -> BitBoard {
193        self.king_attacks[square as usize]
194    }
195
196    pub fn get_bishop_mask(&self, square: u8) -> BitBoard {
197        self.bishop_masks[square as usize]
198    }
199
200    pub fn get_rook_mask(&self, square: u8) -> BitBoard {
201        self.rook_masks[square as usize]
202    }
203
204    pub fn get_queen_mask(&self, square: u8) -> BitBoard {
205        self.get_bishop_mask(square) | self.get_rook_mask(square)
206    }
207
208    pub fn get_bishop_blocks(&self, square: u8) -> BitBoard {
209        self.bishop_blocks[square as usize]
210    }
211
212    pub fn get_rook_blocks(&self, square: u8) -> BitBoard {
213        self.rook_blocks[square as usize]
214    }
215
216    pub fn get_queen_blocks(&self, square: u8) -> BitBoard {
217        self.get_bishop_blocks(square) | self.get_rook_blocks(square)
218    }
219
220    pub fn get_bishop_attacks(&self, square: u8, occupancy: BitBoard) -> BitBoard {
221        let block_mask = self.get_bishop_blocks(square);
222        let occupied_blocking_mask = occupancy & block_mask;
223        let key = magic_hash(BISHOP_MAGICS[square as usize], occupied_blocking_mask);
224        self.bishop_attacks[square as usize][key]
225    }
226
227    pub fn get_rook_attacks(&self, square: u8, occupancy: BitBoard) -> BitBoard {
228        let block_mask = self.get_rook_blocks(square);
229        let occupied_blocking_mask = occupancy & block_mask;
230        let key = magic_hash(ROOK_MAGICS[square as usize], occupied_blocking_mask);
231        self.rook_attacks[square as usize][key]
232    }
233
234    pub fn get_queen_attacks(&self, square: u8, occupancy: BitBoard) -> BitBoard {
235        self.get_bishop_attacks(square, occupancy) | self.get_rook_attacks(square, occupancy)
236    }
237}
238
239pub fn build_pawn_masks() -> [[BitBoard; 64]; 2] {
240    let mut table = [[BitBoard::empty(); 64]; 2];
241
242    for index in 0usize..64 {
243        let square = Square::new(index as u8);
244
245        let mut white_mask = 0u64;
246        if let Some(index) = square.index_up() {
247            white_mask |= 1 << index;
248        }
249        table[Color::White as usize][index] = BitBoard::new(white_mask);
250
251        let mut black_mask = 0u64;
252        if let Some(index) = square.index_down() {
253            black_mask |= 1 << index;
254        }
255        table[Color::Black as usize][index] = BitBoard::new(black_mask);
256    }
257
258    table
259}
260
261pub fn build_pawn_attacks() -> [[BitBoard; 64]; 2] {
262    let mut table = [[BitBoard::empty(); 64]; 2];
263
264    for index in 0usize..64 {
265        let square = Square::new(index as u8);
266
267        let mut white_attacks = 0u64;
268        if let Some(index) = square.index_up_left() {
269            white_attacks |= 1 << index;
270        }
271        if let Some(index) = square.index_up_right() {
272            white_attacks |= 1 << index;
273        }
274        table[Color::White as usize][index] = BitBoard::new(white_attacks);
275
276        let mut black_attacks = 0u64;
277        if let Some(index) = square.index_down_left() {
278            black_attacks |= 1 << index;
279        }
280        if let Some(index) = square.index_down_right() {
281            black_attacks |= 1 << index;
282        }
283        table[Color::Black as usize][index] = BitBoard::new(black_attacks);
284    }
285
286    table
287}
288
289pub fn build_knight_attacks() -> [BitBoard; 64] {
290    let mut table = [BitBoard::empty(); 64];
291
292    for (index, bb) in table.iter_mut().enumerate() {
293        let square = Square::new(index as u8);
294
295        let mut attacks = 0u64;
296        if let Some(index) = square.index_jump(1, 2) {
297            attacks |= 1 << index;
298        }
299        if let Some(index) = square.index_jump(2, 1) {
300            attacks |= 1 << index;
301        }
302        if let Some(index) = square.index_jump(2, -1) {
303            attacks |= 1 << index;
304        }
305        if let Some(index) = square.index_jump(1, -2) {
306            attacks |= 1 << index;
307        }
308        if let Some(index) = square.index_jump(-1, -2) {
309            attacks |= 1 << index;
310        }
311        if let Some(index) = square.index_jump(-2, -1) {
312            attacks |= 1 << index;
313        }
314        if let Some(index) = square.index_jump(-2, 1) {
315            attacks |= 1 << index;
316        }
317        if let Some(index) = square.index_jump(-1, 2) {
318            attacks |= 1 << index;
319        }
320
321        *bb = BitBoard::new(attacks);
322    }
323
324    table
325}
326
327pub fn build_king_attacks() -> [BitBoard; 64] {
328    let mut table = [BitBoard::empty(); 64];
329
330    for (index, bb) in table.iter_mut().enumerate() {
331        let square = Square::new(index as u8);
332
333        let mut attacks = 0u64;
334        if let Some(index) = square.index_up() {
335            attacks |= 1 << index;
336        }
337        if let Some(index) = square.index_down() {
338            attacks |= 1 << index;
339        }
340        if let Some(index) = square.index_left() {
341            attacks |= 1 << index;
342        }
343        if let Some(index) = square.index_right() {
344            attacks |= 1 << index;
345        }
346        if let Some(index) = square.index_up_left() {
347            attacks |= 1 << index;
348        }
349        if let Some(index) = square.index_up_right() {
350            attacks |= 1 << index;
351        }
352        if let Some(index) = square.index_down_left() {
353            attacks |= 1 << index;
354        }
355        if let Some(index) = square.index_down_right() {
356            attacks |= 1 << index;
357        }
358
359        *bb = BitBoard::new(attacks);
360    }
361
362    table
363}
364
365pub fn build_bishop_masks() -> [BitBoard; 64] {
366    let mut table = [BitBoard::empty(); 64];
367
368    for (index, bb) in table.iter_mut().enumerate() {
369        let square = Square::new(index as u8);
370
371        let mut mask = 0u64;
372        for index in square.trace_up_left() {
373            mask |= 1 << index;
374        }
375        for index in square.trace_up_right() {
376            mask |= 1 << index;
377        }
378        for index in square.trace_down_left() {
379            mask |= 1 << index;
380        }
381        for index in square.trace_down_right() {
382            mask |= 1 << index;
383        }
384
385        *bb = BitBoard::new(mask);
386    }
387
388    table
389}
390
391pub fn build_rook_masks() -> [BitBoard; 64] {
392    let mut table = [BitBoard::empty(); 64];
393
394    for (index, bb) in table.iter_mut().enumerate() {
395        let square = Square::new(index as u8);
396
397        let mut mask = 0u64;
398        for index in square.trace_up() {
399            mask |= 1 << index;
400        }
401        for index in square.trace_down() {
402            mask |= 1 << index;
403        }
404        for index in square.trace_left() {
405            mask |= 1 << index;
406        }
407        for index in square.trace_right() {
408            mask |= 1 << index;
409        }
410
411        *bb = BitBoard::new(mask);
412    }
413
414    table
415}
416
417pub fn build_bishop_blocks() -> [BitBoard; 64] {
418    let mut table = [BitBoard::empty(); 64];
419
420    for (index, bb) in table.iter_mut().enumerate() {
421        let square = Square::new(index as u8);
422
423        let mut mask = 0u64;
424
425        let up_left: Vec<u8> = square.trace_up_left().collect();
426        for &index in &up_left[..up_left.len().saturating_sub(1)] {
427            mask |= 1 << index;
428        }
429
430        let up_right: Vec<u8> = square.trace_up_right().collect();
431        for &index in &up_right[..up_right.len().saturating_sub(1)] {
432            mask |= 1 << index;
433        }
434
435        let down_left: Vec<u8> = square.trace_down_left().collect();
436        for &index in &down_left[..down_left.len().saturating_sub(1)] {
437            mask |= 1 << index;
438        }
439
440        let down_right: Vec<u8> = square.trace_down_right().collect();
441        for &index in &down_right[..down_right.len().saturating_sub(1)] {
442            mask |= 1 << index;
443        }
444
445        *bb = BitBoard::new(mask);
446    }
447
448    table
449}
450
451pub fn build_rook_blocks() -> [BitBoard; 64] {
452    let mut table = [BitBoard::empty(); 64];
453
454    for (index, bb) in table.iter_mut().enumerate() {
455        let square = Square::new(index as u8);
456
457        let mut mask = 0u64;
458
459        let up: Vec<u8> = square.trace_up().collect();
460        for &index in &up[..up.len().saturating_sub(1)] {
461            mask |= 1 << index;
462        }
463
464        let down: Vec<u8> = square.trace_down().collect();
465        for &index in &down[..down.len().saturating_sub(1)] {
466            mask |= 1 << index;
467        }
468
469        let left: Vec<u8> = square.trace_left().collect();
470        for &index in &left[..left.len().saturating_sub(1)] {
471            mask |= 1 << index;
472        }
473
474        let right: Vec<u8> = square.trace_right().collect();
475        for &index in &right[..right.len().saturating_sub(1)] {
476            mask |= 1 << index;
477        }
478
479        *bb = BitBoard::new(mask);
480    }
481
482    table
483}
484
485pub fn calculate_bishop_attack(square: u8, occupancy: BitBoard) -> BitBoard {
486    let mut result = BitBoard::empty();
487    let square = Square::new(square);
488
489    for index in square.trace_up_left() {
490        result.set_bit(index);
491        if occupancy.get_bit(index) {
492            break;
493        }
494    }
495
496    for index in square.trace_up_right() {
497        result.set_bit(index);
498        if occupancy.get_bit(index) {
499            break;
500        }
501    }
502
503    for index in square.trace_down_left() {
504        result.set_bit(index);
505        if occupancy.get_bit(index) {
506            break;
507        }
508    }
509
510    for index in square.trace_down_right() {
511        result.set_bit(index);
512        if occupancy.get_bit(index) {
513            break;
514        }
515    }
516
517    result
518}
519
520pub fn calculate_rook_attack(square: u8, occupancy: BitBoard) -> BitBoard {
521    let mut result = BitBoard::empty();
522    let square = Square::new(square);
523
524    for index in square.trace_up() {
525        result.set_bit(index);
526        if occupancy.get_bit(index) {
527            break;
528        }
529    }
530
531    for index in square.trace_down() {
532        result.set_bit(index);
533        if occupancy.get_bit(index) {
534            break;
535        }
536    }
537
538    for index in square.trace_left() {
539        result.set_bit(index);
540        if occupancy.get_bit(index) {
541            break;
542        }
543    }
544
545    for index in square.trace_right() {
546        result.set_bit(index);
547        if occupancy.get_bit(index) {
548            break;
549        }
550    }
551
552    result
553}
554
555pub fn build_occupancy_variations(block_mask: BitBoard) -> Vec<BitBoard> {
556    let occupancy_count = 1usize << block_mask.count_set_bits();
557    (0..occupancy_count)
558        .map(|index| block_mask.occupancy_variation(index as u16))
559        .collect()
560}
561
562pub fn build_bishop_attacks() -> Vec<Vec<BitBoard>> {
563    let mut table = Vec::new();
564    let block_masks = build_bishop_blocks();
565
566    for square in 0..64 {
567        let magic = BISHOP_MAGICS[square];
568        let block_mask = block_masks[square];
569        let occupancies = build_occupancy_variations(block_mask);
570        let attacks: Vec<BitBoard> = occupancies
571            .iter()
572            .map(|occupancy| calculate_bishop_attack(square as u8, *occupancy))
573            .collect();
574
575        let mut square_table = vec![BitBoard::empty(); 4096];
576        for i in 0usize..occupancies.len() {
577            let key = magic_hash(magic, occupancies[i]);
578            square_table[key] = attacks[i];
579        }
580        table.push(square_table);
581    }
582
583    table
584}
585
586pub fn build_rook_attacks() -> Vec<Vec<BitBoard>> {
587    let mut table = Vec::new();
588    let block_masks = build_rook_blocks();
589
590    for square in 0..64 {
591        let magic = ROOK_MAGICS[square];
592        let block_mask = block_masks[square];
593        let occupancies = build_occupancy_variations(block_mask);
594        let attacks: Vec<BitBoard> = occupancies
595            .iter()
596            .map(|occupancy| calculate_rook_attack(square as u8, *occupancy))
597            .collect();
598
599        let mut square_table = vec![BitBoard::empty(); 4096];
600        for i in 0usize..occupancies.len() {
601            let key = magic_hash(magic, occupancies[i]);
602            square_table[key] = attacks[i];
603        }
604        table.push(square_table);
605    }
606
607    table
608}
609
610#[cfg(test)]
611mod tests {
612    use super::AttackTable;
613    use crate::game::bit_board::BitBoard;
614    use crate::game::color::Color;
615
616    #[test]
617    fn test_pawn_attack() {
618        let table = AttackTable::build();
619
620        let mut attacks_white = table.get_pawn_attacks(9, Color::White);
621        assert_eq!(attacks_white.pop_lowest_set_bit(), Some(16));
622        assert_eq!(attacks_white.pop_lowest_set_bit(), Some(18));
623        assert!(attacks_white.is_empty());
624
625        let mut attacks_black = table.get_pawn_attacks(9, Color::Black);
626        assert_eq!(attacks_black.pop_lowest_set_bit(), Some(0));
627        assert_eq!(attacks_black.pop_lowest_set_bit(), Some(2));
628        assert!(attacks_black.is_empty());
629    }
630
631    #[test]
632    fn test_knight_attack() {
633        let table = AttackTable::build();
634
635        let mut knight_attacks1 = table.get_knight_attacks(53);
636        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(36));
637        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(38));
638        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(43));
639        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(47));
640        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(59));
641        assert_eq!(knight_attacks1.pop_lowest_set_bit(), Some(63));
642        assert!(knight_attacks1.is_empty());
643
644        let mut knight_attacks2 = table.get_knight_attacks(56);
645        assert_eq!(knight_attacks2.pop_lowest_set_bit(), Some(41));
646        assert_eq!(knight_attacks2.pop_lowest_set_bit(), Some(50));
647        assert!(knight_attacks2.is_empty());
648
649        let mut knight_attacks3 = table.get_knight_attacks(35);
650        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(18));
651        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(20));
652        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(25));
653        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(29));
654        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(41));
655        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(45));
656        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(50));
657        assert_eq!(knight_attacks3.pop_lowest_set_bit(), Some(52));
658        assert!(knight_attacks1.is_empty());
659    }
660
661    #[test]
662    fn test_king_attack() {
663        let table = AttackTable::build();
664
665        let mut king_attacks1 = table.get_king_attacks(56);
666        assert_eq!(king_attacks1.pop_lowest_set_bit(), Some(48));
667        assert_eq!(king_attacks1.pop_lowest_set_bit(), Some(49));
668        assert_eq!(king_attacks1.pop_lowest_set_bit(), Some(57));
669        assert!(king_attacks1.is_empty());
670
671        let mut king_attacks2 = table.get_king_attacks(18);
672        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(9));
673        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(10));
674        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(11));
675        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(17));
676        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(19));
677        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(25));
678        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(26));
679        assert_eq!(king_attacks2.pop_lowest_set_bit(), Some(27));
680        assert!(king_attacks2.is_empty());
681    }
682
683    #[test]
684    fn test_bishop_mask() {
685        let table = AttackTable::build();
686
687        let mut bishop_moves = table.get_bishop_mask(27);
688        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(0));
689        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(6));
690        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(9));
691        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(13));
692        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(18));
693        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(20));
694        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(34));
695        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(36));
696        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(41));
697        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(45));
698        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(48));
699        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(54));
700        assert_eq!(bishop_moves.pop_lowest_set_bit(), Some(63));
701        assert!(bishop_moves.is_empty());
702    }
703
704    #[test]
705    fn test_rook_mask() {
706        let table = AttackTable::build();
707
708        let mut rook_moves = table.get_rook_mask(27);
709        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(3));
710        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(11));
711        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(19));
712        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(24));
713        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(25));
714        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(26));
715        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(28));
716        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(29));
717        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(30));
718        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(31));
719        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(35));
720        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(43));
721        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(51));
722        assert_eq!(rook_moves.pop_lowest_set_bit(), Some(59));
723        assert!(rook_moves.is_empty());
724    }
725
726    #[test]
727    fn test_queen_mask() {
728        let table = AttackTable::build();
729
730        let mut queen_moves = table.get_queen_mask(42);
731        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(2));
732        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(7));
733        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(10));
734        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(14));
735        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(18));
736        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(21));
737        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(24));
738        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(26));
739        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(28));
740        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(33));
741        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(34));
742        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(35));
743        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(40));
744        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(41));
745        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(43));
746        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(44));
747        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(45));
748        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(46));
749        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(47));
750        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(49));
751        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(50));
752        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(51));
753        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(56));
754        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(58));
755        assert_eq!(queen_moves.pop_lowest_set_bit(), Some(60));
756        assert!(queen_moves.is_empty());
757    }
758
759    #[test]
760    fn test_bishop_blocks() {
761        let table = AttackTable::build();
762
763        let mut bishop_blocks = table.get_bishop_blocks(27);
764        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(9));
765        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(13));
766        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(18));
767        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(20));
768        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(34));
769        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(36));
770        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(41));
771        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(45));
772        assert_eq!(bishop_blocks.pop_lowest_set_bit(), Some(54));
773        assert!(bishop_blocks.is_empty());
774    }
775
776    #[test]
777    fn test_rook_blocks() {
778        let table = AttackTable::build();
779
780        let mut rook_blocks = table.get_rook_blocks(27);
781        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(11));
782        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(19));
783        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(25));
784        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(26));
785        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(28));
786        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(29));
787        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(30));
788        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(35));
789        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(43));
790        assert_eq!(rook_blocks.pop_lowest_set_bit(), Some(51));
791        assert!(rook_blocks.is_empty());
792    }
793
794    #[test]
795    fn test_queen_blocks() {
796        let table = AttackTable::build();
797
798        let mut queen_blocks = table.get_queen_blocks(42);
799        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(10));
800        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(14));
801        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(18));
802        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(21));
803        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(26));
804        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(28));
805        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(33));
806        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(34));
807        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(35));
808        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(41));
809        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(43));
810        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(44));
811        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(45));
812        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(46));
813        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(49));
814        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(50));
815        assert_eq!(queen_blocks.pop_lowest_set_bit(), Some(51));
816        assert!(queen_blocks.is_empty());
817    }
818
819    #[test]
820    fn test_bishop_attacks() {
821        let table = AttackTable::build();
822
823        let mut occupancy1 = BitBoard::empty();
824        occupancy1.set_bit(5);
825        occupancy1.set_bit(9);
826        occupancy1.set_bit(11);
827        occupancy1.set_bit(18);
828        occupancy1.set_bit(25);
829        occupancy1.set_bit(34);
830        occupancy1.set_bit(45);
831
832        let mut bishop_attacks1 = table.get_bishop_attacks(18, occupancy1);
833        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(9));
834        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(11));
835        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(25));
836        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(27));
837        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(36));
838        assert_eq!(bishop_attacks1.pop_lowest_set_bit(), Some(45));
839        assert!(bishop_attacks1.is_empty());
840
841        let mut occupancy2 = BitBoard::empty();
842        occupancy2.set_bit(49);
843        occupancy2.set_bit(56);
844
845        let mut bishop_attacks2 = table.get_bishop_attacks(56, occupancy2);
846        assert_eq!(bishop_attacks2.pop_lowest_set_bit(), Some(49));
847        assert!(bishop_attacks2.is_empty());
848    }
849
850    #[test]
851    fn test_rook_attacks() {
852        let table = AttackTable::build();
853
854        let mut occupancy1 = BitBoard::empty();
855        occupancy1.set_bit(10);
856        occupancy1.set_bit(20);
857        occupancy1.set_bit(32);
858        occupancy1.set_bit(34);
859        occupancy1.set_bit(38);
860        occupancy1.set_bit(42);
861        occupancy1.set_bit(53);
862
863        let mut rook_attacks1 = table.get_rook_attacks(34, occupancy1);
864        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(10));
865        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(18));
866        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(26));
867        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(32));
868        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(33));
869        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(35));
870        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(36));
871        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(37));
872        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(38));
873        assert_eq!(rook_attacks1.pop_lowest_set_bit(), Some(42));
874        assert!(rook_attacks1.is_empty());
875
876        let mut occupancy2 = BitBoard::empty();
877        occupancy2.set_bit(48);
878        occupancy2.set_bit(56);
879        occupancy2.set_bit(57);
880
881        let mut rook_attacks2 = table.get_rook_attacks(56, occupancy2);
882        assert_eq!(rook_attacks2.pop_lowest_set_bit(), Some(48));
883        assert_eq!(rook_attacks2.pop_lowest_set_bit(), Some(57));
884        assert!(rook_attacks2.is_empty());
885    }
886
887    #[test]
888    fn test_queen_attacks() {
889        let table = AttackTable::build();
890
891        let mut occupancy = BitBoard::empty();
892        occupancy.set_bit(6);
893        occupancy.set_bit(9);
894        occupancy.set_bit(20);
895        occupancy.set_bit(22);
896        occupancy.set_bit(26);
897        occupancy.set_bit(35);
898        occupancy.set_bit(36);
899        occupancy.set_bit(39);
900        occupancy.set_bit(41);
901        occupancy.set_bit(45);
902        occupancy.set_bit(50);
903        occupancy.set_bit(52);
904
905        let mut queen_attacks = table.get_queen_attacks(36, occupancy);
906        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(9));
907        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(18));
908        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(20));
909        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(22));
910        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(27));
911        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(28));
912        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(29));
913        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(35));
914        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(37));
915        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(38));
916        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(39));
917        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(43));
918        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(44));
919        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(45));
920        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(50));
921        assert_eq!(queen_attacks.pop_lowest_set_bit(), Some(52));
922        assert!(queen_attacks.is_empty());
923    }
924}