src/main.c

changeset 175
e0e061cf4829
parent 174
2929e86c4817
child 176
ef8c39362342
--- a/src/main.c	Fri Aug 14 13:52:27 2026 +0200
+++ b/src/main.c	Mon Aug 17 12:01:19 2026 +0200
@@ -901,49 +901,19 @@
     gamestate_cleanup(&viewedstate);
 }
 
-static void game_play_singlemachine(void) {
+static void game_play_singlemachine(GameState *gamestate) {
     inputy = getmaxy(stdscr) - 6;
 
-    GameState gamestate;
-    gamestate_init(&gamestate);
-    settings_apply(&gamestate);
-    uint8_t curcol = WHITE;
-
-    if (settings.continuepgn) {
-        FILE *pgnfile = fopen(settings.continuepgn, "r");
-        if (pgnfile) {
-            int result = read_pgn(pgnfile, &gamestate);
-            fclose(pgnfile);
-            if (result) {
-                printw("Invalid PGN file content at position %zu:\n%s\n",
-                        pgn_error_position(), pgn_error_str(result));
-                gamestate_cleanup(&gamestate);
-                return;
-            }
-            if (!is_game_running(&gamestate)) {
-                addstr("Game has ended. Use -S to analyze it.\n");
-                gamestate_cleanup(&gamestate);
-                return;
-            }
-            curcol = current_color(&gamestate);
-        } else {
-            printw("Can't read PGN file (%s)\n", strerror(errno));
-            gamestate_cleanup(&gamestate);
-            return;
-        }
-    }
-
-    bool running;
-    do {
+    uint8_t curcol = current_color(gamestate);
+    bool running = is_game_running(gamestate);
+    while (running) {
         clear();
         uint8_t perspective = settings.disableflip ? WHITE : curcol;
-        draw_board(&gamestate, perspective);
-        running = !domove_singlemachine(&gamestate, curcol);
+        draw_board(gamestate, perspective);
+        running = !domove_singlemachine(gamestate, curcol);
         curcol = opponent_color(curcol);
-    }  while (running);
-
-    game_review(&gamestate);
-    gamestate_cleanup(&gamestate);
+    }
+    game_review(gamestate);
 }
 
 static void game_play(GameState *gamestate, int opponent, bool as_client) {
@@ -1056,78 +1026,48 @@
     return 0;
 }
 
-static int server_run(void) {
+static int server_run(GameState *gamestate) {
     Server server;
 
-    GameState gamestate;
-    gamestate_init(&gamestate);
-    settings_apply(&gamestate);
-    if (settings.continuepgn) {
-        /* preload PGN data before handshake */
-        bool cancel = false;
-        FILE *pgnfile = fopen(settings.continuepgn, "r");
-        if (pgnfile) {
-            int result = read_pgn(pgnfile, &gamestate);
-            fclose(pgnfile);
-            if (result) {
-                printw("Invalid PGN file content at position %zu:\n%s\n",
-                        pgn_error_position(), pgn_error_str(result));
-                cancel = true;
-            } else if (!is_game_running(&gamestate)) {
-                addstr("Game has ended. Use -s to analyze it locally.\n");
-                cancel = true;
-            }
-        } else {
-            printw("Can't read PGN file (%s)\n", strerror(errno));
-            cancel = true;
-        }
-        if (cancel) {
-            gamestate_cleanup(&gamestate);
-            return 1;
-        }
-    }
-    dump_gameinfo(&gamestate);
+    dump_gameinfo(gamestate);
 
     if (server_open(&server)) {
         net_destroy(&server);
-        gamestate_cleanup(&gamestate);
         return 1;
     }
 
     if (server_handshake(server.client)) {
         net_destroy(&server);
-        gamestate_cleanup(&gamestate);
         return 1;
     }
 
     int fd = server.client->fd;
     if (settings.continuepgn) {
         /* Continue game, send PGN data */
-        uint16_t mc = gamestate.movecount;
+        uint16_t mc = gamestate->movecount;
         size_t pgndata_size = sizeof(GameInfo)+sizeof(mc)+mc*sizeof(Move);
         char *pgndata = malloc(pgndata_size);
-        memcpy(pgndata, &(gamestate.info), sizeof(GameInfo));
+        memcpy(pgndata, &(gamestate->info), sizeof(GameInfo));
         unsigned offset = sizeof(GameInfo);
         memcpy(pgndata+offset, &mc, sizeof(mc));
         offset += sizeof(mc);
-        memcpy(pgndata+offset, gamestate.moves, mc*sizeof(Move));
+        memcpy(pgndata+offset, gamestate->moves, mc*sizeof(Move));
         net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size);
         free(pgndata);
     } else {
         /* Start new game */
         net_send_data(fd, NETCODE_GAMEINFO,
-            &(gamestate.info), sizeof(GameInfo));
+            &(gamestate->info), sizeof(GameInfo));
     }
     addstr("\rClient connected - awaiting challenge acceptance...");
     refresh();
     int code = net_recieve_code(fd);
-    int exitcode = 0;
     if (code == NETCODE_ACCEPT) {
         addstr("\rClient connected - challenge accepted.");
         clrtoeol();
-        game_play(&gamestate, fd, false);
+        game_play(gamestate, fd, false);
         net_destroy(&server);
-        game_review(&gamestate);
+        game_review(gamestate);
     } else if (code == NETCODE_DECLINE) {
         addstr("\rClient connected - challenge declined.");
         clrtoeol();
@@ -1139,12 +1079,10 @@
     } else {
         addstr("\rInvalid client response");
         clrtoeol();
-
         net_destroy(&server);
-        exitcode = 1;
+        return 1;
     }
-    gamestate_cleanup(&gamestate);
-    return exitcode;
+    return 0;
 }
 
 
@@ -1178,7 +1116,7 @@
     return 0;
 }
 
-static int client_run(void) {
+static int client_run(GameState *gamestate) {
     Server server;
 
     if (client_connect(&server)) {
@@ -1192,35 +1130,33 @@
     }
 
     uint8_t code = net_recieve_code(server.fd);
-    GameState gamestate;
-    gamestate_init(&gamestate);
     bool played = false;
     if (code == NETCODE_GAMEINFO) {
         /* Start new game */
-        net_recieve_data(server.fd, &(gamestate.info), sizeof(GameInfo));
-        dump_gameinfo(&gamestate);
+        net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo));
+        dump_gameinfo(gamestate);
         if (prompt_yesno("Accept challenge")) {
             net_send_code(server.fd, NETCODE_ACCEPT);
-            game_play(&gamestate, server.fd, true);
+            game_play(gamestate, server.fd, true);
             played = true;
         } else {
             net_send_code(server.fd, NETCODE_DECLINE);
         }
     } else if (code == NETCODE_PGNDATA) {
-        net_recieve_data(server.fd, &(gamestate.info), sizeof(GameInfo));
+        net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo));
         uint16_t mc;
         net_recieve_data(server.fd, &mc, sizeof(mc));
         Move *moves = calloc(mc, sizeof(Move));
         net_recieve_data(server.fd, moves, mc*sizeof(Move));
         for (size_t i = 0 ; i < mc ; i++) {
-            apply_move(&gamestate, &(moves[i]));
+            apply_move(gamestate, &(moves[i]));
         }
         free(moves);
-        dump_gameinfo(&gamestate);
+        dump_gameinfo(gamestate);
         if (prompt_yesno(
                 "\n\nServer wants to continue a game. Accept challenge")) {
             net_send_code(server.fd, NETCODE_ACCEPT);
-            game_play(&gamestate, server.fd, true);
+            game_play(gamestate, server.fd, true);
             played = true;
         } else {
             net_send_code(server.fd, NETCODE_DECLINE);
@@ -1232,9 +1168,8 @@
     }
 
     if (played) {
-        game_review(&gamestate);
+        game_review(gamestate);
     }
-    gamestate_cleanup(&gamestate);
 
     net_destroy(&server);
     return 0;
@@ -1261,14 +1196,42 @@
         return EXIT_FAILURE;
     }
     atexit(cleanup);
-    
-    int exitcode;
-    if (settings.singlemachine) {
-        game_play_singlemachine();
-        exitcode = EXIT_SUCCESS;
-    } else {
-        exitcode = settings.ishost ? server_run() : client_run();
+
+    GameState gamestate;
+    gamestate_init(&gamestate);
+    settings_apply(&gamestate);
+
+    int exitcode = EXIT_SUCCESS;
+
+    if (settings.continuepgn) {
+        FILE *pgnfile = fopen(settings.continuepgn, "r");
+        if (pgnfile) {
+            int result = read_pgn(pgnfile, &gamestate);
+            fclose(pgnfile);
+            if (result) {
+                printw("Invalid PGN file content at position %zu:\n%s\n",
+                        pgn_error_position(), pgn_error_str(result));
+                exitcode = EXIT_FAILURE;
+            }
+            /* clear resignation and remis flags to allow game continuation */
+            gamestate.wresign = gamestate.bresign = gamestate.remis = false;
+        } else {
+            printw("Can't read PGN file (%s)\n", strerror(errno));
+            exitcode = EXIT_FAILURE;
+        }
     }
+
+    if (exitcode == EXIT_SUCCESS) {
+        if (settings.singlemachine || !is_game_running(&gamestate)) {
+            game_play_singlemachine(&gamestate);
+        } else if (settings.ishost) {
+            exitcode = server_run(&gamestate);
+        } else {
+            exitcode = client_run(&gamestate);
+        }
+    }
+
+    gamestate_cleanup(&gamestate);
     
     mvaddstr(getmaxy(stdscr)-1, 0,
         "Game has ended. Press any key to leave...");

mercurial