src/chess/rules.c

changeset 195
27d02ccb0cef
parent 194
619f07c95894
--- a/src/chess/rules.c	Tue Aug 25 18:59:18 2026 +0200
+++ b/src/chess/rules.c	Tue Aug 25 19:42:15 2026 +0200
@@ -126,22 +126,22 @@
 }
 
 size_t piece_moves_allowed(const GameState *gamestate,
-        Rank r, File f, Move *moves) {
-    Piece p = piece_at(gamestate, r, f);
+        File f, Rank r, Move *moves) {
+    Piece p = piece_at(gamestate, f, r);
     Color c = piece_color(p);
     switch (piece_type(p)) {
         case KING:
-            return king_moves_allowed(gamestate, c, r, f, moves);
+            return king_moves_allowed(gamestate, c, f, r, moves);
         case QUEEN:
-            return queen_moves_allowed(gamestate, c, r, f, moves);
+            return queen_moves_allowed(gamestate, c, f, r, moves);
         case ROOK:
-            return rook_moves_allowed(gamestate, c, r, f, moves);
+            return rook_moves_allowed(gamestate, c, f, r, moves);
         case KNIGHT:
-            return knight_moves_allowed(gamestate, c, r, f, moves);
+            return knight_moves_allowed(gamestate, c, f, r, moves);
         case BISHOP:
-            return bishop_moves_allowed(gamestate, c, r, f, moves);
+            return bishop_moves_allowed(gamestate, c, f, r, moves);
         case PAWN:
-            return pawn_moves_allowed(gamestate, c, r, f, moves);
+            return pawn_moves_allowed(gamestate, c, f, r, moves);
         default:
             return 0;
     }
@@ -154,8 +154,8 @@
     Move moves[QUEEN_MOVES_MAX];
     for (Rank r = 0; r < 8; r++) {
         for (File f = 0; f < 8; f++) {
-            if (piece_color(piece_at(gamestate, r, f)) == next_player
-                && piece_moves_allowed(gamestate, r, f, moves) > 0) {
+            if (piece_color(piece_at(gamestate, f, r)) == next_player
+                && piece_moves_allowed(gamestate, f, r, moves) > 0) {
                 return false;
             }
         }
@@ -205,11 +205,11 @@
     bool op_has_bbishop = false, op_has_wbishop = false;
     for (Rank r = 0 ; r < 8 ; r++) {
         for (File f = 0 ; f < 8 ; f++) {
-            Piece p = piece_at(gamestate, r, f);
+            Piece p = piece_at(gamestate, f, r);
             if (piece_color(p) == color) {
                 piece_count[piece_type(p)]++;
                 if (piece_type(p) == BISHOP) {
-                    if (field_color(r, f) == WHITE) {
+                    if (field_color(f, r) == WHITE) {
                         has_wbishop = true;
                     } else {
                         has_bbishop = true;
@@ -218,7 +218,7 @@
             } else {
                 op_piece_count[piece_type(p)]++;
                 if (piece_type(p) == BISHOP) {
-                    if (field_color(r, f) == WHITE) {
+                    if (field_color(f, r) == WHITE) {
                         op_has_wbishop = true;
                     } else {
                         op_has_bbishop = true;
@@ -320,29 +320,29 @@
 static void apply_move_internal(GameState *gamestate, Move *move) {
     /* en passant capture */
     if (move->capture && piece_type(move->piece) == PAWN &&
-            piece_at(gamestate, move->torank, move->tofile) == 0) {
-        piece_remove(gamestate, move->fromrank, move->tofile);
+            piece_at(gamestate, move->tofile, move->torank) == 0) {
+        piece_remove(gamestate, move->tofile, move->fromrank);
     }
     
     /* remove old en passant threats */
     for (File file = 0 ; file < 8 ; file++) {
-        enpassant_threat_remove(gamestate, 3, file);
-        enpassant_threat_remove(gamestate, 4, file);
+        enpassant_threat_remove(gamestate, file, 3);
+        enpassant_threat_remove(gamestate, file, 4);
     }
     
     /* move (and maybe capture or promote) */
-    piece_remove(gamestate, move->fromrank, move->fromfile);
+    piece_remove(gamestate, move->fromfile, move->fromrank);
     if (move->promotion) {
-        piece_set(gamestate, move->torank, move->tofile, move->promotion);
+        piece_set(gamestate, move->tofile, move->torank, move->promotion);
     } else {
-        piece_set(gamestate, move->torank, move->tofile, move->piece);
+        piece_set(gamestate, move->tofile, move->torank, move->piece);
     }
 
     /* add new en passant threat */
     if (piece_type(move->piece) == PAWN && (
             (move->fromrank == 1 && move->torank == 3) ||
             (move->fromrank == 6 && move->torank == 4))) {
-        enpassant_threat_add(gamestate, move->torank, move->tofile);
+        enpassant_threat_add(gamestate, move->tofile, move->torank);
     }
     
     /* castling */
@@ -424,7 +424,7 @@
     Rank opkingrank = 0;
     for (Rank rank = 0 ; rank < 8 ; rank++) {
         for (File file = 0 ; file < 8 ; file++) {
-            Piece p = piece_at(&simulation, rank, file);
+            Piece p = piece_at(&simulation, file, rank);
             if (p == mkpiece(KING, oppcolor)) {
                 opkingfile = file;
                 opkingrank = rank;
@@ -435,7 +435,7 @@
     /* determine if the opposing king is now threatened */
     Move threats[16];
     size_t threatcount;
-    bool incheck = get_threats(&simulation, opkingrank, opkingfile,
+    bool incheck = get_threats(&simulation, opkingfile, opkingrank,
         piececolor, threats, &threatcount);
 
     if (!incheck) {
@@ -457,7 +457,7 @@
                 continue;
 
             /* check if escape field is already covered (threatened) */
-            if (is_covered(&simulation, er, ef, piececolor))
+            if (is_covered(&simulation, ef, er, piececolor))
                 continue;
 
             /* check if an attacking piece blocks the field */
@@ -472,7 +472,7 @@
                 move_retaliate.tofile = ef;
                 move_retaliate.capture = true;
                 apply_move_internal(&sim_retaliate, &move_retaliate);
-                canescape = !is_covered(&sim_retaliate, er, ef, piececolor);
+                canescape = !is_covered(&sim_retaliate, ef, er, piececolor);
                 gamestate_cleanup(&sim_retaliate);
                 continue;
             }
@@ -485,7 +485,7 @@
     /* can't escape, can the king be rescued? */
     if (!canescape && threatcount == 1) {
         canescape = is_protected(&simulation,
-                threats[0].fromrank, threats[0].fromfile, oppcolor);
+            threats[0].fromfile, threats[0].fromrank, oppcolor);
     }
 
     /* can't capture, can he block? */
@@ -502,7 +502,7 @@
                 while (!canescape && file != threat->tofile - d) {
                     file += d;
                     canescape |= is_protected(&simulation,
-                        threat->torank, file, oppcolor);
+                        file, threat->torank, oppcolor);
                 }
             } else if (threat->fromfile == threat->tofile) {
                 /* rook aspect (on file) */
@@ -511,7 +511,7 @@
                 while (!canescape && rank != threat->torank - d) {
                     rank += d;
                     canescape |= is_protected(&simulation,
-                        rank, threat->tofile, oppcolor);
+                        threat->tofile, rank, oppcolor);
                 }
             } else {
                 /* bishop aspect */
@@ -524,8 +524,8 @@
                         && rank != threat->torank - dr) {
                     rank += dr;
                     file += df;
-                    canescape |= is_protected(&simulation, rank, file,
-                        oppcolor);
+                    canescape |= is_protected(&simulation,
+                        file, rank, oppcolor);
                 }
             }
         }
@@ -566,7 +566,7 @@
             /* resolve ambiguities, if any */
             Move candidates[16];
             size_t ccount;
-            if (get_real_candidates(gamestate, move->torank, move->tofile,
+            if (get_real_candidates(gamestate, move->tofile, move->torank,
                     piece_color(move->piece), candidates, &ccount)) {
                 unsigned int ambranks = 0, ambfiles = 0, ambpiece = 0;
                 for (size_t i = 0 ; i < ccount ; i++) {
@@ -637,12 +637,12 @@
     }
 
     /* does piece exist */
-    if (piece_at(gamestate, move->fromrank, move->fromfile) != move->piece) {
+    if (piece_at(gamestate, move->fromfile, move->fromrank) != move->piece) {
         return PIECE_NOT_FOUND;
     }
 
     /* is there any piece at the destination? */
-    Piece piece_at_dst = piece_at(gamestate, move->torank, move->tofile);
+    Piece piece_at_dst = piece_at(gamestate, move->tofile, move->torank);
 
     /* can't capture own pieces */
     if (piece_color(piece_at_dst) == piece_color(move->piece)) {
@@ -654,7 +654,7 @@
         /* ... or the capture happens en passant */
         if (!move->capture || piece_type(move->piece) != PAWN ||
                 !enpassant_threat_exists(gamestate,
-                    move->fromrank, move->tofile)) {
+                    move->tofile, move->fromrank)) {
             return RULES_VIOLATED;
         }
     }
@@ -709,14 +709,14 @@
     Rank kingrank = 0;
     for (Rank rank = 0 ; rank < 8 ; rank++) {
         for (File file = 0 ; file < 8 ; file++) {
-            Piece p = piece_at(&simulation, rank, file);
+            Piece p = piece_at(&simulation, file, rank);
             if (p == mkpiece(KING, piececolor)) {
                 kingfile = file;
                 kingrank = rank;
             }
         }
     }
-    if (is_covered(&simulation, kingrank, kingfile, oppcolor)) {
+    if (is_covered(&simulation, kingfile, kingrank, oppcolor)) {
         if (piece_type(move->piece) == KING) {
             result = KING_MOVES_INTO_CHECK;
         } else {
@@ -752,21 +752,21 @@
     return VALID_MOVE_SEMANTICS;
 }
 
-Piece piece_at(const GameState *gamestate, Rank rank, File file) {
+Piece piece_at(const GameState *gamestate, File file, Rank rank) {
     return gamestate->board[rank][file] & (PIECE_MASK|COLOR_MASK);
 }
 
-void piece_set(GameState *gamestate, Rank rank, File file, Piece piece) {
+void piece_set(GameState *gamestate, File file, Rank rank, Piece piece) {
     gamestate->board[rank][file] = piece;
 }
 
-bool get_candidates(const GameState *gamestate, Rank rank, File file,
+bool get_candidates(const GameState *gamestate, File file, Rank rank,
         Color color, Move *moves, size_t *movecount) {
     Move candidates[32];
     size_t ccount = 0;
     for (Rank r = 0 ; r < 8 ; r++) {
         for (File f = 0 ; f < 8 ; f++) {
-            Piece p = piece_at(gamestate, r, f);
+            Piece p = piece_at(gamestate, f, r);
             if (piece_color(p) == color) {
                 /* non-capturing move */
                 memset(&(candidates[ccount]), 0, sizeof(Move));
@@ -809,22 +809,22 @@
     return result;
 }
 
-bool get_threats(const GameState *gamestate, Rank rank, File file,
+bool get_threats(const GameState *gamestate, File file, Rank rank,
         Color color, Move *threats, size_t *threatcount) {
 
     /* simulate a capturing move on the target position */
     Color opcolor = opponent_color(color);
     GameState simulation = gamestate_copy_sim(gamestate);
-    if (piece_color(piece_at(&simulation, rank, file)) != opcolor) {
+    if (piece_color(piece_at(&simulation, file, rank)) != opcolor) {
         /* set a fake pawn if the field is not occupied by the opponent */
-        piece_set(&simulation, rank, file, mkpiece(PAWN, opcolor));
+        piece_set(&simulation, file, rank, mkpiece(PAWN, opcolor));
     }
 
     Move candidates[16];
     size_t ccount = 0;
     for (Rank r = 0 ; r < 8 ; r++) {
         for (File f = 0 ; f < 8 ; f++) {
-            Piece p = piece_at(&simulation, r, f);
+            Piece p = piece_at(&simulation, f, r);
             if (piece_color(p) == color) {
                 memset(&(candidates[ccount]), 0, sizeof(Move));
                 candidates[ccount].piece = p;
@@ -874,7 +874,7 @@
     Rank kingrank = 0;
     for (Rank rank = 0 ; rank < 8 ; rank++) {
         for (File file = 0 ; file < 8 ; file++) {
-            if (piece_at(&simulation, rank, file) == mkpiece(KING, color)) {
+            if (piece_at(&simulation, file, rank) == mkpiece(KING, color)) {
                 kingfile = file;
                 kingrank = rank;
             }
@@ -882,13 +882,13 @@
     }
     
     bool covered = is_covered(&simulation,
-        kingrank, kingfile, opponent_color(color));
+        kingfile, kingrank, opponent_color(color));
     gamestate_cleanup(&simulation);
     
     return covered;
 }
 
-bool get_real_candidates(const GameState *gamestate, Rank rank, File file,
+bool get_real_candidates(const GameState *gamestate, File file, Rank rank,
         Color color, Move *moves, size_t *movecount) {
 
     if (movecount) {
@@ -897,7 +897,7 @@
 
     Move candidates[16];
     size_t ccount;
-    if (get_candidates(gamestate, rank, file, color, candidates, &ccount)) {
+    if (get_candidates(gamestate, file, rank, color, candidates, &ccount)) {
         bool result = false;
         for (size_t i = 0 ; i < ccount ; i++) {
             if (!is_pinned(gamestate, &candidates[i])) {
@@ -913,7 +913,7 @@
     }
 }
 
-bool get_real_threats(const GameState *gamestate, Rank rank, File file,
+bool get_real_threats(const GameState *gamestate, File file, Rank rank,
         Color color, Move *threats, size_t *threatcount) {
     
     if (threatcount) {
@@ -922,7 +922,7 @@
 
     Move candidates[16];
     size_t ccount;
-    if (get_threats(gamestate, rank, file, color, candidates, &ccount)) {
+    if (get_threats(gamestate, file, rank, color, candidates, &ccount)) {
         bool result = false;
         for (size_t i = 0 ; i < ccount ; i++) {
             if (!is_pinned(gamestate, &candidates[i])) {
@@ -950,7 +950,7 @@
     size_t candidatecount;
 
     /* determine all candidate moves and sort out the invalid ones */
-    if (get_candidates(gamestate, move->torank, move->tofile, color,
+    if (get_candidates(gamestate, move->tofile, move->torank, color,
             candidates, &candidatecount)) {
         
         bool found = false;
@@ -1186,11 +1186,12 @@
     return eval_move1(mstr, &move, color);
 }
 
-bool is_protected(const GameState *gamestate, Rank rank, File file, Color color) {
+bool is_protected(const GameState *gamestate,
+        File file, Rank rank, Color color) {
     Move candidates[16];
     size_t ccount;
     /* we need all candidates - not only threats! */
-    if (get_candidates(gamestate, rank, file, color, candidates, &ccount)) {
+    if (get_candidates(gamestate, file, rank, color, candidates, &ccount)) {
         for (size_t i = 0 ; i < ccount ; i++) {
             /* skip the king */
             if (piece_type(candidates[i].piece) == KING) continue;
@@ -1273,11 +1274,11 @@
 }
 
 size_t filter_moves_allowed(const GameState *gamestate,
-        Color c, Rank r, File f, Move *moves, moves_generator_func func) {
+        Color c, File f, Rank r, Move *moves, moves_generator_func func) {
 
     /* worst case: the queen has the most moves */
     Move candidates[QUEEN_MOVES_MAX];
-    size_t candidatecount = func(gamestate, c, r, f, candidates);
+    size_t candidatecount = func(gamestate, c, f, r, candidates);
     size_t count = 0;
 
     for (size_t i = 0 ; i < candidatecount ; i++) {

mercurial