diff -r 2929e86c4817 -r e0e061cf4829 src/main.c --- 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...");