myopic_core/
castlezone.rs1use crate::bitboard::BitBoard;
2use crate::pieces::Piece;
3use crate::square::Square;
4use crate::Side;
5use anyhow::anyhow;
6use std::fmt::{Display, Formatter};
7use std::str::FromStr;
8use enumset::*;
9
10#[derive(Debug, EnumSetType, PartialOrd, Ord, Hash)]
13#[rustfmt::skip]
14pub enum CastleZone { WK, WQ, BK, BQ }
15
16impl Display for CastleZone {
17 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
18 write!(f, "{}", format!("{:?}", self).to_lowercase())
19 }
20}
21
22impl FromStr for CastleZone {
23 type Err = anyhow::Error;
24
25 fn from_str(s: &str) -> Result<Self, Self::Err> {
26 match s {
27 "wk" | "WK" => Ok(CastleZone::WK),
28 "wq" | "WQ" => Ok(CastleZone::WQ),
29 "bk" | "BK" => Ok(CastleZone::BK),
30 "bq" | "BQ" => Ok(CastleZone::BQ),
31 _ => Err(anyhow!("Cannot parse {} as CastleZone", s)),
32 }
33 }
34}
35
36impl CastleZone {
37 pub fn side(&self) -> Side {
39 match self {
40 CastleZone::WK | CastleZone::WQ => Side::White,
41 CastleZone::BK | CastleZone::BQ => Side::Black,
42 }
43 }
44
45 pub fn kingside(side: Side) -> CastleZone {
47 match side {
48 Side::White => CastleZone::WK,
49 Side::Black => CastleZone::BK,
50 }
51 }
52
53 pub fn queenside(side: Side) -> CastleZone {
55 match side {
56 Side::White => CastleZone::WQ,
57 Side::Black => CastleZone::BQ,
58 }
59 }
60
61 pub fn iter() -> impl Iterator<Item = CastleZone> {
63 [
64 CastleZone::WK,
65 CastleZone::WQ,
66 CastleZone::BK,
67 CastleZone::BQ,
68 ]
69 .iter()
70 .cloned()
71 }
72
73 pub fn source_squares(self) -> BitBoard {
77 match self {
78 CastleZone::WK => Square::E1 | Square::H1,
79 CastleZone::WQ => Square::E1 | Square::A1,
80 CastleZone::BK => Square::E8 | Square::H8,
81 CastleZone::BQ => Square::E8 | Square::A8,
82 }
83 }
84
85 pub fn rook_data(self) -> (Piece, Square, Square) {
89 match self {
90 CastleZone::WK => (Piece::WR, Square::H1, Square::F1),
91 CastleZone::BK => (Piece::BR, Square::H8, Square::F8),
92 CastleZone::WQ => (Piece::WR, Square::A1, Square::D1),
93 CastleZone::BQ => (Piece::BR, Square::A8, Square::D8),
94 }
95 }
96
97 pub fn king_data(self) -> (Piece, Square, Square) {
101 match self {
102 CastleZone::WK => (Piece::WK, Square::E1, Square::G1),
103 CastleZone::BK => (Piece::BK, Square::E8, Square::G8),
104 CastleZone::WQ => (Piece::WK, Square::E1, Square::C1),
105 CastleZone::BQ => (Piece::BK, Square::E8, Square::C8),
106 }
107 }
108
109 pub fn unoccupied_requirement(self) -> BitBoard {
113 match self {
114 CastleZone::WK => Square::F1 | Square::G1,
115 CastleZone::WQ => Square::B1 | Square::C1 | Square::D1,
116 CastleZone::BK => Square::F8 | Square::G8,
117 CastleZone::BQ => Square::B8 | Square::C8 | Square::D8,
118 }
119 }
120
121 pub fn uncontrolled_requirement(self) -> BitBoard {
125 match self {
126 CastleZone::WK => Square::E1 | Square::F1 | Square::G1,
127 CastleZone::WQ => Square::E1 | Square::C1 | Square::D1,
128 CastleZone::BK => Square::E8 | Square::F8 | Square::G8,
129 CastleZone::BQ => Square::E8 | Square::C8 | Square::D8,
130 }
131 }
132
133 pub fn lift(self) -> EnumSet<CastleZone> {
135 enum_set!(self)
136 }
137}
138
139#[cfg(test)]
140mod test {
141 use crate::CastleZone;
142
143 #[test]
144 fn display() {
145 assert_eq!("wk", CastleZone::WK.to_string().as_str());
146 assert_eq!("wq", CastleZone::WQ.to_string().as_str());
147 assert_eq!("bk", CastleZone::BK.to_string().as_str());
148 assert_eq!("bq", CastleZone::BQ.to_string().as_str());
149 }
150
151 #[test]
152 fn from_str() {
153 assert_eq!(CastleZone::WK, "wk".parse::<CastleZone>().unwrap());
154 assert_eq!(CastleZone::WK, "WK".parse::<CastleZone>().unwrap());
155 assert_eq!(CastleZone::WQ, "wq".parse::<CastleZone>().unwrap());
156 assert_eq!(CastleZone::WQ, "WQ".parse::<CastleZone>().unwrap());
157 assert_eq!(CastleZone::BK, "bk".parse::<CastleZone>().unwrap());
158 assert_eq!(CastleZone::BK, "BK".parse::<CastleZone>().unwrap());
159 assert_eq!(CastleZone::BQ, "bq".parse::<CastleZone>().unwrap());
160 assert_eq!(CastleZone::BQ, "BQ".parse::<CastleZone>().unwrap());
161 }
162}