src/chess/rules.c

changeset 182
04c65336777f
parent 181
8bda076d0a16
--- a/src/chess/rules.c	Sat Aug 22 15:15:52 2026 +0200
+++ b/src/chess/rules.c	Sat Aug 22 16:22:05 2026 +0200
@@ -106,94 +106,6 @@
     return (gamestate->movecount % 2 == 0) ? WHITE : BLACK;
 }
 
-/* MUST be called BETWEEN validating AND applying a move to work correctly */
-static void format_move(const GameState *gamestate, Move *move) {
-    char *string = &(move->string[0]);
-    
-    /* at least 8 characters should be available, wipe them out */
-    memset(string, 0, 8);
-    
-    unsigned int idx;
-    if (piece_type(move->piece) == KING &&
-            abs(move->tofile-move->fromfile) == 2) {
-        /* special formats for castling */
-        if (move->tofile==fileidx('c')) {
-            memcpy(string, "O-O-O", 5);
-            idx = 5;
-        } else {
-            memcpy(string, "O-O", 3);
-            idx = 3;
-        }
-    } else {
-        /* start by notating the piece character */
-        string[0] = getpiecechr(move->piece);
-        idx = string[0] ? 1 : 0;
-
-        /* find out how many source information we do need */
-        if (piece_type(move->piece) == PAWN) {
-            if (move->capture) {
-                string[idx++] = filechr(move->fromfile);
-            }
-        } else if (piece_type(move->piece) != KING) {
-            /* resolve ambiguities, if any */
-            Move candidates[16];
-            size_t ccount;
-            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++) {
-                    if (candidates[i].piece == move->piece) {
-                        ambpiece++;
-                        if (candidates[i].fromrow == move->fromrow) {
-                            ambrows++;
-                        }
-                        if (candidates[i].fromfile == move->fromfile) {
-                            ambfiles++;
-                        }
-                    }
-                }
-                /* neither file, nor row are ambiguous, name file */
-                if (ambpiece > 1 && ambrows == 1 && ambfiles == 1) {
-                    /* this is most likely the case with Knights
-                     * in diagonal opposition */
-                    string[idx++] = filechr(move->fromfile);
-                } else {
-                    /* ambiguous row, name file */
-                    if (ambrows > 1) {
-                        string[idx++] = filechr(move->fromfile);
-                    }
-                    /* ambiguous file, name row */
-                    if (ambfiles > 1) {
-                        string[idx++] = rowchr(move->fromrow);
-                    }
-                }
-            }
-        }
-
-        /* capturing? */
-        if (move->capture) {
-            string[idx++] = 'x';
-        }
-
-        /* destination */
-        string[idx++] = filechr(move->tofile);
-        string[idx++] = rowchr(move->torow);
-
-        /* promotion? */
-        if (move->promotion) {
-            string[idx++] = '=';
-            string[idx++] = getpiecechr(move->promotion);
-        }
-    }
-    
-    /* check? */
-    if (move->checkmate) {
-        string[idx++] = '#';
-    } else if (move->check) {
-        string[idx++] = '+';
-    }
-}
-
 static void calc_movetime(GameState *gamestate, Move *move) {
     /* only if move has no time info, compute it */
     if (move->movetime > 0) return;
@@ -622,6 +534,106 @@
     return canescape ? 1 : 2;
 }
 
+
+static void format_move_impl(const GameState *gamestate, Move *move) {
+    char *string = &(move->string[0]);
+
+    /* at least 8 characters should be available, wipe them out */
+    memset(string, 0, 8);
+
+    unsigned int idx;
+    if (piece_type(move->piece) == KING &&
+            abs(move->tofile-move->fromfile) == 2) {
+        /* special formats for castling */
+        if (move->tofile==fileidx('c')) {
+            memcpy(string, "O-O-O", 5);
+            idx = 5;
+        } else {
+            memcpy(string, "O-O", 3);
+            idx = 3;
+        }
+    } else {
+        /* start by notating the piece character */
+        string[0] = getpiecechr(move->piece);
+        idx = string[0] ? 1 : 0;
+
+        /* find out how many source information we do need */
+        if (piece_type(move->piece) == PAWN) {
+            if (move->capture) {
+                string[idx++] = filechr(move->fromfile);
+            }
+        } else if (piece_type(move->piece) != KING) {
+            /* resolve ambiguities, if any */
+            Move candidates[16];
+            size_t ccount;
+            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++) {
+                    if (candidates[i].piece == move->piece) {
+                        ambpiece++;
+                        if (candidates[i].fromrow == move->fromrow) {
+                            ambrows++;
+                        }
+                        if (candidates[i].fromfile == move->fromfile) {
+                            ambfiles++;
+                        }
+                    }
+                }
+                /* neither file, nor row are ambiguous, name file */
+                if (ambpiece > 1 && ambrows == 1 && ambfiles == 1) {
+                    /* this is most likely the case with Knights
+                     * in diagonal opposition */
+                    string[idx++] = filechr(move->fromfile);
+                } else {
+                    /* ambiguous row, name file */
+                    if (ambrows > 1) {
+                        string[idx++] = filechr(move->fromfile);
+                    }
+                    /* ambiguous file, name row */
+                    if (ambfiles > 1) {
+                        string[idx++] = rowchr(move->fromrow);
+                    }
+                }
+            }
+        }
+
+        /* capturing? */
+        if (move->capture) {
+            string[idx++] = 'x';
+        }
+
+        /* destination */
+        string[idx++] = filechr(move->tofile);
+        string[idx++] = rowchr(move->torow);
+
+        /* promotion? */
+        if (move->promotion) {
+            string[idx++] = '=';
+            string[idx++] = getpiecechr(move->promotion);
+        }
+    }
+
+    /* check? */
+    if (move->checkmate) {
+        string[idx++] = '#';
+    } else if (move->check) {
+        string[idx++] = '+';
+    }
+}
+
+void format_move(const GameState *gamestate, Move *move) {
+    /* correct check/checkmate flags */
+    move->check = move->checkmate = false;
+    switch (determine_check_or_checkmate(gamestate, move)) {
+        case 2: move->checkmate = true;
+        case 1: move->check = true;
+    }
+
+    /* format the move string */
+    format_move_impl(gamestate, move);
+}
+
 static int validate_move_rules(const GameState *gamestate, const Move *move) {
     assert((move->piece & ~(PIECE_MASK|COLOR_MASK)) == 0);
 
@@ -1162,18 +1174,18 @@
             }
 
             /* format the move string */
-            format_move(gamestate, move);
+            format_move_impl(gamestate, move);
         }
     }
     return result;
 }
 
-int eval_move_lazy(const GameState *gamestate,
+int eval_move(const GameState *gamestate,
         const char *mstr, Color color, Move *move) {
     return eval_move2(gamestate, mstr, color, move, true);
 }
 
-int eval_move(const GameState *gamestate,
+int eval_move_strict(const GameState *gamestate,
         const char *mstr, Color color, Move *move) {
     return eval_move2(gamestate, mstr, color, move, false);
 }

mercurial