home · contact · privacy
Server: Add ENEMY_FOV option (default: off) to force FOV on enemies.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 13 May 2014 04:01:02 +0000 (06:01 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 13 May 2014 04:01:02 +0000 (06:01 +0200)
README
TODO
confserver/world
src/server/ai.c
src/server/configfile.c
src/server/field_of_view.c
src/server/field_of_view.h
src/server/io.c
src/server/map.c
src/server/map.h
src/server/world.h

diff --git a/README b/README
index ff6a3969e2cb23016505e1b934c2d1f59fab4aaa..1923471d851ed791720fbc071a5eb9ff8de3bee6 100644 (file)
--- a/README
+++ b/README
@@ -13,7 +13,9 @@ numbers of turns to finish.
 
 Enemies' AI is very dumb so far: Each turn, they try to move towards their
 shortest-path-wise nearest enemy. If no enemy is found in their surroundings,
-they just wait.
+they just wait. Contrary to the player, they by default see the whole map. (To
+make them see only what is in their line of sight, enable ENEMY_FOV in the
+server config file; see below "Hacking / server internals and configuration".)
 
 Once you start a new world, every move of yours is recorded in a file called
 "record". Once you re-start the game, all of your previous moves are replayed
@@ -78,8 +80,9 @@ Hacking / server internals and configuration
 --------------------------------------------
 
 The ./confserver/world file defines the map object types, actions available to
-them and the map itself. Each definition consists of a multi-line block wherein
-each line sets one attribute of the object type, action or the map.
+them, the map itself, the map object type (species) of the player and whether
+enemies see the whole map or only a line-of-sight field of view. Each definition
+consists of a single- or multi-line block wherein each line sets one attribute.
 
 Here's a typical map definition block:
 
@@ -130,6 +133,12 @@ yet: or if they are inanimate, but are otherwise crushed). Note that the
 after, it may even be the same). "START_NUMBER" sets the number of objects that
 are to appear of the given type on the map on game start.
 
+A line of "PLAYER_TYPE" followed by a number sets the map object type (id) of
+the player's creature. "ENEMY_FOV" followed by "0" or "1" sets whether enemies
+see the whole map or only that to which they have an unobstructed line of sight.
+Since plomrogue's FOV algorithm is currently very expensive, this is disabled by
+default.
+
 All these definition block members must be present within their blocks, but only
 "ACTION" / "OBJECT" / "MAP_TYPE" must be positioned at their respective blocks'
 first line; the others may appear in whatever order and even multiple times. If
diff --git a/TODO b/TODO
index 414e1550a715709090833998aba408abd5cd8842..bb54d85113c81676b86669f970b516a1ede5146c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -13,6 +13,8 @@ BOTH SERVER/CLIENT:
 
 SERVER:
 
+- optimize too-slow AI / FOV algorithms
+
 - is it actually useful to define map object action ids in the config file?
 
 - for game continuation, replace re-playing of whole record files with loading
index 724d0120f2d6056fb439383712443fd42cc672b2..bf2488cb102eeeca631e1d31b351ca176bb10c8e 100644 (file)
@@ -3,6 +3,7 @@ HEIGHT 64
 WIDTH 64
 
 PLAYER_TYPE 0
+ENEMY_FOV 0
 
 ACTION 1
 NAME wait
index 9c31153c40595180c5db22d89ee725e654c7de98..d099c5748ce2d69ca6df26e3652d9141532d787c 100644 (file)
@@ -5,6 +5,7 @@
 #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" /* build_fov_map() */
 #include "map_object_actions.h" /* get_moa_id_by_name() */
 #include "map_objects.h" /* struct MapObj */
 #include "world.h" /* global world */
@@ -27,15 +28,16 @@ static void get_neighbor_scores(uint16_t * score_map, uint16_t pos_i,
  * each cell's score against the score of its immediate neighbors in N_DIRS
  * directions. If it's neighbors are low enough that the result would be lower
  * than the current value, re-set it to 1 point higher than its lowest-scored
- * neighbor- Repeat this whole process until all cells have settled on their
+ * neighbor. Repeat this whole process until all cells have settled on their
  * final score. Ignore cells whose position in "score_map" fits cells of
- * unreachable terrain in world.map.cells. Expect "max_score" to be the maximum
- * score for cells, marking them as unreachable.
+ * unreachable terrain in world.map.cells or whose score is greater than
+ * "max_score". Expect "max_score" to be the maximum score for cells, marking
+ * them as unreachable.
  */
 static void dijkstra_map(uint16_t * score_map, uint16_t max_score);
 
 /* Return numpad char of direction ("8", "6", "2", "4" etc.) of enemy with the
- * shortest path to "mo_origin". If no enemy is around, return 0.
+ * shortest path visible to "mo_origin". If no enemy is around, return 0.
  */
 static char get_dir_to_nearest_enemy(struct MapObj * mo_origin);
 
@@ -93,7 +95,7 @@ static void dijkstra_map(uint16_t * score_map, uint16_t max_score)
         scores_still_changing = 0;
         for (pos = 0; pos < map_size; pos++)
         {
-            if ('.' == world.map.cells[pos])
+            if ('.' == world.map.cells[pos] && score_map[pos] <= max_score)
             {
                 get_neighbor_scores(score_map, pos, max_score, neighbors);
                 min_neighbor = max_score;
@@ -120,18 +122,27 @@ static char get_dir_to_nearest_enemy(struct MapObj * mo_origin)
 {
     char * f_name = "get_dir_to_nearest_enemy()";
 
-    /* Calculate for each cell the distance to the nearest map actor that is
-     * not "mo_origin", with movement only possible in the directions of "dir".
+    /* Calculate for each cell the distance to the visibly nearest map actor not
+     * "mo_origin", with movement only possible in the directions of "dir".
      * (Actors' own cells start with a distance of 0 towards themselves.)
      */
     uint32_t map_size = world.map.size.y * world.map.size.x;
-    uint16_t max_score = UINT16_MAX;
+    uint16_t max_score = UINT16_MAX - 1;
     uint16_t * score_map = try_malloc(map_size * sizeof(uint16_t), f_name);
+    uint8_t * fov_map = world.enemy_fov ? build_fov_map(mo_origin) : NULL;
     uint32_t i;
     for (i = 0; i < map_size; i++)
     {
-        score_map[i] = max_score;
+        if (world.enemy_fov)
+        {
+            score_map[i] = fov_map[i] & VISIBLE ? max_score : UINT16_MAX;
+        }
+        else
+        {
+            score_map[i] = max_score;
+        }
     }
+    free(fov_map);
     struct MapObj * mo = world.map_objs;
     for (; mo != NULL; mo = mo->next)
     {
index fc2c771f42d952a3c5c5721d8dd533153ee264f1..14464396dc7e93ff6af93396d8a0faee0e2f78bf 100644 (file)
@@ -93,6 +93,9 @@ static void test_corpse_ids();
 /* set_members() helper specifically for editing world.map members. */
 static uint8_t set_map_members(char * token0,char * token1,uint8_t * map_flags);
 
+/* If "token0" matches "comparand", set world.enemy_fov to "token1". */
+static uint8_t set_enemy_fov(char * token0, char * comparand, char * token1);
+
 /* If "token0" matches "comparand", set world.player_type to int in "token1". */
 static uint8_t set_player_type(char * token0, char * comparand, char * token1);
 
@@ -121,6 +124,7 @@ static void tokens_into_entries(char * token0, char * token1)
     char * str_obj = "OBJECT";
     char * str_map = "MAP_TYPE";
     char * str_player = "PLAYER_TYPE";
+    char * str_enemyfov = "ENEMY_FOV";
     static struct MapObjAct ** moa_p_p = &world.map_obj_acts;
     static struct MapObjDef ** mod_p_p = &world.map_obj_defs;
     static uint8_t action_flags = READY_ACT;
@@ -129,7 +133,8 @@ static void tokens_into_entries(char * token0, char * token1)
     static struct EntryHead * moa = NULL;
     static struct EntryHead * mod = NULL;
     if (!token0 || !strcmp(token0, str_act) || !strcmp(token0, str_obj)
-                || !strcmp(token0, str_map) || !strcmp(token0, str_player))
+                || !strcmp(token0, str_map) || !strcmp(token0, str_player)
+                || !strcmp(token0, str_enemyfov))
     {
         parse_and_reduce_to_readyflag(&action_flags, READY_ACT);
         parse_and_reduce_to_readyflag(&object_flags, READY_OBJ);
@@ -152,6 +157,7 @@ static void tokens_into_entries(char * token0, char * token1)
                                   (struct EntryHead *) world.map_obj_defs)
                    || start_map(token0, str_map, &map_flags)
                    || set_player_type(token0, str_player, token1)
+                   || set_enemy_fov(token0, str_enemyfov, token1)
                    || set_members(token0, token1, &object_flags, &action_flags,
                                   &map_flags, (struct MapObjDef *)mod,
                                   (struct MapObjAct *) moa)))
@@ -255,6 +261,21 @@ static uint8_t set_map_members(char * token0, char * token1,uint8_t * map_flags)
 
 
 
+static uint8_t set_enemy_fov(char * token0, char * comparand, char * token1)
+{
+    if (strcmp(token0, comparand))
+    {
+        return 0;
+    }
+    parsetest_int(token1, '8');
+    int test = atoi(token1) > 1;
+    err_line(test, "Value must be 0 or 1.");
+    world.enemy_fov = atoi(token1);
+    return 1;
+}
+
+
+
 static uint8_t set_player_type(char * token0, char * comparand, char * token1)
 {
     if (strcmp(token0, comparand))
index a48582a28220aae8da064330e13ef61fbb298486..c92c11a86ec637b0248ebbaf5b1ad68e354fea9e 100644 (file)
@@ -7,22 +7,13 @@
 #include <string.h> /* memset(), strchr(), strdup() */
 #include "../common/rexit.h" /* exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
-#include "map_objects.h" /* MapObj, MapObjDef, get_player() */
+#include "map.h" /* yx_to_map_pos() */
+#include "map_objects.h" /* MapObj */
 #include "yx_uint8.h" /* yx_uint8 */
 #include "world.h" /* global world  */
 
 
 
-/* States that cells in the fov map may be in. */
-enum fov_cell_states {
-    VISIBLE      = 0x01,
-    HIDDEN       = 0x02,
-    SHADOW_LEFT  = 0x04,
-    SHADOW_RIGHT = 0x08,
-    LIMIT        = 0x10,
-    HIDE_LATER   = 0x20
-};
-
 /* Values for mv_yx_in_dir_wrap()'s wrapping directory memory. */
 enum wraps
 {
@@ -33,7 +24,7 @@ enum wraps
 };
 
 /* Transform "yx" to an index position in the world map. */
-static uint16_t yx_to_pos(struct yx_uint8 * yx);
+//static uint16_t yx_to_pos(struct yx_uint8 * yx);
 
 /* Move "yx" into hex direction "d". If this moves "yx" beyond the minimal (0)
  * or maximal (UINT8_MAX) column or row, it wraps to the opposite side. Such
@@ -148,31 +139,6 @@ static void set_view_of_cell_and_shadows(struct yx_uint8 * yx_cell,
                                          struct yx_uint8 * yx_eye,
                                          uint8_t * fov_map);
 
-/* Return overlay of world map wherein all cell positions visible from player's
- * positions have flag VISIBLE set.
- *
- * This is achieved by spiraling out clock-wise from the player position,
- * flagging cells as VISIBLE unless they're already marked as HIDDEN, and, on
- * running into obstacles for view that are not HIDDEN, casting shadows from
- * these, i.e. drawing cells as HIDDEN that would be hidden by said obstacle,
- * before continuing the original spiraling path.
- *
- * Shadowcasting during spiraling is initially lazy, flagging only the shadows'
- * interior cells as HIDDEN and their border cells as HIDE_LATER. Only at the
- * end are all cells flagged HIDE_LATER flagged as HIDDEN. This is to handle
- * cases where obstacles to view sit right at the border of pre-estabilshed
- * shadows, therefore might be ignored if HIDDEN and not cast shadows on their
- * own that may slightly extend beyond the pre-established shadows they border.
- */
-static uint8_t * build_fov_map();
-
-
-
-static uint16_t yx_to_pos(struct yx_uint8 * yx)
-{
-    return (yx->y * world.map.size.x) + yx->x;
-}
-
 
 
 static uint8_t mv_yx_in_dir_wrap(char d, struct yx_uint8 * yx, uint8_t unwrap)
@@ -290,7 +256,7 @@ extern void draw_border_circle(struct yx_uint8 yx, uint8_t radius,
     {
          if (mv_yx_in_dir_legal(dir, &yx))
          {
-            uint16_t pos = yx_to_pos(&yx);
+            uint16_t pos = yx_to_map_pos(&yx);
             fov_map[pos] = LIMIT;
         }
     }
@@ -518,7 +484,7 @@ static uint16_t shadow_arm(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_start,
                            uint8_t shift_right)
 {
     struct yx_uint8 yx_border = *yx_start;
-    uint16_t pos;
+    uint16_t pos = yx_to_map_pos(&yx_border);
     if (mv_yx_in_dir_legal(dir, &yx_border))
     {
         uint8_t met_limit = 0;
@@ -527,7 +493,7 @@ static uint16_t shadow_arm(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_start,
         yx_border = *yx_start;
         while (!met_limit && mv_yx_in_dir_legal(dirs[i_dirs], &yx_border))
         {
-            pos = yx_to_pos(&yx_border);
+            pos = yx_to_map_pos(&yx_border);
             met_limit = fov_map[pos] & LIMIT;
             fov_map[pos] = fov_map[pos] | flag;
             i_dirs = dirs[i_dirs + 1] ? i_dirs + 1 : 0;
@@ -546,7 +512,7 @@ static void shadow(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_start,
     uint16_t pos_a, pos_b, pos_start, i;
     pos_a = shadow_arm(yx_eye, yx_start, fov_map, dir_left, SHADOW_LEFT, 0);
     pos_b = shadow_arm(yx_eye, yx_start, fov_map, dir_right, SHADOW_RIGHT, 1);
-    pos_start = yx_to_pos(yx_start);
+    pos_start = yx_to_map_pos(yx_start);
     fov_map[pos_start] = fov_map[pos_start] | SHADOW_LEFT | SHADOW_RIGHT;
     fill_shadow(yx_eye, yx_start, fov_map, pos_a, pos_b);
     for (i = 0; i < world.map.size.y * world.map.size.x; i++)
@@ -568,7 +534,7 @@ static void set_view_of_cell_and_shadows(struct yx_uint8 * yx_cell,
                                          uint8_t * fov_map)
 {
     char * dirs = "dcxswe";
-    uint16_t pos = yx_to_pos(yx_cell);
+    uint16_t pos = yx_to_map_pos(yx_cell);
     if (!(fov_map[pos] & HIDDEN))
     {
         fov_map[pos] = fov_map[pos] | VISIBLE;
@@ -594,17 +560,16 @@ static void set_view_of_cell_and_shadows(struct yx_uint8 * yx_cell,
 
 
 
-static uint8_t * build_fov_map()
+extern uint8_t * build_fov_map(struct MapObj * eye)
 {
     char * f_name = "build_fov_map()";
     uint8_t radius = 2 * world.map.size.y;
     uint32_t map_size = world.map.size.y * world.map.size.x;
-    struct MapObj * player = get_player();
-    struct yx_uint8 yx = player->pos;
+    struct yx_uint8 yx = eye->pos;
     uint8_t * fov_map = try_malloc(map_size, f_name);
     memset(fov_map, 0, map_size);
     draw_border_circle(yx, radius, fov_map);
-    fov_map[yx_to_pos(&yx)] = VISIBLE;
+    fov_map[yx_to_map_pos(&yx)] = VISIBLE;
     uint8_t dist;
     for (dist = 1; dist <= radius; dist++)
     {
@@ -617,7 +582,7 @@ static uint8_t * build_fov_map()
             first_round = 0;
             if (mv_yx_in_dir_legal(i_dir, &yx))
             {
-                set_view_of_cell_and_shadows(&yx, &player->pos, fov_map);
+                set_view_of_cell_and_shadows(&yx, &eye->pos, fov_map);
             }
         }
     }
@@ -631,42 +596,3 @@ static uint8_t * build_fov_map()
     }
     return fov_map;
 }
-
-
-
-extern char * build_visible_map()
-{
-    char * f_name = "build_visible_map()";
-    uint8_t * fov_map = build_fov_map();
-    uint32_t map_size = world.map.size.y * world.map.size.x;
-    char * visible_map = try_malloc(map_size, f_name);
-    memset(visible_map, ' ', map_size);
-    uint16_t pos_i;
-    for (pos_i = 0; pos_i < map_size; pos_i++)
-    {
-        if (fov_map[pos_i] & VISIBLE)
-        {
-            visible_map[pos_i] = world.map.cells[pos_i];
-        }
-    }
-    struct MapObj * o;
-    struct MapObjDef * d;
-    char c;
-    uint8_t i;
-    for (i = 0; i < 2; i++)
-    {
-        for (o = world.map_objs; o != 0; o = o->next)
-        {
-            if (   fov_map[yx_to_pos(&o->pos)] & VISIBLE
-                && (   (0 == i && 0 == o->lifepoints)
-                    || (1 == i && 0 < o->lifepoints)))
-            {
-                d = get_map_object_def(o->type);
-                c = d->char_on_map;
-                visible_map[yx_to_pos(&o->pos)] = c;
-            }
-        }
-    }
-    free(fov_map);
-    return visible_map;
-}
index eb117ae4f7cbacbdb408dd198faead5ef7924931..ee337eb1d69636d4d95e764c685a94cc02d5e99b 100644 (file)
@@ -1,6 +1,6 @@
 /* src/server/field_of_view.h
  *
- * Generate view of map as visible to player.
+ * Generate field of view maps.
  */
 
 
@@ -8,12 +8,38 @@
 #ifndef FIELD_OF_VIEW_H
 #define FIELD_OF_VIEW_H
 
+#include <stdint.h> /* uint8_t */
+struct MapObj;
 
 
-/* Return map cells sequence as visible to the player, with invisible cells as
- * whitespace. Super-impose over visible map cells map objects positioned there.
+
+/* States that cells in the fov map may be in. */
+enum fov_cell_states {
+    VISIBLE      = 0x01,
+    HIDDEN       = 0x02,
+    SHADOW_LEFT  = 0x04,
+    SHADOW_RIGHT = 0x08,
+    LIMIT        = 0x10,
+    HIDE_LATER   = 0x20
+};
+
+/* Return overlay of world map wherein all cell positions visible from player's
+ * positions have flag VISIBLE set.
+ *
+ * This is achieved by spiraling out clock-wise from the player position,
+ * flagging cells as VISIBLE unless they're already marked as HIDDEN, and, on
+ * running into obstacles for view that are not HIDDEN, casting shadows from
+ * these, i.e. drawing cells as HIDDEN that would be hidden by said obstacle,
+ * before continuing the original spiraling path.
+ *
+ * Shadowcasting during spiraling is initially lazy, flagging only the shadows'
+ * interior cells as HIDDEN and their border cells as HIDE_LATER. Only at the
+ * end are all cells flagged HIDE_LATER flagged as HIDDEN. This is to handle
+ * cases where obstacles to view sit right at the border of pre-estabilshed
+ * shadows, therefore might be ignored if HIDDEN and not cast shadows on their
+ * own that may slightly extend beyond the pre-established shadows they border.
  */
-extern char * build_visible_map();
+extern uint8_t * build_fov_map(struct MapObj * eye);
 
 
 
index 81251c1e4ff34612d7e1f9ecf6a964d23f8373bf..7fbb511055b2e30842a24b713bcfb5502dbf42ae 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, uint32_t */
+#include <stdint.h> /* uint8_t, uint16_t, uint32_t */
 #include <stdio.h> /* defines EOF, FILE, sprintf() */
 #include <stdlib.h> /* free() */
-#include <string.h> /* strlen(), memcpy() */
+#include <string.h> /* strlen(), memcpy(), memset() */
 #include <sys/types.h> /* time_t */
 #include <time.h> /* time(), nanosleep() */
 #include "../common/readwrite.h" /* try_fopen(), try_fclose_unlink_rename(),
@@ -16,7 +16,8 @@
                                   */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "cleanup.h" /* set_cleanup_flag() */
-#include "field_of_view.h" /* build_visible_map() */
+#include "field_of_view.h" /* VISIBLE, build_fov_map() */
+#include "map.h" /* yx_to_map_pos() */
 #include "map_objects.h" /* structs MapObj, MapObjDef, get_map_obj_def() */
 #include "world.h" /* global world  */
 
@@ -45,10 +46,15 @@ static void write_value_as_line(uint32_t value, FILE * file);
 /* Write to "file" player's inventory, one item name per line. End in "%\n". */
 static void write_inventory(struct MapObj * player, FILE * file);
 
-/* Write to "file" game map as visible to the player, build_visible_map()-drawn.
+/* Return map cells sequence as visible to the "player", with invisible cells as
+ * whitespace. Super-impose over visible map cells map objects positioned there.
+ */
+static char * build_visible_map(struct MapObj * player);
+
+/* Write to "file" game map as visible to "player", build_visible_map()-drawn.
  * Write one row per \n-delimited line.
  */
-static void write_map(FILE * file);
+static void write_map(struct MapObj * player, FILE * file);
 
 
 
@@ -138,7 +144,7 @@ static void update_worldstate_file()
     write_value_as_line(player->pos.x, file);
     write_value_as_line(world.map.size.y, file);
     write_value_as_line(world.map.size.x, file);
-    write_map(file);
+    write_map(player, file);
     if (world.log)
     {
         try_fwrite(world.log, strlen(world.log), 1, file, f_name);
@@ -188,10 +194,49 @@ static void write_inventory(struct MapObj * player, FILE * file)
 
 
 
-static void write_map(FILE * file)
+static char * build_visible_map(struct MapObj * player)
+{
+    char * f_name = "build_visible_map()";
+    uint8_t * fov_map = build_fov_map(player);
+    uint32_t map_size = world.map.size.y * world.map.size.x;
+    char * visible_map = try_malloc(map_size, f_name);
+    memset(visible_map, ' ', map_size);
+    uint16_t pos_i;
+    for (pos_i = 0; pos_i < map_size; pos_i++)
+    {
+        if (fov_map[pos_i] & VISIBLE)
+        {
+            visible_map[pos_i] = world.map.cells[pos_i];
+        }
+    }
+    struct MapObj * o;
+    struct MapObjDef * d;
+    char c;
+    uint8_t i;
+    for (i = 0; i < 2; i++)
+    {
+        for (o = world.map_objs; o != 0; o = o->next)
+        {
+            if (   fov_map[yx_to_map_pos(&o->pos)] & VISIBLE
+                && (   (0 == i && 0 == o->lifepoints)
+                    || (1 == i && 0 < o->lifepoints)))
+            {
+                d = get_map_object_def(o->type);
+                c = d->char_on_map;
+                visible_map[yx_to_map_pos(&o->pos)] = c;
+            }
+        }
+    }
+    free(fov_map);
+    return visible_map;
+}
+
+
+
+static void write_map(struct MapObj * player, FILE * file)
 {
     char * f_name = "write_map()";
-    char * visible_map = build_visible_map();
+    char * visible_map = build_visible_map(player);
     uint16_t x, y;
     for (y = 0; y < world.map.size.y; y++)
     {
index 36c446580205e67041237c3e950c8441d62b6ac4..52a9b0b7d11bdefafc9d4d7b3580101d69073ced 100644 (file)
@@ -156,3 +156,11 @@ extern uint8_t is_passable(struct yx_uint8 pos)
     }
     return passable;
 }
+
+
+
+extern uint16_t yx_to_map_pos(struct yx_uint8 * yx)
+{
+    return (yx->y * world.map.size.x) + yx->x;
+}
+
index 45ddeaf3da448fb9ddbbd934c6d3b9474e8454d3..9e3c54858033011cc193c4a5b81007d5f5e39a5c 100644 (file)
@@ -1,12 +1,12 @@
 /* src/server/map.h
  *
- * Struct for the game map and routines to create and scroll on it.
+ * Struct for the game map and routines to create and navigate on it.
  */
 
 #ifndef MAP_H
 #define MAP_H
 
-#include <stdint.h> /* uint8_t */
+#include <stdint.h> /* uint8_t, uint16_t */
 #include "../common/yx_uint8.h" /* yx_uint8 struct */
 #include "../common/yx_uint16.h" /* yx_uint16 struct */
 
@@ -34,6 +34,9 @@ extern void init_map();
  */
 extern uint8_t is_passable(struct yx_uint8 pos);
 
+/* Transform "yx" to an index position in the world map. */
+extern uint16_t yx_to_map_pos(struct yx_uint8 * yx);
+
 
 
 #endif
index ed019f2fb25742f9e64b944d9eef71b3ac723119..be772fcd3ed473ebd0bb50e6c00ab9c2d20d9cd2 100644 (file)
@@ -40,6 +40,7 @@ struct World
     uint8_t player_type; /* Map object type that player will start as. */
     uint8_t is_verbose; /* Should server send debugging info to stdout? */
     uint8_t map_obj_count; /* Counts map objects generated so far. */
+    uint8_t enemy_fov; /* != 0 if non-player actors only see field of view. */
 };
 
 extern struct World world;