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

> I think you attached the wrong patch.
> 
Sigh, that's what happens with too many branch windows open at the same
time....  (Sorry, that was the patch I was committing in S2_1.)


Index: server/citytools.c
===================================================================
--- server/citytools.c  (revision 14015)
+++ server/citytools.c  (working copy)
@@ -838,6 +838,7 @@
   city_list_unlink(pgiver->cities, pcity);
   pcity->owner = ptaker;
   map_claim_ownership(pcity->tile, ptaker, pcity->tile);
+  map_claim_border(pcity->tile, ptaker);
   city_list_prepend(ptaker->cities, pcity);
 
   transfer_city_units(ptaker, pgiver, old_city_units,
@@ -946,31 +947,13 @@
 void create_city(struct player *pplayer, struct tile *ptile,
                 const char *name)
 {
-  struct city *pcity;
   int x_itr, y_itr;
   struct nation_type *nation = nation_of_player(pplayer);
-  struct base_type *pbase;
+  struct base_type *pbase = tile_get_base(ptile);
+  struct city *pcity = create_city_virtual(pplayer, ptile, name);
 
   freelog(LOG_DEBUG, "Creating city %s", name);
 
-  /* Ensure that we claim the ground we stand on */
-  map_claim_ownership(ptile, pplayer, ptile);
-
-  if (terrain_control.may_road) {
-    tile_set_special(ptile, S_ROAD);
-    if (player_knows_techs_with_flag(pplayer, TF_RAILROAD)) {
-      tile_set_special(ptile, S_RAILROAD);
-      update_tile_knowledge(ptile);
-    }
-  }
-
-  /* It is possible that update_tile_knowledge() already sent tile information
-   * to some players, but we don't want to make any special handling for
-   * those cases.  The network code may prevent asecond packet from being
-   * sent anyway. */
-  send_tile_info(NULL, ptile, FALSE);
-
-  pcity = create_city_virtual(pplayer, ptile, name);
   pcity->ai.trade_want = TRADE_WEIGHTING;
   pcity->id = get_next_id_number();
   idex_register_city(pcity);
@@ -1007,9 +990,26 @@
   city_refresh_vision(pcity);
 
   tile_set_city(ptile, pcity);
-
   city_list_prepend(pplayer->cities, pcity);
 
+  /* Claim the ground we stand on */
+  map_claim_ownership(ptile, pplayer, ptile);
+  map_claim_border(ptile, pplayer);
+
+  if (terrain_control.may_road) {
+    tile_set_special(ptile, S_ROAD);
+    if (player_knows_techs_with_flag(pplayer, TF_RAILROAD)) {
+      tile_set_special(ptile, S_RAILROAD);
+      update_tile_knowledge(ptile);
+    }
+  }
+
+  /* It is possible that update_tile_knowledge() already sent tile information
+   * to some players, but we don't want to make any special handling for
+   * those cases.  The network code may prevent a second packet from being
+   * sent anyway. */
+  send_tile_info(NULL, ptile, FALSE);
+
   /* it is possible to build a city on a tile that is already worked
    * this will displace the worker on the newly-built city's tile -- Syela */
   for (y_itr = 0; y_itr < CITY_MAP_SIZE; y_itr++) {
@@ -1041,8 +1041,7 @@
   city_refresh(pcity);
   auto_arrange_workers(pcity);
 
-  /* Put vision back to normal, if base acted as a watchtower */
-  pbase = tile_get_base(ptile);
+  /* If base acted as a watchtower, put vision back to normal */
   if (pbase) {
     tile_remove_base(ptile);
     unit_list_refresh_vision(ptile->units);
@@ -1709,7 +1708,6 @@
 bool update_dumb_city(struct player *pplayer, struct city *pcity)
 {
   bv_imprs improvements;
-  struct player_tile *plrtile = map_get_player_tile(pcity->tile, pplayer);
   struct vision_site *pdcity = map_get_player_city(pcity->tile, pplayer);
   /* pcity->occupied isn't used at the server, so we go straight to the
    * unit list to check the occupied status. */
@@ -1726,37 +1724,31 @@
     }
   } improvement_iterate_end;
 
-  if (pdcity
-      && pdcity->identity == pcity->id
-      && strcmp(pdcity->name, pcity->name) == 0
-      && pdcity->size == pcity->size
-      && pdcity->occupied == occupied
-      && pdcity->walls == walls
-      && pdcity->happy == happy
-      && pdcity->unhappy == unhappy
-      && vision_owner(pdcity) == city_owner(pcity)
-      && BV_ARE_EQUAL(pdcity->improvements, improvements)) {
+  if (NULL == pdcity) {
+    pdcity = create_vision_site_from_city(pcity);
+    map_get_player_tile(pcity->tile, pplayer)->site = pdcity;
+  } else if (pdcity->identity == pcity->id
+         && vision_owner(pdcity) == city_owner(pcity)
+         && pdcity->size == pcity->size
+         && 0 == strcmp(pdcity->name, pcity->name)
+         && pdcity->occupied == occupied
+         && pdcity->walls == walls
+         && pdcity->happy == happy
+         && pdcity->unhappy == unhappy
+         && BV_ARE_EQUAL(pdcity->improvements, improvements)) {
     return FALSE;
   }
 
-  if (NULL == pdcity) {
-    pdcity = plrtile->site = fc_calloc(1, sizeof(*pdcity));
-    pdcity->identity = pcity->id;
-  }
   if (pdcity->identity != pcity->id) {
     freelog(LOG_ERROR, "Trying to update old city (wrong ID)"
            " at %i,%i for player %s",
-           pcity->tile->x, pcity->tile->y, pplayer->name);
+           TILE_XY(pcity->tile), pplayer->name);
     pdcity->identity = pcity->id;   /* ?? */
   }
-  sz_strlcpy(pdcity->name, pcity->name);
-  pdcity->size = pcity->size;
   pdcity->occupied = occupied;
   pdcity->walls = walls;
   pdcity->happy = happy;
   pdcity->unhappy = unhappy;
-  pdcity->owner = city_owner(pcity);
-  pdcity->location = pcity->tile;
   pdcity->improvements = improvements;
 
   return TRUE;
Index: server/maphand.c
===================================================================
--- server/maphand.c    (revision 14015)
+++ server/maphand.c    (working copy)
@@ -58,6 +58,10 @@
 static Continent_id *lake_surrounders;
 static int *continent_sizes, *ocean_sizes;
 
+/* Suppress send_tile_info() during game_load() */
+static bool send_tile_suppressed = FALSE;
+
+
 /**************************************************************************
   Number this tile and nearby tiles (recursively) with the specified
   continent number nr, using a flood-fill algorithm.
@@ -598,6 +602,17 @@
 }
 
 /**************************************************************************
+  Suppress send_tile_info() during game_load()
+**************************************************************************/
+bool send_tile_suppression(bool now)
+{
+  bool formerly = send_tile_suppressed;
+
+  send_tile_suppressed = now;
+  return formerly;
+}
+
+/**************************************************************************
   Send tile information to all the clients in dest which know and see
   the tile. If dest is NULL, sends to all clients (game.est_connections)
   which know and see tile.
@@ -610,6 +625,10 @@
 {
   struct packet_tile_info info;
 
+  if (send_tile_suppressed) {
+    return;
+  }
+
   if (!dest) {
     dest = game.est_connections;
   }
@@ -1095,6 +1114,7 @@
 {
   pplayer->private_map
     = fc_malloc(MAP_INDEX_SIZE * sizeof(*pplayer->private_map));
+
   whole_map_iterate(ptile) {
     player_tile_init(ptile, pplayer);
   } whole_map_iterate_end;
@@ -1109,11 +1129,20 @@
     return;
   }
 
+  /* removing borders */
   whole_map_iterate(ptile) {
-    struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
+    struct player_tile *playtile = map_get_player_tile(ptile, pplayer);
 
-    if (plrtile->site) {
-      free(plrtile->site);
+    /* cleverly uses return that is NULL for non-site tile */
+    playtile->site = map_get_player_base(ptile, pplayer);
+  } whole_map_iterate_end;
+
+  /* only after removing borders! */
+  whole_map_iterate(ptile) {
+    struct vision_site *psite = map_get_player_base(ptile, pplayer);
+
+    if (NULL != psite) {
+      free_vision_site(psite);
     }
   } whole_map_iterate_end;
 
@@ -1137,7 +1166,8 @@
   vision_layer_iterate(v) {
     plrtile->seen_count[v] = 0;
     BV_CLR(ptile->tile_seen[v], player_index(pplayer));
-  } vision_layer_iterate_end
+  } vision_layer_iterate_end;
+
   if (!game.fogofwar_old) {
     plrtile->seen_count[V_MAIN] = 1;
     if (map_is_known(ptile, pplayer)) {
@@ -1293,8 +1323,8 @@
        
       /* update and send city knowledge */
       /* remove outdated cities */
-      if (dest_tile->site) {
-       if (!from_tile->site) {
+      if (dest_tile->site && dest_tile->site->location == ptile) {
+       if (!from_tile->site || from_tile->site->location != ptile) {
          /* As the city was gone on the newer from_tile
             it will be removed by this function */
          reality_check_city(pdest, ptile);
@@ -1306,8 +1336,8 @@
            reality_check_city(pdest, ptile);
       }
       /* Set and send new city info */
-      if (from_tile->site) {
-       if (!dest_tile->site) {
+      if (from_tile->site && from_tile->site->location == ptile) {
+       if (!dest_tile->site || dest_tile->site->location != ptile) {
          dest_tile->site = fc_calloc(1, sizeof(*dest_tile->site));
        }
        /* struct assignment copy */
@@ -1675,23 +1705,8 @@
   }
 }
 
+#ifdef OWNER_SOURCE
 /*************************************************************************
-  Update tile worker states for all cities that have the given map tile
-  within their radius. Does not sync with client.
-
-  This function is inefficient and so should only be called when the
-  owner actually changes.
-*************************************************************************/
-static void tile_update_owner(struct tile *ptile)
-{
-  /* This implementation is horribly inefficient, but this doesn't cause
-   * problems since it's not called often. */
-  cities_iterate(pcity) {
-    update_city_tile_status_map(pcity, ptile);
-  } cities_iterate_end;
-}
-
-/*************************************************************************
   Add any unique home city not found in list but found on tile to the 
   list.
 *************************************************************************/
@@ -1717,36 +1732,141 @@
     } city_list_iterate_end;
   } unit_list_iterate_end;
 }
+#endif
 
 /*************************************************************************
-  Claim ownership of a single tile.  This does no checks.
+  Claim ownership of a single tile.
 *************************************************************************/
-void map_claim_ownership(struct tile *ptile, struct player *owner,
-                         struct tile *source)
+void map_claim_ownership(struct tile *ptile, struct player *powner,
+                         struct tile *psource)
 {
-  ptile->owner_source = source;
-  tile_set_owner(ptile, owner);
+  struct player *ploser = tile_owner(ptile);
+
+  if (NULL != ploser) {
+    struct player_tile *playtile = map_get_player_tile(ptile, ploser);
+
+    /* cleverly uses return that is NULL for non-site tile */
+    playtile->site = map_get_player_base(ptile, ploser);
+
+    if (NULL != playtile->site && ptile == psource) {
+      /* has new owner */
+      playtile->site->owner = powner;
+    }
+  }
+
+  if (NULL != powner /* assume && NULL != psource */) {
+    struct city *pcity = tile_city(ptile);
+    struct player_tile *playtile = map_get_player_tile(psource, powner);
+
+    if (NULL != playtile->site) {
+      if (ptile != psource) {
+        map_get_player_tile(ptile, powner)->site = playtile->site;
+      } else if (NULL != pcity) {
+        playtile->site = update_vision_site_from_city(playtile->site, pcity);
+      } else {
+        /* has new owner */
+        playtile->site->owner = powner;
+      }
+    } else {
+      assert(ptile == psource);
+      if (NULL != pcity) {
+        playtile->site = create_vision_site_from_city(pcity);
+      } else {
+        playtile->site = create_vision_site(-1/*FIXME*/, psource, powner);
+      }
+    }
+  }
+
+  tile_set_owner(ptile, powner);
   send_tile_info(NULL, ptile, FALSE);
-  tile_update_owner(ptile);
+
+  /* This implementation is somewhat inefficient.  By design, it's not
+   * called often.  Does not send updates to client.
+   */
+  if (NULL != ploser && ploser != powner) {
+    city_list_iterate(ploser->cities, pcity) {
+      update_city_tile_status_map(pcity, ptile);
+    } city_list_iterate_end;
+  }
+  if (NULL != powner && ploser != powner) {
+    city_list_iterate(powner->cities, pcity) {
+      update_city_tile_status_map(pcity, ptile);
+    } city_list_iterate_end;
+  }
 }
 
 /*************************************************************************
-  Establish range of a border source.
+  Update borders for this source.  Call this for each new source.
 *************************************************************************/
-static int map_border_range(struct tile *ptile)
+void map_claim_border(struct tile *ptile, struct player *powner)
 {
-  int range;
-  struct city *pcity = tile_city(ptile);
+  struct vision_site *psite = map_get_player_site(ptile, powner);
+  int range = game.info.borders;
 
-  if (NULL != pcity) {
-    range = MIN(pcity->size + 1, game.info.borders);
-    if (pcity->size > game.info.borders) {
-      range += (pcity->size - game.info.borders) / 2;
+  if (0 == range) {
+    /* no borders */
+    return;
+  }
+  if (VISION_SITE_RUIN == psite->identity) {
+    /* should never be called! */
+    freelog(LOG_VERBOSE, "Warning: border source (%d,%d) is ruin!",
+            TILE_XY(ptile));
+    return;
+  }
+  if (VISION_SITE_RUIN < psite->identity) {
+    /* city expansion */
+    range = MIN(psite->size + 1, game.info.borders);
+    if (psite->size > game.info.borders) {
+      range += (psite->size - game.info.borders) / 2;
     }
-  } else {
-    range = game.info.borders;
   }
-  return range;
+  range *= range; /* due to sq dist */
+
+  freelog(LOG_VERBOSE, "border source (%d,%d) range %d",
+          TILE_XY(ptile), range);
+
+  circle_dxyr_iterate(ptile, range, dtile, dx, dy, dr) {
+    struct player *downer = tile_owner(dtile);
+
+    if (!map_is_known(dtile, powner)) {
+      /* border tile never seen */
+      continue;
+    }
+    if (NULL != downer && downer != powner) {
+      struct vision_site *dsite = map_get_player_site(dtile, downer);
+      int r = sq_map_distance(dsite->location, dtile);
+
+      /* border tile claimed by another */
+      if (VISION_SITE_RUIN == dsite->identity) {
+        /* ruins don't keep their borders */
+        dsite->owner = powner;
+        tile_set_owner(dtile, powner);
+        continue;
+      } else if (r < dr) {
+        /* nearest shall prevail */
+        continue;
+      } else if (r == dr) {
+        if (dsite->identity < psite->identity) {
+          /* lower shall prevail: airport/fortress/city */
+          continue;
+        } else if (dsite->identity == psite->identity) {
+          /* neither shall prevail */
+          map_claim_ownership(dtile, NULL, NULL);
+          continue;
+        }
+      }
+    }
+
+    if (is_ocean_tile(dtile)) {
+      if (is_claimable_ocean(dtile, ptile)) {
+        map_claim_ownership(dtile, powner, ptile);
+      }
+    } else {
+      if (tile_continent(dtile) == tile_continent(ptile)) {
+        map_claim_ownership(dtile, powner, ptile);
+      }
+    }
+  } circle_dxyr_iterate_end;
 }
 
 /*************************************************************************
@@ -1768,6 +1888,16 @@
     cities_to_refresh = city_list_new();
   }
 
+  /* base sites are done first, as they may be thorn in city side. */
+  sites_iterate(psite) {
+    map_claim_border(psite->location, vision_owner(psite));
+  } sites_iterate_end;
+
+  cities_iterate(pcity) {
+    map_claim_border(pcity->tile, city_owner(pcity));
+  } cities_iterate_end;
+
+#ifdef OWNER_SOURCE
   /* First transfer ownership for sources that have changed hands. */
   whole_map_iterate(ptile) {
     if (tile_owner(ptile) 
@@ -1880,6 +2010,7 @@
       } circle_dxyr_iterate_end;
     }
   } whole_map_iterate_end;
+#endif
 
   /* Update happiness in all homecities we have collected */ 
   if (game.info.happyborders > 0) {
Index: server/maphand.h
===================================================================
--- server/maphand.h    (revision 14015)
+++ server/maphand.h    (working copy)
@@ -46,14 +46,18 @@
 
 void global_warming(int effect);
 void nuclear_winter(int effect);
+void upgrade_city_rails(struct player *pplayer, bool discovery);
+
 void give_map_from_player_to_player(struct player *pfrom, struct player 
*pdest);
 void give_seamap_from_player_to_player(struct player *pfrom, struct player 
*pdest);
 void give_citymap_from_player_to_player(struct city *pcity,
                                        struct player *pfrom, struct player 
*pdest);
 void send_all_known_tiles(struct conn_list *dest);
+
+bool send_tile_suppression(bool now);
 void send_tile_info(struct conn_list *dest, struct tile *ptile,
                     bool send_unknown);
-void upgrade_city_rails(struct player *pplayer, bool discovery);
+
 void send_map_info(struct conn_list *dest);
 
 void map_show_tile(struct player *pplayer, struct tile *ptile);
@@ -93,8 +97,9 @@
 void disable_fog_of_war(void);
 
 void map_calculate_borders(void);
-void map_claim_ownership(struct tile *ptile, struct player *owner,
-                         struct tile *place);
+void map_claim_border(struct tile *ptile, struct player *powner);
+void map_claim_ownership(struct tile *ptile, struct player *powner,
+                         struct tile *psource);
 
 void check_terrain_change(struct tile *ptile, struct terrain *oldter);
 int get_continent_size(Continent_id id);
Index: server/unittools.c
===================================================================
--- server/unittools.c  (revision 14015)
+++ server/unittools.c  (working copy)
@@ -744,6 +744,7 @@
       /* Claim base if it has "ClaimTerritory" flag */
       if (tile_has_base_flag(ptile, BF_CLAIM_TERRITORY)) {
         map_claim_ownership(ptile, unit_owner(punit), ptile);
+        map_claim_border(ptile, unit_owner(punit));
       }
 
       unit_activity_done = TRUE;
@@ -2727,6 +2728,7 @@
                                   BF_CLAIM_TERRITORY)
       && (!tile_owner(pdesttile) || pplayers_at_war(tile_owner(pdesttile), 
pplayer))) {
     map_claim_ownership(pdesttile, pplayer, pdesttile);
+    map_claim_border(pdesttile, pplayer);
   }
 
   unit_list_unlink(psrctile->units, punit);
Index: server/sanitycheck.c
===================================================================
--- server/sanitycheck.c        (revision 14015)
+++ server/sanitycheck.c        (working copy)
@@ -167,7 +167,7 @@
       SANITY_TILE(ptile, tile_owner(ptile) != NULL);
     }
     if (tile_owner(ptile) != NULL) {
-      SANITY_TILE(ptile, ptile->owner_source != NULL);
+      SANITY_TILE(ptile, map_get_player_site(ptile, tile_owner(ptile)) != 
NULL);
     }
 
     index_to_map_pos(&x, &y, tile_index(ptile));
Index: server/savegame.c
===================================================================
--- server/savegame.c   (revision 14015)
+++ server/savegame.c   (working copy)
@@ -883,6 +883,7 @@
     }
   } whole_map_iterate_end;
 
+#ifdef OWNER_SOURCE
   /* Owner and ownership source are stored as plain numbers */
   if (has_capability("new_owner_map", savefile_options)) {
     int x, y;
@@ -946,6 +947,7 @@
       }
     }
   }
+#endif
 
   if (secfile_lookup_bool_default(file, TRUE, "game.save_known")) {
     int known[MAP_INDEX_SIZE];
@@ -1075,6 +1077,7 @@
                         get_savegame_special(ptile->special, mod));
   } special_halfbyte_iterate_end;
 
+#ifdef OWNER_SOURCE
   /* Store owner and ownership source as plain numbers */
   {
     int x, y;
@@ -1120,6 +1123,7 @@
       secfile_insert_str(file, line, "map.source%03d", y);
     }
   }
+#endif
 
   secfile_insert_bool(file, game.save_options.save_known, "game.save_known");
   if (game.save_options.save_known) {
@@ -1745,6 +1749,15 @@
     unit_list_append(plr->units, punit);
 
     unit_list_prepend(punit->tile->units, punit);
+
+    /* Claim ownership of fortress? */
+    if (tile_has_base_flag_for_unit(punit->tile, unit_type(punit),
+                                    BF_CLAIM_TERRITORY)
+     && (!tile_owner(punit->tile)
+      || pplayers_at_war(tile_owner(punit->tile), plr))) {
+      map_claim_ownership(punit->tile, plr, punit->tile);
+      map_claim_border(punit->tile, plr);
+    }
   }
 }
 
@@ -1835,7 +1848,7 @@
 
     if ((is_sea_barbarian(plr) && nat_barb_type != SEA_BARBARIAN)
         || (is_land_barbarian(plr) && nat_barb_type != LAND_BARBARIAN)) {
-      freelog(LOG_ERROR, "Reassigning barbarian nation for %s", plr->name);
+      freelog(LOG_VERBOSE, "Reassigning barbarian nation for %s", plr->name);
       plr->nation = NO_NATION_SELECTED;
     } else {
       player_set_nation(plr, pnation);
@@ -2532,9 +2545,13 @@
                                (pcity->ai.founder_want < 0), 
                                "player%d.c%d.ai.founder_boat", plrno, i);
 
-    /* do after all the set_worker_city() are done. */
+    /* After all the set_worker_city() are done. */
     tile_set_city(pcity->tile, pcity);
     city_list_append(plr->cities, pcity);
+
+    /* After all the set_worker_city() are done. */
+    map_claim_ownership(ptile, plr, ptile);
+    map_claim_border(ptile, plr);
   }
 
   load_player_units(plr, plrno, file);
@@ -3324,7 +3341,8 @@
       i = 0;
       
       whole_map_iterate(ptile) {
-       if (NULL != (pdcity = map_get_player_city(ptile, plr))) {
+       if (NULL != (pdcity = map_get_player_city(ptile, plr))
+        && plr != vision_owner(pdcity)) {
          secfile_insert_int(file, pdcity->identity, "player%d.dc%d.id",
                             plrno, i);
          secfile_insert_int(file, ptile->nat_x,
@@ -3550,6 +3568,7 @@
   enum tile_special_type *special_order = NULL;
   int technology_order_size = 0;
   int civstyle = 0;
+  bool was_send_tile_suppressed = send_tile_suppression(TRUE);
 
   /* [savefile] */
   savefile_options = secfile_lookup_str(file, "savefile.options");
@@ -4201,6 +4220,8 @@
   if (!game.info.is_new_game) {
     set_myrand_state(rstate);
   }
+
+  send_tile_suppression(was_send_tile_suppressed);
 }
 
 /***************************************************************
Index: common/city.c
===================================================================
--- common/city.c       (revision 14015)
+++ common/city.c       (working copy)
@@ -446,6 +446,7 @@
 **************************************************************************/
 struct player *city_owner(const struct city *pcity)
 {
+  assert(NULL != pcity->owner);
   return pcity->owner;
 }
 
Index: common/tile.c
===================================================================
--- common/tile.c       (revision 14015)
+++ common/tile.c       (working copy)
@@ -53,7 +53,12 @@
 ****************************************************************************/
 struct city *tile_city(const struct tile *ptile)
 {
-  return ptile->city;
+  struct city *pcity = ptile->worked;
+
+  if (NULL != pcity && ptile == pcity->tile) {
+    return pcity;
+  }
+  return NULL;
 }
 
 /****************************************************************************
@@ -61,7 +66,7 @@
 ****************************************************************************/
 void tile_set_city(struct tile *ptile, struct city *pcity)
 {
-  ptile->city = pcity;
+  ptile->worked = pcity;               /* probably duplicate effort */
 }
 
 #ifndef tile_terrain
Index: common/tile.h
===================================================================
--- common/tile.h       (revision 14015)
+++ common/tile.h       (working copy)
@@ -41,11 +41,9 @@
   bv_special special;
   struct resource *resource;           /* NULL for no resource */
   struct terrain *terrain;             /* NULL for unknown tiles */
-  struct city *city;        /* city standing on the tile, NULL if none */
   struct unit_list *units;
-  struct city *worked;      /* city working tile, or NULL if none */
-  struct player *owner;     /* Player owning this tile, or NULL. */
-  struct tile *owner_source; /* what makes it owned by owner */
+  struct player *owner;                        /* NULL for not owned */
+  struct city *worked;                 /* NULL for not worked */
   char *spec_sprite;
 };
 
Index: common/terrain.c
===================================================================
--- common/terrain.c    (revision 14015)
+++ common/terrain.c    (working copy)
@@ -766,11 +766,8 @@
    case TC_LAND:
      adjc_iterate(ptile, adjc_tile) {
        struct terrain* pterrain = tile_terrain(adjc_tile);
-
-       if (T_UNKNOWN == pterrain) {
-         continue;
-       }
-       if (!terrain_has_flag(pterrain, TER_OCEANIC)) {
+       if (T_UNKNOWN != pterrain
+           && !terrain_has_flag(pterrain, TER_OCEANIC)) {
          return TRUE;
        }
      } adjc_iterate_end;
Index: common/player.c
===================================================================
--- common/player.c     (revision 14015)
+++ common/player.c     (working copy)
@@ -188,13 +188,18 @@
   plr->nation = NO_NATION_SELECTED;
   plr->team = NULL;
   plr->is_ready = FALSE;
+
   plr->revolution_finishes = -1;
   plr->capital = FALSE;
+  plr->city_style=0;            /* should be first basic style */
+  plr->cities = city_list_new();
+  plr->sites = site_list_new();
   plr->units = unit_list_new();
-  plr->cities = city_list_new();
+
   plr->connections = conn_list_new();
   plr->current_conn = NULL;
   plr->is_connected = FALSE;
+
   plr->was_created = FALSE;
   plr->is_alive=TRUE;
   plr->is_dying = FALSE;
@@ -205,7 +210,6 @@
     plr->diplstates[i].has_reason_to_cancel = 0;
     plr->diplstates[i].contact_turns_left = 0;
   }
-  plr->city_style=0;            /* should be first basic style */
   plr->ai.control=FALSE;
   plr->ai.handicap = 0;
   plr->ai.skill_level = 0;
Index: common/player.h
===================================================================
--- common/player.h     (revision 14015)
+++ common/player.h     (working copy)
@@ -178,8 +178,9 @@
   bv_player embassy;
   struct player_diplstate diplstates[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
   int city_style;
+  struct city_list *cities;
+  struct site_list *sites;
   struct unit_list *units;
-  struct city_list *cities;
   struct player_score score;
   struct player_economic economic;
 
Index: common/vision.c
===================================================================
--- common/vision.c     (revision 14015)
+++ common/vision.c     (working copy)
@@ -71,3 +71,51 @@
 {
   return vision->radius_sq[vlayer];
 }
+
+/****************************************************************************
+  ...
+****************************************************************************/
+void free_vision_site(struct vision_site *psite)
+{
+  free(psite);
+}
+
+/****************************************************************************
+  Returns the basic structure.
+****************************************************************************/
+struct vision_site *create_vision_site(int identity, struct tile *location,
+                                      struct player *owner)
+{
+  struct vision_site *psite = fc_calloc(1, sizeof(*psite));
+
+  psite->identity = identity;
+  psite->location = location;
+  psite->owner = owner;
+  return psite;
+}
+
+/****************************************************************************
+  Returns the basic structure filled with initial elements.
+****************************************************************************/
+struct vision_site *create_vision_site_from_city(const struct city *pcity)
+{
+  struct vision_site *psite = create_vision_site(pcity->id, pcity->tile,
+                                                city_owner(pcity));
+
+  psite->size = pcity->size;
+  sz_strlcpy(psite->name, pcity->name);
+  return psite;
+}
+
+/****************************************************************************
+  Returns the basic structure filled with current elements.
+****************************************************************************/
+struct vision_site *update_vision_site_from_city(struct vision_site *psite,
+                                                const struct city *pcity)
+{
+  psite->identity = pcity->id;
+  psite->owner = pcity->owner;
+  psite->size = pcity->size;
+  sz_strlcpy(psite->name, pcity->name);
+  return psite;
+}
Index: common/vision.h
===================================================================
--- common/vision.h     (revision 14015)
+++ common/vision.h     (working copy)
@@ -126,6 +126,12 @@
 };
 
 #define vision_owner(v) ((v)->owner)
+void free_vision_site(struct vision_site *psite);
+struct vision_site *create_vision_site(int identity, struct tile *location,
+                                      struct player *owner);
+struct vision_site *create_vision_site_from_city(const struct city *pcity);
+struct vision_site *update_vision_site_from_city(struct vision_site *psite,
+                                                const struct city *pcity);
 
 /* get 'struct site_list' and related functions: */
 #define SPECLIST_TAG site
Index: common/map.c
===================================================================
--- common/map.c        (revision 14015)
+++ common/map.c        (working copy)
@@ -277,11 +277,9 @@
   tile_clear_all_specials (ptile);
   ptile->resource = NULL;
   ptile->terrain  = T_UNKNOWN;
-  ptile->city     = NULL;
   ptile->units    = unit_list_new();
-  ptile->worked   = NULL; /* pointer to city working tile */
-  ptile->owner    = NULL; /* Tile not claimed by any nation. */
-  ptile->owner_source = NULL;
+  ptile->owner    = NULL; /* Not claimed by any player. */
+  ptile->worked   = NULL; /* No city working here. */
   ptile->spec_sprite = NULL;
 }
 
@@ -582,9 +580,15 @@
   }
 
   cardinal_adjc_iterate(ptile, tile1) {
+    struct terrain* pterrain1 = tile_terrain(tile1);
+
+    if (T_UNKNOWN == pterrain1) {
+      continue;
+    }
+
     if (tile_has_special(tile1, S_RIVER)
      || tile_has_special(tile1, S_IRRIGATION)
-     || is_ocean_tile(tile1)) {
+     || terrain_has_flag(pterrain1, TER_OCEANIC)) {
       return TRUE;
     }
   } cardinal_adjc_iterate_end;
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 14015)
+++ client/packhand.c   (working copy)
@@ -655,12 +655,14 @@
 static void handle_city_packet_common(struct city *pcity, bool is_new,
                                       bool popup, bool investigate)
 {
-  if(is_new) {
+  if (is_new) {
     pcity->units_supported = unit_list_new();
     pcity->info_units_supported = unit_list_new();
     pcity->info_units_present = unit_list_new();
+
+    tile_set_city(pcity->tile, pcity);
     city_list_prepend(city_owner(pcity)->cities, pcity);
-    tile_set_city(pcity->tile, pcity);
+
     if (city_owner(pcity) == game.player_ptr) {
       city_report_dialog_update();
     }
@@ -677,7 +679,6 @@
     }
   }
 
-
   if (can_client_change_view()) {
     refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
   }
@@ -2019,14 +2020,21 @@
 **************************************************************************/
 void handle_tile_info(struct packet_tile_info *packet)
 {
+  enum known_type old_known;
+  bool known_changed = FALSE;
   bool tile_changed = FALSE;
-  bool known_changed = FALSE;
   struct terrain *pterrain = terrain_by_number(packet->type);
   struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
-  enum known_type old_known = client_tile_get_known(ptile);
+  
+  if (NULL == ptile) {
+    freelog(LOG_ERROR,
+            "handle_tile_info() invalid tile (%d,%d).",
+            TILE_XY(packet));
+    return;
+  }
+  old_known = client_tile_get_known(ptile);
 
-  if (NULL == tile_terrain(ptile)
-   || terrain_number(tile_terrain(ptile)) != packet->type) {
+  if (NULL == tile_terrain(ptile) || pterrain != tile_terrain(ptile)) {
     tile_changed = TRUE;
     switch (old_known) {
     case TILE_UNKNOWN:
@@ -2034,14 +2042,13 @@
       break;
     case TILE_KNOWN_FOGGED:
     case TILE_KNOWN:
-      if (pterrain || TILE_UNKNOWN == packet->known) {
+      if (NULL != pterrain || TILE_UNKNOWN == packet->known) {
         tile_set_terrain(ptile, pterrain);
       } else {
         tile_changed = FALSE;
         freelog(LOG_ERROR,
                 "handle_tile_info() unknown terrain (%d,%d).",
-                packet->x,
-                packet->y);
+                TILE_XY(packet));
       }
       break;
     };
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to