src/chess/rules.h

changeset 163
2a6d83f4677e
parent 161
3ff96fec144a
equal deleted inserted replaced
162:f0fc70b6f8f9 163:2a6d83f4677e
41 #define AMBIGUOUS_MOVE 3 41 #define AMBIGUOUS_MOVE 3
42 #define NEED_PROMOTION 4 42 #define NEED_PROMOTION 4
43 #define PIECE_PINNED 5 43 #define PIECE_PINNED 5
44 #define KING_IN_CHECK 6 44 #define KING_IN_CHECK 6
45 #define KING_MOVES_INTO_CHECK 7 45 #define KING_MOVES_INTO_CHECK 7
46 #define RULES_VIOLATED 10 46 #define MISSING_CHECK 8
47 #define MISSING_CHECKMATE 9
48 #define INVALID_CHECK 10
49 #define INVALID_CHECKMATE 11
50 #define RULES_VIOLATED 32
47 51
48 #define ENPASSANT_THREAT 0x40u 52 #define ENPASSANT_THREAT 0x40u
49 53
50 #define WHITE 0x10u 54 #define WHITE 0x10u
51 #define BLACK 0x20u 55 #define BLACK 0x20u
81 typedef uint8_t Piece; 85 typedef uint8_t Piece;
82 typedef uint8_t Color; 86 typedef uint8_t Color;
83 87
84 struct movetimeval { 88 struct movetimeval {
85 uint64_t tv_sec; 89 uint64_t tv_sec;
86 int32_t tv_usec; // important that this is signed b/c potential carry 90 int32_t tv_usec; /* important that this is signed b/c potential carry */
87 }; 91 };
88 92
89 typedef struct { 93 typedef struct {
90 Piece piece; 94 Piece piece;
91 File fromfile; 95 File fromfile;
92 Row fromrow; 96 Row fromrow;
93 File tofile; 97 File tofile;
94 Row torow; 98 Row torow;
95 uint8_t promotion; 99 Piece promotion;
96 uint8_t check; 100 uint8_t check; /* must always be set if checkmate is set */
101 uint8_t checkmate;
97 uint8_t capture; 102 uint8_t capture;
103 uint8_t padding[7]; /* necessary for stable ABI across networks */
98 struct movetimeval timestamp; 104 struct movetimeval timestamp;
99 struct movetimeval movetime; 105 struct movetimeval movetime;
100 char string[8]; 106 char string[8];
101 } Move; 107 } Move;
102 108
187 Row row, File file) { 193 Row row, File file) {
188 return gamestate->board[row][file] & ENPASSANT_THREAT; 194 return gamestate->board[row][file] & ENPASSANT_THREAT;
189 } 195 }
190 196
191 static inline bool is_game_running(const GameState *gamestate) { 197 static inline bool is_game_running(const GameState *gamestate) {
192 return !(gamestate->checkmate || gamestate->wresign || gamestate->bresign || gamestate->threefold || gamestate->stalemate || gamestate->remis || gamestate->review); 198 return !(gamestate->checkmate || gamestate->wresign || gamestate->bresign
199 || gamestate->threefold || gamestate->stalemate || gamestate->remis
200 || gamestate->review);
201 }
202
203 static inline bool is_check_position(const GameState *gamestate) {
204 return gamestate->moves[gamestate->movecount - 1].check;
193 } 205 }
194 206
195 /** 207 /**
196 * Initializes a game state and prepares the chess board. 208 * Initializes a game state and prepares the chess board.
197 * @param gamestate the game state to initialize 209 * @param gamestate the game state to initialize
240 * Returns the color of the player who is next to move. 252 * Returns the color of the player who is next to move.
241 * 253 *
242 * @param gamestate the current game state 254 * @param gamestate the current game state
243 * @return the color of the player who is next to move 255 * @return the color of the player who is next to move
244 */ 256 */
245 Color current_color(GameState *gamestate); 257 Color current_color(const GameState *gamestate);
246 258
247 /** 259 /**
248 * Returns the piece at the specified position. 260 * Returns the piece at the specified position.
249 * 261 *
250 * @param gamestate the current game state 262 * @param gamestate the current game state
274 static inline void piece_remove(GameState *gamestate, Row row, File file) { 286 static inline void piece_remove(GameState *gamestate, Row row, File file) {
275 piece_set(gamestate, row, file, 0); 287 piece_set(gamestate, row, file, 0);
276 } 288 }
277 289
278 /** 290 /**
279 * Checks, if a specified field is covered by a piece of a certain color. 291 * Determines a list of possible moves to the specified field.
292 *
293 * The out-parameters may both be NULL, but if any of them is set, the other
294 * must be set, too.
295 *
296 * @param gamestate the current game state
297 * @param row row of the field to check
298 * @param file file of the field to check
299 * @param color the color of the piece that should move to the field
300 * @param moves the array where to store the moves
301 * (must be large enough, 16 is always enough)
302 * @param movecount a pointer where the number of moves is stored
303 * @return true, if any piece of the specified color can move to the specified
304 * field
305 */
306 bool get_candidates(const GameState *gamestate, Row row, File file,
307 Color color, Move* moves, size_t* movecount);
308
309 /**
310 * Checks, if a specified field is threatened by a piece of a certain color.
311 *
312 * A field is threatened, if there is a piece of the specified color that could
313 * capture an opponent piece on this field, regardless of being pinned.
280 * 314 *
281 * The out-parameters may both be NULL, but if any of them is set, the other 315 * The out-parameters may both be NULL, but if any of them is set, the other
282 * must be set, too. 316 * must be set, too.
283 * 317 *
284 * @param gamestate the current game state 318 * @param gamestate the current game state
285 * @param row row of the field to check 319 * @param row row of the field to check
286 * @param file file of the field to check 320 * @param file file of the field to check
287 * @param color the color of the piece that should threaten the field 321 * @param color the color of the piece that should threaten the field
288 * @param threats the array where to store the threats (should be able to hold 322 * @param threats the array where to store the threats
289 * the rare maximum of 16 elements) 323 * (must be large enough, 16 is always enough)
290 * @param threatcount a pointer where the count of threats is stored 324 * @param threatcount a pointer where the count of threats is stored
291 * @return true, if any piece of the specified color threatens the specified 325 * @return true, if any piece of the specified color threatens the specified
292 * field (i.e. could capture an opponent piece) 326 * field
293 */ 327 */
294 bool get_threats(GameState *gamestate, Row row, File file, 328 bool get_threats(const GameState *gamestate, Row row, File file,
295 Color color, Move* threats, size_t* threatcount); 329 Color color, Move* threats, size_t* threatcount);
296 330
297 /** 331 /**
298 * Checks, if a specified field is covered by a piece of a certain color AND 332 * Checks, if a specified field is threatened by a piece of a certain color AND
299 * if this piece is not pinned and therefore able to perform the move. 333 * if this piece is not pinned and therefore able to perform the move.
300 * 334 *
301 * The out-parameters may both be NULL, but if any of them is set, the other 335 * The out-parameters may both be NULL, but if any of them is set, the other
302 * must be set, too. 336 * must be set, too.
303 * 337 *
304 * @param gamestate the current game state 338 * @param gamestate the current game state
305 * @param row row of the field to check 339 * @param row row of the field to check
306 * @param file file of the field to check 340 * @param file file of the field to check
307 * @param color the color of the piece that should threaten the field 341 * @param color the color of the piece that should threaten the field
308 * @param threats the array where to store the threats (should be able to hold 342 * @param threats the array where to store the threats
309 * the rare maximum of 16 elements) 343 * (must be large enough, 16 is always enough)
310 * @param threatcount a pointer where the count of threats is stored 344 * @param threatcount a pointer where the count of threats is stored
311 * @return true, if any piece of the specified color threatens the specified 345 * @return true, if any piece of the specified color threatens the specified
312 * field (i.e. could capture an opponent piece) 346 * field and is not pinned
313 */ 347 */
314 bool get_real_threats(GameState *gamestate, Row row, File file, 348 bool get_real_threats(const GameState *gamestate, Row row, File file,
315 Color color, Move* threats, size_t* threatcount); 349 Color color, Move* threats, size_t* threatcount);
316 350
317 /** 351 /**
318 * Checks, if a specified field is covered by a piece of a certain color. 352 * Checks, if a specified field is threatened by a piece of a certain color.
353 *
354 * A field is threatened, if there is a piece of the specified color that could
355 * capture an opponent piece on this field, regardless of being pinned.
319 * 356 *
320 * @param gamestate the current game state 357 * @param gamestate the current game state
321 * @param row row of the field to check 358 * @param row row of the field to check
322 * @param file file of the field to check 359 * @param file file of the field to check
323 * @param color the color of the piece that should cover the field 360 * @param color the color of the piece that should cover the field
328 get_threats(gamestate, row, file, color, NULL, NULL) 365 get_threats(gamestate, row, file, color, NULL, NULL)
329 366
330 /** 367 /**
331 * Checks, if a specified field is attacked by a piece of a certain color. 368 * Checks, if a specified field is attacked by a piece of a certain color.
332 * 369 *
333 * I.e. the field is covered by a piece AND this piece is not pinned and 370 * I.e. the field is threatened by a piece AND this piece is not pinned and
334 * therefore able to perform the move. 371 * therefore able to perform the move.
335 * 372 *
336 * @param gamestate the current game state 373 * @param gamestate the current game state
337 * @param row row of the field to check 374 * @param row row of the field to check
338 * @param file file of the field to check 375 * @param file file of the field to check
344 get_real_threats(gamestate, row, file, color, NULL, NULL) 381 get_real_threats(gamestate, row, file, color, NULL, NULL)
345 382
346 /** 383 /**
347 * Checks, if a specified field is protected by a piece of a certain color. 384 * Checks, if a specified field is protected by a piece of a certain color.
348 * 385 *
349 * I.e. the field is covered by a piece that is NOT the king AND this piece is 386 * This is the same as is_attacked(), but only considers pieces that are not
350 * not pinned and therefore able to perform the move. 387 * the king.
351 * 388 *
352 * @param gamestate the current game state 389 * @param gamestate the current game state
353 * @param row row of the field to check 390 * @param row row of the field to check
354 * @param file file of the field to check 391 * @param file file of the field to check
355 * @param color the color of the piece that should cover the field 392 * @param color the color of the piece that should cover the field
356 * @return true, if any piece (excluding the king) of the specified color 393 * @return true, if any piece (excluding the king) of the specified color
357 * threatens the specified field and could capture an opponent piece 394 * threatens the specified field and could capture an opponent piece
358 */ 395 */
359 bool is_protected(GameState *gamestate, Row row, File file, Color color); 396 bool is_protected(const GameState *gamestate, Row row, File file, Color color);
360 397
361 /** 398 /**
362 * Checks, if the specified move cannot be performed, because the piece is 399 * Checks, if the specified move cannot be performed, because the piece is
363 * either pinned or cannot remove the check. 400 * either pinned or cannot remove the check.
364 * 401 *
370 * @param gamestate the current game state 407 * @param gamestate the current game state
371 * @param move the move to check 408 * @param move the move to check
372 * @return true, if the move cannot be performed because the king would be in 409 * @return true, if the move cannot be performed because the king would be in
373 * check after the move 410 * check after the move
374 */ 411 */
375 bool is_pinned(GameState *gamestate, Move *move); 412 bool is_pinned(const GameState *gamestate, const Move *move);
376 413
377 /** 414 /**
378 * Evaluates a move syntactically and stores the move data in the specified 415 * Evaluates a move syntactically and stores the move data in the specified
379 * object. 416 * object.
380 * 417 *
381 * When short algebraic notation is used, the source position is determined by 418 * When short algebraic notation is used, the source position is determined by
382 * the evaluating the allowed moves according to the current game state. 419 * evaluating the allowed moves according to the current game state.
420 *
421 * This function expects correct notation of check and checkmate indicators.
422 * For a more lazy evaluation, use eval_move_lazy().
383 * 423 *
384 * For a purely syntactic check, regardless of whether a piece exists that is 424 * For a purely syntactic check, regardless of whether a piece exists that is
385 * allowed to move that way, use check_move(). 425 * allowed to move that way, use check_move().
386 * 426 *
387 * @param gamestate the current game state 427 * @param gamestate the current game state
388 * @param mstr the input string to parse 428 * @param mstr the input string to parse
429 * @param color the color of the player to evaluate the move for
389 * @param move a pointer to object where the move data shall be stored 430 * @param move a pointer to object where the move data shall be stored
431 * @return status code (see macros in this file for the list of codes)
432 */
433 int eval_move(const GameState *gamestate,
434 const char *mstr, Color color, Move *move);
435
436 /**
437 * Evaluates a move syntactically and stores the move data in the specified
438 * object.
439 *
440 * When short algebraic notation is used, the source position is determined by
441 * evaluating the allowed moves according to the current game state.
442 *
443 * This function automatically corrects missing or incorrect check/checkmate
444 * indicators. Use eval_move() if you want to keep the original notation.
445 *
446 * For a purely syntactic check, regardless of whether a piece exists that is
447 * allowed to move that way, use check_move().
448 *
449 * @param gamestate the current game state
450 * @param mstr the input string to parse
390 * @param color the color of the player to evaluate the move for 451 * @param color the color of the player to evaluate the move for
452 * @param move a pointer to object where the move data shall be stored
391 * @return status code (see macros in this file for the list of codes) 453 * @return status code (see macros in this file for the list of codes)
392 */ 454 */
393 int eval_move(GameState *gamestate, const char *mstr, Move *move, Color color); 455 int eval_move_lazy(const GameState *gamestate,
456 const char *mstr, Color color, Move *move);
394 457
395 /** 458 /**
396 * Syntactically checks a move without verifying that a piece exists that is 459 * Syntactically checks a move without verifying that a piece exists that is
397 * allowed to move that way. 460 * allowed to move that way.
398 * 461 *
406 * Validates move by applying chess rules. 469 * Validates move by applying chess rules.
407 * @param gamestate the current game state 470 * @param gamestate the current game state
408 * @param move the move to validate 471 * @param move the move to validate
409 * @return status code (see macros in this file for the list of codes) 472 * @return status code (see macros in this file for the list of codes)
410 */ 473 */
411 int validate_move(GameState *gamestate, Move *move); 474 int validate_move(const GameState *gamestate, const Move *move);
412 475
413 /** 476 /**
414 * Applies a move and deletes captured pieces. 477 * Applies a move and deletes captured pieces.
415 * 478 *
416 * @param gamestate the current game state 479 * @param gamestate the current game state
425 * 488 *
426 * @param gamestate the current game state 489 * @param gamestate the current game state
427 * @param move_number the half-move that would now be played 490 * @param move_number the half-move that would now be played
428 * @param replay the struct to populate with the state at the specified move 491 * @param replay the struct to populate with the state at the specified move
429 */ 492 */
430 void gamestate_at_move(GameState *gamestate, 493 void gamestate_at_move(const GameState *gamestate,
431 unsigned move_number, GameState *replay); 494 unsigned move_number, GameState *replay);
432 495
433 /** 496 /**
434 * Returns the remaining time on the clock for the specified 497 * Returns the remaining time on the clock for the specified
435 * half-move number. 498 * half-move number.
437 * @param gamestate the current game state 500 * @param gamestate the current game state
438 * @param move_number the half-move that is now going to be played 501 * @param move_number the half-move that is now going to be played
439 * @return the remaining time - if time control is disabled, this function 502 * @return the remaining time - if time control is disabled, this function
440 * always returns zero 503 * always returns zero
441 */ 504 */
442 uint16_t remaining_movetime2(GameState *gamestate, unsigned move_number); 505 uint16_t remaining_movetime2(const GameState *gamestate, unsigned move_number);
443 506
444 /** 507 /**
445 * Returns the remaining time on the clock for the specified player. 508 * Returns the remaining time on the clock for the specified player.
446 * 509 *
447 * @param gamestate the current game state 510 * @param gamestate the current game state
448 * @param color either BLACK or WHITE 511 * @param color either BLACK or WHITE
449 * @return the remaining time - if time control is disabled, this function 512 * @return the remaining time - if time control is disabled, this function
450 * always returns zero 513 * always returns zero
451 */ 514 */
452 uint16_t remaining_movetime(GameState *gamestate, Color color); 515 uint16_t remaining_movetime(const GameState *gamestate, Color color);
453 516
454 /** 517 /**
455 * Converts clock time to string. 518 * Converts clock time to string.
456 * 519 *
457 * @param time the time to format 520 * @param time the time to format
470 * But implementation may choose to automatically draw the game anyway. 533 * But implementation may choose to automatically draw the game anyway.
471 * 534 *
472 * @param gamestate the current game state 535 * @param gamestate the current game state
473 * @return true if the game is in a threefold repetition position 536 * @return true if the game is in a threefold repetition position
474 */ 537 */
475 bool check_threefold_repetition(GameState *gamestate); 538 bool check_threefold_repetition(const GameState *gamestate);
476 539
477 #endif /* RULES_H */ 540 #endif /* RULES_H */
478 541

mercurial