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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::error::Error;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Contains information on who is still allowed to castle and in which direction.
pub struct CastlingRights {
/// If white is allowed to castle king side.
pub white_king_side: bool,
/// If white is allowed to castle queen side.
pub white_queen_side: bool,
/// If black is allowed to castle king side.
pub black_king_side: bool,
/// If black is allowed to castle queen side.
pub black_queen_side: bool,
}
impl CastlingRights {
/// Create new [`CastlingRights`] where no castling is allowed.
///
/// returns: [`CastlingRights`]
///
/// # Examples
///
/// ```
/// use giga_chess::game::castling_rights::CastlingRights;
///
/// let rights = CastlingRights::none();
///
/// assert!(!rights.white_king_side);
/// assert!(!rights.white_queen_side);
/// assert!(!rights.black_king_side);
/// assert!(!rights.black_queen_side);
/// ```
pub fn none() -> Self {
Self {
white_king_side: false,
white_queen_side: false,
black_king_side: false,
black_queen_side: false,
}
}
/// Formats available castling rights FEN-compliant.
///
/// returns: String
///
/// # Examples
///
/// ```
/// use giga_chess::game::castling_rights::CastlingRights;
///
/// let rights1 = CastlingRights::default();
/// assert_eq!(rights1.get_fen_string(), "KQkq");
///
/// let rights2 = CastlingRights::none();
/// assert_eq!(rights2.get_fen_string(), "-");
///
/// let rights3 = CastlingRights {
/// white_king_side: true,
/// white_queen_side: false,
/// black_king_side: false,
/// black_queen_side: true,
/// };
/// assert_eq!(rights3.get_fen_string(), "Kq");
/// ```
pub fn get_fen_string(&self) -> String {
let mut fen = String::new();
if self.white_king_side {
fen.push('K');
}
if self.white_queen_side {
fen.push('Q');
}
if self.black_king_side {
fen.push('k');
}
if self.black_queen_side {
fen.push('q');
}
if fen.is_empty() { "-".to_string() } else { fen }
}
}
impl Default for CastlingRights {
fn default() -> Self {
Self {
white_king_side: true,
white_queen_side: true,
black_king_side: true,
black_queen_side: true,
}
}
}
impl TryFrom<&str> for CastlingRights {
type Error = Box<dyn Error>;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value == "-" {
return Ok(Self::none());
}
let mut rights = Self::default();
for c in value.chars() {
match c {
'K' => rights.white_king_side = true,
'Q' => rights.white_queen_side = true,
'k' => rights.black_king_side = true,
'q' => rights.black_queen_side = true,
_ => return Err(format!("Invalid character '{}'", value).into()),
}
}
Ok(rights)
}
}