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}