src/chess/rules.c

changeset 160
f87832cba8b8
parent 158
52d452d0e7bf
--- a/src/chess/rules.c	Tue Jul 28 13:44:10 2026 +0200
+++ b/src/chess/rules.c	Wed Jul 29 13:45:51 2026 +0200
@@ -40,6 +40,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/time.h>
+#include <assert.h>
 
 void gamestate_init(GameState *gamestate) {
     memset(gamestate, 0, sizeof(GameState));
@@ -101,7 +102,7 @@
     return simulation;
 }
 
-uint8_t current_color(GameState *gamestate) {
+Color current_color(GameState *gamestate) {
     return (gamestate->movecount % 2 == 0) ? WHITE : BLACK;
 }
 
@@ -113,7 +114,7 @@
     memset(string, 0, 8);
     
     unsigned int idx;
-    if ((move->piece&PIECE_MASK) == KING &&
+    if (piece_type(move->piece) == KING &&
             abs(move->tofile-move->fromfile) == 2) {
         /* special formats for castling */
         if (move->tofile==fileidx('c')) {
@@ -129,19 +130,18 @@
         idx = string[0] ? 1 : 0;
 
         /* find out how many source information we do need */
-        uint8_t piece = move->piece & PIECE_MASK;
-        if (piece == PAWN) {
+        if (piece_type(move->piece) == PAWN) {
             if (move->capture) {
                 string[idx++] = filechr(move->fromfile);
             }
-        } else if (piece != KING) {
+        } else if (piece_type(move->piece) != KING) {
             /* resolve ambiguities, if any */
             Move threats[16];
-            uint8_t threatcount;
+            size_t threatcount;
             if (get_threats(gamestate, move->torow, move->tofile,
-                    move->piece&COLOR_MASK, threats, &threatcount)) {
+                    piece_color(move->piece), threats, &threatcount)) {
                 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0;
-                for (uint8_t i = 0 ; i < threatcount ; i++) {
+                for (size_t i = 0 ; i < threatcount ; i++) {
                     if (threats[i].piece == move->piece) {
                         ambpiece++;
                         if (threats[i].fromrow == move->fromrow) {
@@ -222,8 +222,8 @@
     }
 }
 
-char getpiecechr(uint8_t piece) {
-    switch (piece & PIECE_MASK) {
+char getpiecechr(Piece piece) {
+    switch (piece_type(piece)) {
     case ROOK: return 'R';
     case KNIGHT: return 'N';
     case BISHOP: return 'B';
@@ -233,9 +233,9 @@
     }
 }
 
-char* getpieceunicode(uint8_t piece) {
-    if ((piece & COLOR_MASK) == WHITE) {
-        switch (piece & PIECE_MASK) {
+char* getpieceunicode(Piece piece) {
+    if (piece_color(piece) == WHITE) {
+        switch (piece_type(piece)) {
         case PAWN: return "\u2659";
         case ROOK: return "\u2656";
         case KNIGHT: return "\u2658";
@@ -245,7 +245,7 @@
         default: return "";
         }
     } else {
-        switch (piece & PIECE_MASK) {
+        switch (piece_type(piece)) {
         case PAWN: return "\u265f";
         case ROOK: return "\u265c";
         case KNIGHT: return "\u265e";
@@ -257,13 +257,13 @@
     }
 }
 
-uint8_t getpiece(char c) {
+Piece getpiece(char c, Color color) {
     switch (c) {
-        case 'R': return ROOK;
-        case 'N': return KNIGHT;
-        case 'B': return BISHOP;
-        case 'Q': return QUEEN;
-        case 'K': return KING;
+        case 'R': return mkpiece(ROOK, color);
+        case 'N': return mkpiece(KNIGHT, color);
+        case 'B': return mkpiece(BISHOP, color);
+        case 'Q': return mkpiece(QUEEN, color);
+        case 'K': return mkpiece(KING, color);
         default: return 0;
     }
 }
@@ -276,45 +276,43 @@
             format_move(gamestate, move);
         }
     }
-    
-    uint8_t piece = move->piece & PIECE_MASK;
-    uint8_t color = move->piece & COLOR_MASK;
-    
+
     /* en passant capture */
-    if (move->capture && piece == PAWN &&
-        mdst(gamestate->board, move) == 0) {
-        gamestate->board[move->fromrow][move->tofile] = 0;
+    if (move->capture && piece_type(move->piece) == PAWN &&
+            piece_at(gamestate, mdst(move)) == 0) {
+        piece_remove(gamestate, move->fromrow, move->tofile);
     }
     
     /* remove old en passant threats */
-    for (uint8_t file = 0 ; file < 8 ; file++) {
-        gamestate->board[3][file] &= ~ENPASSANT_THREAT;
-        gamestate->board[4][file] &= ~ENPASSANT_THREAT;
-    }
-    
-    /* add new en passant threat */
-    if (piece == PAWN && (
-        (move->fromrow == 1 && move->torow == 3) ||
-        (move->fromrow == 6 && move->torow == 4))) {
-        move->piece |= ENPASSANT_THREAT;
+    for (File file = 0 ; file < 8 ; file++) {
+        enpassant_threat_remove(gamestate, 3, file);
+        enpassant_threat_remove(gamestate, 4, file);
     }
     
     /* move (and maybe capture or promote) */
-    msrc(gamestate->board, move) = 0;
+    piece_remove(gamestate, msrc(move));
     if (move->promotion) {
-        mdst(gamestate->board, move) = move->promotion;
+        piece_set(gamestate, mdst(move), move->promotion);
     } else {
-        mdst(gamestate->board, move) = move->piece;
+        piece_set(gamestate, mdst(move), move->piece);
+    }
+
+    /* add new en passant threat */
+    if (piece_type(move->piece) == PAWN && (
+            (move->fromrow == 1 && move->torow == 3) ||
+            (move->fromrow == 6 && move->torow == 4))) {
+        enpassant_threat_add(gamestate, move->torow, move->tofile);
     }
     
     /* castling */
-    if (piece == KING && move->fromfile == fileidx('e')) {
+    if (piece_type(move->piece) == KING && move->fromfile == fileidx('e')) {
+        const Color color = piece_color(move->piece);
         if (move->tofile == fileidx('g')) {
             gamestate->board[move->torow][fileidx('h')] = 0;
-            gamestate->board[move->torow][fileidx('f')] = color|ROOK;
+            gamestate->board[move->torow][fileidx('f')] = mkpiece(ROOK, color);
         } else if (move->tofile == fileidx('c')) {
             gamestate->board[move->torow][fileidx('a')] = 0;
-            gamestate->board[move->torow][fileidx('d')] = color|ROOK;
+            gamestate->board[move->torow][fileidx('d')] = mkpiece(ROOK, color);
         }
     }
     
@@ -363,6 +361,8 @@
 }
 
 static int validate_move_rules(GameState *gamestate, Move *move) {
+    assert((move->piece & ~(PIECE_MASK|COLOR_MASK)) == 0);
+
     /* validate indices (don't trust opponent) */
     if (!isidx(move->fromrow) || !isidx(move->fromfile) ||
         !isidx(move->torow) || !isidx(move->tofile)) {
@@ -375,31 +375,31 @@
     }
     
     /* does piece exist */
-    if ((msrc(gamestate->board, move)&(PIECE_MASK|COLOR_MASK))
-           != (move->piece&(PIECE_MASK|COLOR_MASK))) {
+    if (piece_at(gamestate, msrc(move)) != move->piece) {
         return PIECE_NOT_FOUND;
     }
+
+    /* is there any piece at the destination? */
+    Piece piece_at_dst = piece_at(gamestate, mdst(move));
     
     /* can't capture own pieces */
-    if ((mdst(gamestate->board, move) & COLOR_MASK)
-            == (move->piece & COLOR_MASK)) {
+    if (piece_color(piece_at_dst) == piece_color(move->piece)) {
         return RULES_VIOLATED;
     }
-    
+
     /* must capture, if and only if destination is occupied... */
-    if ((mdst(gamestate->board, move) == 0 && move->capture) ||
-            (mdst(gamestate->board, move) != 0 && !move->capture)) {
+    if (!((piece_at_dst == 0) ^ move->capture)) {
         /* ... or the capture happens en passant */
-        if (!move->capture || (move->piece & PIECE_MASK) != PAWN ||
-                !(gamestate->board[move->fromrow][move->tofile]
-                  & ENPASSANT_THREAT)) {
+        if (!move->capture || piece_type(move->piece) != PAWN ||
+                !enpassant_threat_exists(gamestate,
+                    move->fromrow, move->tofile)) {
             return INVALID_MOVE_SYNTAX;
         }
     }
     
     /* validate individual rules */
     bool chkrules;
-    switch (move->piece & PIECE_MASK) {
+    switch (piece_type(move->piece)) {
     case PAWN:
         chkrules = pawn_chkrules(gamestate, move) &&
             !pawn_isblocked(gamestate, move);
@@ -445,18 +445,18 @@
     apply_move_impl(&simulation, &simmove, true);
     
     /* find kings for check validation */
-    uint8_t piececolor = (move->piece & COLOR_MASK);
-    uint8_t oppcolor = opponent_color(piececolor);
+    Color piececolor = piece_color(move->piece);
+    Color oppcolor = opponent_color(piececolor);
     
-    uint8_t mykingfile = 0, mykingrow = 0, opkingfile = 0, opkingrow = 0;
-    for (uint8_t row = 0 ; row < 8 ; row++) {
-        for (uint8_t file = 0 ; file < 8 ; file++) {
-            if (simulation.board[row][file] ==
-                    (piececolor == WHITE?WKING:BKING)) {
+    File mykingfile = 0, opkingfile = 0;
+    Row  mykingrow = 0, opkingrow = 0;
+    for (Row row = 0 ; row < 8 ; row++) {
+        for (File file = 0 ; file < 8 ; file++) {
+            Piece p = piece_at(&simulation, row, file);
+            if (p == mkpiece(KING, piececolor)) {
                 mykingfile = file;
                 mykingrow = row;
-            } else if (simulation.board[row][file] ==
-                    (piececolor == WHITE?BKING:WKING)) {
+            } else if (p == mkpiece(KING, oppcolor)) {
                 opkingfile = file;
                 opkingrow = row;
             }
@@ -466,7 +466,7 @@
     /* don't move into or stay in check position */
     if (is_covered(&simulation, mykingrow, mykingfile, oppcolor)) {
         gamestate_cleanup(&simulation);
-        if ((move->piece & PIECE_MASK) == KING) {
+        if (piece_type(move->piece) == KING) {
             return KING_MOVES_INTO_CHECK;
         } else {
             /* last move is always not null in this case */
@@ -477,7 +477,7 @@
     
     /* correct check and checkmate flags (move is still valid) */
     Move threats[16];
-    uint8_t threatcount;
+    size_t threatcount;
     move->check = get_threats(&simulation, opkingrow, opkingfile,
         piececolor, threats, &threatcount);
     
@@ -489,23 +489,23 @@
                 if (dr == 0 && df == 0) continue;
                 if (!isidx(opkingrow + dr)) continue;
                 if (!isidx(opkingfile + df)) continue;
-                uint8_t er = opkingrow + dr;
-                uint8_t ef = opkingfile + df;
+                Row er = opkingrow + dr;
+                File ef = opkingfile + df;
 
                 /* check if escape field is already covered (threatened) */
                 if (is_covered(&simulation, er, ef, piececolor))
                     continue;
 
                 /* check if piece of the king's color blocks the field */
-                if ((simulation.board[er][ef] & COLOR_MASK) == oppcolor)
+                if (piece_color(simulation.board[er][ef]) == oppcolor)
                     continue;
 
                 /* check if an attacking piece blocks the field */
-                if ((simulation.board[er][ef] & COLOR_MASK) == piececolor) {
+                if (piece_color(simulation.board[er][ef]) == piececolor) {
                     /* test if the king can fight back */
                     GameState sim_retaliate = gamestate_copy_sim(&simulation);
                     Move move_retaliate = {0};
-                    move_retaliate.piece = (oppcolor|KING);
+                    move_retaliate.piece = mkpiece(KING, oppcolor);
                     move_retaliate.fromrow = opkingrow;
                     move_retaliate.fromfile = opkingfile;
                     move_retaliate.torow = er;
@@ -530,15 +530,14 @@
         /* can't capture, can he block? */
         if (!canescape && threatcount == 1) {
             Move *threat = &(threats[0]);
-            uint8_t threatpiece = threat->piece & PIECE_MASK;
+            unsigned tptype = piece_type(threat->piece);
             
             /* knight, pawns and the king cannot be blocked */
-            if (threatpiece == BISHOP || threatpiece == ROOK
-                || threatpiece == QUEEN) {
+            if (tptype == BISHOP || tptype == ROOK || tptype == QUEEN) {
                 if (threat->fromrow == threat->torow) {
                     /* rook aspect (on row) */
                     int d = threat->tofile > threat->fromfile ? 1 : -1;
-                    uint8_t file = threat->fromfile;
+                    File file = threat->fromfile;
                     while (!canescape && file != threat->tofile - d) {
                         file += d;
                         canescape |= is_protected(&simulation,
@@ -547,7 +546,7 @@
                 } else if (threat->fromfile == threat->tofile) {
                     /* rook aspect (on file) */
                     int d = threat->torow > threat->fromrow ? 1 : -1;
-                    uint8_t row = threat->fromrow;
+                    Row row = threat->fromrow;
                     while (!canescape && row != threat->torow - d) {
                         row += d;
                         canescape |= is_protected(&simulation,
@@ -558,10 +557,10 @@
                     int dr = threat->torow > threat->fromrow ? 1 : -1;
                     int df = threat->tofile > threat->fromfile ? 1 : -1;
 
-                    uint8_t row = threat->fromrow;
-                    uint8_t file = threat->fromfile;
+                    Row row = threat->fromrow;
+                    File file = threat->fromfile;
                     while (!canescape && file != threat->tofile - df
-                        && row != threat->torow - dr) {
+                            && row != threat->torow - dr) {
                         row += dr;
                         file += df;
                         canescape |= is_protected(&simulation, row, file,
@@ -581,32 +580,40 @@
     return VALID_MOVE_SEMANTICS;
 }
 
-bool get_threats(GameState *gamestate, uint8_t row, uint8_t file,
-        uint8_t color, Move *threats, uint8_t *threatcount) {
+Piece piece_at(const GameState *gamestate, Row row, File file) {
+    return gamestate->board[row][file] & (PIECE_MASK|COLOR_MASK);
+}
+
+void piece_set(GameState *gamestate, Row row, File file, Piece piece) {
+    gamestate->board[row][file] = piece;
+}
+
+bool get_threats(GameState *gamestate, Row row, File file,
+        Color color, Move *threats, size_t *threatcount) {
     Move candidates[32];
-    int candidatecount = 0;
-    for (uint8_t r = 0 ; r < 8 ; r++) {
-        for (uint8_t f = 0 ; f < 8 ; f++) {
-            if ((gamestate->board[r][f] & COLOR_MASK) == color) {
+    size_t ccount = 0;
+    for (Row r = 0 ; r < 8 ; r++) {
+        for (File f = 0 ; f < 8 ; f++) {
+            if (piece_color(gamestate->board[r][f]) == color) {
                 /* non-capturing move */
-                memset(&(candidates[candidatecount]), 0, sizeof(Move));
-                candidates[candidatecount].piece = gamestate->board[r][f];
-                candidates[candidatecount].fromrow = r;
-                candidates[candidatecount].fromfile = f;
-                candidates[candidatecount].torow = row;
-                candidates[candidatecount].tofile = file;
-                if ((gamestate->board[r][f]&PIECE_MASK) == PAWN
-                        && (row == 0 || row == 7)) {
+                memset(&(candidates[ccount]), 0, sizeof(Move));
+                Piece p = piece_at(gamestate, r, f);
+                candidates[ccount].piece = p;
+                candidates[ccount].fromrow = r;
+                candidates[ccount].fromfile = f;
+                candidates[ccount].torow = row;
+                candidates[ccount].tofile = file;
+                if (piece_type(p) == PAWN && (row == 0 || row == 7)) {
                     /* the exact piece for promotion does not matter */
-                    candidates[candidatecount].promotion = color|QUEEN;
+                    candidates[ccount].promotion = mkpiece(QUEEN, color);
                 }
-                candidatecount++;
+                ccount++;
 
                 /* capturing move */
-                memcpy(&(candidates[candidatecount]),
-                    &(candidates[candidatecount-1]), sizeof(Move));
-                candidates[candidatecount].capture = 1;
-                candidatecount++;
+                memcpy(&(candidates[ccount]),
+                    &(candidates[ccount-1]), sizeof(Move));
+                candidates[ccount].capture = 1;
+                ccount++;
             }
         }
     }
@@ -618,7 +625,7 @@
     
     bool result = false;
     
-    for (int i = 0 ; i < candidatecount ; i++) {
+    for (size_t i = 0 ; i < ccount ; i++) {
         if (validate_move_rules(gamestate, &(candidates[i]))
                 == VALID_MOVE_SEMANTICS) {
             result = true;
@@ -632,15 +639,16 @@
 }
 
 bool is_pinned(GameState *gamestate, Move *move) {
-    uint8_t color = move->piece & COLOR_MASK;
+    Color color = piece_color(move->piece);
 
     GameState simulation = gamestate_copy_sim(gamestate);
     Move simmove = *move;
     apply_move(&simulation, &simmove);
     
-    uint8_t kingfile = 0, kingrow = 0;
-    for (uint8_t row = 0 ; row < 8 ; row++) {
-        for (uint8_t file = 0 ; file < 8 ; file++) {
+    File kingfile = 0;
+    Row kingrow = 0;
+    for (Row row = 0 ; row < 8 ; row++) {
+        for (File file = 0 ; file < 8 ; file++) {
             if (simulation.board[row][file] == (color|KING)) {
                 kingfile = file;
                 kingrow = row;
@@ -655,21 +663,22 @@
     return covered;
 }
 
-bool get_real_threats(GameState *gamestate, uint8_t row, uint8_t file,
-        uint8_t color, Move *threats, uint8_t *threatcount) {
+bool get_real_threats(GameState *gamestate, Row row, File file,
+        Color color, Move *threats, size_t *threatcount) {
     
     if (threatcount) {
         *threatcount = 0;
     }
 
     Move candidates[16];
-    uint8_t candidatecount;
+    size_t candidatecount;
     if (get_threats(gamestate, row, file, color, candidates, &candidatecount)) {
         
         bool result = false;
-        uint8_t kingfile = 0, kingrow = 0;
-        for (uint8_t r = 0 ; r < 8 ; r++) {
-            for (uint8_t f = 0 ; f < 8 ; f++) {
+        File kingfile = 0;
+        Row kingrow = 0;
+        for (Row r = 0 ; r < 8 ; r++) {
+            for (File f = 0 ; f < 8 ; f++) {
                 if (gamestate->board[r][f] == (color|KING)) {
                     kingfile = f;
                     kingrow = r;
@@ -677,7 +686,7 @@
             }
         }
 
-        for (uint8_t i = 0 ; i < candidatecount ; i++) {
+        for (size_t i = 0 ; i < candidatecount ; i++) {
             // TODO: check if we really need full-blown simulations here
             GameState simulation = gamestate_copy_sim(gamestate);
             Move simmove = candidates[i];
@@ -700,12 +709,11 @@
 
 static int getlocation(GameState *gamestate, Move *move) {   
 
-    uint8_t color = move->piece & COLOR_MASK;
-    uint8_t piece = move->piece & PIECE_MASK;
+    Color color = piece_color(move->piece);
     bool incheck = gamestate->movecount > 0 ? last_move(gamestate).check:false;
     
     Move threats[16], *threat = NULL;
-    uint8_t threatcount;
+    size_t threatcount;
 
     /* determine all threats and sort out the unreal threats on our own */
     if (get_threats(gamestate, move->torow, move->tofile, color,
@@ -714,7 +722,7 @@
         bool found = false;
         
         /* find threats for the specified position */
-        for (uint8_t i = 0 ; i < threatcount ; i++) {
+        for (size_t i = 0 ; i < threatcount ; i++) {
             if (threats[i].piece == move->piece &&
                     (move->fromrow == POS_UNSPECIFIED ||
                     move->fromrow == threats[i].fromrow) &&
@@ -739,7 +747,7 @@
         /* can't threaten specified position */
         if (!threat) {
             if (found) {
-                if (piece == KING) {
+                if (piece_type(move->piece) == KING) {
                     return KING_MOVES_INTO_CHECK;
                 } else if (incheck) {
                     return KING_IN_CHECK;
@@ -760,7 +768,7 @@
     }
 }
 
-static int eval_move1(const char *pstr, Move *move, uint8_t color) {
+static int eval_move1(const char *pstr, Move *move, Color color) {
     memset(move, 0, sizeof(Move));
     move->fromfile = POS_UNSPECIFIED;
     move->fromrow = POS_UNSPECIFIED;
@@ -780,11 +788,10 @@
     
     /* evaluate promotion */
     if (len > 3 && mstr[len-2] == '=') {
-        move->promotion = getpiece(mstr[len-1]);
+        move->promotion = getpiece(mstr[len-1], color);
         if (!move->promotion) {
             return INVALID_MOVE_SYNTAX;
         } else {
-            move->promotion |= color;
             len -= 2;
             mstr[len] = 0;
         }
@@ -792,26 +799,26 @@
     
     if (len == 2) {
         /* pawn move (e.g. "e4") */
-        move->piece = PAWN;
+        move->piece = mkpiece(PAWN, color);
         move->tofile = fileidx(mstr[0]);
         move->torow = rowidx(mstr[1]);
     } else if (len == 3) {
         if (strcmp(mstr, "O-O") == 0) {
             /* king side castling */
-            move->piece = KING;
+            move->piece = mkpiece(KING, color);
             move->fromfile = fileidx('e');
             move->tofile = fileidx('g');
             move->fromrow = move->torow = color == WHITE ? 0 : 7;
         } else {
             /* move (e.g. "Nf3") */
-            move->piece = getpiece(mstr[0]);
+            move->piece = getpiece(mstr[0], color);
             move->tofile = fileidx(mstr[1]);
             move->torow = rowidx(mstr[2]);
         }
     } else if (len == 4) {
-        move->piece = getpiece(mstr[0]);
-        if (!move->piece) {
-            move->piece = PAWN;
+        move->piece = getpiece(mstr[0], color);
+        if (move->piece == 0) {
+            move->piece = mkpiece(PAWN, color);
             move->fromfile = fileidx(mstr[0]);
         }
         if (mstr[1] == 'x') {
@@ -821,7 +828,9 @@
             /* move (e.g. "Ndf3", "N2c3", "e2e4") */
             if (isfile(mstr[1])) {
                 move->fromfile = fileidx(mstr[1]);
-                if (move->piece == PAWN) {
+                /* when the piece is a pawn, second char cannot be a file */
+                if (piece_type(move->piece) == PAWN) {
+                    /* invalidate the result */
                     move->piece = 0;
                 }
             } else {
@@ -833,12 +842,12 @@
     } else if (len == 5) {
         if (strcmp(mstr, "O-O-O") == 0) {
             /* queen side castling "O-O-O" */
-            move->piece = KING;
+            move->piece = mkpiece(KING, color);
             move->fromfile = fileidx('e');
             move->tofile = fileidx('c');
             move->fromrow = move->torow = color == WHITE ? 0 : 7;
         } else {
-            move->piece = getpiece(mstr[0]);
+            move->piece = getpiece(mstr[0], color);
             if (mstr[2] == 'x') {
                 move->capture = 1;
                 if (move->piece) {
@@ -852,7 +861,7 @@
                     }
                 } else {
                     /* long notation capture (e.g. "e5xf6") */
-                    move->piece = PAWN;
+                    move->piece = mkpiece(PAWN, color);
                     move->fromfile = fileidx(mstr[0]);
                     move->fromrow = rowidx(mstr[1]);
                 }
@@ -868,7 +877,7 @@
         /* long notation capture (e.g. "Nc5xf3") */
         if (mstr[3] == 'x') {
             move->capture = 1;
-            move->piece = getpiece(mstr[0]);
+            move->piece = getpiece(mstr[0], color);
             move->fromfile = fileidx(mstr[1]);
             move->fromrow = rowidx(mstr[2]);
             move->tofile = fileidx(mstr[4]);
@@ -881,14 +890,12 @@
         return INVALID_MOVE_SYNTAX;
     }
 
-    if (move->piece == PAWN
-        && move->torow == (color==WHITE?7:0)
-        && !move->promotion) {
+    if (piece_type(move->piece) == PAWN
+            && move->torow == (color==WHITE?7:0)
+            && !move->promotion) {
         return NEED_PROMOTION;
     }
 
-    move->piece |= color;
-
     /* up to this point
      * destination indices must be specified and valid
      * source indices must either be valid or unspecified
@@ -902,7 +909,7 @@
 }
 
 int eval_move(GameState *gamestate, const char *mstr,
-        Move *move, uint8_t color) {
+        Move *move, Color color) {
     int result = eval_move1(mstr, move, color);
     if (result == VALID_MOVE_SYNTAX) {
         if (move->fromfile == POS_UNSPECIFIED
@@ -913,18 +920,16 @@
     return result;
 }
 
-int check_move(const char *mstr, uint8_t color) {
+int check_move(const char *mstr, Color color) {
     Move move;
     return eval_move1(mstr, &move, color);
 }
 
-bool is_protected(GameState *gamestate, uint8_t row, uint8_t file,
-        uint8_t color) {
-    
+bool is_protected(GameState *gamestate, Row row, File file, Color color) {
     Move threats[16];
-    uint8_t threatcount;
+    size_t threatcount;
     if (get_real_threats(gamestate, row, file, color, threats, &threatcount)) {
-        for (int i = 0 ; i < threatcount ; i++) {
+        for (size_t i = 0 ; i < threatcount ; i++) {
             if (threats[i].piece != (color|KING)) {
                 return true;
             }
@@ -935,7 +940,7 @@
     }
 }
 
-uint16_t remaining_movetime(GameState *gamestate, uint8_t color) {
+uint16_t remaining_movetime(GameState *gamestate, Color color) {
     unsigned move_number = gamestate->movecount;
     if (color == BLACK) {
         move_number |= 1;

mercurial