src/chess/rules.c

changeset 168
663676cfef6e
parent 167
fd1d3f0a7a73
--- a/src/chess/rules.c	Sun Aug 02 15:08:43 2026 +0200
+++ b/src/chess/rules.c	Sun Aug 02 15:19:47 2026 +0200
@@ -138,11 +138,10 @@
             /* resolve ambiguities, if any */
             Move candidates[16];
             size_t ccount;
-            if (get_candidates(gamestate, move->torow, move->tofile,
+            if (get_real_candidates(gamestate, move->torow, move->tofile,
                     piece_color(move->piece), candidates, &ccount)) {
                 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0;
                 for (size_t i = 0 ; i < ccount ; i++) {
-                    // TODO: check if we need to discard pinned pieces here
                     if (candidates[i].piece == move->piece) {
                         ambpiece++;
                         if (candidates[i].fromrow == move->fromrow) {
@@ -668,7 +667,6 @@
         Color color, Move *threats, size_t *threatcount) {
 
     /* simulate a capturing move on the target position */
-    // TODO: this does NOT disregard the pin, as stated in the spec!
     Color opcolor = opponent_color(color);
     GameState simulation = gamestate_copy_sim(gamestate);
     if (piece_color(piece_at(&simulation, row, file)) != opcolor) {
@@ -730,7 +728,7 @@
     Row kingrow = 0;
     for (Row row = 0 ; row < 8 ; row++) {
         for (File file = 0 ; file < 8 ; file++) {
-            if (simulation.board[row][file] == (color|KING)) {
+            if (piece_at(&simulation, row, file) == mkpiece(KING, color)) {
                 kingfile = file;
                 kingrow = row;
             }
@@ -744,6 +742,31 @@
     return covered;
 }
 
+bool get_real_candidates(const GameState *gamestate, Row row, File file,
+        Color color, Move *moves, size_t *movecount) {
+
+    if (movecount) {
+        *movecount = 0;
+    }
+
+    Move candidates[16];
+    size_t ccount;
+    if (get_candidates(gamestate, row, file, color, candidates, &ccount)) {
+        bool result = false;
+        for (size_t i = 0 ; i < ccount ; i++) {
+            if (!is_pinned(gamestate, &candidates[i])) {
+                result = true;
+                if (moves && movecount) {
+                    moves[(*movecount)++] = candidates[i];
+                }
+            }
+        }
+        return result;
+    } else {
+        return false;
+    }
+}
+
 bool get_real_threats(const GameState *gamestate, Row row, File file,
         Color color, Move *threats, size_t *threatcount) {
     
@@ -752,36 +775,17 @@
     }
 
     Move candidates[16];
-    size_t candidatecount;
-    if (get_threats(gamestate, row, file, color, candidates, &candidatecount)) {
-        
+    size_t ccount;
+    if (get_threats(gamestate, row, file, color, candidates, &ccount)) {
         bool result = false;
-        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;
-                }
-            }
-        }
-
-        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];
-            apply_move(&simulation, &simmove);
-            if (!is_covered(&simulation, kingrow, kingfile,
-                    opponent_color(color))) {
+        for (size_t i = 0 ; i < ccount ; i++) {
+            if (!is_pinned(gamestate, &candidates[i])) {
                 result = true;
                 if (threats && threatcount) {
                     threats[(*threatcount)++] = candidates[i];
                 }
             }
-            gamestate_cleanup(&simulation);
         }
-        
         return result;
     } else {
         return false;

mercurial