1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::implementation::cache::rays::RaySet;
use crate::implementation::MutBoardImpl;
use crate::MutBoard;
use myopic_core::bitboard::BitBoard;
use myopic_core::{Side, Square};
use super::{BLACK_SLIDERS, WHITE_SLIDERS};
use myopic_core::pieces::Piece;
use myopic_core::reflectable::Reflectable;
impl MutBoardImpl {
pub fn pinned_set_impl(&mut self) -> RaySet {
match &self.cache.pinned_set {
Some(x) => x.clone(),
None => {
let result = self.compute_pinned();
self.cache.pinned_set = Some(result.clone());
result
}
}
}
fn compute_pinned(&self) -> RaySet {
let locs = |side: Side| self.side(side);
let (active, passive) = (locs(self.active), locs(self.active.reflect()));
let king_loc = self.pieces.king_location(self.active);
let mut constraint_areas: Vec<(Square, BitBoard)> = Vec::with_capacity(2);
let mut pinned_locations = BitBoard::EMPTY;
for potential_pinner in self.compute_potential_pinners(king_loc) {
let cord = BitBoard::cord(king_loc, potential_pinner);
if (cord & active).size() == 2 && (cord & passive).size() == 1 {
let pinned_loc = ((cord & active) - king_loc).into_iter().next().unwrap();
constraint_areas.push((pinned_loc, cord));
pinned_locations |= pinned_loc;
}
}
RaySet { ray_points: pinned_locations, rays: constraint_areas }
}
fn compute_potential_pinners(&self, king_loc: Square) -> BitBoard {
let passive_sliders = match self.active {
Side::White => BLACK_SLIDERS,
Side::Black => WHITE_SLIDERS,
};
let locs = |p: Piece| self.pieces.locs_impl(p);
passive_sliders.iter().flat_map(|&p| locs(p) & p.empty_control(king_loc)).collect()
}
}
#[cfg(test)]
mod test {
use myopic_core::bitboard::constants::*;
use super::*;
fn execute_test(fen: &'static str, expected_pinned: RaySet) {
let board = crate::fen_position(fen).unwrap();
assert_eq!(expected_pinned.reflect(), board.reflect().compute_pinned());
assert_eq!(expected_pinned, board.compute_pinned());
}
#[test]
fn case_one() {
let fen = "K2Q4/7p/1B4n1/2bq4/2rkp1R1/4p3/5br1/6B1 b KQkq - 5 10";
let expected_pinned = RaySet {
ray_points: C5 | D5 | E4,
rays: vec![
(Square::E4, D4 | E4 | F4 | G4),
(Square::C5, B6 | C5 | D4),
(Square::D5, D4 | D5 | D6 | D7 | D8),
],
};
execute_test(fen, expected_pinned);
}
}