src/chess/rules.c

changeset 157
07cbfc477b22
parent 156
05fc8a454700
child 158
52d452d0e7bf
--- a/src/chess/rules.c	Fri Jul 24 15:35:06 2026 +0200
+++ b/src/chess/rules.c	Tue Jul 28 12:58:49 2026 +0200
@@ -34,6 +34,7 @@
 #include "bishop.h"
 #include "queen.h"
 #include "king.h"
+#include "fen.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -43,6 +44,7 @@
 void gamestate_init(GameState *gamestate) {
     memset(gamestate, 0, sizeof(GameState));
 
+    // TODO: implement feature - game can be started from arbitrary position
     Board initboard = {
         {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK},
         {WPAWN, WPAWN,   WPAWN,   WPAWN,  WPAWN, WPAWN,   WPAWN,   WPAWN},
@@ -54,25 +56,39 @@
         {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK}
     };
     memcpy(gamestate->board, initboard, sizeof(Board));
+    char fen[FEN_MAX_LENGTH];
+    fen_compute(fen, gamestate);
+    gamestate->fen_start = strdup(fen);
 }
 
 void gamestate_cleanup(GameState *gamestate) {
     free(gamestate->moves);
+    free(gamestate->fen_start);
+    for (unsigned i = 0 ; i < gamestate->movecount ; i++) {
+        free(gamestate->fen[i]);
+    }
+    free(gamestate->fen);
     gamestate->movecount = gamestate->movecapacity = 0;
 }
 
 static GameState gamestate_copy_sim(GameState *gamestate) {
     GameState simulation = *gamestate;
 
-    // create a new move list for the simulation
+    /* create new move and position lists for the simulation */
     simulation.movecapacity = 4;
     simulation.movecount = 0;
     simulation.moves = malloc(4 * sizeof(Move));
+    simulation.fen = malloc(4 * sizeof(char*));
 
-    // copy the most recent move if a move was played
+    /* copy the most recent move and position if a move was played */
     if (gamestate->movecount > 0) {
+        simulation.fen_start = strdup(gamestate->movecount == 1 ?
+            gamestate->fen_start : gamestate->fen[gamestate->movecount - 2]);
         simulation.moves[0] = last_move(gamestate);
+        simulation.fen[0] = strdup(gamestate->fen[gamestate->movecount - 1]);
         simulation.movecount++;
+    } else {
+        simulation.fen_start = strdup(gamestate->fen_start);
     }
 
     return simulation;
@@ -199,25 +215,6 @@
     }
 }
 
-static void addmove(GameState* gamestate, Move *data) {
-    if (gamestate->movecount == gamestate->movecapacity) {
-        gamestate->movecapacity += 64; /* 32 more full moves */
-        gamestate->moves = realloc(gamestate->moves,
-            gamestate->movecapacity * sizeof(Move));
-    }
-
-    Move *move = &gamestate->moves[gamestate->movecount];
-    *move = *data;
-
-    /* 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++;
-}
-
 char getpiecechr(uint8_t piece) {
     switch (piece & PIECE_MASK) {
     case ROOK: return 'R';
@@ -314,8 +311,31 @@
         }
     }
     
-    /* add move, even in simulation (checkmate test needs it) */
-    addmove(gamestate, move);
+    /* add move to the moves array and the new position to the FEN array */
+    if (gamestate->movecount == gamestate->movecapacity) {
+        gamestate->movecapacity += 64; /* 32 more full moves */
+        gamestate->moves = realloc(gamestate->moves,
+            gamestate->movecapacity * sizeof(Move));
+        gamestate->fen = realloc(gamestate->fen,
+            gamestate->movecapacity * sizeof(char*));
+    }
+
+    /* copy the move data into the game's move array */
+    Move *melem = &gamestate->moves[gamestate->movecount];
+    *melem = *move;
+
+    /* calculate the FEN and store it in the FEN array */
+    char fen[FEN_MAX_LENGTH];
+    fen_compute(fen, gamestate);
+    gamestate->fen[gamestate->movecount] = strdup(fen);
+
+    /* only if move has no time info, compute it */
+    if (melem->movetime.tv_sec == 0 && melem->movetime.tv_usec == 0) {
+        calc_movetime(gamestate, melem);
+    }
+
+    /* important: only "add" the move after calculating the time! */
+    gamestate->movecount++;
 }
 
 void apply_move(GameState *gamestate, Move *move) {

mercurial