Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2005:
[Freeciv-Dev] (PR#14334) rewrite fog backend
Home

[Freeciv-Dev] (PR#14334) rewrite fog backend

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#14334) rewrite fog backend
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 14 Oct 2005 18:56:44 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=14334 >

This patch rewrites the maphand.c fog backend.

* pending_seen values are dropped.  They are simply not necessary.

* map_unfog_tile takes a can_reveal_tiles parameter.  If FALSE then the 
old pending-seen behavior is invoked and the tile is not revealed.

* Several other maphand.h functions are renamed for consistency.

-jason

Index: server/srv_main.c
===================================================================
--- server/srv_main.c   (revision 11131)
+++ server/srv_main.c   (working copy)
@@ -334,7 +334,7 @@
     if (get_player_bonus(pplayer, EFT_REVEAL_CITIES) > 0) {
       players_iterate(other_player) {
        city_list_iterate(other_player->cities, pcity) {
-         show_circle(pplayer, pcity->tile, 0);
+         map_show_tile(pplayer, pcity->tile);
        } city_list_iterate_end;
       } players_iterate_end;
     }
@@ -342,7 +342,7 @@
       /* map_know_all will mark all unknown tiles as known and send
        * tile, unit, and city updates as necessary.  No other actions are
        * needed. */
-      map_know_all(pplayer);
+      map_show_all(pplayer);
     }
   } phase_players_iterate_end;
 }
Index: server/citytools.c
===================================================================
--- server/citytools.c  (revision 11131)
+++ server/citytools.c  (working copy)
@@ -1535,7 +1535,8 @@
       }
     } else {
       if (!map_is_known(ptile, pviewer)) {
-       show_circle(pviewer, ptile, 0);
+       /* Without the conditional we'd have an infinite loop here. */
+       map_show_tile(pviewer, ptile);
       }
       if (map_is_known_and_seen(ptile, pviewer)) {
        if (pcity) {            /* it's there and we see it; update and send */
Index: server/barbarian.c
===================================================================
--- server/barbarian.c  (revision 11131)
+++ server/barbarian.c  (working copy)
@@ -314,7 +314,7 @@
 
   /* FIXME: I don't know if this is needed */
   if (utile) {
-    show_circle(barbarians, utile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
+    map_show_circle(barbarians, utile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
   }
 
   return alive;
@@ -467,8 +467,8 @@
   } unit_list_iterate_end;
 
   /* to let them know where to get you */
-  show_circle(barbarians, utile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
-  show_circle(barbarians, pc->tile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
+  map_show_circle(barbarians, utile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
+  map_show_circle(barbarians, pc->tile, BARBARIAN_INITIAL_VISION_RADIUS_SQ);
 
   /* There should probably be a different message about Sea Raiders */
   if (is_land_barbarian(barbarians)) {
Index: server/gamehand.c
===================================================================
--- server/gamehand.c   (revision 11131)
+++ server/gamehand.c   (working copy)
@@ -80,7 +80,7 @@
   }
 
   /* Expose visible area. */
-  show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
+  map_show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
 
   switch(crole) {
   case 'c':
Index: server/maphand.c
===================================================================
--- server/maphand.c    (revision 11131)
+++ server/maphand.c    (working copy)
@@ -56,9 +56,6 @@
 static Continent_id *lake_surrounders;
 static int *continent_sizes, *ocean_sizes;
 
-static void map_unfog_tile(struct player *pplayer, struct tile *ptile);
-static void map_fog_tile(struct player *pplayer, struct tile *ptile);
-
 /**************************************************************************
   Number this tile and nearby tiles (recursively) with the specified
   continent number nr, using a flood-fill algorithm.
@@ -504,72 +501,6 @@
 }
 
 /****************************************************************************
-  Get the "pending" seen value for this tile.
-
-  "pending" seen is a reference count on the number of sources that are
-  in vision range of this tile, but don't have full vision of their own.
-  Cities are the primary example: a city in sight of an unknown tile will
-  not unfog that tile (thus incrementing the "seen" value) but will
-  instead add to the "pending_seen" value.  Once the tile is discovered by
-  another unit, all pending_seen values are turned into regular seen
-  references.
-****************************************************************************/
-static int map_get_pending_seen(struct player *pplayer, struct tile *ptile)
-{
-  return map_get_player_tile(ptile, pplayer)->pending_seen;
-}
-
-/****************************************************************************
-  Set the "pending" seen value for this tile.
-
-  See map_get_pending_seen.
-****************************************************************************/
-static void map_set_pending_seen(struct player *pplayer, struct tile *ptile,
-                                int newv)
-{
-  map_get_player_tile(ptile, pplayer)->pending_seen = newv;
-}
-
-/****************************************************************************
-  Increase the "pending" seen value.
-
-  See map_get_pending_seen.
-****************************************************************************/
-static void increment_pending_seen(struct player *pplayer, struct tile *ptile)
-{
-  map_get_player_tile(ptile, pplayer)->pending_seen += 1;
-}
-
-/****************************************************************************
-  Decrease the "pending" seen value.
-
-  See map_get_pending_seen.
-****************************************************************************/
-static void decrement_pending_seen(struct player *pplayer, struct tile *ptile)
-{
-  struct player_tile *plr_tile = map_get_player_tile(ptile, pplayer);
-
-  assert(plr_tile->pending_seen != 0);
-  plr_tile->pending_seen -= 1;
-}
-
-/****************************************************************************
-  Turn "pending" seen values into seen (unfogged) values.
-
-  See map_get_pending_seen.
-****************************************************************************/
-static void reveal_pending_seen(struct player *pplayer, struct tile *ptile)
-{
-  int pseen = map_get_pending_seen(pplayer, ptile);
-
-  map_set_pending_seen(pplayer, ptile, 0);
-  while (pseen > 0) {
-    map_unfog_tile(pplayer, ptile);
-    pseen--;
-  }
-}
-
-/****************************************************************************
   Checks for hidden units around (x,y).  Such units can be invisible even
   on a KNOWN_AND_SEEN tile, so unfogging might not reveal them.
 ****************************************************************************/
@@ -611,8 +542,9 @@
 }
 
 /****************************************************************************
-  Backend function to do some of the work of unfogging a tile.  It's not
-  entirely clear when this should be called instead of map_unfog_tile.
+  This is a backend function that marks a tile as unfogged.  Call this when
+  map_unfog_tile adds the first point of visibility to the tile, or when
+  shared vision changes cause a tile to become unfogged.
 ****************************************************************************/
 static void really_unfog_tile(struct player *pplayer, struct tile *ptile)
 {
@@ -658,32 +590,30 @@
   NULL.  The caller may wish to buffer_shared_vision if calling this
   function multiple times.
 ****************************************************************************/
-static void map_unfog_tile(struct player *pplayer, struct tile *ptile)
+static void map_unfog_tile(struct player *pplayer, struct tile *ptile,
+                          bool can_reveal_tiles)
 {
-  /* Did the tile just become visible?
-     - send info about units and cities and the tile itself */
-
   /* Increase seen count. */
   shared_vision_change_seen(ptile, pplayer, +1);
 
-  /* And then give the vision. */
+  /* And then give the vision.  Did the tile just become visible?
+   * Then send info about units and cities and the tile itself. */
   players_iterate(pplayer2) {
-    if (pplayer2 != pplayer
-       && !really_gives_vision(pplayer, pplayer2)) {
-      continue;
-    }
+    if (pplayer2 == pplayer || really_gives_vision(pplayer, pplayer2)) {
+      bool known = map_is_known(ptile, pplayer2);
 
-    if (map_get_seen(ptile, pplayer2) == 1
-       || !map_is_known(ptile, pplayer2)) {
-      really_unfog_tile(pplayer2, ptile);
+      if ((!known && can_reveal_tiles)
+         || (known && map_get_seen(ptile, pplayer2) == 1)) {
+       really_unfog_tile(pplayer2, ptile);
+      }
     }
-    reveal_pending_seen(pplayer2, ptile);
   } players_iterate_end;
 }
 
 /****************************************************************************
-  Backend function to do some of the work of unfogging a tile.  It's not
-  entirely clear when this should be called instead of map_unfog_tile.
+  This is a backend function that marks a tile as fogged.  Call this when
+  map_fog_tile removes the last point of visibility from the tile, or when
+  shared vision changes cause a tile to become fogged.
 ****************************************************************************/
 static void really_fog_tile(struct player *pplayer, struct tile *ptile)
 {
@@ -707,24 +637,16 @@
 **************************************************************************/
 static void map_fog_tile(struct player *pplayer, struct tile *ptile)
 {
-  if (map_is_known(ptile, pplayer)) {
-    /* the player himself */
-    shared_vision_change_seen(ptile, pplayer, -1);
-    if (map_get_seen(ptile, pplayer) == 0) {
-      really_fog_tile(pplayer, ptile);
-    }
+  shared_vision_change_seen(ptile, pplayer, -1);
 
-    /* players (s)he gives shared vision */
+  if (map_is_known(ptile, pplayer)) {
     players_iterate(pplayer2) {
-      if (!really_gives_vision(pplayer, pplayer2)) {
-       continue;
+      if (pplayer2 == pplayer || really_gives_vision(pplayer, pplayer2)) {
+       if (map_get_seen(ptile, pplayer2) == 0) {
+         really_fog_tile(pplayer2, ptile);
+       }
       }
-      if (map_get_seen(ptile, pplayer2) == 0) {
-       really_fog_tile(pplayer2, ptile);
-      }
     } players_iterate_end;
-  } else {
-    decrement_pending_seen(pplayer, ptile);
   }
 }
 
@@ -772,92 +694,107 @@
     buffer_shared_vision(pplayer);
     circle_dxyr_iterate(ptile, max_radius, tile1, dx, dy, dr) {
       if (dr > old_radius_sq && dr <= new_radius_sq) {
-       if (can_reveal_tiles || map_is_known(tile1, pplayer)) {
-         map_unfog_tile(pplayer, tile1);
-       } else {
-         increment_pending_seen(pplayer, tile1);
-       }
+       map_unfog_tile(pplayer, tile1, can_reveal_tiles);
       } else if (dr > new_radius_sq && dr <= old_radius_sq) {
-       if (can_reveal_tiles || map_is_known(tile1, pplayer)) {
-         map_fog_tile(pplayer, tile1);
-       } else {
-         decrement_pending_seen(pplayer, tile1);
-       }
+       map_fog_tile(pplayer, tile1);
       }
     } circle_dxyr_iterate_end;
     unbuffer_shared_vision(pplayer);
   }
 }
 
-/**************************************************************************
-Shows area even if still fogged. If the tile is not "seen" units are not
-shown
-**************************************************************************/
-static void really_show_tile(struct player *pplayer, struct tile *ptile)
+/****************************************************************************
+  Shows the area to the player.  Unless the tile is "seen", it will remain
+  fogged and units will be hidden.
+
+  Callers may wish to buffer_shared_vision before calling this function.
+****************************************************************************/
+void map_show_tile(struct player *src_player, struct tile *ptile)
 {
-  struct city *pcity;
-  bool old_known = map_is_known(ptile, pplayer);
+  static int recurse = 0;
+  freelog(LOG_DEBUG, "Showing %i,%i to %s",
+         TILE_XY(ptile), src_player->name);
 
-  freelog(LOG_DEBUG, "Showing %i,%i", TILE_XY(ptile));
+  assert(recurse == 0);
+  recurse++;
 
-  if (!map_is_known_and_seen(ptile, pplayer)) {
-    map_set_known(ptile, pplayer);
+  players_iterate(pplayer) {
+    if (pplayer == src_player || really_gives_vision(pplayer, src_player)) {
+      struct city *pcity;
+      bool old_known = map_is_known(ptile, pplayer);
 
-    /* as the tile may be fogged send_tile_info won't always do this for us */
-    update_player_tile_knowledge(pplayer, ptile);
-    update_player_tile_last_seen(pplayer, ptile);
+      if (!map_is_known_and_seen(ptile, pplayer)) {
+       map_set_known(ptile, pplayer);
 
-    send_tile_info(pplayer->connections, ptile);
+       /* as the tile may be fogged send_tile_info won't always do this for us 
*/
+       update_player_tile_knowledge(pplayer, ptile);
+       update_player_tile_last_seen(pplayer, ptile);
 
-    /* remove old cities that exist no more */
-    reality_check_city(pplayer, ptile);
-    if ((pcity = tile_get_city(ptile))) {
-      /* as the tile may be fogged send_city_info won't do this for us */
-      update_dumb_city(pplayer, pcity);
-      send_city_info(pplayer, pcity);
-    }
+       send_tile_info(pplayer->connections, ptile);
 
-    if (map_get_seen(ptile, pplayer) != 0) {
-      unit_list_iterate(ptile->units, punit)
-       send_unit_info(pplayer, punit);
-      unit_list_iterate_end;
-    }
+       /* remove old cities that exist no more */
+       reality_check_city(pplayer, ptile);
+       if ((pcity = tile_get_city(ptile))) {
+         /* as the tile may be fogged send_city_info won't do this for us */
+         update_dumb_city(pplayer, pcity);
+         send_city_info(pplayer, pcity);
+       }
 
-    /* If the tile was not known before we need to refresh the cities that
-       can use the tile. */
-    if (!old_known) {
-      map_city_radius_iterate(ptile, tile1) {
-       pcity = tile_get_city(tile1);
-       if (pcity && city_owner(pcity) == pplayer) {
-         update_city_tile_status_map(pcity, ptile);
+       if (map_get_seen(ptile, pplayer) != 0) {
+         unit_list_iterate(ptile->units, punit)
+           send_unit_info(pplayer, punit);
+         unit_list_iterate_end;
        }
-      } map_city_radius_iterate_end;
-      sync_cities();
+
+       /* If the tile was not known before we need to refresh the cities that
+          can use the tile. */
+       if (!old_known) {
+         map_city_radius_iterate(ptile, tile1) {
+           pcity = tile_get_city(tile1);
+           if (pcity && city_owner(pcity) == pplayer) {
+             update_city_tile_status_map(pcity, ptile);
+           }
+         } map_city_radius_iterate_end;
+         sync_cities();
+       }
+      }
     }
-  }
+  } players_iterate_end;
+
+  recurse--;
 }
 
-/**************************************************************************
-Shows area, ie send terrain etc., even if still fogged, sans units and cities.
-**************************************************************************/
-void show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
+/****************************************************************************
+  Shows the area to the player.  Unless the tile is "seen", it will remain
+  fogged and units will be hidden.
+****************************************************************************/
+void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
 {
   buffer_shared_vision(pplayer);
 
   circle_iterate(ptile, radius_sq, tile1) {
-    players_iterate(pplayer2) {
-      if (pplayer == pplayer2
-         || really_gives_vision(pplayer, pplayer2)) {
-       really_show_tile(pplayer2, tile1);
-       reveal_pending_seen(pplayer2, tile1);
-      }
-    } players_iterate_end;
+    map_show_tile(pplayer, tile1);
   } circle_iterate_end;
 
   unbuffer_shared_vision(pplayer);
 }
 
 /****************************************************************************
+  Shows the area to the player.  Unless the tile is "seen", it will remain
+  fogged and units will be hidden.
+****************************************************************************/
+void map_show_all(struct player *pplayer)
+{
+  buffer_shared_vision(pplayer);
+
+  whole_map_iterate(ptile) {
+    map_show_tile(pplayer, ptile);
+  } whole_map_iterate_end;
+
+  unbuffer_shared_vision(pplayer);
+}
+
+/****************************************************************************
   Return whether the player knows the tile.  Knowing a tile means you've
   seen it once (as opposed to seeing a tile which means you can see it now).
 ****************************************************************************/
@@ -917,9 +854,7 @@
 static int map_get_own_seen(struct tile *ptile, struct player *pplayer)
 {
   int own_seen = map_get_player_tile(ptile, pplayer)->own_seen;
-  if (own_seen != 0) {
-    assert(map_is_known(ptile, pplayer));
-  }
+
   return own_seen;
 }
 
@@ -948,32 +883,24 @@
   BV_CLR(ptile->tile_known, pplayer->player_no);
 }
 
-/***************************************************************
-...
-***************************************************************/
-void map_know_all(struct player *pplayer)
-{
-  buffer_shared_vision(pplayer);
-  whole_map_iterate(ptile) {
-    show_circle(pplayer, ptile, 0);
-  } whole_map_iterate_end;
-  unbuffer_shared_vision(pplayer);
-}
-
-/***************************************************************
-...
-***************************************************************/
+/****************************************************************************
+  Call this function to unfog all tiles.  This should only be called when
+  a player dies or at the end of the game as it will result in permanent
+  vision of the whole map.
+****************************************************************************/
 void map_know_and_see_all(struct player *pplayer)
 {
   buffer_shared_vision(pplayer);
+
   whole_map_iterate(ptile) {
-    map_unfog_tile(pplayer, ptile);
+    map_unfog_tile(pplayer, ptile, TRUE);
   } whole_map_iterate_end;
+
   unbuffer_shared_vision(pplayer);
 }
 
 /**************************************************************************
-...
+  Unfogs all tiles for all players.  See map_know_and_see_all.
 **************************************************************************/
 void show_map_to_all(void)
 {
@@ -1030,14 +957,11 @@
   plrtile->city = NULL;
 
   plrtile->seen_count = 0;
-  plrtile->pending_seen = 0;
   BV_CLR(ptile->tile_seen, pplayer->player_no);
   if (!game.fogofwar_old) {
+    plrtile->seen_count = 1;
     if (map_is_known(ptile, pplayer)) {
-      plrtile->seen_count = 1;
       BV_SET(ptile->tile_seen, pplayer->player_no);
-    } else {
-      plrtile->pending_seen = 1;
     }
   }
 
@@ -1174,8 +1098,6 @@
        send_city_info_at_tile(pdest, pdest->connections, NULL, ptile);
       }
 
-      reveal_pending_seen(pdest, ptile);
-
       map_city_radius_iterate(ptile, tile1) {
        struct city *pcity = tile_get_city(tile1);
        if (pcity && city_owner(pcity) == pdest) {
@@ -1273,9 +1195,9 @@
          int change = map_get_own_seen(ptile, pplayer);
          if (change != 0) {
            map_change_seen(ptile, pplayer2, change);
-           if (map_get_seen(ptile, pplayer2) == change) {
+           if (map_get_seen(ptile, pplayer2) == change
+               && map_is_known(ptile, pplayer)) {
              really_unfog_tile(pplayer2, ptile);
-             reveal_pending_seen(pplayer2, ptile);
            }
          }
        } whole_map_iterate_end;
@@ -1348,11 +1270,7 @@
 {
   buffer_shared_vision(pplayer);
   whole_map_iterate(ptile) {
-    if (map_is_known(ptile, pplayer)) {
-      map_fog_tile(pplayer, ptile);
-    } else {
-      decrement_pending_seen(pplayer, ptile);
-    }
+    map_fog_tile(pplayer, ptile);
   } whole_map_iterate_end;
   unbuffer_shared_vision(pplayer);
 }
@@ -1374,11 +1292,7 @@
 {
   buffer_shared_vision(pplayer);
   whole_map_iterate(ptile) {
-    if (map_is_known(ptile, pplayer)) {
-      map_unfog_tile(pplayer, ptile);
-    } else {
-      increment_pending_seen(pplayer, ptile);
-    }
+    map_unfog_tile(pplayer, ptile, FALSE);
   } whole_map_iterate_end;
   unbuffer_shared_vision(pplayer);
 }
Index: server/maphand.h
===================================================================
--- server/maphand.h    (revision 11131)
+++ server/maphand.h    (working copy)
@@ -46,7 +46,6 @@
      the square stays unknown. However, we still have to keep count
      of the seen points, so they are kept in here. When the tile
      then becomes known they are moved to seen. */
-  unsigned short pending_seen;
   struct dumb_city* city;
   short last_updated;
 };
@@ -65,14 +64,17 @@
 void conceal_hidden_units(struct player *pplayer, struct tile *ptile);
 void upgrade_city_rails(struct player *pplayer, bool discovery);
 void send_map_info(struct conn_list *dest);
-void show_circle(struct player *pplayer,struct tile *ptile, int radius_sq);
 
+void map_show_tile(struct player *pplayer, struct tile *ptile);
+void map_show_circle(struct player *pplayer,
+                    struct tile *ptile, int radius_sq);
+void map_show_all(struct player *pplayer);
+
 bool map_is_known_and_seen(const struct tile *ptile, struct player *pplayer);
 void map_change_seen(struct tile *ptile, struct player *pplayer, int change);
 bool map_is_known(const struct tile *ptile, const struct player *pplayer);
 void map_set_known(struct tile *ptile, struct player *pplayer);
 void map_clear_known(struct tile *ptile, struct player *pplayer);
-void map_know_all(struct player *pplayer);
 void map_know_and_see_all(struct player *pplayer);
 void show_map_to_all(void);
 
Index: server/unittools.c
===================================================================
--- server/unittools.c  (revision 11132)
+++ server/unittools.c  (working copy)
@@ -2116,7 +2116,7 @@
 
   /* Safe terrain, really? Not transformed since player last saw it. */
   if (!can_unit_exist_at_tile(punit, ptile)) {
-    show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
+    map_show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
     notify_player(pplayer, ptile, E_UNIT_LOST,
                      _("Your %s paradropped into the %s "
                        "and was lost."),
@@ -2127,7 +2127,7 @@
 
   if ((ptile->city && pplayers_non_attack(pplayer, city_owner(ptile->city)))
       || is_non_allied_unit_tile(ptile, pplayer)) {
-    show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
+    map_show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
     maybe_make_contact(ptile, pplayer);
     notify_player(pplayer, ptile, E_UNIT_LOST_ATT,
                      _("Your %s was killed by enemy units at the "
Index: server/sanitycheck.c
===================================================================
--- server/sanitycheck.c        (revision 11131)
+++ server/sanitycheck.c        (working copy)
@@ -89,7 +89,6 @@
       /* underflow of unsigned int */
       SANITY_CHECK(plr_tile->seen_count < 60000);
       SANITY_CHECK(plr_tile->own_seen < 60000);
-      SANITY_CHECK(plr_tile->pending_seen < 60000);
 
       if (plr_tile->seen_count > 0) {
        SANITY_CHECK(BV_ISSET(ptile->tile_seen, pplayer->player_no));
@@ -98,9 +97,6 @@
       }
 
       SANITY_CHECK(plr_tile->own_seen <= plr_tile->seen_count);
-      if (map_is_known(ptile, pplayer)) {
-       SANITY_CHECK(plr_tile->pending_seen == 0);
-      }
     } players_iterate_end;
   } whole_map_iterate_end;
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#14334) rewrite fog backend, Jason Short <=