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.
 
 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
 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)
 
 
 - 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 
 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
 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);
 extern void cleanup()
 {
     free(world.map.cells);
+    free(world.mem_map);
     free(world.log);
     free(world.player_inventory);
     if (cleanup_flags & CLEANUP_INTERFACE)
     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"
 
 #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() */
 #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)
 {
 
 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);
     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++)
         {
     {
         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++;
         }
     }
             z++;
         }
     }
index d0b9dc022b303f1e61de8a12d64e140c2273c8af..c0cf977bf0d802ec24f9cb3207ab2154ebe59b0d 100644 (file)
  */
 static void read_inventory(char * read_buf, uint32_t linemax, FILE * 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).
  */
  * 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.
 
 /* 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__);
     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__);
     }
         }
         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);
         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__);
     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 */
 
 #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() */
 #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();
 
     /* Initialize the whole interface. */
     world.winDB.t_screen = initscr();
+    start_color();
     set_cleanup_flag(CLEANUP_NCURSES);
     noecho();
     curs_set(0);
     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 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 */
     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() */
     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 <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 */
 #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;
     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;
         }
         {
             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);
 
                           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)
 
 
 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;
 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);
     }
     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
 };
 
     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);
 
 
 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 <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 <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 */
 #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_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();
 
 /* 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 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])
     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 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])))
     {
     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])
     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)
 {
     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)
         || 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;
 }
     }
     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 */
 
 
 #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_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";
     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_PROGRESS,
     S_CMD_T_HP,
     S_CMD_T_CARRIES,
+    S_CMD_T_MEMMAP,
     S_CMD_WAIT,
     S_CMD_MOVE,
     S_CMD_PICKUP,
     S_CMD_WAIT,
     S_CMD_MOVE,
     S_CMD_PICKUP,
@@ -52,7 +53,7 @@ enum string_num
 
 extern void init_strings();
 
 
 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 <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 <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(),
 #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);
 
 /* 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);
 
  */
 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_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__);
 {
     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);
     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)
     {
     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__);
     }
     {
         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__);
 }
 
     try_fputc('\n', file, __func__);
 }
 
@@ -107,17 +131,39 @@ static void write_thing(FILE * file, struct Thing * t)
     {
         write_thing(file, o);
     }
     {
         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)
     {
     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__);
 }
     }
     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++)
         {
     {
         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);
         }
         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);
 {
     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)
     {
     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)
     {
         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");
         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)
     {
         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__);
     }
     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);
     }
     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);
 }
     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 "../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() */
 #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 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
 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;
         }
         {
             return 1;
         }
+        else
+        {
+            char * tok2 = token_from_line(NULL);
+            if (tok2 && parse_god_command_2arg(tok0, tok1, tok2))
+            {
+                return 1;
+            }
+        }
     }
     return 0;
 }
     }
     return 0;
 }
@@ -199,7 +207,6 @@ static void turn_over()
                 ai(thing);
             }
             thing->progress++;
                 ai(thing);
             }
             thing->progress++;
-
             struct ThingAction * ta = get_thing_action(thing->command);
             if (thing->progress == ta->effort)
             {
             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.");
         if (player == hitted)
         {
             update_log(" You die.");
+            memset(hitted->fov_map, ' ', world.map.length * world.map.length);
             return;
         }
             return;
         }
+        else
+        {
+            free(hitted->fov_map);
+            hitted->fov_map = NULL;
+            free(hitted->mem_map);
+            hitted->mem_map = NULL;
+        }
         update_log(" It dies.");
     }
 }
         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_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    */
     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 */
     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 */
     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 */