src/chess/rules.h

changeset 160
f87832cba8b8
parent 157
07cbfc477b22
equal deleted inserted replaced
159:07c7be5661f4 160:f87832cba8b8
28 */ 28 */
29 29
30 #ifndef RULES_H 30 #ifndef RULES_H
31 #define RULES_H 31 #define RULES_H
32 32
33 #include <stdlib.h>
33 #include <stdint.h> 34 #include <stdint.h>
34 #include <stdbool.h> 35 #include <stdbool.h>
35 36
36 #define VALID_MOVE_SYNTAX 0 37 #define VALID_MOVE_SYNTAX 0
37 #define VALID_MOVE_SEMANTICS 0 /* use same code for a success */ 38 #define VALID_MOVE_SEMANTICS 0 /* use same code for a success */
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')
167 184
168 /* secure versions - use, if index is not checked with isidx() */ 185 /* secure versions - use, if index is not checked with isidx() */
169 #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED) 186 #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED)
170 #define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED) 187 #define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED)
171 188
172
173 /** 189 /**
174 * Initializes a game state and prepares the chess board. 190 * Initializes a game state and prepares the chess board.
175 * @param gamestate the game state to initialize 191 * @param gamestate the game state to initialize
176 */ 192 */
177 void gamestate_init(GameState *gamestate); 193 void gamestate_init(GameState *gamestate);
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

mercurial