src/chess/rules.c

changeset 122
e65d9b5e9324
parent 115
206201d544be
--- a/src/chess/rules.c	Tue May 19 17:59:24 2026 +0200
+++ b/src/chess/rules.c	Tue May 19 18:03:06 2026 +0200
@@ -144,6 +144,32 @@
     }
 }
 
+static void calc_movetime(GameState *gamestate, Move *move) {
+    struct timeval curtimestamp;
+    gettimeofday(&curtimestamp, NULL);
+    move->timestamp.tv_sec = curtimestamp.tv_sec;
+    move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec;
+
+    if (gamestate->movecount > 1) {
+        struct movetimeval lasttstamp = last_move(gamestate).timestamp;
+        uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec;
+        suseconds_t micros;
+        if (curtimestamp.tv_usec < lasttstamp.tv_usec) {
+            micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec);
+            sec--;
+        } else {
+            micros = curtimestamp.tv_usec - lasttstamp.tv_usec;
+        }
+
+        move->movetime.tv_sec = sec;
+        move->movetime.tv_usec = (int32_t) micros;
+    } else {
+        /* no move time for the first move of both white and black */
+        move->movetime.tv_usec = 0;
+        move->movetime.tv_sec = 0;
+    }
+}
+
 static void addmove(GameState* gamestate, Move *data) {
     if (gamestate->movecount == gamestate->movecapacity) {
         gamestate->movecapacity += 64; /* 32 more full moves */
@@ -154,29 +180,12 @@
     Move *move = &gamestate->moves[gamestate->movecount];
     *move = *data;
 
-    struct timeval curtimestamp;
-    gettimeofday(&curtimestamp, NULL);
-    move->timestamp.tv_sec = curtimestamp.tv_sec;
-    move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec;
-    
-    if (gamestate->movecount > 1) {
-        struct movetimeval lasttstamp = last_move(gamestate).timestamp;
-        uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec;
-        suseconds_t micros;
-        if (curtimestamp.tv_usec < lasttstamp.tv_usec) {
-            micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec);
-            sec--;
-        } else {
-            micros = curtimestamp.tv_usec - lasttstamp.tv_usec;
-        }
-        
-        move->movetime.tv_sec = sec;
-        move->movetime.tv_usec = (int32_t) micros;
-    } else {
-        /* no move time for the first move of both white and black */
-        move->movetime.tv_usec = 0;
-        move->movetime.tv_sec = 0;
+    /* only if move has no time info, compute it */
+    if (move->movetime.tv_sec == 0 && move->movetime.tv_usec == 0) {
+        calc_movetime(gamestate, move);
     }
+
+    /* important: only "add" the move after calculating the time! */
     gamestate->movecount++;
 }
 
@@ -280,7 +289,19 @@
 }
 
 void apply_move(GameState *gamestate, Move *move) {
-    apply_move_impl(gamestate, move, 0);
+    apply_move_impl(gamestate, move, false);
+}
+
+void gamestate_at_move(GameState *gamestate,
+        unsigned move_number, GameState *replay) {
+    gamestate_init(replay);
+    replay->review = true;
+    if (move_number > gamestate->movecount) {
+        move_number = gamestate->movecount;
+    }
+    for (unsigned i = 0 ; i < move_number ; i++) {
+        apply_move_impl(replay, &(gamestate->moves[i]), true);
+    }
 }
 
 static int validate_move_rules(GameState *gamestate, Move *move) {
@@ -357,7 +378,7 @@
     /* simulate move for check validation */
     GameState simulation = gamestate_copy_sim(gamestate);
     Move simmove = *move;
-    apply_move_impl(&simulation, &simmove, 1);
+    apply_move_impl(&simulation, &simmove, true);
     
     /* find kings for check validation */
     uint8_t piececolor = (move->piece & COLOR_MASK);

mercurial