| 42 #define PIECE_PINNED 5 |
43 #define PIECE_PINNED 5 |
| 43 #define KING_IN_CHECK 6 |
44 #define KING_IN_CHECK 6 |
| 44 #define KING_MOVES_INTO_CHECK 7 |
45 #define KING_MOVES_INTO_CHECK 7 |
| 45 #define RULES_VIOLATED 10 |
46 #define RULES_VIOLATED 10 |
| 46 |
47 |
| 47 #define ENPASSANT_THREAT 0x40 |
48 #define ENPASSANT_THREAT 0x40u |
| 48 |
49 |
| 49 #define WHITE 0x10 |
50 #define WHITE 0x10u |
| 50 #define BLACK 0x20 |
51 #define BLACK 0x20u |
| 51 #define opponent_color(color) ((color)==WHITE?BLACK:WHITE) |
52 #define opponent_color(color) ((color)==WHITE?BLACK:WHITE) |
| 52 |
53 |
| 53 #define PIECE_MASK 0x0F |
54 #define PIECE_MASK 0x0Fu |
| 54 #define COLOR_MASK 0x30 |
55 #define COLOR_MASK 0x30u |
| 55 |
56 |
| 56 #define PAWN 0x01 |
57 #define PAWN 0x01u |
| 57 #define ROOK 0x02 |
58 #define ROOK 0x02u |
| 58 #define KNIGHT 0x03 |
59 #define KNIGHT 0x03u |
| 59 #define BISHOP 0x04 |
60 #define BISHOP 0x04u |
| 60 #define QUEEN 0x05 |
61 #define QUEEN 0x05u |
| 61 #define KING 0x06 |
62 #define KING 0x06u |
| 62 |
63 |
| 63 #define WPAWN (WHITE|PAWN) |
64 #define WPAWN (WHITE|PAWN) |
| 64 #define WROOK (WHITE|ROOK) |
65 #define WROOK (WHITE|ROOK) |
| 65 #define WKNIGHT (WHITE|KNIGHT) |
66 #define WKNIGHT (WHITE|KNIGHT) |
| 66 #define WBISHOP (WHITE|BISHOP) |
67 #define WBISHOP (WHITE|BISHOP) |
| 72 #define BBISHOP (BLACK|BISHOP) |
73 #define BBISHOP (BLACK|BISHOP) |
| 73 #define BQUEEN (BLACK|QUEEN) |
74 #define BQUEEN (BLACK|QUEEN) |
| 74 #define BKING (BLACK|KING) |
75 #define BKING (BLACK|KING) |
| 75 |
76 |
| 76 typedef uint8_t Board[8][8]; |
77 typedef uint8_t Board[8][8]; |
| |
78 typedef uint8_t BoardIndex; |
| |
79 typedef BoardIndex Row; |
| |
80 typedef BoardIndex File; |
| |
81 typedef uint8_t Piece; |
| |
82 typedef uint8_t Color; |
| 77 |
83 |
| 78 struct movetimeval { |
84 struct movetimeval { |
| 79 uint64_t tv_sec; |
85 uint64_t tv_sec; |
| 80 int32_t tv_usec; // important that this is signed b/c potential carry |
86 int32_t tv_usec; // important that this is signed b/c potential carry |
| 81 }; |
87 }; |
| 82 |
88 |
| 83 typedef struct { |
89 typedef struct { |
| 84 uint8_t piece; |
90 Piece piece; |
| 85 uint8_t fromfile; |
91 File fromfile; |
| 86 uint8_t fromrow; |
92 Row fromrow; |
| 87 uint8_t tofile; |
93 File tofile; |
| 88 uint8_t torow; |
94 Row torow; |
| 89 uint8_t promotion; |
95 uint8_t promotion; |
| 90 uint8_t check; |
96 uint8_t check; |
| 91 uint8_t capture; |
97 uint8_t capture; |
| 92 struct movetimeval timestamp; |
98 struct movetimeval timestamp; |
| 93 struct movetimeval movetime; |
99 struct movetimeval movetime; |
| 138 /** this flag is only supposed to be set when the opponent disconnects */ |
144 /** this flag is only supposed to be set when the opponent disconnects */ |
| 139 bool ragequit; |
145 bool ragequit; |
| 140 bool review; |
146 bool review; |
| 141 } GameState; |
147 } GameState; |
| 142 |
148 |
| |
149 #define piece_type(piece) ((piece)&PIECE_MASK) |
| |
150 #define piece_color(piece) ((piece)&COLOR_MASK) |
| |
151 #define mkpiece(type,color) ((type)|(color)) |
| |
152 |
| |
153 #define enpassant_threat_add(gamestate, row, file) \ |
| |
154 (gamestate->board[row][file] |= ENPASSANT_THREAT) |
| |
155 #define enpassant_threat_remove(gamestate, row, file) \ |
| |
156 (gamestate->board[row][file] &= ~ENPASSANT_THREAT) |
| |
157 #define enpassant_threat_exists(gamestate, row, file) \ |
| |
158 (gamestate->board[row][file] & ENPASSANT_THREAT) |
| |
159 |
| 143 #define is_game_running(gamestate) !((gamestate)->checkmate || \ |
160 #define is_game_running(gamestate) !((gamestate)->checkmate || \ |
| 144 (gamestate)->wresign || (gamestate)->bresign || (gamestate)->threefold || \ |
161 (gamestate)->wresign || (gamestate)->bresign || (gamestate)->threefold || \ |
| 145 (gamestate)->stalemate || (gamestate)->remis || (gamestate)->review) |
162 (gamestate)->stalemate || (gamestate)->remis || (gamestate)->review) |
| 146 |
163 |
| 147 #define last_move(gamestate) \ |
164 #define last_move(gamestate) \ |
| 148 ((gamestate)->moves[(gamestate)->movecount-1]) |
165 ((gamestate)->moves[(gamestate)->movecount-1]) |
| 149 |
166 |
| 150 #define POS_UNSPECIFIED UINT8_MAX |
167 #define POS_UNSPECIFIED UINT8_MAX |
| 151 #define mdst(b,m) b[(m)->torow][(m)->tofile] |
168 #define mdst(m) (m)->torow, (m)->tofile |
| 152 #define msrc(b,m) b[(m)->fromrow][(m)->fromfile] |
169 #define msrc(m) (m)->fromrow, (m)->fromfile |
| 153 |
170 |
| 154 /** Checks if the index is specified and valid. */ |
171 /** Checks if the index is specified and valid. */ |
| 155 #define isidx(idx) ((uint8_t)(idx) < 8) |
172 #define isidx(idx) ((BoardIndex)(idx) < 8) |
| 156 /** Checks if the index is unspecified or valid. */ |
173 /** Checks if the index is unspecified or valid. */ |
| 157 #define isidxr(idx) ((idx) == POS_UNSPECIFIED || (uint8_t)(idx) < 8) |
174 #define isidxr(idx) ((idx) == POS_UNSPECIFIED || (BoardIndex)(idx) < 8) |
| 158 |
175 |
| 159 #define isfile(file) (file >= 'a' && file <= 'h') |
176 #define isfile(file) (file >= 'a' && file <= 'h') |
| 160 #define isrow(row) (row >= '1' && row <= '8') |
177 #define isrow(row) (row >= '1' && row <= '8') |
| 161 |
178 |
| 162 #define rowidx(row) (row-'1') |
179 #define rowidx(row) (row-'1') |
| 184 |
200 |
| 185 /** |
201 /** |
| 186 * Maps a character to a piece. |
202 * Maps a character to a piece. |
| 187 * |
203 * |
| 188 * Does not work for pawns, since they don't have a character. |
204 * Does not work for pawns, since they don't have a character. |
| 189 * |
205 * |
| 190 * @param c one of R,N,B,Q,K |
206 * @param c one of R,N,B,Q,K |
| 191 * @return numeric value for the specified piece |
207 * @param color the piece color |
| 192 */ |
208 * @return the specified piece or zero when the character is invalid |
| 193 uint8_t getpiece(char c); |
209 */ |
| |
210 Piece getpiece(char c, Color color); |
| 194 |
211 |
| 195 /** |
212 /** |
| 196 * Maps a piece to a character. |
213 * Maps a piece to a character. |
| 197 * |
214 * |
| 198 * Does not work for pawns, scince they don't have a character. |
215 * Does not work for pawns, since they don't have a character. |
| 199 * |
216 * |
| 200 * @param piece may have color or additional flags |
217 * @param piece may have color or additional flags |
| 201 * @return character value for the specified piece |
218 * @return character value for the specified piece |
| 202 */ |
219 */ |
| 203 char getpiecechr(uint8_t piece); |
220 char getpiecechr(Piece piece); |
| 204 |
221 |
| 205 /** |
222 /** |
| 206 * Maps a piece to a unicode character sequence. |
223 * Maps a piece to a unicode character sequence. |
| 207 * |
224 * |
| 208 * The returned unicode is for black pieces. |
225 * The returned unicode is for black pieces. |
| 209 * You may colorize the output by setting the terminal foreground color. |
226 * You may colorize the output by setting the terminal foreground color. |
| 210 * |
227 * |
| 211 * @param piece the piece to dispaly |
228 * @param piece the piece to display |
| 212 * @return unicode character sequence for the specified piece |
229 * @return unicode character sequence for the specified piece |
| 213 */ |
230 */ |
| 214 char* getpieceunicode(uint8_t piece); |
231 char* getpieceunicode(Piece piece); |
| 215 |
232 |
| 216 /** |
233 /** |
| 217 * Returns the color of the player who is next to move. |
234 * Returns the color of the player who is next to move. |
| 218 * |
235 * |
| 219 * @param gamestate the current game state |
236 * @param gamestate the current game state |
| 220 * @return the color of the player who is next to move |
237 * @return the color of the player who is next to move |
| 221 */ |
238 */ |
| 222 uint8_t current_color(GameState *gamestate); |
239 Color current_color(GameState *gamestate); |
| |
240 |
| |
241 /** |
| |
242 * Returns the piece at the specified position. |
| |
243 * |
| |
244 * @param gamestate the current game state |
| |
245 * @param row the row |
| |
246 * @param file the file |
| |
247 * @return the piece at the specified position |
| |
248 */ |
| |
249 Piece piece_at(const GameState *gamestate, Row row, File file); |
| |
250 |
| |
251 /** |
| |
252 * Places a piece at the specified position in the current game state. |
| |
253 * |
| |
254 * @param gamestate the current game state |
| |
255 * @param row the row |
| |
256 * @param file the file |
| |
257 * @param piece the piece to place at the specified position |
| |
258 */ |
| |
259 void piece_set(GameState *gamestate, Row row, File file, Piece piece); |
| |
260 |
| |
261 /** |
| |
262 * Removes the piece at the specified position in the current game state. |
| |
263 * |
| |
264 * @param gamestate the current game state |
| |
265 * @param row the row |
| |
266 * @param file the file |
| |
267 */ |
| |
268 static inline void piece_remove(GameState *gamestate, Row row, File file) { |
| |
269 piece_set(gamestate, row, file, 0); |
| |
270 } |
| 223 |
271 |
| 224 /** |
272 /** |
| 225 * Checks, if a specified field is covered by a piece of a certain color. |
273 * Checks, if a specified field is covered by a piece of a certain color. |
| 226 * |
274 * |
| 227 * The out-parameters may both be NULL, but if any of them is set, the other |
275 * The out-parameters may both be NULL, but if any of them is set, the other |
| 231 * @param row row of the field to check |
279 * @param row row of the field to check |
| 232 * @param file file of the field to check |
280 * @param file file of the field to check |
| 233 * @param color the color of the piece that should threaten the field |
281 * @param color the color of the piece that should threaten the field |
| 234 * @param threats the array where to store the threats (should be able to hold |
282 * @param threats the array where to store the threats (should be able to hold |
| 235 * the rare maximum of 16 elements) |
283 * the rare maximum of 16 elements) |
| 236 * @param threatcount a pointer to an uint8_t where the count of threats is |
284 * @param threatcount a pointer where the count of threats is stored |
| 237 * stored |
|
| 238 * @return true, if any piece of the specified color threatens the specified |
285 * @return true, if any piece of the specified color threatens the specified |
| 239 * field (i.e. could capture an opponent piece) |
286 * field (i.e. could capture an opponent piece) |
| 240 */ |
287 */ |
| 241 bool get_threats(GameState *gamestate, uint8_t row, uint8_t file, |
288 bool get_threats(GameState *gamestate, Row row, File file, |
| 242 uint8_t color, Move* threats, uint8_t* threatcount); |
289 Color color, Move* threats, size_t* threatcount); |
| 243 |
290 |
| 244 /** |
291 /** |
| 245 * Checks, if a specified field is covered by a piece of a certain color AND |
292 * Checks, if a specified field is covered by a piece of a certain color AND |
| 246 * if this piece is not pinned and therefore able to perform the move. |
293 * if this piece is not pinned and therefore able to perform the move. |
| 247 * |
294 * |
| 252 * @param row row of the field to check |
299 * @param row row of the field to check |
| 253 * @param file file of the field to check |
300 * @param file file of the field to check |
| 254 * @param color the color of the piece that should threaten the field |
301 * @param color the color of the piece that should threaten the field |
| 255 * @param threats the array where to store the threats (should be able to hold |
302 * @param threats the array where to store the threats (should be able to hold |
| 256 * the rare maximum of 16 elements) |
303 * the rare maximum of 16 elements) |
| 257 * @param threatcount a pointer to an uint8_t where the count of threats is |
304 * @param threatcount a pointer where the count of threats is stored |
| 258 * stored |
|
| 259 * @return true, if any piece of the specified color threatens the specified |
305 * @return true, if any piece of the specified color threatens the specified |
| 260 * field (i.e. could capture an opponent piece) |
306 * field (i.e. could capture an opponent piece) |
| 261 */ |
307 */ |
| 262 bool get_real_threats(GameState *gamestate, uint8_t row, uint8_t file, |
308 bool get_real_threats(GameState *gamestate, Row row, File file, |
| 263 uint8_t color, Move* threats, uint8_t* threatcount); |
309 Color color, Move* threats, size_t* threatcount); |
| 264 |
310 |
| 265 /** |
311 /** |
| 266 * Checks, if a specified field is covered by a piece of a certain color. |
312 * Checks, if a specified field is covered by a piece of a certain color. |
| 267 * |
313 * |
| 268 * @param gamestate the current game state |
314 * @param gamestate the current game state |
| 302 * @param file file of the field to check |
348 * @param file file of the field to check |
| 303 * @param color the color of the piece that should cover the field |
349 * @param color the color of the piece that should cover the field |
| 304 * @return true, if any piece (excluding the king) of the specified color |
350 * @return true, if any piece (excluding the king) of the specified color |
| 305 * threatens the specified field and could capture an opponent piece |
351 * threatens the specified field and could capture an opponent piece |
| 306 */ |
352 */ |
| 307 bool is_protected(GameState *gamestate, uint8_t row, uint8_t file, |
353 bool is_protected(GameState *gamestate, Row row, File file, Color color); |
| 308 uint8_t color); |
|
| 309 |
354 |
| 310 /** |
355 /** |
| 311 * Checks, if the specified move cannot be performed, because the piece is |
356 * Checks, if the specified move cannot be performed, because the piece is |
| 312 * either pinned or cannot remove the check. |
357 * either pinned or cannot remove the check. |
| 313 * |
358 * |
| 337 * @param mstr the input string to parse |
382 * @param mstr the input string to parse |
| 338 * @param move a pointer to object where the move data shall be stored |
383 * @param move a pointer to object where the move data shall be stored |
| 339 * @param color the color of the player to evaluate the move for |
384 * @param color the color of the player to evaluate the move for |
| 340 * @return status code (see macros in this file for the list of codes) |
385 * @return status code (see macros in this file for the list of codes) |
| 341 */ |
386 */ |
| 342 int eval_move(GameState *gamestate, const char *mstr, |
387 int eval_move(GameState *gamestate, const char *mstr, Move *move, Color color); |
| 343 Move *move, uint8_t color); |
|
| 344 |
388 |
| 345 /** |
389 /** |
| 346 * Syntactically checks a move without verifying that a piece exists that is |
390 * Syntactically checks a move without verifying that a piece exists that is |
| 347 * allowed to move that way. |
391 * allowed to move that way. |
| 348 * |
392 * |
| 349 * @param mstr the input string to parse |
393 * @param mstr the input string to parse |
| 350 * @param color the color of the player to evaluate the move for |
394 * @param color the color of the player to evaluate the move for |
| 351 * @return status code (see macros in this file for the list of codes) |
395 * @return status code (see macros in this file for the list of codes) |
| 352 */ |
396 */ |
| 353 int check_move(const char *mstr, uint8_t color); |
397 int check_move(const char *mstr, Color color); |
| 354 |
398 |
| 355 /** |
399 /** |
| 356 * Validates move by applying chess rules. |
400 * Validates move by applying chess rules. |
| 357 * @param gamestate the current game state |
401 * @param gamestate the current game state |
| 358 * @param move the move to validate |
402 * @param move the move to validate |
| 397 * @param gamestate the current game state |
441 * @param gamestate the current game state |
| 398 * @param color either BLACK or WHITE |
442 * @param color either BLACK or WHITE |
| 399 * @return the remaining time - if time control is disabled, this function |
443 * @return the remaining time - if time control is disabled, this function |
| 400 * always returns zero |
444 * always returns zero |
| 401 */ |
445 */ |
| 402 uint16_t remaining_movetime(GameState *gamestate, uint8_t color); |
446 uint16_t remaining_movetime(GameState *gamestate, Color color); |
| 403 |
447 |
| 404 /** |
448 /** |
| 405 * Converts clock time to string. |
449 * Converts clock time to string. |
| 406 * |
450 * |
| 407 * @param time the time to format |
451 * @param time the time to format |