home · contact · privacy
Add auto-mapping / map memory.
authorChristian Heller <c.heller@plomlompom.de>
Sat, 2 Aug 2014 03:20:05 +0000 (05:20 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Sat, 2 Aug 2014 03:20:05 +0000 (05:20 +0200)
19 files changed:
SERVER_COMMANDS
TODO
src/client/cleanup.c
src/client/draw_wins.c
src/client/io.c
src/client/main.c
src/client/world.h
src/server/ai.c
src/server/field_of_view.c
src/server/field_of_view.h
src/server/god_commands.c
src/server/god_commands.h
src/server/hardcoded_strings.c
src/server/hardcoded_strings.h
src/server/io.c
src/server/run.c
src/server/thing_actions.c
src/server/things.c
src/server/things.h

index d574180d0ca503cb067ff9da55a57b74b16e1ea0..c229f63847a195ccba34da79c3754c79d9935ccf 100644 (file)
@@ -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 c37c5c23f141ee9aa39ae727c73295f68edf6e2c..c8b668126d80ff99a19d069220ac28b92787ea9c 100644 (file)
--- 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
index 3499246c7abcb6b324844a0c52bd401eb238174c..f4b97bfe6cef34c1aa0bfa721a22675ba48581a7 100644 (file)
@@ -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)
index bb86bb95ffd161a999d03acf2d36ecb364ecb16c..6736a1bbb77b980872fa2950c6b57201f546bb22 100644 (file)
@@ -2,7 +2,7 @@
 
 #define _POSIX_C_SOURCE 200809L /* strdup() */
 #include "draw_wins.h"
-#include <ncurses.h> /* typedefs attr_t, chtype, define A_REVERSE */
+#include <ncurses.h> /* attr_t, chtype, init_pair(), A_REVERSE, COLOR_PAIR() */
 #include <stddef.h> /* NULL */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT16_MAX */
 #include <stdio.h> /* 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++;
         }
     }
index d0b9dc022b303f1e61de8a12d64e140c2273c8af..c0cf977bf0d802ec24f9cb3207ab2154ebe59b0d 100644 (file)
  */
 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__);
index 9c6a72ac3f19a3c8942d2c89a68955b703935ee7..68841ca640552960d11759408f5d4a9188576c67 100644 (file)
@@ -2,7 +2,7 @@
 
 #define _POSIX_C_SOURCE 1 /* sigaction, sigaction() */
 #define _DARWIN_C_SOURCE 1 /* SIGWINCH on OS X */
-#include <ncurses.h> /* keypad() */
+#include <ncurses.h> /* keypad(), start_color() */
 #include <signal.h> /* SIGWINCH, sigaction, sigaction() */
 #include <stddef.h> /* NULL */
 #include <stdlib.h> /* 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);
index 5d5017317991abb586d4548ffad9ba234a360b46..bf4394a7624fca483be8f3b24c16b66acbb1c38d 100644 (file)
@@ -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() */
index b761c6bbbc8039fd2ba75908228f3b006ed9bc8a..5be48f3b7e00939ce19c2bbd5c2547dcaf68f91c 100644 (file)
@@ -5,7 +5,6 @@
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT16_MAX */
 #include <stdlib.h> /* 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;
         }
index 440c84c2d6bea8a050673b30a7f3ff4a1321a5fc..f14fffd1c11b090057dd707d94f93ec6383d2508 100644 (file)
@@ -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);
 }
index 6920594d174fbce272761eca7ad2a24e55871a1f..9060f1dcb7b849d01196fed23f04be4b9fed681e 100644 (file)
@@ -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);
 
 
index 6eec5722d6bddcf729f9264d104a1490e9d9de5c..755acd5881b4ff8bf4ba604c08d89c0f8d83e986 100644 (file)
@@ -4,10 +4,11 @@
 #include <stddef.h> /* NULL */
 #include <stdint.h> /* uint8_t */
 #include <stdlib.h> /* atoi(), free() */
-#include <string.h> /* strcmp() */
+#include <string.h> /* strcmp(), memset(), memcpy() */
 #include <unistd.h> /* 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;
+}
index 87af27e0b8d97e1a561b8cb9a71b1433c6297397..d9b1558b48f26568efa126d1705e26ca43d9b9df 100644 (file)
@@ -11,8 +11,9 @@
 #include <stdint.h> /* 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);
 
 
 
index e9578c7572549854a451bd4b3b3a1e34a33ed366..4e801cfb3476646fd6125a948697e39b0e669dda 100644 (file)
@@ -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";
index 27832904de51852b22985e95a6b8576016873804..3c8dd8161d96c742974d186e3bd5a4dfbf05a06c 100644 (file)
@@ -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];
 
 
 
index f6d6928a2f9e4b9ff1dfeb89f58049c31877427c..70a010780c9a97ba866c3c88f8f296134e0fc7b0 100644 (file)
@@ -5,10 +5,10 @@
 #include <errno.h> /* global errno */
 #include <limits.h> /* PIPE_BUF */
 #include <stddef.h> /* size_t, NULL */
-#include <stdint.h> /* uint8_t, uint16_t, uint32_t */
+#include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT8_MAX */
 #include <stdio.h> /* defines EOF, FILE, sprintf(), fprintf() */
 #include <stdlib.h> /* free() */
-#include <string.h> /* strlen(), memcpy(), memset(), strchr() */
+#include <string.h> /* strlen(), snprintf(), memcpy(), memset(), strchr() */
 #include <sys/types.h> /* time_t */
 #include <time.h> /* time(), nanosleep() */
 #include "../common/readwrite.h" /* atomic_write_start(), atomic_write_finish(),
 
 
 
-/* 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);
 }
index 6cbbd58ee85b587ce2d6597ea364d0daede2b88e..ecfae2bc4d7ed4dea0f3067b970f36b920f0ffad 100644 (file)
@@ -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)
             {
index 8d6a802417ea6df95068892fe3b89b77cad7057f..40a44ba17ce71dd4ed51a8ae29137b9618edce95 100644 (file)
@@ -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.");
     }
 }
index 4a5a490dbcc6f3f93abeace2576cd7c88b838159..e73a09a283c09fb843292996c0b6ee3561f68d2f 100644 (file)
@@ -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    */
index d5ef508a4aa5bd3034aa2e182d2ead9bd47265b3..4b9291cc4895bdb96868584d89fe18964e3c9636 100644 (file)
@@ -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 */