From edebb2bf9aa780ee2f7006c1d2be9168564d34df Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sat, 2 Aug 2014 05:20:05 +0200 Subject: [PATCH] Add auto-mapping / map memory. --- SERVER_COMMANDS | 4 + TODO | 6 ++ src/client/cleanup.c | 1 + src/client/draw_wins.c | 36 +++++++-- src/client/io.c | 20 +++-- src/client/main.c | 3 +- src/client/world.h | 3 +- src/server/ai.c | 3 +- src/server/field_of_view.c | 23 ++++++ src/server/field_of_view.h | 2 +- src/server/god_commands.c | 56 ++++++++++++-- src/server/god_commands.h | 5 +- src/server/hardcoded_strings.c | 3 +- src/server/hardcoded_strings.h | 3 +- src/server/io.c | 130 +++++++++++++++++++++++---------- src/server/run.c | 13 +++- src/server/thing_actions.c | 8 ++ src/server/things.c | 1 + src/server/things.h | 1 + 19 files changed, 252 insertions(+), 69 deletions(-) diff --git a/SERVER_COMMANDS b/SERVER_COMMANDS index d574180..c229f63 100644 --- a/SERVER_COMMANDS +++ b/SERVER_COMMANDS @@ -157,6 +157,10 @@ T_CARRIES [0 to 255] Add thing of ID in argument to inventory of selected thing, if said thing is available for carrying and not the selected thing. +T_MEMMAP [0 to 255] [string] +Set part of selected thing's memory of the game map to string argument: the line +of the argument's number. + TT_ID [-32768 to 32767] Select thing type to manipulate by argument as ID. If argument is <0 or <255, change it to the lowest unused thing type ID. If thing type of ID does not exist diff --git a/TODO b/TODO index c37c5c2..c8b6681 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,10 @@ IN GENERAL: - expand use of hardcoded_strings module(s) +SERVER: + +- check whether saving every player turn slows down gameplay + BOTH SERVER/CLIENT: - make server and client communicate by specific world state info requests @@ -12,3 +16,5 @@ BOTH SERVER/CLIENT: CLIENT: - re-work unnecessary complex command / keybinding / server message mapping + +- fix memory leakin draw_wins module diff --git a/src/client/cleanup.c b/src/client/cleanup.c index 3499246..f4b97bf 100644 --- a/src/client/cleanup.c +++ b/src/client/cleanup.c @@ -19,6 +19,7 @@ static uint32_t cleanup_flags = 0x0000; extern void cleanup() { free(world.map.cells); + free(world.mem_map); free(world.log); free(world.player_inventory); if (cleanup_flags & CLEANUP_INTERFACE) diff --git a/src/client/draw_wins.c b/src/client/draw_wins.c index bb86bb9..6736a1b 100644 --- a/src/client/draw_wins.c +++ b/src/client/draw_wins.c @@ -2,7 +2,7 @@ #define _POSIX_C_SOURCE 200809L /* strdup() */ #include "draw_wins.h" -#include /* typedefs attr_t, chtype, define A_REVERSE */ +#include /* attr_t, chtype, init_pair(), A_REVERSE, COLOR_PAIR() */ #include /* NULL */ #include /* uint8_t, uint16_t, uint32_t, UINT16_MAX */ #include /* sprintf() */ @@ -339,14 +339,40 @@ extern void draw_win_log(struct Win * win) extern void draw_win_map(struct Win * win) { + init_pair(1, COLOR_WHITE, COLOR_BLUE); + init_pair(2, COLOR_BLUE, COLOR_BLACK); + attr_t attr_fov = 0; + attr_t attr_mem = COLOR_PAIR(2); + attr_t attr_sha = COLOR_PAIR(1); try_resize_winmap(win, world.map.length, world.map.length * 2); - uint16_t z = 0; - uint16_t x, y; - for (y = 0; y < world.map.length; y++) + uint16_t x, y, z; + for (y = 0, z = 0; y < world.map.length; y++) { for (x = 0; x < world.map.length; x++) { - set_ch_on_yx(win, y, x * 2 + (y % 2), world.map.cells[z]); + attr_t attr_c = ' ' == world.mem_map[z] ? attr_sha : attr_mem; + chtype c = world.mem_map[z] | attr_c; + set_ch_on_yx(win, y, x * 2 + (y % 2), c); + if (x + (y % 2) < world.map.length) + { + set_ch_on_yx(win, y, x * 2 + (y % 2) + 1, ' ' | attr_c); + } + z++; + } + } + for (y = 0, z = 0; y < world.map.length; y++) + { + for (x = 0; x < world.map.length; x++) + { + if (' ' != world.map.cells[z]) + { + chtype c = world.map.cells[z] | attr_fov; + set_ch_on_yx(win, y, x * 2 + (y % 2), c); + if (x + (y % 2) < world.map.length) + { + set_ch_on_yx(win, y, x * 2 + (y % 2) + 1, ' ' | attr_fov); + } + } z++; } } diff --git a/src/client/io.c b/src/client/io.c index d0b9dc0..c0cf977 100644 --- a/src/client/io.c +++ b/src/client/io.c @@ -30,11 +30,11 @@ */ static void read_inventory(char * read_buf, uint32_t linemax, FILE * file); -/* Read the next characters in "file" into world.map.cells. In detail: Read +/* Read the next characters in "file" into "map". In detail: Read * world.map.length times world.map.length characters, followed by one ignored * character (that we assume is a newline). */ -static void read_map_cells(FILE * file); +static void read_map_cells(FILE * file, char ** map); /* Repeatedly use try_fgets() with given arguments to read the remaining lines * of "file" into the world.log string. @@ -116,17 +116,22 @@ static void read_inventory(char * read_buf, uint32_t linemax, FILE * file) -static void read_map_cells(FILE * file) +static void read_map_cells(FILE * file, char ** map) { - free(world.map.cells); - world.map.cells = try_malloc(world.map.length * world.map.length, __func__); + if (*map) + { + free(*map); + *map = NULL; + } + *map = try_malloc(world.map.length * world.map.length, __func__); + char * map_cells = *map; uint16_t y, x; for (y = 0; y < world.map.length; y++) { for (x = 0; x < world.map.length; x++) { char c = try_fgetc(file, __func__); - world.map.cells[(y * world.map.length) + x] = c; + map_cells[y * world.map.length + x] = c; } try_fgetc(file, __func__); } @@ -213,7 +218,8 @@ static uint8_t read_world() first_read = 0; } world.map.length = read_value_from_line(read_buf, linemax, file); - read_map_cells(file); + read_map_cells(file, &world.map.cells); + read_map_cells(file, &world.mem_map); read_log(read_buf, linemax, file); free(read_buf); try_fclose(file, __func__); diff --git a/src/client/main.c b/src/client/main.c index 9c6a72a..68841ca 100644 --- a/src/client/main.c +++ b/src/client/main.c @@ -2,7 +2,7 @@ #define _POSIX_C_SOURCE 1 /* sigaction, sigaction() */ #define _DARWIN_C_SOURCE 1 /* SIGWINCH on OS X */ -#include /* keypad() */ +#include /* keypad(), start_color() */ #include /* SIGWINCH, sigaction, sigaction() */ #include /* NULL */ #include /* exit() */ @@ -44,6 +44,7 @@ int main(int argc, char * argv[]) /* Initialize the whole interface. */ world.winDB.t_screen = initscr(); + start_color(); set_cleanup_flag(CLEANUP_NCURSES); noecho(); curs_set(0); diff --git a/src/client/world.h b/src/client/world.h index 5d50173..bf4394a 100644 --- a/src/client/world.h +++ b/src/client/world.h @@ -26,12 +26,13 @@ struct World struct KeyBindingDB kb_global; /* globally availabe keybindings */ struct KeyBindingDB kb_wingeom; /* Win geometry config view keybindings */ struct KeyBindingDB kb_winkeys; /* Win keybindings config view keybindings*/ - struct Map map; /* game map geometry and content */ + struct Map map; /* game map geometry and content of player's map view */ time_t last_update; /* used for comparison with worldstate file's mtime */ char * log; /* log of player's activities */ char * path_interface; /* path of interface configuration file */ char * path_commands; /* path of commands config file */ char * player_inventory; /* one-item-per-line string list of owned items */ + char * mem_map; /* map cells of player's map memory */ struct yx_uint8 player_pos; /* coordinates of player on map */ uint16_t turn; /* world/game turn */ uint8_t halfdelay; /* how long to wait for getch() input in io_loop() */ diff --git a/src/server/ai.c b/src/server/ai.c index b761c6b..5be48f3 100644 --- a/src/server/ai.c +++ b/src/server/ai.c @@ -5,7 +5,6 @@ #include /* uint8_t, uint16_t, uint32_t, UINT16_MAX */ #include /* free() */ #include "../common/try_malloc.h" /* try_malloc() */ -#include "field_of_view.h" /* VISIBLE */ #include "hardcoded_strings.h" /* s */ #include "thing_actions.h" /* get_thing_action_id_by_name() */ #include "things.h" /* struct Thing */ @@ -133,7 +132,7 @@ static char get_dir_to_nearest_enemy(struct Thing * t_origin) for (i = 0; i < map_size; i++) { score_map[i] = UINT16_MAX; - if (t_origin->fov_map[i] & VISIBLE && world.map.cells[i] == '.') + if ('.' == t_origin->mem_map[i]) { score_map[i] = max_score; } diff --git a/src/server/field_of_view.c b/src/server/field_of_view.c index 440c84c..f14fffd 100644 --- a/src/server/field_of_view.c +++ b/src/server/field_of_view.c @@ -84,6 +84,9 @@ static void eval_position(uint16_t dist, uint16_t hex_i, uint8_t * fov_map, struct yx_uint8 * test_pos, struct shadow_angle ** shadows); +/* Update "t"'s .mem_map memory with what's in its current field of view. */ +static void update_map_memory(struct Thing * t, uint32_t map_size); + static void mv_yx_in_hex_dir(char d, struct yx_uint8 * yx) @@ -327,6 +330,25 @@ static void eval_position(uint16_t dist, uint16_t hex_i, uint8_t * fov_map, +static void update_map_memory(struct Thing * t, uint32_t map_size) +{ + if (!t->mem_map) + { + t->mem_map = try_malloc(map_size, __func__); + memset(t->mem_map, ' ', map_size); + } + uint32_t i; + for (i = 0; i < map_size; i++) + { + if (' ' == t->mem_map[i] && t->fov_map[i] & VISIBLE) + { + t->mem_map[i] = world.map.cells[i]; + } + } +} + + + extern void build_fov_map(struct Thing * t) { uint32_t map_size = world.map.length * world.map.length; @@ -363,4 +385,5 @@ extern void build_fov_map(struct Thing * t) } mv_yx_in_dir_wrap(0, NULL, 1); free_angles(shadows); + update_map_memory(t, map_size); } diff --git a/src/server/field_of_view.h b/src/server/field_of_view.h index 6920594..9060f1d 100644 --- a/src/server/field_of_view.h +++ b/src/server/field_of_view.h @@ -19,7 +19,7 @@ enum fov_cell_states { VISIBLE = 0x01 }; -/* Build "t"'s field of view. */ +/* Build "t"'s field of view and update its map memory with the result. */ extern void build_fov_map(struct Thing * t); diff --git a/src/server/god_commands.c b/src/server/god_commands.c index 6eec572..755acd5 100644 --- a/src/server/god_commands.c +++ b/src/server/god_commands.c @@ -4,10 +4,11 @@ #include /* NULL */ #include /* uint8_t */ #include /* atoi(), free() */ -#include /* strcmp() */ +#include /* strcmp(), memset(), memcpy() */ #include /* F_OK, access(), unlink() */ #include "../common/parse_file.h" /* err_line(), parse_val(), parsetest_int() */ #include "../common/rexit.h" /* exit_trouble() */ +#include "../common/try_malloc.h" /* try_malloc() */ #include "cleanup.h" /* unset_cleanup_flag() */ #include "field_of_view.h" /* build_fov_map() */ #include "hardcoded_strings.h" /* s */ @@ -48,7 +49,7 @@ static uint8_t parse_position(char* tok0, char * tok1, struct Thing * t); static uint8_t parse_carry(char * tok0, char * tok1, struct Thing * t); /* Parse/apply god command in "tok0"/"tok1" to manipulate a Thing. */ -static uint8_t parse_thing_manipulation(char * tok0, char * tok1); +static uint8_t parse_thing_manipulation_1arg(char * tok0, char * tok1); /* Performs parse_world_active()'s world activation legality tests. */ static uint8_t world_may_be_set_active(); @@ -70,9 +71,15 @@ static uint8_t set_map_length(char * tok0, char * tok1); +/* Thing, ThingType or ThingAction selected to be manipulated. */ +static struct Thing * t = NULL; +static struct ThingType * tt = NULL; +static struct ThingAction * ta = NULL; + + + static uint8_t parse_thingtype_manipulation(char * tok0, char * tok1) { - static struct ThingType * tt = NULL; if (!tt && ( !strcmp(tok0, s[S_CMD_TT_CONSUM]) || !strcmp(tok0, s[S_CMD_TT_SYMB]) || !strcmp(tok0, s[S_CMD_TT_STARTN]) || !strcmp(tok0, s[S_CMD_TT_NAME]) @@ -128,7 +135,6 @@ static uint8_t try_func_name(struct ThingAction * ta, char * name, static uint8_t parse_thingaction_manipulation(char * tok0, char * tok1) { - static struct ThingAction * ta = NULL; if (!ta && (!strcmp(tok0, s[S_CMD_TA_EFFORT]) || !strcmp(tok0, s[S_CMD_TA_NAME]))) { @@ -272,9 +278,8 @@ static uint8_t parse_carry(char * tok0, char * tok1, struct Thing * t) -static uint8_t parse_thing_manipulation(char * tok0, char * tok1) +static uint8_t parse_thing_manipulation_1arg(char * tok0, char * tok1) { - static struct Thing * t = NULL; if (!t && ( !strcmp(tok0, s[S_CMD_T_PROGRESS]) || !strcmp(tok0, s[S_CMD_T_TYPE]) || !strcmp(tok0, s[S_CMD_T_CARRIES]) || !strcmp(tok0, s[S_CMD_T_POSY]) @@ -410,7 +415,7 @@ extern uint8_t parse_god_command_1arg(char * tok0, char * tok1) { if ( parse_thingtype_manipulation(tok0, tok1) || parse_thingaction_manipulation(tok0, tok1) - || parse_thing_manipulation(tok0, tok1) + || parse_thing_manipulation_1arg(tok0, tok1) || set_map_length(tok0,tok1) || parse_val(tok0,tok1,s[S_CMD_SEED_RAND],'U', (char *)&world.seed) || parse_val(tok0,tok1,s[S_CMD_TURN],'u',(char *)&world.turn) @@ -433,3 +438,40 @@ extern uint8_t parse_god_command_1arg(char * tok0, char * tok1) } return 1; } + + + +extern uint8_t parse_god_command_2arg(char * tok0, char * tok1, char * tok2) +{ + if (!t && !strcmp(tok0, s[S_CMD_T_MEMMAP])) + { + err_line(1, "No thing defined to manipulate yet."); + return 1; + } + if (!strcmp(tok0, s[S_CMD_T_MEMMAP])) + { + uint8_t y = atoi(tok1); + if (parsetest_int(tok1, '8') || y >= world.map.length) + { + err_line(1, "Illegal value for map line number."); + return 1; + } + if (strlen(tok2) != world.map.length) + { + err_line(1, "Map line length is unequal map width."); + return 1; + } + if (!t->mem_map) + { + uint32_t map_size = world.map.length * world.map.length; + t->mem_map = try_malloc(map_size, __func__); + memset(t->mem_map, ' ', map_size); + } + memcpy(t->mem_map + y * world.map.length, tok2, world.map.length); + } + else + { + return 0; + } + return 1; +} diff --git a/src/server/god_commands.h b/src/server/god_commands.h index 87af27e..d9b1558 100644 --- a/src/server/god_commands.h +++ b/src/server/god_commands.h @@ -11,8 +11,9 @@ #include /* uint8_t */ -/* Parse/apply god command "tok0" with argument "tok1". */ -extern uint8_t parse_god_command_1arg(char * tok1, char * tok2); +/* Parse/apply god command "tok0" with argument "tok1", "tok2" etc. . */ +extern uint8_t parse_god_command_1arg(char * tok0, char * tok1); +extern uint8_t parse_god_command_2arg(char * tok0, char * tok1, char * tok2); diff --git a/src/server/hardcoded_strings.c b/src/server/hardcoded_strings.c index e9578c7..4e801cf 100644 --- a/src/server/hardcoded_strings.c +++ b/src/server/hardcoded_strings.c @@ -4,7 +4,7 @@ -char * s[38]; +char * s[39]; @@ -36,6 +36,7 @@ extern void init_strings() s[S_CMD_T_PROGRESS] = "T_PROGRESS"; s[S_CMD_T_HP] = "T_LIFEPOINTS"; s[S_CMD_T_CARRIES] = "T_CARRIES"; + s[S_CMD_T_MEMMAP] = "T_MEMMAP"; s[S_CMD_WAIT] = "wait"; s[S_CMD_MOVE] = "move"; s[S_CMD_PICKUP] = "pick_up"; diff --git a/src/server/hardcoded_strings.h b/src/server/hardcoded_strings.h index 2783290..3c8dd81 100644 --- a/src/server/hardcoded_strings.h +++ b/src/server/hardcoded_strings.h @@ -36,6 +36,7 @@ enum string_num S_CMD_T_PROGRESS, S_CMD_T_HP, S_CMD_T_CARRIES, + S_CMD_T_MEMMAP, S_CMD_WAIT, S_CMD_MOVE, S_CMD_PICKUP, @@ -52,7 +53,7 @@ enum string_num extern void init_strings(); -extern char * s[38]; +extern char * s[39]; diff --git a/src/server/io.c b/src/server/io.c index f6d6928..70a0107 100644 --- a/src/server/io.c +++ b/src/server/io.c @@ -5,10 +5,10 @@ #include /* global errno */ #include /* PIPE_BUF */ #include /* size_t, NULL */ -#include /* uint8_t, uint16_t, uint32_t */ +#include /* uint8_t, uint16_t, uint32_t, UINT8_MAX */ #include /* defines EOF, FILE, sprintf(), fprintf() */ #include /* free() */ -#include /* strlen(), memcpy(), memset(), strchr() */ +#include /* strlen(), snprintf(), memcpy(), memset(), strchr() */ #include /* time_t */ #include /* time(), nanosleep() */ #include "../common/readwrite.h" /* atomic_write_start(), atomic_write_finish(), @@ -26,9 +26,12 @@ -/* Write to "file" god commands (one per line) to recreate thing "t". */ -static void write_key_value(FILE * file, char * key, uint32_t value); -static void write_key_string(FILE * file, char * key, char * string); +/* Helpers to write lines of god commands to recreate thing "t". */ +static void write_key_space(FILE * file, char * key); +static void write_value(FILE * file, uint32_t value); +static void write_string(FILE * file, char * string); +static void write_key_space_value(FILE * file, char * key, uint32_t value); +static void write_key_space_string(FILE * file, char * key, char * string); /* Write to "file" \n-delimited line of "key" + space + "value" as string. */ static void write_thing(FILE * file, struct Thing * t); @@ -61,30 +64,34 @@ static void write_inventory(struct Thing * player, FILE * file); */ static char * build_visible_map(struct Thing * player); -/* Write to "file" game map as visible to "player", build_visible_map()-drawn. - * Write one row per \n-delimited line. +/* Write to "file" game map as visible to "player" right now, as drawn by + * build_visible_map(), and thereafter game map as memorized by player in its + * .mem_map. Write one row per \n-delimited line. */ static void write_map(struct Thing * player, FILE * file); -static void write_key_value(FILE * file, char * key, uint32_t value) +static void write_key_space(FILE * file, char * key) { try_fwrite(key, strlen(key), 1, file, __func__); try_fputc(' ', file, __func__); +} + + + +static void write_value(FILE * file, uint32_t value) +{ char * line = try_malloc(11, __func__); exit_trouble(-1 == sprintf(line, "%u", value), __func__, s[S_FCN_SPRINTF]); try_fwrite(line, strlen(line), 1, file, __func__); free(line); - try_fputc('\n', file, __func__); } -static void write_key_string(FILE * file, char * key, char * string) +static void write_string(FILE * file, char * string) { - try_fwrite(key, strlen(key), 1, file, __func__); - try_fputc(' ', file, __func__); uint8_t contains_space = NULL != strchr(string, ' '); if (contains_space) { @@ -95,6 +102,23 @@ static void write_key_string(FILE * file, char * key, char * string) { try_fputc('\'', file, __func__); } +} + + + +static void write_key_space_value(FILE * file, char * key, uint32_t value) +{ + write_key_space(file, key); + write_value(file, value); + try_fputc('\n', file, __func__); +} + + + +static void write_key_space_string(FILE * file, char * key, char * string) +{ + write_key_space(file, key); + write_string(file, string); try_fputc('\n', file, __func__); } @@ -107,17 +131,39 @@ static void write_thing(FILE * file, struct Thing * t) { write_thing(file, o); } - write_key_value(file, s[S_CMD_T_ID], t->id); - write_key_value(file, s[S_CMD_T_TYPE], t->type); - write_key_value(file, s[S_CMD_T_POSY], t->pos.y); - write_key_value(file, s[S_CMD_T_POSX], t->pos.x); - write_key_value(file, s[S_CMD_T_COMMAND], t->command); - write_key_value(file, s[S_CMD_T_ARGUMENT], t->arg); - write_key_value(file, s[S_CMD_T_PROGRESS], t->progress); - write_key_value(file, s[S_CMD_T_HP], t->lifepoints); + write_key_space_value(file, s[S_CMD_T_ID], t->id); + write_key_space_value(file, s[S_CMD_T_TYPE], t->type); + write_key_space_value(file, s[S_CMD_T_POSY], t->pos.y); + write_key_space_value(file, s[S_CMD_T_POSX], t->pos.x); + write_key_space_value(file, s[S_CMD_T_COMMAND], t->command); + write_key_space_value(file, s[S_CMD_T_ARGUMENT], t->arg); + write_key_space_value(file, s[S_CMD_T_PROGRESS], t->progress); + write_key_space_value(file, s[S_CMD_T_HP], t->lifepoints); for (o = t->owns; o; o = o->next) { - write_key_value(file, s[S_CMD_T_CARRIES], o->id); + write_key_space_value(file, s[S_CMD_T_CARRIES], o->id); + } + if (t->mem_map) + { + uint32_t map_size = world.map.length * world.map.length;/* snprintf() */ + char * mem_map_copy = try_malloc(map_size + 1, __func__);/* reads one */ + memcpy(mem_map_copy, t->mem_map, map_size); /* byte beyond map_size */ + mem_map_copy[map_size] = '\0'; /* if string is not \0-terminated. */ + uint16_t y; + char string[UINT8_MAX + 1 + 1]; + for (y = 0; y < world.map.length; y++) + { + + int test = snprintf(string, world.map.length + 1, "%s", + mem_map_copy + (y * world.map.length)); + exit_trouble(test < 0, __func__, "snprintf()"); + write_key_space(file, s[S_CMD_T_MEMMAP]); + write_value(file, y); + try_fputc(' ', file, __func__); + write_string(file, string); + try_fputc('\n', file, __func__); + } + free(mem_map_copy); } try_fputc('\n', file, __func__); } @@ -301,11 +347,19 @@ static void write_map(struct Thing * player, FILE * file) { for (x = 0; x < world.map.length; x++) { - try_fputc(visible_map[(y * world.map.length) + x], file, __func__); + try_fputc(visible_map[y * world.map.length + x], file, __func__); } try_fputc('\n', file, __func__); } free(visible_map); + for (y = 0; y < world.map.length; y++) + { + for (x = 0; x < world.map.length; x++) + { + try_fputc(player->mem_map[y * world.map.length + x], file, __func__); + } + try_fputc('\n', file, __func__); + } } @@ -340,44 +394,44 @@ extern void save_world() { char * path_tmp; FILE * file = atomic_write_start(s[S_PATH_SAVE], &path_tmp); - write_key_value(file, s[S_CMD_MAPLENGTH], world.map.length); - write_key_value(file, s[S_CMD_PLAYTYPE], world.player_type); + write_key_space_value(file, s[S_CMD_MAPLENGTH], world.map.length); + write_key_space_value(file, s[S_CMD_PLAYTYPE], world.player_type); try_fputc('\n', file, __func__); struct ThingAction * ta; for (ta = world.thing_actions; ta; ta = ta->next) { - write_key_value(file, s[S_CMD_TA_ID], ta->id); - write_key_value(file, s[S_CMD_TA_EFFORT], ta->effort); - write_key_string(file, s[S_CMD_TA_NAME], ta->name); + write_key_space_value(file, s[S_CMD_TA_ID], ta->id); + write_key_space_value(file, s[S_CMD_TA_EFFORT], ta->effort); + write_key_space_string(file, s[S_CMD_TA_NAME], ta->name); try_fputc('\n', file, __func__); } struct ThingType * tt; for (tt = world.thing_types; tt; tt = tt->next) { - write_key_value(file, s[S_CMD_TT_ID], tt->id); - write_key_value(file, s[S_CMD_TT_STARTN], tt->start_n); - write_key_value(file, s[S_CMD_TT_HP], tt->lifepoints); + write_key_space_value(file, s[S_CMD_TT_ID], tt->id); + write_key_space_value(file, s[S_CMD_TT_STARTN], tt->start_n); + write_key_space_value(file, s[S_CMD_TT_HP], tt->lifepoints); int test = fprintf(file, "%s %c\n", s[S_CMD_TT_SYMB], tt->char_on_map); exit_trouble(test < 0, __func__, "fprintf"); - write_key_string(file, s[S_CMD_TT_NAME], tt->name); - write_key_value(file, s[S_CMD_TT_CONSUM], tt->consumable); + write_key_space_string(file, s[S_CMD_TT_NAME], tt->name); + write_key_space_value(file, s[S_CMD_TT_CONSUM], tt->consumable); try_fputc('\n', file, __func__); } for (tt = world.thing_types; tt; tt = tt->next) { - write_key_value(file, s[S_CMD_TT_ID], tt->id); - write_key_value(file, s[S_CMD_TT_CORPS], tt->corpse_id); + write_key_space_value(file, s[S_CMD_TT_ID], tt->id); + write_key_space_value(file, s[S_CMD_TT_CORPS], tt->corpse_id); } try_fputc('\n', file, __func__); - write_key_value(file, s[S_CMD_SEED_MAP], world.seed_map); - write_key_value(file, s[S_CMD_SEED_RAND], world.seed); - write_key_value(file, s[S_CMD_TURN], world.turn); + write_key_space_value(file, s[S_CMD_SEED_MAP], world.seed_map); + write_key_space_value(file, s[S_CMD_SEED_RAND], world.seed); + write_key_space_value(file, s[S_CMD_TURN], world.turn); try_fputc('\n', file, __func__); struct Thing * t; for (t = world.things; t; t = t->next) { write_thing(file, t); } - write_key_value(file, s[S_CMD_WORLD_ACTIVE], 1); + write_key_space_value(file, s[S_CMD_WORLD_ACTIVE], 1); atomic_write_finish(file, s[S_PATH_SAVE], path_tmp); } diff --git a/src/server/run.c b/src/server/run.c index 6cbbd58..ecfae2b 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -18,7 +18,7 @@ #include "../common/try_malloc.h" /* try_malloc() */ #include "ai.h" /* ai() */ #include "cleanup.h" /* unset_cleanup_flag() */ -#include "god_commands.h" /* parse_god_command_1arg() */ +#include "god_commands.h" /* parse_god_command_1arg(),parse_god_command_2arg()*/ #include "hardcoded_strings.h" /* s */ #include "io.h" /* io_round(), save_world() */ #include "things.h" /* Thing, get_thing_action_id_by_name(), get_player() */ @@ -39,7 +39,7 @@ static uint8_t parse_player_command_0arg(char * tok0); /* Parse player command "tok0" with one argument "tok1" to player action. */ static uint8_t parse_player_command_1arg(char * tok0, char * tok1); -/* Parse/apply command "tok0". */ +/* Parse/apply command "tok0" (read further tokens as necessary). */ static uint8_t parse_command(char * tok0); /* Compares first line of server out file to world.server_test, aborts if they @@ -149,6 +149,14 @@ static uint8_t parse_command(char * tok0) { return 1; } + else + { + char * tok2 = token_from_line(NULL); + if (tok2 && parse_god_command_2arg(tok0, tok1, tok2)) + { + return 1; + } + } } return 0; } @@ -199,7 +207,6 @@ static void turn_over() ai(thing); } thing->progress++; - struct ThingAction * ta = get_thing_action(thing->command); if (thing->progress == ta->effort) { diff --git a/src/server/thing_actions.c b/src/server/thing_actions.c index 8d6a802..40a44ba 100644 --- a/src/server/thing_actions.c +++ b/src/server/thing_actions.c @@ -142,8 +142,16 @@ static void actor_hits_actor(struct Thing * hitter, struct Thing * hitted) if (player == hitted) { update_log(" You die."); + memset(hitted->fov_map, ' ', world.map.length * world.map.length); return; } + else + { + free(hitted->fov_map); + hitted->fov_map = NULL; + free(hitted->mem_map); + hitted->mem_map = NULL; + } update_log(" It dies."); } } diff --git a/src/server/things.c b/src/server/things.c index 4a5a490..e73a09a 100644 --- a/src/server/things.c +++ b/src/server/things.c @@ -156,6 +156,7 @@ extern void free_things(struct Thing * t) free_things(t->owns); free_things(t->next); free(t->fov_map); + free(t->mem_map); free(t); if (t == world.things) /* So add_things()' NULL-delimited thing */ { /* iteration loop does not iterate over */ diff --git a/src/server/things.h b/src/server/things.h index d5ef508..4b9291c 100644 --- a/src/server/things.h +++ b/src/server/things.h @@ -19,6 +19,7 @@ struct Thing struct Thing * owns; /* chain of things owned / in inventory */ struct yx_uint8 pos; /* coordinate on map */ uint8_t * fov_map; /* map of the thing's field of view */ + uint8_t * mem_map; /* map knowledge of thing by FOV and memory */ uint8_t type; /* ID of appropriate thing definition */ uint8_t lifepoints; /* 0: thing is inanimate; >0: hitpoints */ uint8_t command; /* thing's current action; 0 if none */ -- 2.30.2