-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpiece.hpp
More file actions
261 lines (234 loc) · 7.57 KB
/
Copy pathpiece.hpp
File metadata and controls
261 lines (234 loc) · 7.57 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#pragma once
#include <bitbishop/color.hpp>
#include <bitbishop/config.hpp>
#include <cctype>
#include <format>
#include <stdexcept>
/**
* @brief Represents a chess piece.
*
* This class wraps a lightweight enum and provides utility methods
* for querying piece color, converting to/from characters, and comparison.
*
* By convention:
* - White pieces are uppercase (P, N, B, R, Q, K)
* - Black pieces are lowercase (p, n, b, r, q, k)
*/
class Piece {
public:
/**
* @brief Enum of all supported piece types.
*
* Stored in a compact underlying type to ensure `Piece` remains lightweight.
*/
enum Type : std::uint8_t { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING };
/**
* @brief Number of distinct piece types discarding color.
*
* Useful for array sizing and iteration without magic numbers.
*/
static CX_VALUE std::size_t TYPE_COUNT = 6;
/**
* @brief Number of distinct piece types considering color (6 whites, 6 blacks).
*
* Useful for array sizing and iteration without magic numbers.
*/
static CX_VALUE std::size_t DISTINCT_PIECES_COUNT = 12;
/**
* @brief Distinct piece types.
*/
static CX_VALUE std::array<Type, TYPE_COUNT> ALL_TYPES = {PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING};
private:
/**
* @brief The type of the piece (pawn, knight, etc.).
*/
Type m_type;
/**
* @brief The color of the piece (white or black).
*/
Color m_color;
public:
/**
* @brief Constructs a piece from a type and color.
* @param type Piece type
* @param color Piece color
*/
CX_FN Piece(Type type, Color color) : m_type(type), m_color(color) {}
/**
* @brief Constructs a piece from a character representation.
*
* Uppercase indicates white pieces, lowercase indicates black pieces.
*
* @param character Character representing the piece ('P', 'n', etc.)
* @throw std::invalid_argument If the character does not represent a valid piece
*/
CX_FN Piece(char character) {
m_type = Piece::type_from_char(character);
m_color = Piece::color_from_char(character);
}
/**
* @brief Returns the piece type.
* @return Type enum
*/
[[nodiscard]] CX_FN Type type() const { return m_type; }
/**
* @brief Returns the piece color.
* @return Color enum
*/
[[nodiscard]] CX_FN Color color() const { return m_color; }
/**
* @brief Checks if the piece is white.
* @return true if white, false otherwise
*/
[[nodiscard]] CX_FN bool is_white() const { return m_color == Color::WHITE; }
/**
* @brief Checks if the piece is black.
* @return true if black, false otherwise
*/
[[nodiscard]] CX_FN bool is_black() const { return m_color == Color::BLACK; }
/** @brief Checks if the piece is a pawn. */
[[nodiscard]] CX_FN bool is_pawn() const { return m_type == Type::PAWN; }
/** @brief Checks if the piece is a knight. */
[[nodiscard]] CX_FN bool is_knight() const { return m_type == Type::KNIGHT; }
/** @brief Checks if the piece is a bishop. */
[[nodiscard]] CX_FN bool is_bishop() const { return m_type == Type::BISHOP; }
/** @brief Checks if the piece is a rook. */
[[nodiscard]] CX_FN bool is_rook() const { return m_type == Type::ROOK; }
/** @brief Checks if the piece is a queen. */
[[nodiscard]] CX_FN bool is_queen() const { return m_type == Type::QUEEN; }
/** @brief Checks if the piece is a king. */
[[nodiscard]] CX_FN bool is_king() const { return m_type == Type::KING; }
/**
* @brief Checks if the piece is a sliding piece (bishop, rook, queen).
* @return true if sliding, false otherwise
*/
[[nodiscard]] CX_FN bool is_slider() {
return m_type == Piece::BISHOP || m_type == Piece::ROOK || m_type == Piece::QUEEN;
}
/**
* @brief Returns the type associated with a character representation.
*
* @param character Piece character ('P', 'b', etc.)
* @return Corresponding piece type
* @throw std::invalid_argument If the character is invalid
*/
[[nodiscard]] static CX_FN Type type_from_char(char character) {
switch (character) {
case 'P':
case 'p':
return PAWN;
case 'N':
case 'n':
return KNIGHT;
case 'B':
case 'b':
return BISHOP;
case 'R':
case 'r':
return ROOK;
case 'Q':
case 'q':
return QUEEN;
case 'K':
case 'k':
return KING;
}
throw std::invalid_argument("Invalid piece character at compile time");
}
/**
* @brief Extracts piece color from character representation.
*
* @param character Piece character ('P' = white, 'p' = black)
* @return Detected color
* @throw std::invalid_argument If the character is not alphabetic
*/
[[nodiscard]] static CX_FN Color color_from_char(char character) {
if (character >= 'A' && character <= 'Z') {
return Color::WHITE;
}
if (character >= 'a' && character <= 'z') {
return Color::BLACK;
}
throw std::invalid_argument("Invalid character at compile time");
}
/**
* @brief Human-readable name of a piece type.
*
* @param type Piece type enum
* @return C-string name ("pawn", "knight", etc.)
*/
[[nodiscard]] static CX_FN const char* name(Type type) {
switch (type) {
case PAWN:
return "pawn";
case KNIGHT:
return "knight";
case BISHOP:
return "bishop";
case ROOK:
return "rook";
case QUEEN:
return "queen";
case KING:
return "king";
}
return "unknown";
}
/**
* @brief Converts a type and color to its representative character.
*
* @param type Piece type
* @param color Piece color
* @return Uppercase for white, lowercase for black (e.g., 'Q' or 'q')
*/
[[nodiscard]] static CX_FN char to_char(Type type, Color color) {
static CX_CONST std::array<char, TYPE_COUNT> whiteSymbols = {'P', 'N', 'B', 'R', 'Q', 'K'};
static CX_CONST std::array<char, TYPE_COUNT> blackSymbols = {'p', 'n', 'b', 'r', 'q', 'k'};
return (color == Color::WHITE) ? whiteSymbols[type] : blackSymbols[type];
}
/**
* @brief Converts the stored piece to its character representation.
* @return Character ('P', 'k', etc.)
*/
[[nodiscard]] CX_FN char to_char() const { return Piece::to_char(m_type, m_color); }
/**
* @brief Tells if a piece can result from a promotion.
* @return True if the piece is a Queen, Rook, Bishop or a Knight.
*/
[[nodiscard]] CX_FN bool is_promotion() const {
return (m_type == Piece::Type::QUEEN || m_type == Piece::Type::ROOK || m_type == Piece::Type::BISHOP ||
m_type == Piece::Type::KNIGHT);
}
/**
* @brief Equality operator.
* @param other Piece to compare against
* @return true if both type and color match
*/
CX_FN bool operator==(const Piece& other) const { return m_type == other.m_type && m_color == other.m_color; }
/**
* @brief Inequality operator.
* @param other Piece to compare against
* @return true if type or color differ
*/
CX_FN bool operator!=(const Piece& other) const { return !(*this == other); }
};
namespace Pieces {
#define DEFINE_PIECE(name, ch) \
/** @brief Predefined piece constant for convenience. */ \
CX_INLINE Piece name { ch }
// White pieces
DEFINE_PIECE(WHITE_PAWN, 'P');
DEFINE_PIECE(WHITE_KNIGHT, 'N');
DEFINE_PIECE(WHITE_BISHOP, 'B');
DEFINE_PIECE(WHITE_ROOK, 'R');
DEFINE_PIECE(WHITE_QUEEN, 'Q');
DEFINE_PIECE(WHITE_KING, 'K');
// Black pieces
DEFINE_PIECE(BLACK_PAWN, 'p');
DEFINE_PIECE(BLACK_KNIGHT, 'n');
DEFINE_PIECE(BLACK_BISHOP, 'b');
DEFINE_PIECE(BLACK_ROOK, 'r');
DEFINE_PIECE(BLACK_QUEEN, 'q');
DEFINE_PIECE(BLACK_KING, 'k');
#undef DEFINE_PIECE
} // namespace Pieces