fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned default tip

Fri, 24 Jul 2026 15:35:06 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 24 Jul 2026 15:35:06 +0200
changeset 156
05fc8a454700
parent 155
835776e0338f

fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned

fixes #899 and fixes #932

src/chess/rules.c file | annotate | diff | comparison | revisions
--- a/src/chess/rules.c	Fri Jul 24 12:53:58 2026 +0200
+++ b/src/chess/rules.c	Fri Jul 24 15:35:06 2026 +0200
@@ -680,27 +680,28 @@
     Move threats[16], *threat = NULL;
     uint8_t threatcount;
 
+    /* determine all threats and sort out the unreal threats on our own */
     if (get_threats(gamestate, move->torow, move->tofile, color,
             threats, &threatcount)) {
         
-        int reason = PIECE_NOT_FOUND;
+        bool found = false;
         
         /* find threats for the specified position */
-        for (uint8_t i = 0 ; i < threatcount ; i++) {            
+        for (uint8_t i = 0 ; i < threatcount ; i++) {
             if (threats[i].piece == move->piece &&
                     (move->fromrow == POS_UNSPECIFIED ||
                     move->fromrow == threats[i].fromrow) &&
                     (move->fromfile == POS_UNSPECIFIED ||
                     move->fromfile == threats[i].fromfile)) {
 
-                if (threat) {
-                    return AMBIGUOUS_MOVE;
-                } else {
-                    /* found threat is no real threat */
-                    // TODO: why didn't we call get_real_threats() ?
-                    if (is_pinned(gamestate, &(threats[i]))) {
-                        reason = incheck?KING_IN_CHECK:
-                            (piece==KING?KING_MOVES_INTO_CHECK:PIECE_PINNED);
+                /* found a threat, here it does not matter if it's valid! */
+                found = true;
+
+                /* discard pinned pieces */
+                if (!is_pinned(gamestate, &(threats[i]))) {
+                    if (threat) {
+                        /* we've already found a valid threat */
+                        return AMBIGUOUS_MOVE;
                     } else {
                         threat = &(threats[i]);
                     }
@@ -710,7 +711,17 @@
         
         /* can't threaten specified position */
         if (!threat) {
-            return reason;
+            if (found) {
+                if (piece == KING) {
+                    return KING_MOVES_INTO_CHECK;
+                } else if (incheck) {
+                    return KING_IN_CHECK;
+                } else {
+                    return PIECE_PINNED;
+                }
+            } else {
+                return PIECE_NOT_FOUND;
+            }
         }
 
         /* found a threat, copy the source location */

mercurial