convert some macros to static inline functions

Thu, 30 Jul 2026 11:49:47 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 30 Jul 2026 11:49:47 +0200
changeset 161
3ff96fec144a
parent 160
f87832cba8b8
child 162
f0fc70b6f8f9

convert some macros to static inline functions

also fixes a theoretical memmory access bug in king_isblocked()

src/chess/king.c file | annotate | diff | comparison | revisions
src/chess/rules.c file | annotate | diff | comparison | revisions
src/chess/rules.h file | annotate | diff | comparison | revisions
--- 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 <stdlib.h>
 
-static bool king_castling_chkmoved(GameState *gamestate,
-    uint8_t row, uint8_t file) {
+#include <string.h>
 
+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);
     }
     
--- 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;
--- 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

mercurial