home · contact · privacy
Server: Internally, rename "map object" stuff to "thing" stuff.
[plomrogue] / src / server / field_of_view.c
index a48582a28220aae8da064330e13ef61fbb298486..95b26d49bcd5ca5555894eabf32c13a489552476 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 "things.h" /* Thing */
 #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
 {
@@ -32,9 +23,6 @@ enum wraps
     WRAP_W = 0x08
 };
 
-/* Transform "yx" to an index position in the world map. */
-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
  * wrapping is returned as a wraps enum value and stored, so that further calls
@@ -148,31 +136,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)
@@ -242,7 +205,7 @@ static uint8_t mv_yx_in_dir_wrap(char d, struct yx_uint8 * yx, uint8_t unwrap)
 extern uint8_t mv_yx_in_dir_legal(char dir, struct yx_uint8 * yx)
 {
     uint8_t wraptest = mv_yx_in_dir_wrap(dir, yx, 0);
-    if (!wraptest && yx->x < world.map.size.x && yx->y < world.map.size.y)
+    if (!wraptest && yx->x < world.map.length && yx->y < world.map.length)
     {
         return 1;
     }
@@ -290,7 +253,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;
         }
     }
@@ -420,7 +383,7 @@ static char * eye_to_cell(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_cell,
     int16_t diff_x = yx_cell->x - yx_eye->x;
     uint8_t indent = yx_eye->y % 2;
     char * dir = dir_from_delta(indent, diff_y, diff_x);
-    char * dirs;
+    char * dirs = NULL;
     if (1 == strlen(dir))
     {
         return strdup(dir);
@@ -457,11 +420,11 @@ static char * eye_to_cell(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_cell,
 static uint8_t is_top_left_shaded(uint16_t pos_a, uint16_t pos_b,
                                   int16_t a_y_on_left)
 {
-    uint16_t start_last_row = world.map.size.x * (world.map.size.y - 1);
+    uint16_t start_last_row = world.map.length * (world.map.length - 1);
     uint8_t a_on_left_or_bottom =    0 <= a_y_on_left
                                   || (pos_a >= start_last_row);
-    uint8_t b_on_top_or_right =    pos_b < world.map.size.x
-                                || pos_b % world.map.size.x==world.map.size.x-1;
+    uint8_t b_on_top_or_right =    pos_b < world.map.length
+                                || pos_b % world.map.length==world.map.length-1;
     return pos_a != pos_b && b_on_top_or_right && a_on_left_or_bottom;
 }
 
@@ -470,18 +433,18 @@ static uint8_t is_top_left_shaded(uint16_t pos_a, uint16_t pos_b,
 static void fill_shadow(struct yx_uint8 * yx_eye, struct yx_uint8 * yx_cell,
                         uint8_t * fov_map, uint16_t pos_a, uint16_t pos_b)
 {
-    int16_t a_y_on_left = !(pos_a%world.map.size.x)? pos_a/world.map.size.x :-1;
-    int16_t b_y_on_left = !(pos_b%world.map.size.x)? pos_b/world.map.size.x :-1;
+    int16_t a_y_on_left = !(pos_a%world.map.length)? pos_a/world.map.length :-1;
+    int16_t b_y_on_left = !(pos_b%world.map.length)? pos_b/world.map.length :-1;
     uint8_t top_left_shaded = is_top_left_shaded(pos_a, pos_b, a_y_on_left);
     uint16_t pos;
     uint8_t y, x, in_shade;
-    for (y = 0; y < world.map.size.y; y++)
+    for (y = 0; y < world.map.length; y++)
     {
         in_shade =    (top_left_shaded || (b_y_on_left >= 0 && y > b_y_on_left))
                    && (a_y_on_left < 0 || y < a_y_on_left);
-        for (x = 0; x < world.map.size.x; x++)
+        for (x = 0; x < world.map.length; x++)
         {
-            pos = (y * world.map.size.x) + x;
+            pos = (y * world.map.length) + x;
             if (yx_eye->y == yx_cell->y && yx_eye->x < yx_cell->x)
             {
                 uint8_t val = fov_map[pos] & (SHADOW_LEFT | SHADOW_RIGHT);
@@ -518,7 +481,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 +490,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,10 +509,10 @@ 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++)
+    for (i = 0; i < world.map.length * world.map.length; i++)
     {
         if (fov_map[i] & (SHADOW_LEFT | SHADOW_RIGHT) && i != pos_start)
         {
@@ -568,7 +531,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 +557,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 Thing * 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;
+    uint8_t radius = 2 * world.map.length;
+    uint32_t map_size = world.map.length * world.map.length;
+    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,12 +579,12 @@ 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);
             }
         }
     }
     uint16_t i;
-    for (i = 0; i < world.map.size.y * world.map.size.x; i++)
+    for (i = 0; i < world.map.length * world.map.length; i++)
     {
         if (fov_map[i] & HIDE_LATER)
         {
@@ -631,42 +593,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;
-}