1use crate::{
2 Player::{self, *},
3 Square,
4 position::EnPassant,
5 square::Rank::{Six, Three},
6};
7
8use super::{Bitboard, Board};
9
10impl Board {
12 pub const fn attacks_on(
22 self,
23 square: Square,
24 attacker: Player,
25 occupied: Bitboard,
26 ) -> Bitboard {
27 let straight = square.rook_sight(occupied).intersection(self.rooks_and_queens());
30 let diagonal = square.bishop_sight(occupied).intersection(self.bishops_and_queens());
31 let knights = square.knight_moves().intersection(self.knights());
32 let kings = square.king_moves().intersection(self.kings());
33
34 let pawns = square.pawn_attack_moves(attacker.other()).intersection(self.pawns());
37
38 let attacks = straight.union(diagonal).union(knights).union(kings).union(pawns);
39
40 self.player(attacker).intersection(occupied).intersection(attacks)
43 }
44
45 #[inline]
46 pub const fn attacked_en_passant(
47 self,
48 en_passant: EnPassant,
49 turn: Player,
50 ) -> Option<EnPassant> {
51 let to = en_passant.square();
52 let pawns = self.pawns().intersection(self.player(turn));
53 if pawns.intersection(to.pawn_attack_moves(turn.other())).is_empty() {
54 None
55 } else {
56 Some(en_passant)
57 }
58 }
59
60 #[inline]
61 pub const fn effective_en_passant(
62 self,
63 en_passant: Option<EnPassant>,
64 turn: Player,
65 ) -> Option<EnPassant> {
66 let Some(en_passant) = en_passant else {
67 return None;
68 };
69 let to = en_passant.square();
70 let expected = match to.rank() {
71 Three => Black,
72 Six => White,
73 _ => return None,
74 };
75 if !turn.eq(expected) {
76 return None;
77 }
78
79 let Some(captured) = to.checked_add(turn.other().pawn_push()) else {
81 return None;
82 };
83 let Some(piece) = self.get(captured) else {
84 return None;
85 };
86 if !piece.eq(turn.other().pawn()) {
87 return None;
88 }
89
90 self.attacked_en_passant(en_passant, turn)
91 }
92
93 pub fn king_shields(self, player: Player) -> Bitboard {
94 match self.king_of(player) {
95 Some(king) => {
96 let attacker = self.player(player.other());
97 let straight =
98 king.rook_sight(Bitboard::EMPTY).intersection(self.rooks_and_queens());
99 let diagonal =
100 king.bishop_sight(Bitboard::EMPTY).intersection(self.bishops_and_queens());
101 let snipers = straight.union(diagonal).intersection(attacker);
102
103 let mut shields = Bitboard::EMPTY;
104 let mut snipers = snipers;
105 while let Some(sniper) = snipers.pop_first() {
106 let blockers = king.between(sniper).intersection(self.occupied());
107 if !blockers.more_than_one() {
108 shields.append(blockers.intersection(self.player(player)));
109 }
110 }
111
112 shields
113 }
114 None => Bitboard::EMPTY,
115 }
116 }
117}