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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use square;
use square::Square;
use bitboard;
use bitboard::Bitboard;
use types::{Color, White, Black, Role, Pockets, RemainingChecks};
use board::Board;
use std::iter::FromIterator;
use option_filter::OptionFilterExt;
pub trait Setup {
fn board(&self) -> &Board;
fn pockets(&self) -> Option<&Pockets>;
fn turn(&self) -> Color;
fn castling_rights(&self) -> Bitboard;
fn ep_square(&self) -> Option<Square>;
fn remaining_checks(&self) -> Option<&RemainingChecks>;
fn halfmove_clock(&self) -> u32;
fn fullmoves(&self) -> u32;
fn us(&self) -> Bitboard {
self.board().by_color(self.turn())
}
fn our(&self, role: Role) -> Bitboard {
self.us() & self.board().by_role(role)
}
fn them(&self) -> Bitboard {
self.board().by_color(!self.turn())
}
fn their(&self, role: Role) -> Bitboard {
self.them() & self.board().by_role(role)
}
}
pub fn clean_castling_rights(setup: &Setup, strict: bool) -> Bitboard {
let castling = setup.castling_rights() & setup.board().rooks();
let clean_strict = |color: Color| -> Bitboard {
let king = color.fold(square::E1, square::E8);
if setup.board().kings().contains(king) && !setup.board().promoted().contains(king) {
castling & setup.board().by_color(color)
& Bitboard::relative_rank(color, 0)
& bitboard::CORNERS
} else {
Bitboard(0)
}
};
let clean_loose = |color: Color| -> Bitboard {
if let Some(king) = setup.board().king_of(color) {
if king.file() == 0 || king.file() == 7 || king.rank() != color.fold(0, 7) {
return Bitboard(0)
}
let castling = castling & setup.board().by_color(color) &
Bitboard::relative_rank(color, 0);
let a_side = castling.first().filter(|rook| rook.file() < king.file());
let h_side = castling.last().filter(|rook| king.file() < rook.file());
Bitboard::from_iter(a_side) | Bitboard::from_iter(h_side)
} else {
Bitboard(0)
}
};
if strict {
clean_strict(Black) | clean_strict(White)
} else {
clean_loose(Black) | clean_loose(White)
}
}