src/chess/rules.h

changeset 193
d1420f5c5704
parent 186
8230904458a7
child 194
619f07c95894
--- a/src/chess/rules.h	Mon Aug 24 16:13:51 2026 +0200
+++ b/src/chess/rules.h	Tue Aug 25 18:35:18 2026 +0200
@@ -49,11 +49,27 @@
 #define INVALID_CHECKMATE     11
 #define RULES_VIOLATED        32
 
+#if __STDC_VERSION__ < 202310L
+/* since #warning is also a C23 feature, the only hope is this: */
+#pragma GCC warning "Type safety for enums is only available since C23"
+#define enum_uint8_t(name) enum e##name
+#define typedef_enum_uint8_t(name) typedef uint8_t name
+#else
+#define enum_uint8_t(name) enum e##name : uint8_t
+#define typedef_enum_uint8_t(name) typedef enum e##name name
+#endif
+
 #define ENPASSANT_THREAT 0x40u
 
-#define WHITE 0x10u
-#define BLACK 0x20u
-#define opponent_color(color) ((color)==WHITE?BLACK:WHITE)
+enum_uint8_t(Color) {
+    WHITE = 0x10u,
+    BLACK = 0x20u,
+};
+typedef_enum_uint8_t(Color);
+
+static inline Color opponent_color(Color color) {
+    return color == WHITE ? BLACK : WHITE;
+}
 
 #define PIECE_MASK 0x0Fu
 #define COLOR_MASK 0x30u
@@ -65,25 +81,36 @@
 #define QUEEN  0x05u
 #define KING   0x06u
 
-#define WPAWN   (WHITE|PAWN)
-#define WROOK   (WHITE|ROOK)
-#define WKNIGHT (WHITE|KNIGHT)
-#define WBISHOP (WHITE|BISHOP)
-#define WQUEEN  (WHITE|QUEEN)
-#define WKING   (WHITE|KING)
-#define BPAWN   (BLACK|PAWN)
-#define BROOK   (BLACK|ROOK)
-#define BKNIGHT (BLACK|KNIGHT)
-#define BBISHOP (BLACK|BISHOP)
-#define BQUEEN  (BLACK|QUEEN)
-#define BKING   (BLACK|KING)
+enum_uint8_t(Piece) {
+    WPAWN   = WHITE|PAWN,
+    WROOK   = WHITE|ROOK,
+    WKNIGHT = WHITE|KNIGHT,
+    WBISHOP = WHITE|BISHOP,
+    WQUEEN  = WHITE|QUEEN,
+    WKING   = WHITE|KING,
+    BPAWN   = BLACK|PAWN,
+    BROOK   = BLACK|ROOK,
+    BKNIGHT = BLACK|KNIGHT,
+    BBISHOP = BLACK|BISHOP,
+    BQUEEN  = BLACK|QUEEN,
+    BKING   = BLACK|KING,
+};
+typedef_enum_uint8_t(Piece);
+
+#define POS_UNSPECIFIED 255u
+enum_uint8_t(Row) {
+    RANK_1 = 0, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8,
+    RANK_UNSPECIFIED = POS_UNSPECIFIED
+};
+typedef_enum_uint8_t(Row);
+
+enum_uint8_t(File) {
+    FILE_A = 0, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H,
+    FILE_UNSPECIFIED = POS_UNSPECIFIED
+};
+typedef_enum_uint8_t(File);
 
 typedef uint8_t Board[8][8];
-typedef uint8_t BoardIndex;
-typedef BoardIndex Row;
-typedef BoardIndex File;
-typedef uint8_t Piece;
-typedef uint8_t Color;
 
 struct movetimeval {
     uint64_t sec;
@@ -154,31 +181,26 @@
     bool review;
 } GameState;
 
-#define piece_type(piece) ((piece)&PIECE_MASK)
-#define piece_color(piece) ((piece)&COLOR_MASK)
-#define mkpiece(type,color) ((type)|(color))
+#define piece_type(piece) ((uint8_t)(piece)&PIECE_MASK)
+#define piece_color(piece) ((uint8_t)(piece)&COLOR_MASK)
+#define mkpiece(type,color) (Piece)((type)|(color))
 
-#define POS_UNSPECIFIED UINT8_MAX
 #define mdst(m) (m)->torow, (m)->tofile
 #define msrc(m) (m)->fromrow, (m)->fromfile
 
 /** Checks if the index is specified and valid. */
-#define isidx(idx) ((BoardIndex)(idx) < 8)
+static inline bool isidx(uint8_t idx) {return idx < 8;}
 /** Checks if the index is unspecified or valid. */
-#define isidxr(idx) ((idx) == POS_UNSPECIFIED || (BoardIndex)(idx) < 8)
-
-#define isfile(file) (file >= 'a' && file <= 'h')
-#define isrow(row) (row >= '1' && row <= '8')
+static inline bool isidxr(uint8_t idx) {return idx==POS_UNSPECIFIED || idx<8;}
 
-#define rowidx(row) (row-'1')
-#define fileidx(file) (file-'a')
+static inline bool isfile(char file) {return file >= 'a' && file <= 'h';}
+static inline bool isrow(char row) {return row >= '1' && row <= '8';}
 
-#define rowchr(row) (row+'1')
-#define filechr(file) (file+'a')
+static inline Row rowidx(char row) {return row-'1';}
+static inline File fileidx(char file) {return file-'a';}
 
-/* secure versions - use, if index is not checked with isidx() */
-#define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED)
-#define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED)
+static inline char rowchr(Row row) {return (char)row+'1';}
+static inline char filechr(File file) {return (char)file+'a';}
 
 
 static inline void enpassant_threat_add(GameState *gamestate,

mercurial