# HG changeset patch # User Mike Becker # Date 1785404987 -7200 # Node ID 3ff96fec144a226c5a7d45b37ceeab760313166b # Parent f87832cba8b8144f7182db9158177738ca5c1e17 convert some macros to static inline functions also fixes a theoretical memmory access bug in king_isblocked() diff -r f87832cba8b8 -r 3ff96fec144a src/chess/king.c --- a/src/chess/king.c Wed Jul 29 13:45:51 2026 +0200 +++ b/src/chess/king.c Thu Jul 30 11:49:47 2026 +0200 @@ -29,11 +29,10 @@ #include "rules.h" #include "king.h" -#include -static bool king_castling_chkmoved(GameState *gamestate, - uint8_t row, uint8_t file) { +#include +static bool king_castling_chkmoved(GameState *gamestate, Row row, File file) { for (unsigned i = 0; i < gamestate->movecount; i++) { if (gamestate->moves[i].fromfile == file && gamestate->moves[i].fromrow == row) { @@ -51,7 +50,7 @@ } else { /* castling */ if (move->fromrow == move->torow && - move->fromrow == ((move->piece&COLOR_MASK) == WHITE ? 0 : 7) && + move->fromrow == (piece_color(move->piece) == WHITE ? 0 : 7) && move->fromfile == fileidx('e') && (move->tofile == fileidx('c') || move->tofile == fileidx('g'))) { @@ -67,7 +66,7 @@ bool king_isblocked(GameState *gamestate, Move *move) { - uint8_t opponent_color = opponent_color(move->piece&COLOR_MASK); + uint8_t opponent_color = opponent_color(piece_color(move->piece)); /* being in check does not "block" the king, so don't test it here */ bool blocked = false; @@ -78,8 +77,11 @@ blocked |= gamestate->board[move->torow][fileidx('b')]; } uint8_t midfile = (move->tofile+move->fromfile)/2; - blocked |= last_move(gamestate).check || - gamestate->board[move->torow][midfile] || + bool incheck = false; + if (gamestate->movecount > 0) { + incheck = gamestate->moves[gamestate->movecount-1].check; + } + blocked |= incheck || gamestate->board[move->torow][midfile] || is_covered(gamestate, move->torow, midfile, opponent_color); } diff -r f87832cba8b8 -r 3ff96fec144a src/chess/rules.c --- a/src/chess/rules.c Wed Jul 29 13:45:51 2026 +0200 +++ b/src/chess/rules.c Thu Jul 30 11:49:47 2026 +0200 @@ -92,7 +92,7 @@ if (gamestate->movecount > 0) { simulation.fen_start = strdup(gamestate->movecount == 1 ? gamestate->fen_start : gamestate->fen[gamestate->movecount - 2]); - simulation.moves[0] = last_move(gamestate); + simulation.moves[0] = gamestate->moves[gamestate->movecount - 1]; simulation.fen[0] = strdup(gamestate->fen[gamestate->movecount - 1]); simulation.movecount++; } else { @@ -200,7 +200,8 @@ move->movetime.tv_usec = 0; move->movetime.tv_sec = 0; if (gamestate->movecount > 1) { - struct movetimeval lasttstamp = last_move(gamestate).timestamp; + struct movetimeval lasttstamp = + gamestate->moves[gamestate->movecount - 1].timestamp; uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; suseconds_t micros; if (curtimestamp.tv_usec < lasttstamp.tv_usec) { @@ -469,9 +470,11 @@ if (piece_type(move->piece) == KING) { return KING_MOVES_INTO_CHECK; } else { - /* last move is always not null in this case */ - return last_move(gamestate).check ? - KING_IN_CHECK : PIECE_PINNED; + if (gamestate->moves[gamestate->movecount - 1].check) { + return KING_IN_CHECK; + } else { + return PIECE_PINNED; + } } } @@ -710,7 +713,10 @@ static int getlocation(GameState *gamestate, Move *move) { Color color = piece_color(move->piece); - bool incheck = gamestate->movecount > 0 ? last_move(gamestate).check:false; + bool incheck = false; + if (gamestate->movecount > 0) { + incheck = gamestate->moves[gamestate->movecount - 1].check; + } Move threats[16], *threat = NULL; size_t threatcount; diff -r f87832cba8b8 -r 3ff96fec144a src/chess/rules.h --- a/src/chess/rules.h Wed Jul 29 13:45:51 2026 +0200 +++ b/src/chess/rules.h Thu Jul 30 11:49:47 2026 +0200 @@ -150,20 +150,6 @@ #define piece_color(piece) ((piece)&COLOR_MASK) #define mkpiece(type,color) ((type)|(color)) -#define enpassant_threat_add(gamestate, row, file) \ - (gamestate->board[row][file] |= ENPASSANT_THREAT) -#define enpassant_threat_remove(gamestate, row, file) \ - (gamestate->board[row][file] &= ~ENPASSANT_THREAT) -#define enpassant_threat_exists(gamestate, row, file) \ - (gamestate->board[row][file] & ENPASSANT_THREAT) - -#define is_game_running(gamestate) !((gamestate)->checkmate || \ - (gamestate)->wresign || (gamestate)->bresign || (gamestate)->threefold || \ - (gamestate)->stalemate || (gamestate)->remis || (gamestate)->review) - -#define last_move(gamestate) \ - ((gamestate)->moves[(gamestate)->movecount-1]) - #define POS_UNSPECIFIED UINT8_MAX #define mdst(m) (m)->torow, (m)->tofile #define msrc(m) (m)->fromrow, (m)->fromfile @@ -186,6 +172,26 @@ #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED) #define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED) + +static inline void enpassant_threat_add(GameState *gamestate, + Row row, File file) { + gamestate->board[row][file] |= ENPASSANT_THREAT; +} + +static inline void enpassant_threat_remove(GameState *gamestate, + Row row, File file) { + gamestate->board[row][file] &= ~ENPASSANT_THREAT; +} + +static inline bool enpassant_threat_exists(const GameState *gamestate, + Row row, File file) { + return gamestate->board[row][file] & ENPASSANT_THREAT; +} + +static inline bool is_game_running(const GameState *gamestate) { + return !(gamestate->checkmate || gamestate->wresign || gamestate->bresign || gamestate->threefold || gamestate->stalemate || gamestate->remis || gamestate->review); +} + /** * Initializes a game state and prepares the chess board. * @param gamestate the game state to initialize