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
// bitflags...
use bitflags::bitflags;
// types...
use crate::types::color::Color;
bitflags! {
/// Represents a chess piece.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(transparent)]
pub struct Piece: u16 {
/// A pawn.
const P = 0x0001;
/// A knight.
const N = 0x0002;
/// A bishop.
const B = 0x0004;
/// A rook.
const R = 0x0008;
/// A queen.
const Q = 0x0010;
/// A king.
const K = 0x0020;
/// A black piece.
const BLACK = 0x2000;
/// A white piece.
const WHITE = 0x4000;
/// A moved piece.
const MOVED = 0x8000;
}
}
impl Piece {
/// Sets the [`Piece`] as one that has been moved.
pub fn conquer(&mut self) {
self.insert(Self::MOVED)
}
/// Sets the [`Piece`] as one that has not been moved.
pub fn retreat(&mut self) {
self.remove(Self::MOVED)
}
/// Returns whether the [`Piece`] is a piece and a color (i.e., a useable piece).
pub fn useable(&self) -> bool {
self.is_piece() && self.is_color()
}
/// Returns whether the [`Piece`] meets the requirements for capturing the other [`Piece`].
pub fn capturable(&self, other: Self) -> bool {
self.is_enemy(other) && !other.intersects(Self::K)
}
/// Returns whether the [`Piece`] meets the requirements for castling.
pub fn castleable(&self) -> bool {
self.intersects(Self::R | Self::K) && !self.is_moved()
}
/// Returns whether the [`Piece`] meets the requirements for a pawn's double-square move.
pub fn doubleable(&self) -> bool {
self.intersects(Self::P) && !self.is_moved()
}
/// Returns whether the [`Piece`] meets the requirements for en-passant.
pub fn enpassable(&self) -> bool {
self.intersects(Self::P) && !self.is_moved()
}
/// Returns whether the [`Piece`] meets the requirements for being promoted from.
pub fn promotable(&self) -> bool {
self.intersects(Self::P)
}
/// Returns whether the [`Piece`] meets the requirements for being promoted to.
pub fn switchable(&self) -> bool {
self.intersects(Self::N | Self::B | Self::R | Self::Q)
}
/// Returns whether the [`Piece`] is flagged as some color.
fn is_color(&self) -> bool {
self.intersects(Self::BLACK | Self::WHITE)
}
/// Returns whether the [`Piece`]s are not flagged with the same color.
fn is_enemy(&self, other: Self) -> bool {
!self.intersection(other).intersects(Self::BLACK | Self::WHITE)
}
/// Returns whether the [`Piece`] is flagged as being moved.
fn is_moved(&self) -> bool {
self.intersects(Self::MOVED)
}
/// Returns whether the [`Piece`] is flagged as some piece.
fn is_piece(&self) -> bool {
self.intersects(Self::P | Self::N | Self::B | Self::R | Self::Q | Self::K)
}
}
impl From<Color> for Piece {
fn from(value: Color) -> Self {
match value {
Color::Black => Self::BLACK,
Color::White => Self::WHITE,
}
}
}