diff -r 05fc8a454700 -r 07cbfc477b22 src/chess/rules.c --- 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 #include @@ -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) {