Complete.Org: Mailing Lists: Archives: freeciv-dev: December 2004:
[Freeciv-Dev] (PR#11309) track how many cities cover a tile
Home

[Freeciv-Dev] (PR#11309) track how many cities cover a tile

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#11309) track how many cities cover a tile
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 2 Dec 2004 15:30:50 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=11309 >

This is a preliminary patch to track how many cities' citymaps cover a tile.

In a MoM-style system terrain bonuses can be acquired from tiles within 
the citymap even if they are not worked.  For instance each forest may 
give +3% production, each hill +5%, and each mountain +7%.  However this 
bonus cannot be accumulated by more than one city so it is divided 
between all cities that cover the tile.  Hence we need to keep track of 
that number.  In fact this is surely the hardest part of the task since 
it is the most bug-prone.

It's a bit tricky.  This patch keeps a ptile->covered.  It is built on 
the server when a savegame is loaded, incremented when a city is built, 
and removed when a city is removed.

It is sent to the client as part of the *city* packet - this makes the 
client easier since a city packet will generate a city refresh and 
agents update, but I'm not sure about the server bits since when a city 
is built we need to resent city packets for all cities with overlapping 
citymaps.  This is a problem.

Another problem is that it should respect borders.  Cities should not be 
able to "cover" tiles inside other civs' borders.  This is also tricky 
because it means the tile needs to be rebuilt from scratch when borders 
change.

jason

? diff
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.429
diff -u -r1.429 packhand.c
--- client/packhand.c   2 Dec 2004 10:14:53 -0000       1.429
+++ client/packhand.c   2 Dec 2004 23:30:11 -0000
@@ -514,6 +514,9 @@
       set_worker_city(pcity, x, y, packet->city_map[i]);
     }
   }
+  city_map_checked_iterate(pcity->tile, x, y, tile1) {
+    tile1->covered = packet->covered[x + y * CITY_MAP_SIZE];
+  } city_map_checked_iterate_end;
   
   impr_type_iterate(i) {
     if (pcity->improvements[i] == I_NONE && packet->improvements[i] == '1'
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.265
diff -u -r1.265 city.c
--- common/city.c       2 Dec 2004 10:20:30 -0000       1.265
+++ common/city.c       2 Dec 2004 23:30:11 -0000
@@ -104,7 +104,6 @@
 {
   int x, y;
 
-  assert(is_valid_city_coords(city_map_x, city_map_y));
   x = city_tile->x + city_map_x - CITY_MAP_SIZE / 2;
   y = city_tile->y + city_map_y - CITY_MAP_SIZE / 2;
 
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.208
diff -u -r1.208 map.c
--- common/map.c        30 Nov 2004 05:39:12 -0000      1.208
+++ common/map.c        2 Dec 2004 23:30:11 -0000
@@ -358,6 +358,7 @@
   ptile->known    = 0;
   ptile->continent = 0;
   ptile->city     = NULL;
+  ptile->covered = 0;
   unit_list_init(&ptile->units);
   ptile->worked   = NULL; /* pointer to city working tile */
   ptile->assigned = 0; /* bitvector */
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.229
diff -u -r1.229 map.h
--- common/map.h        30 Nov 2004 05:39:12 -0000      1.229
+++ common/map.h        2 Dec 2004 23:30:11 -0000
@@ -49,6 +49,7 @@
                           Player_no is index */
   int assigned; /* these can save a lot of CPU usage -- Syela */
   struct city *worked;      /* city working tile, or NULL if none */
+  int covered; /* Number of cities whose citymaps cover the tile. */
   Continent_id continent;
   signed char move_cost[8]; /* don't know if this helps! */
   struct player *owner;     /* Player owning this tile, or NULL. */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.61
diff -u -r1.61 packets.def
--- common/packets.def  30 Nov 2004 06:54:06 -0000      1.61
+++ common/packets.def  2 Dec 2004 23:30:11 -0000
@@ -423,6 +423,7 @@
 
   BIT_STRING improvements[B_LAST+1];
   CITY_MAP city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
+  UINT8 covered[CITY_MAP_SIZE * CITY_MAP_SIZE];
 
   BOOL did_buy, did_sell, was_happy, airlift, diplomat_investigate;
 
Index: common/packets_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.c,v
retrieving revision 1.64
diff -u -r1.64 packets_gen.c
--- common/packets_gen.c        30 Nov 2004 06:54:06 -0000      1.64
+++ common/packets_gen.c        2 Dec 2004 23:30:13 -0000
@@ -5045,7 +5045,7 @@
   return 0;
 }
 
-BV_DEFINE(packet_city_info_100_fields, 45);
+BV_DEFINE(packet_city_info_100_fields, 46);
 
 static struct packet_city_info *receive_packet_city_info_100(struct connection 
*pc, enum packet_type type)
 {
@@ -5410,23 +5410,38 @@
       }
     }
   }
-  real_packet->did_buy = BV_ISSET(fields, 38);
-  real_packet->did_sell = BV_ISSET(fields, 39);
-  real_packet->was_happy = BV_ISSET(fields, 40);
-  real_packet->airlift = BV_ISSET(fields, 41);
-  real_packet->diplomat_investigate = BV_ISSET(fields, 42);
-  if (BV_ISSET(fields, 43)) {
+  if (BV_ISSET(fields, 38)) {
+    
     {
+      int i;
+    
+      for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+        {
       int readin;
     
       dio_get_uint8(&din, &readin);
-      real_packet->city_options = readin;
+      real_packet->covered[i] = readin;
+    }
+      }
     }
   }
+  real_packet->did_buy = BV_ISSET(fields, 39);
+  real_packet->did_sell = BV_ISSET(fields, 40);
+  real_packet->was_happy = BV_ISSET(fields, 41);
+  real_packet->airlift = BV_ISSET(fields, 42);
+  real_packet->diplomat_investigate = BV_ISSET(fields, 43);
   if (BV_ISSET(fields, 44)) {
     {
       int readin;
     
+      dio_get_uint8(&din, &readin);
+      real_packet->city_options = readin;
+    }
+  }
+  if (BV_ISSET(fields, 45)) {
+    {
+      int readin;
+    
       dio_get_sint16(&din, &readin);
       real_packet->turn_founded = readin;
     }
@@ -5713,33 +5728,49 @@
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 37);}
 
+
+    {
+      differ = (CITY_MAP_SIZE * CITY_MAP_SIZE != CITY_MAP_SIZE * 
CITY_MAP_SIZE);
+      if(!differ) {
+        int i;
+        for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+          if (old->covered[i] != real_packet->covered[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 38);}
+
   differ = (old->did_buy != real_packet->did_buy);
   if(differ) {different++;}
-  if(packet->did_buy) {BV_SET(fields, 38);}
+  if(packet->did_buy) {BV_SET(fields, 39);}
 
   differ = (old->did_sell != real_packet->did_sell);
   if(differ) {different++;}
-  if(packet->did_sell) {BV_SET(fields, 39);}
+  if(packet->did_sell) {BV_SET(fields, 40);}
 
   differ = (old->was_happy != real_packet->was_happy);
   if(differ) {different++;}
-  if(packet->was_happy) {BV_SET(fields, 40);}
+  if(packet->was_happy) {BV_SET(fields, 41);}
 
   differ = (old->airlift != real_packet->airlift);
   if(differ) {different++;}
-  if(packet->airlift) {BV_SET(fields, 41);}
+  if(packet->airlift) {BV_SET(fields, 42);}
 
   differ = (old->diplomat_investigate != real_packet->diplomat_investigate);
   if(differ) {different++;}
-  if(packet->diplomat_investigate) {BV_SET(fields, 42);}
+  if(packet->diplomat_investigate) {BV_SET(fields, 43);}
 
   differ = (old->city_options != real_packet->city_options);
   if(differ) {different++;}
-  if(differ) {BV_SET(fields, 43);}
+  if(differ) {BV_SET(fields, 44);}
 
   differ = (old->turn_founded != real_packet->turn_founded);
   if(differ) {different++;}
-  if(differ) {BV_SET(fields, 44);}
+  if(differ) {BV_SET(fields, 45);}
 
   if (different == 0 && !force_send_of_unchanged) {
     return 0;
@@ -5914,15 +5945,25 @@
       }
     } 
   }
-  /* field 38 is folded into the header */
+  if (BV_ISSET(fields, 38)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+        dio_put_uint8(&dout, real_packet->covered[i]);
+      }
+    } 
+  }
   /* field 39 is folded into the header */
   /* field 40 is folded into the header */
   /* field 41 is folded into the header */
   /* field 42 is folded into the header */
-  if (BV_ISSET(fields, 43)) {
+  /* field 43 is folded into the header */
+  if (BV_ISSET(fields, 44)) {
     dio_put_uint8(&dout, real_packet->city_options);
   }
-  if (BV_ISSET(fields, 44)) {
+  if (BV_ISSET(fields, 45)) {
     dio_put_sint16(&dout, real_packet->turn_founded);
   }
 
Index: common/packets_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.h,v
retrieving revision 1.54
diff -u -r1.54 packets_gen.h
--- common/packets_gen.h        30 Nov 2004 06:54:07 -0000      1.54
+++ common/packets_gen.h        2 Dec 2004 23:30:13 -0000
@@ -204,6 +204,7 @@
   struct worklist worklist;
   char improvements[B_LAST+1];
   enum city_tile_type city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
+  int covered[CITY_MAP_SIZE * CITY_MAP_SIZE];
   bool did_buy;
   bool did_sell;
   bool was_happy;
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.283
diff -u -r1.283 citytools.c
--- server/citytools.c  2 Dec 2004 10:20:30 -0000       1.283
+++ server/citytools.c  2 Dec 2004 23:30:14 -0000
@@ -991,6 +991,12 @@
 
   city_list_insert(&pplayer->cities, pcity);
 
+  /* Increment all tiles that the citymap covers.  Note that this ignores
+   * borders. */
+  map_city_radius_iterate(pcity->tile, ptile) {
+    ptile->covered++;
+  } map_city_radius_iterate_end;
+
   /* 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++) {
@@ -1171,6 +1177,8 @@
 
   /* Update available tiles in adjacent cities. */
   map_city_radius_iterate(ptile, tile1) {
+    assert(tile1->covered > 0);
+    tile1->covered--;
     /* For every tile the city could have used. */
     map_city_radius_iterate(tile1, tile2) {
       /* We see what cities are inside reach of the tile. */
@@ -1624,7 +1632,15 @@
   packet->was_happy = pcity->was_happy;
   for (y = 0; y < CITY_MAP_SIZE; y++) {
     for (x = 0; x < CITY_MAP_SIZE; x++) {
-      packet->city_map[x + y * CITY_MAP_SIZE] = get_worker_city(pcity, x, y);
+      int index = x + y * CITY_MAP_SIZE;
+      struct tile *ptile = city_map_to_map(pcity, x, y);
+
+      packet->city_map[index] = get_worker_city(pcity, x, y);
+      if (ptile) {
+       packet->covered[index] = ptile->covered;
+      } else {
+       packet->covered[index] = 0;
+      }
     }
   }
 
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.210
diff -u -r1.210 savegame.c
--- server/savegame.c   30 Nov 2004 08:37:03 -0000      1.210
+++ server/savegame.c   2 Dec 2004 23:30:14 -0000
@@ -1946,6 +1946,9 @@
     pcity->id=secfile_lookup_int(file, "player%d.c%d.id", plrno, i);
     alloc_id(pcity->id);
     idex_register_city(pcity);
+    map_city_radius_iterate(ptile, tile1) {
+      tile1->covered++;
+    } map_city_radius_iterate_end;
     
     if (section_file_lookup(file, "player%d.c%d.original", plrno, i))
       pcity->original = secfile_lookup_int(file, "player%d.c%d.original", 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#11309) track how many cities cover a tile, Jason Short <=