X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=src%2Fserver%2Finit.c;h=f5c81d3d5081b3ec4ed48f43eeb1801f94f86789;hb=1dc64ee46c2dcbd7eb8a6c4fcd27620dab7d7680;hp=a3c1589b6992c1af654e327f9b193e464329d62e;hpb=d92f16d5959fc846d3eaf669517eecb3969cda08;p=plomrogue diff --git a/src/server/init.c b/src/server/init.c index a3c1589..f5c81d3 100644 --- a/src/server/init.c +++ b/src/server/init.c @@ -1,4 +1,9 @@ -/* src/server/init.c */ +/* src/server/init.c + * + * This file is part of PlomRogue. PlomRogue is licensed under the GPL version 3 + * or any later version. For details on its copyright, license, and warranties, + * see the file NOTICE in the root directory of the PlomRogue source package. + */ #define _POSIX_C_SOURCE 2 /* getopt(), optarg */ #include "init.h" @@ -11,23 +16,128 @@ #include /* mkdir() */ #include /* defines pid_t, time_t */ #include /* time() */ -#include /* optarg, getopt(), access(), unlink(), getpid() */ +#include /* optarg, getopt(), access(), getpid() */ +#include "../common/parse_file.h" /* err_line_zero(), err_line_inc() */ #include "../common/readwrite.h" /* try_fopen(), try_fclose(), textfile_width(), - * try_fgets(), try_fwrite() + * try_fgets(), try_fwrite(), + * detect_atomic_leftover() */ -#include "../common/rexit.h" /* exit_err() */ +#include "../common/rexit.h" /* exit_err(), exit_trouble() */ #include "../common/try_malloc.h" /* try_malloc() */ #include "cleanup.h" /* set_cleanup_flag() */ -#include "field_of_view.h" /* build_fov_map() */ -#include "map.h" /* init_map() */ +#include "field_of_view.h" /* update_map_memory() */ +#include "hardcoded_strings.h" /* s */ +#include "map.h" /* remake_map() */ #include "things.h" /* Thing, ThingType, free_things(), add_things(), - * get_player() + * get_thing_id_action_id_by_name(), get_player() */ -#include "run.h" /* obey_msg(), io_loop() */ +#include "run.h" /* obey_msg(), io_loop(), record(), send_to_outfile() */ #include "world.h" /* global world */ + +/* Pass to obey_msg() lines from file at "path", on "record" write to same. Do + * not pass lines that consist only of a newline character. Transform newline + * in the line passed to \0. + */ +static void obey_lines_from_file(char * path, uint8_t record); + +/* Replay game from record file up to the turn named in world.replay, then turn + * over to manual replay via io_loop(). + */ +static void replay_game(); + +/* Return 1 if the type defined by world.player_type has a .start_n of 0. + * Return 2 if no thing action with .name of s[S_CMD_WAIT] is defined. + * Else, return 0. + */ +static uint8_t world_cannot_be_made(); + + +static void obey_lines_from_file(char * path, uint8_t record) +{ + FILE * file = try_fopen(path, "r", __func__); + uint32_t linemax = textfile_width(file); + char * line = try_malloc(linemax + 1, __func__); + while (try_fgets(line, linemax + 1, file, __func__)) + { + if (strlen(line)) + { + if (strcmp("\n", line)) + { + char * nl = strchr(line, '\n'); + if (nl) + { + *nl = '\0'; + } + obey_msg(line, record); + } + err_line_inc(); + } + } + free(line); + try_fclose(file, __func__); +} + + + +static void replay_game() +{ + exit_err(access(s[S_PATH_RECORD], F_OK), "No record found to replay."); + FILE * file = try_fopen(s[S_PATH_RECORD], "r", __func__); + uint32_t linemax = textfile_width(file); + char * line = try_malloc(linemax + 1, __func__); + while ( world.turn < world.replay + && try_fgets(line, linemax + 1, file, __func__)) + { + obey_msg(line, 0); + err_line_inc(); + } + uint8_t end = 0; + while (3 == io_loop(2)) + { + if (!end) + { + end = (NULL == try_fgets(line, linemax + 1, file, __func__)); + if (!end) + { + obey_msg(line, 0); + err_line_inc(); + } + } + } + free(line); + try_fclose(file, __func__); +} + + + +static uint8_t world_cannot_be_made() +{ + uint8_t player_will_be_generated = 0; + struct ThingType * tt; + for (tt = world.thing_types; tt; tt = tt->next) + { + if (world.player_type == tt->id) + { + player_will_be_generated = 0 < tt->start_n; + break; + } + } + if (!player_will_be_generated) + { + return 1; + } + if (!get_thing_action_id_by_name(s[S_CMD_WAIT])) + { + return 2; + } + return 0; +} + + + extern void obey_argv(int argc, char * argv[]) { int opt; @@ -56,41 +166,42 @@ extern void obey_argv(int argc, char * argv[]) extern void setup_server_io() { - char * f_name = "setup_server_io()"; int test = mkdir("server", 0700); - exit_trouble(test && EEXIST != errno, f_name, "mkdir()"); - world.file_out = try_fopen(world.path_out, "w", f_name); - world.server_test = try_malloc(10 + 1 + 10 + 1 + 1, f_name); - sprintf(world.server_test, "%d %d\n", getpid(), (int) time(0)); + exit_trouble(test && EEXIST != errno, __func__, "mkdir"); + world.file_out = try_fopen(s[S_PATH_OUT], "w", __func__); + world.server_test = try_malloc(10 + 1 + 10 + 1 + 1, __func__); + test = sprintf(world.server_test, "%d %d\n", getpid(), (int) time(0)); + exit_trouble(test < 0, __func__, s[S_FCN_SPRINTF]); try_fwrite(world.server_test, strlen(world.server_test), 1, - world.file_out, f_name); + world.file_out, __func__); fflush(world.file_out); set_cleanup_flag(CLEANUP_OUT); - if (!access(world.path_in, F_OK)) /* This keeps out input from old input */ + char * path_in = s[S_PATH_IN]; + if (!access(path_in, F_OK)) /* This keeps out input from old input */ { /* file streams of clients */ - unlink(world.path_in); /* communicating with server processes */ + unlink(path_in) ; /* communicating with server processes */ } /* superseded by this current one. */ - world.file_in = try_fopen(world.path_in, "w", f_name); - try_fclose(world.file_in, f_name); - world.file_in = try_fopen(world.path_in, "r", f_name); + world.file_in = try_fopen(path_in, "w", __func__); + try_fclose(world.file_in, __func__); + world.file_in = try_fopen(path_in, "r", __func__); set_cleanup_flag(CLEANUP_IN); } -extern void remake_world(uint32_t seed) +extern uint8_t remake_world() { - char * f_name = "remake_world()"; - free(world.log); - world.log = NULL; /* thing_actions.c's update_log() checks for this. */ - world.seed = seed; - world.thing_count = 0; - free(world.map.cells); + uint8_t test = world_cannot_be_made(); + if (test) + { + return test; + } + world.seed_map = world.seed; free_things(world.things); - world.last_update_turn = 0; - init_map(); + remake_map(); + world.exists = 1; struct ThingType * tt; - for (tt = world.thing_types; NULL != tt; tt = tt->next) + for (tt = world.thing_types; tt; tt = tt->next) { if (world.player_type == tt->id) { @@ -98,66 +209,49 @@ extern void remake_world(uint32_t seed) break; } } - for (tt = world.thing_types; NULL != tt; tt = tt->next) + update_map_memory(get_player(), 1); + for (tt = world.thing_types; tt; tt = tt->next) { if (world.player_type != tt->id) { add_things(tt->id, tt->start_n); } } - set_cleanup_flag(CLEANUP_THINGS); - struct Thing * t; - for (t = world.things; NULL != t; t = t->next) - { - t->fov_map = t->lifepoints ? build_fov_map(t) : NULL; - } - if (world.turn) - { - exit_trouble(unlink(world.path_record), f_name, "unlink()"); - } world.turn = 1; + send_to_outfile("NEW_WORLD\n", 1); + return 0; } extern void run_game() { - char * f_name = "run_game()"; - if (!access(world.path_record, F_OK)) + detect_atomic_leftover(s[S_PATH_SAVE]); + detect_atomic_leftover(s[S_PATH_RECORD]); + err_line_zero(); + if (world.replay) { - FILE * file = try_fopen(world.path_record, "r", f_name); - uint32_t linemax = textfile_width(file); - char line[linemax + 1]; - while ( (!world.replay || (world.turn < world.replay)) - && NULL != try_fgets(line, linemax + 1, file, f_name)) - { - obey_msg(line, 0); - } - if (!world.replay) - { - try_fclose(file, f_name); - io_loop(); - return; - } - uint8_t end = 0; - while (!io_loop()) - { - if (!end) - { - end = (NULL == try_fgets(line, linemax + 1, file, f_name)); - if (!end) - { - obey_msg(line, 0); - } - } - } - try_fclose(file, f_name); + replay_game(); return; } - exit_err(world.replay, "No record file found to replay."); - char * command = "seed"; - char msg[strlen(command) + 1 + 11 + 1]; - sprintf(msg, "%s %d", command, (int) time(NULL)); - obey_msg(msg, 1); - io_loop(); + if (!access(s[S_PATH_SAVE], F_OK)) + { + obey_lines_from_file(s[S_PATH_SAVE], 0); + } + else + { + char * err = "No world config file from which to start a new world."; + exit_err(access(s[S_PATH_CONFIG], F_OK), err); + obey_lines_from_file(s[S_PATH_CONFIG], 1); + err_line_zero(); + char * command = s[S_CMD_MAKE_WORLD]; + char * msg = try_malloc(strlen(command) + 1 + 11 + 1, __func__); + int test = sprintf(msg, "%s %d", command, (int) time(NULL)); + exit_trouble(test < 0, __func__, s[S_FCN_SPRINTF]); + obey_msg(msg, 1); + free(msg); + } + err_line_zero(); + io_loop(1); + record(NULL, 1); }