cc30536
--- server/maphand.c	2010-07-25 21:53:39.000000000 +0200
cc30536
+++ server/maphand.c.old	2010-08-30 21:16:58.000000000 +0200
cc30536
@@ -635,33 +635,57 @@
94d4c26
   } players_iterate_end;
94d4c26
 }
94d4c26
 
94d4c26
-/**************************************************************************
94d4c26
-  There doesn't have to be a city.
94d4c26
-**************************************************************************/
94d4c26
-void map_refog_circle(struct player *pplayer, struct tile *ptile,
94d4c26
-                      int old_radius_sq, int new_radius_sq,
94d4c26
-                      bool can_reveal_tiles,
94d4c26
-                      enum vision_layer vlayer)
94d4c26
+/****************************************************************************
94d4c26
+  Really refog the circle for the vision layer.
94d4c26
+****************************************************************************/
94d4c26
+static void real_map_refog_circle(struct player *pplayer, struct tile *ptile,
94d4c26
+                                  int old_radius_sq, int new_radius_sq,
94d4c26
+                                  bool can_reveal_tiles,
94d4c26
+                                  enum vision_layer vlayer)
94d4c26
 {
94d4c26
   if (old_radius_sq != new_radius_sq) {
94d4c26
     int max_radius = MAX(old_radius_sq, new_radius_sq);
94d4c26
 
94d4c26
     freelog(LOG_DEBUG, "Refogging circle at %d,%d from %d to %d",
94d4c26
-	    TILE_XY(ptile), old_radius_sq, new_radius_sq);
cc30536
+	     TILE_XY(ptile), old_radius_sq, new_radius_sq);
94d4c26
 
94d4c26
     buffer_shared_vision(pplayer);
94d4c26
     circle_dxyr_iterate(ptile, max_radius, tile1, dx, dy, dr) {
94d4c26
       if (dr > old_radius_sq && dr <= new_radius_sq) {
94d4c26
-	map_unfog_tile(pplayer, tile1, can_reveal_tiles, vlayer);
cc30536
+	 map_unfog_tile(pplayer, tile1, can_reveal_tiles, vlayer);
94d4c26
       } else if (dr > new_radius_sq && dr <= old_radius_sq) {
94d4c26
-	map_fog_tile(pplayer, tile1, vlayer);
cc30536
+	 map_fog_tile(pplayer, tile1, vlayer);
94d4c26
       }
94d4c26
     } circle_dxyr_iterate_end;
94d4c26
     unbuffer_shared_vision(pplayer);
cc30536
   }
94d4c26
 }
cc30536
+/****************************************************************************
94d4c26
+  There doesn't have to be a city.
94d4c26
+  FIXME: results would be unexpected if the new_invis_radius_sq is bigger
94d4c26
+  than new_main_radius_sq.
94d4c26
+****************************************************************************/
94d4c26
+void map_refog_circle(struct player *pplayer, struct tile *ptile,
94d4c26
+                      int old_main_radius_sq, int new_main_radius_sq,
94d4c26
+                      int old_invis_radius_sq, int new_invis_radius_sq,
94d4c26
+                      bool can_reveal_tiles)
94d4c26
+{
94d4c26
+  if (new_invis_radius_sq < old_invis_radius_sq) {
94d4c26
+    /* Then remove the invisible units first for the clients. */
94d4c26
+    real_map_refog_circle(pplayer, ptile, old_invis_radius_sq,
94d4c26
+                          new_invis_radius_sq, can_reveal_tiles, V_INVIS);
94d4c26
+    real_map_refog_circle(pplayer, ptile, old_main_radius_sq,
94d4c26
+                          new_main_radius_sq, can_reveal_tiles, V_MAIN);
94d4c26
+  } else {
94d4c26
+    real_map_refog_circle(pplayer, ptile, old_main_radius_sq,
94d4c26
+                          new_main_radius_sq, can_reveal_tiles, V_MAIN);
94d4c26
+    real_map_refog_circle(pplayer, ptile, old_invis_radius_sq,
94d4c26
+                          new_invis_radius_sq, can_reveal_tiles, V_INVIS);
94d4c26
+  }
94d4c26
+}
cc30536
 
cc30536
 /****************************************************************************
94d4c26
+/****************************************************************************
94d4c26
   Shows the area to the player.  Unless the tile is "seen", it will remain
94d4c26
   fogged and units will be hidden.
94d4c26
 
cc30536
@@ -740,14 +764,16 @@
94d4c26
         remove_dumb_city(pplayer, ptile);
94d4c26
 
94d4c26
         if (map_get_seen(ptile, pplayer, V_MAIN) > 0) {
94d4c26
-          /* Remove units. */
94d4c26
-          vision_layer_iterate(v) {
94d4c26
+          /* Remove units. Using unit_list_iterate or
94d4c26
+           * unit_list_reverse_iterate is equivalent here, because the
94d4c26
+           * tile info is sent after all units went out of sight. */
94d4c26
+          vision_layer_reverse_iterate(v) {
94d4c26
             unit_list_iterate(ptile->units, punit) {
94d4c26
               if (unit_is_visible_on_layer(punit, v)) {
94d4c26
                 unit_goes_out_of_sight(pplayer, punit);
94d4c26
               }
94d4c26
             } unit_list_iterate_end;
94d4c26
-          } vision_layer_iterate_end;
94d4c26
+          } vision_layer_reverse_iterate_end;
94d4c26
         }
94d4c26
       }
94d4c26
 
cc30536
@@ -909,11 +935,14 @@
94d4c26
 void map_clear_known(struct tile *ptile, struct player *pplayer)
94d4c26
 {
94d4c26
   BV_CLR(ptile->tile_known, player_index(pplayer));
94d4c26
-  vision_layer_iterate(v) {
94d4c26
+  /* Using vision_layer_iterate or vision_layer_reverse_iterate
94d4c26
+   * is equivalent here, because no units are going out of sight, neither
94d4c26
+   * the tile info is sent to the client. */
94d4c26
+  vision_layer_reverse_iterate(v) {
94d4c26
     if (0 == map_get_player_tile(ptile, pplayer)->seen_count[v]) {
94d4c26
       BV_CLR(ptile->tile_seen[v], player_index(pplayer));
94d4c26
     }
94d4c26
-  } vision_layer_iterate_end;
94d4c26
+  } vision_layer_reverse_iterate_end;
94d4c26
 }
94d4c26
 
94d4c26
 /****************************************************************************
cc30536
@@ -1332,7 +1361,7 @@
94d4c26
 	       player_name(pplayer),
94d4c26
 	       player_name(pplayer2));
94d4c26
 	whole_map_iterate(ptile) {
94d4c26
-	  vision_layer_iterate(v) {
94d4c26
+          vision_layer_reverse_iterate(v) {
94d4c26
 	    int change = map_get_own_seen(ptile, pplayer, v);
94d4c26
 
94d4c26
 	    if (change > 0) {
cc30536
@@ -1340,7 +1369,7 @@
94d4c26
 	      if (map_get_seen(ptile, pplayer2, v) == 0)
94d4c26
 		really_fog_tile(pplayer2, ptile, v);
94d4c26
 	    }
94d4c26
-	  } vision_layer_iterate_end;
cc30536
+	  } vision_layer_reverse_iterate_end;
94d4c26
 	} whole_map_iterate_end;
94d4c26
       }
94d4c26
     } players_iterate_end;
cc30536
@@ -1609,27 +1638,18 @@
94d4c26
   if (ploser != powner) {
94d4c26
     base_type_iterate(pbase) {
94d4c26
       if (tile_has_base(ptile, pbase)) {
94d4c26
-        if (pbase->vision_main_sq >= 0) {
94d4c26
-          /* Transfer base provided vision to new owner */
94d4c26
-          if (powner) {
94d4c26
-            map_refog_circle(powner, ptile, -1, pbase->vision_main_sq,
94d4c26
-                             game.info.vision_reveal_tiles, V_MAIN);
94d4c26
-          }
94d4c26
-          if (ploser && pbase != ignore_loss) {
94d4c26
-            map_refog_circle(ploser, ptile, pbase->vision_main_sq, -1,
94d4c26
-                             game.info.vision_reveal_tiles, V_MAIN);
94d4c26
-          }
94d4c26
+        /* Transfer base provided vision to new owner */
94d4c26
+        if (powner) {
94d4c26
+          map_refog_circle(powner, ptile,
94d4c26
+                           -1, pbase->vision_main_sq,
94d4c26
+                           -1, pbase->vision_invis_sq,
94d4c26
+                           game.info.vision_reveal_tiles);
94d4c26
         }
94d4c26
-        if (pbase->vision_invis_sq >= 0) {
94d4c26
-          /* Transfer base provided vision to new owner */
94d4c26
-          if (powner) {
94d4c26
-            map_refog_circle(powner, ptile, -1, pbase->vision_invis_sq,
94d4c26
-                             game.info.vision_reveal_tiles, V_INVIS);
94d4c26
-          }
94d4c26
-          if (ploser && pbase != ignore_loss) {
94d4c26
-            map_refog_circle(ploser, ptile, pbase->vision_invis_sq, -1,
94d4c26
-                             game.info.vision_reveal_tiles, V_INVIS);
94d4c26
-          }
94d4c26
+        if (ploser && pbase != ignore_loss) {
94d4c26
+          map_refog_circle(ploser, ptile,
94d4c26
+                           pbase->vision_main_sq, -1,
94d4c26
+                           pbase->vision_invis_sq, -1,
94d4c26
+                           game.info.vision_reveal_tiles);
94d4c26
         }
94d4c26
       }
94d4c26
     } base_type_iterate_end;
cc30536
@@ -1764,13 +1784,15 @@
94d4c26
 
94d4c26
   See documentation in vision.h.
94d4c26
 ****************************************************************************/
94d4c26
-void vision_change_sight(struct vision *vision, enum vision_layer vlayer,
94d4c26
-			 int radius_sq)
94d4c26
+void vision_change_sight(struct vision *vision, int radius_main_sq,
94d4c26
+                         int radius_invis_sq)
94d4c26
 {
94d4c26
   map_refog_circle(vision->player, vision->tile,
94d4c26
-		   vision->radius_sq[vlayer], radius_sq,
94d4c26
-		   vision->can_reveal_tiles, vlayer);
94d4c26
-  vision->radius_sq[vlayer] = radius_sq;
94d4c26
+                   vision->radius_sq[V_MAIN], radius_main_sq,
94d4c26
+                   vision->radius_sq[V_INVIS], radius_invis_sq,
94d4c26
+                   vision->can_reveal_tiles);
94d4c26
+  vision->radius_sq[V_MAIN] = radius_main_sq;
94d4c26
+  vision->radius_sq[V_INVIS] = radius_invis_sq;
94d4c26
 }
94d4c26
 
94d4c26
 /****************************************************************************
cc30536
@@ -1780,10 +1802,7 @@
94d4c26
 ****************************************************************************/
94d4c26
 void vision_clear_sight(struct vision *vision)
94d4c26
 {
94d4c26
-  /* We don't use vision_layer_iterate because we have to go in reverse
94d4c26
-   * order. */
94d4c26
-  vision_change_sight(vision, V_INVIS, -1);
94d4c26
-  vision_change_sight(vision, V_MAIN, -1);
94d4c26
+  vision_change_sight(vision, -1, -1);
94d4c26
 }
94d4c26
 
94d4c26
 /****************************************************************************
cc30536
@@ -1801,14 +1820,16 @@
94d4c26
       } else {
94d4c26
         struct player *owner = tile_owner(ptile);
94d4c26
 
94d4c26
-        if (old_base->vision_main_sq >= 0 && owner) {
94d4c26
+        if (NULL != owner
94d4c26
+            && (0 <= old_base->vision_main_sq
94d4c26
+                || 0 <= old_base->vision_invis_sq)) {
94d4c26
           /* Base provides vision, but no borders. */
94d4c26
-          map_refog_circle(owner, ptile, old_base->vision_main_sq, -1,
94d4c26
-                           game.info.vision_reveal_tiles, V_MAIN);
cc30536
-        }
cc30536
-        if (old_base->vision_invis_sq >= 0 && owner) {
cc30536
-          map_refog_circle(owner, ptile, old_base->vision_invis_sq, -1,
cc30536
-                           game.info.vision_reveal_tiles, V_INVIS);
94d4c26
+          map_refog_circle(owner, ptile,
94d4c26
+                           0 <= old_base->vision_main_sq
94d4c26
+                           ? old_base->vision_main_sq : -1, -1,
94d4c26
+                           0 <= old_base->vision_invis_sq
94d4c26
+                           ? old_base->vision_invis_sq : -1, -1,
94d4c26
+                           game.info.vision_reveal_tiles);
94d4c26
         }
94d4c26
       }
94d4c26
       tile_remove_base(ptile, old_base);
cc30536
@@ -1830,13 +1851,15 @@
cc30536
   } else {
94d4c26
     struct player *owner = tile_owner(ptile);
94d4c26
 
94d4c26
-    if (pbase->vision_main_sq > 0 && owner) {
94d4c26
-      map_refog_circle(owner, ptile, -1, pbase->vision_main_sq,
94d4c26
-                       game.info.vision_reveal_tiles, V_MAIN);
cc30536
-    }
cc30536
-    if (pbase->vision_invis_sq > 0 && owner) {
cc30536
-      map_refog_circle(owner, ptile, -1, pbase->vision_invis_sq,
cc30536
-                       game.info.vision_reveal_tiles, V_INVIS);
94d4c26
+    if (NULL != owner
94d4c26
+        && (0 < pbase->vision_main_sq
94d4c26
+            || 0 < pbase->vision_invis_sq)) {
94d4c26
+      map_refog_circle(owner, ptile,
94d4c26
+                       -1, 0 < pbase->vision_main_sq
94d4c26
+                       ? pbase->vision_main_sq : -1,
94d4c26
+                       -1, 0 < pbase->vision_invis_sq
94d4c26
+                       ? pbase->vision_invis_sq : -1,
94d4c26
+                       game.info.vision_reveal_tiles);
94d4c26
     }
94d4c26
   }
94d4c26
 }