Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2005:
[Freeciv-Dev] (PR#12954) [PATCH] remove palace and city walls kludge
Home

[Freeciv-Dev] (PR#12954) [PATCH] remove palace and city walls kludge

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12954) [PATCH] remove palace and city walls kludge
From: "Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx>
Date: Wed, 4 May 2005 13:39:13 -0700
Reply-to: bugs@xxxxxxxxxxx

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

This patch fixes forward savedgame compatibility and renames a flag name.
Bug reported by Mike Kaufman, fixes suggested by Jason Dorje.

Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.501
diff -u -u -r1.501 packhand.c
--- client/packhand.c   2 May 2005 15:42:52 -0000       1.501
+++ client/packhand.c   4 May 2005 20:17:19 -0000
@@ -312,24 +312,18 @@
 /**************************************************************************
   Updates a city's list of improvements from packet data. "impr" identifies
   the improvement, and "have_impr" specifies whether the improvement should
-  be added (TRUE) or removed (FALSE). "impr_changed" is set TRUE only if
-  the existing improvement status was changed by this call.
+  be added (TRUE) or removed (FALSE).
 **************************************************************************/
 static void update_improvement_from_packet(struct city *pcity,
-                                          Impr_type_id impr, bool have_impr,
-                                          bool *impr_changed)
+                                          Impr_type_id impr, bool have_impr)
 {
-  if (have_impr && pcity->improvements[impr] == I_NONE) {
-    city_add_improvement(pcity, impr);
-
-    if (impr_changed) {
-      *impr_changed = TRUE;
+  if (have_impr) {
+    if (pcity->improvements[impr] == I_NONE) {
+      city_add_improvement(pcity, impr);
     }
-  } else if (!have_impr && pcity->improvements[impr] != I_NONE) {
-    city_remove_improvement(pcity, impr);
-
-    if (impr_changed) {
-      *impr_changed = TRUE;
+  } else {
+    if (pcity->improvements[impr] != I_NONE) {
+      city_remove_improvement(pcity, impr);
     }
   }
 }
@@ -382,7 +376,7 @@
 void handle_city_info(struct packet_city_info *packet)
 {
   int i;
-  bool city_is_new, city_has_changed_owner = FALSE, need_effect_update = FALSE;
+  bool city_is_new, city_has_changed_owner = FALSE;
   bool need_units_dialog_update = FALSE;
   struct city *pcity;
   bool popup, update_descriptions = FALSE, name_changed = FALSE;
@@ -507,13 +501,14 @@
   }
   
   impr_type_iterate(i) {
-    if (pcity->improvements[i] == I_NONE && packet->improvements[i] == '1'
+    if (pcity->improvements[i] == I_NONE
+       && BV_ISSET(packet->improvements, i)
        && !city_is_new) {
       audio_play_sound(get_improvement_type(i)->soundtag,
                       get_improvement_type(i)->soundtag_alt);
     }
-    update_improvement_from_packet(pcity, i, packet->improvements[i] == '1',
-                                   &need_effect_update);
+    update_improvement_from_packet(pcity, i,
+                                  BV_ISSET(packet->improvements, i));
   } impr_type_iterate_end;
 
   /* We should be able to see units in the city.  But for a diplomat
@@ -632,7 +627,7 @@
 void handle_city_short_info(struct packet_city_short_info *packet)
 {
   struct city *pcity;
-  bool city_is_new, city_has_changed_owner = FALSE, need_effect_update = FALSE;
+  bool city_is_new, city_has_changed_owner = FALSE;
   bool update_descriptions = FALSE;
 
   pcity=find_city_by_id(packet->id);
@@ -696,10 +691,10 @@
     }
   }
 
-  update_improvement_from_packet(pcity, game.palace_building,
-                                packet->capital, &need_effect_update);
-  update_improvement_from_packet(pcity, game.land_defend_building,
-                                packet->walls, &need_effect_update);
+  impr_type_iterate(i) {
+    update_improvement_from_packet(pcity, i,
+                                  BV_ISSET(packet->improvements, i));
+  } impr_type_iterate_end;
 
   /* This sets dumb values for everything else. This is not really required,
      but just want to be at the safe side. */
@@ -1362,20 +1357,6 @@
   game.coolinglevel = pinfo->coolinglevel;
 
   if (!can_client_change_view()) {
-    /*
-     * Hack to allow code that explicitly checks for Palace or City Walls
-     * to work.
-     */
-    game.palace_building = get_building_for_effect(EFT_CAPITAL_CITY);
-    if (game.palace_building == B_LAST) {
-      freelog(LOG_FATAL, "Cannot find any palace building");
-    }
-
-    game.land_defend_building = get_building_for_effect(EFT_LAND_DEFEND);
-    if (game.land_defend_building == B_LAST) {
-      freelog(LOG_FATAL, "Cannot find any land defend building");
-    }
-
     game.player_idx = pinfo->player_idx;
     game.player_ptr = &game.players[game.player_idx];
   }
@@ -2254,6 +2235,7 @@
   b->build_cost = p->build_cost;
   b->upkeep = p->upkeep;
   b->sabotage = p->sabotage;
+  b->flags = p->flags;
   b->helptext = mystrdup(p->helptext);
   sz_strlcpy(b->soundtag, p->soundtag);
   sz_strlcpy(b->soundtag_alt, p->soundtag_alt);
@@ -2646,14 +2628,14 @@
 ...
 **************************************************************************/
 void handle_city_sabotage_list(int diplomat_id, int city_id,
-                              char *improvements)
+                              bv_imprs improvements)
 {
   struct unit *punit = player_find_unit_by_id(game.player_ptr, diplomat_id);
   struct city *pcity = find_city_by_id(city_id);
 
   if (punit && pcity) {
     impr_type_iterate(i) {
-      pcity->improvements[i] = (improvements[i]=='1') ? I_ACTIVE : I_NONE;
+      pcity->improvements[i] = BV_ISSET(improvements, i) ? I_ACTIVE : I_NONE;
     } impr_type_iterate_end;
 
     popup_sabotage_dialog(pcity);
Index: client/packhand_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand_gen.h,v
retrieving revision 1.14
diff -u -u -r1.14 packhand_gen.h
--- client/packhand_gen.h       30 Apr 2005 17:09:25 -0000      1.14
+++ client/packhand_gen.h       4 May 2005 20:17:19 -0000
@@ -42,7 +42,7 @@
 void handle_city_short_info(struct packet_city_short_info *packet);
 void handle_city_incite_info(int city_id, int cost);
 void handle_city_name_suggestion_info(int unit_id, char *name);
-void handle_city_sabotage_list(int diplomat_id, int city_id, char 
*improvements);
+void handle_city_sabotage_list(int diplomat_id, int city_id, bv_imprs 
improvements);
 void handle_player_remove(int player_id);
 struct packet_player_info;
 void handle_player_info(struct packet_player_info *packet);
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.209
diff -u -u -r1.209 game.c
--- common/game.c       2 May 2005 08:56:26 -0000       1.209
+++ common/game.c       4 May 2005 20:17:19 -0000
@@ -266,9 +266,6 @@
   game.default_government = G_MAGIC;        /* flag */
   game.government_when_anarchy = G_MAGIC;   /* flag */
 
-  game.palace_building = B_LAST;
-  game.land_defend_building = B_LAST;
-
   sz_strlcpy(game.demography, GAME_DEFAULT_DEMOGRAPHY);
   sz_strlcpy(game.allow_take, GAME_DEFAULT_ALLOW_TAKE);
 
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.185
diff -u -u -r1.185 game.h
--- common/game.h       4 May 2005 06:18:07 -0000       1.185
+++ common/game.h       4 May 2005 20:17:20 -0000
@@ -175,9 +175,6 @@
   char rulesetdir[MAX_LEN_NAME];
   int firepower_factor;                /* See README.rulesets */
 
-  Impr_type_id palace_building;
-  Impr_type_id land_defend_building;
-
   /* values from game.ruleset */
   struct {
     int num_specialist_types;
Index: common/improvement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v
retrieving revision 1.57
diff -u -u -r1.57 improvement.c
--- common/improvement.c        30 Apr 2005 17:09:27 -0000      1.57
+++ common/improvement.c        4 May 2005 20:17:20 -0000
@@ -27,21 +27,16 @@
 
 #include "improvement.h"
 
-/* Names of impr ranges.
- * (These must correspond to enum impr_range_id in improvement.h.)
- * do not change these unless you know what you're doing! */
-static const char *impr_range_names[] = {
-  "None",
-  "City",
-  "Island",
-  "Player",
-  "World"
-};
-
 static const char *genus_names[IG_LAST] = {
   "GreatWonder", "SmallWonder", "Improvement", "Special"
 };
 
+static const char *flag_names[] = {
+  "VisibleByOthers", "SaveSmallWonder"
+};
+/* Note that these strings must correspond with the enums in impr_flag_id,
+   in common/improvement.h */
+
 /**************************************************************************
 All the city improvements:
 Use get_improvement_type(id) to access the array.
@@ -52,39 +47,6 @@
 struct impr_type improvement_types[B_LAST];
 
 /**************************************************************************
-  Convert impr range names to enum; case insensitive;
-  returns IR_LAST if can't match.
-**************************************************************************/
-enum impr_range impr_range_from_str(const char *str)
-{
-  enum impr_range ret_id;
-
-  assert(ARRAY_SIZE(impr_range_names) == IR_LAST);
-
-  for (ret_id = 0; ret_id < IR_LAST; ret_id++) {
-    if (0 == mystrcasecmp(impr_range_names[ret_id], str)) {
-      return ret_id;
-    }
-  }
-
-  return IR_LAST;
-}
-
-/**************************************************************************
-  Return impr range name; NULL if bad id.
-**************************************************************************/
-const char *impr_range_name(enum impr_range id)
-{
-  assert(ARRAY_SIZE(impr_range_names) == IR_LAST);
-
-  if (id < IR_LAST) {
-    return impr_range_names[id];
-  } else {
-    return NULL;
-  }
-}
-
-/**************************************************************************
   Convert impr genus names to enum; case insensitive;
   returns IG_LAST if can't match.
 **************************************************************************/
@@ -266,6 +228,41 @@
 }
 
 /**************************************************************************
+ Return TRUE if the impr has this flag otherwise FALSE
+**************************************************************************/
+bool impr_flag(Impr_type_id id, enum impr_flag_id flag)
+{
+  assert(flag >= 0 && flag < IF_LAST);
+  return TEST_BIT(improvement_types[id].flags, flag);
+}
+
+/**************************************************************************
+ Convert flag names to enum; case insensitive;
+ returns IF_LAST if can't match.
+**************************************************************************/
+enum impr_flag_id impr_flag_from_str(const char *s)
+{
+  enum impr_flag_id i;
+
+  assert(ARRAY_SIZE(flag_names) == IF_LAST);
+  
+  for(i = 0; i < IF_LAST; i++) {
+    if (mystrcasecmp(flag_names[i], s) == 0) {
+      return i;
+    }
+  }
+  return IF_LAST;
+}
+
+/**************************************************************************
+ Return TRUE if the improvement should be visible to others without spying
+**************************************************************************/
+bool is_improvement_visible(Impr_type_id id)
+{
+  return (is_wonder(id) || impr_flag(id, IF_VISIBLE_BY_OTHERS));
+}
+
+/**************************************************************************
  Returns 1 if the improvement is obsolete, now also works for wonders
 **************************************************************************/
 bool improvement_obsolete(const struct player *pplayer, Impr_type_id id) 
Index: common/improvement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.h,v
retrieving revision 1.45
diff -u -u -r1.45 improvement.h
--- common/improvement.h        30 Apr 2005 17:09:27 -0000      1.45
+++ common/improvement.h        4 May 2005 20:17:21 -0000
@@ -43,15 +43,11 @@
  * to hold full number of improvement types.  */
 #define B_LAST MAX_NUM_ITEMS
 
-/* Range of equivalence (used in equiv_range fields)
- * These must correspond to impr_range_names[] in improvement.c. */
-enum impr_range {
-  IR_NONE,
-  IR_CITY,
-  IR_ISLAND,
-  IR_PLAYER,
-  IR_WORLD,
-  IR_LAST      /* keep this last */
+/* Changing these breaks network compatibility. */
+enum impr_flag_id {
+  IF_VISIBLE_BY_OTHERS, /* improvement should be visible to others without 
spying */
+  IF_SAVE_SMALL_WONDER, /* this small wonder is moved to another city if 
game.savepalace is on. */
+  IF_LAST
 };
 
 enum impr_genus_id {
@@ -62,6 +58,7 @@
   IG_LAST
 };
 
+BV_DEFINE(bv_imprs, B_LAST);
 
 /* Type of improvement. (Read from buildings.ruleset file.) */
 struct impr_type {
@@ -77,6 +74,7 @@
   int build_cost;                      /* Use wrappers to access this. */
   int upkeep;
   int sabotage;                /* Base chance of diplomat sabotage succeeding. 
*/
+  unsigned int flags;
   char *helptext;
   char soundtag[MAX_LEN_NAME];
   char soundtag_alt[MAX_LEN_NAME];
@@ -85,10 +83,6 @@
 
 extern struct impr_type improvement_types[B_LAST];
 
-/* impr range id/string converters */
-enum impr_range impr_range_from_str(const char *str);
-const char *impr_range_name(enum impr_range id);
-
 /* impr genus id/string converters */
 enum impr_genus_id impr_genus_from_str(const char *s);
 
@@ -106,6 +100,11 @@
 const char *get_improvement_name(Impr_type_id id);
 const char *get_improvement_name_orig(Impr_type_id id);
 
+bool impr_flag(Impr_type_id id, enum impr_flag_id flag);
+enum impr_flag_id impr_flag_from_str(const char *s);
+
+bool is_improvement_visible(Impr_type_id id);
+
 bool improvement_obsolete(const struct player *pplayer, Impr_type_id id);
 Impr_type_id find_improvement_by_name(const char *s);
 Impr_type_id find_improvement_by_name_orig(const char *s);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.113
diff -u -u -r1.113 packets.def
--- common/packets.def  2 May 2005 08:45:19 -0000       1.113
+++ common/packets.def  4 May 2005 20:17:21 -0000
@@ -437,7 +437,7 @@
   
   WORKLIST worklist;
 
-  BIT_STRING improvements[B_LAST+1];
+  bitvector(bv_imprs) improvements;
   CITY_MAP city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
 
   BOOL did_buy, did_sell, was_happy, airlift, diplomat_investigate;
@@ -455,8 +455,7 @@
   UINT8 size;
   BOOL happy;
   BOOL unhappy;
-  BOOL capital;
-  BOOL walls;
+  bitvector(bv_imprs) improvements;
   BOOL occupied;
   UINT16 tile_trade;
 end
@@ -537,7 +536,7 @@
 PACKET_CITY_SABOTAGE_LIST=37;sc,lsend
   UNIT diplomat_id;
   CITY city_id;
-  BIT_STRING improvements[B_LAST+1];
+  bitvector(bv_imprs) improvements;
 end
 
 /************** Player packets **********************/
@@ -1148,6 +1147,7 @@
   IMPROVEMENT replaced_by;
   UINT16 build_cost;
   UINT8 upkeep, sabotage;
+  UINT16 flags;
   STRING soundtag[MAX_LEN_NAME];
   STRING soundtag_alt[MAX_LEN_NAME];
   STRING helptext[MAX_LEN_PACKET];
Index: common/packets_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.c,v
retrieving revision 1.114
diff -u -u -r1.114 packets_gen.c
--- common/packets_gen.c        2 May 2005 08:45:19 -0000       1.114
+++ common/packets_gen.c        4 May 2005 20:17:22 -0000
@@ -5464,7 +5464,7 @@
     dio_get_worklist(&din, &real_packet->worklist);
   }
   if (BV_ISSET(fields, 32)) {
-    dio_get_bit_string(&din, real_packet->improvements, 
sizeof(real_packet->improvements));
+    DIO_BV_GET(&din, real_packet->improvements);
   }
   if (BV_ISSET(fields, 33)) {
     
@@ -5820,7 +5820,7 @@
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 31);}
 
-  differ = (strcmp(old->improvements, real_packet->improvements) != 0);
+  differ = !BV_ARE_EQUAL(old->improvements, real_packet->improvements);
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 32);}
 
@@ -6059,7 +6059,7 @@
     dio_put_worklist(&dout, &real_packet->worklist);
   }
   if (BV_ISSET(fields, 32)) {
-    dio_put_bit_string(&dout, real_packet->improvements);
+  DIO_BV_PUT(&dout, packet->improvements);
   }
   if (BV_ISSET(fields, 33)) {
   
@@ -6180,7 +6180,7 @@
   return 0;
 }
 
-BV_DEFINE(packet_city_short_info_100_fields, 11);
+BV_DEFINE(packet_city_short_info_100_fields, 10);
 
 static struct packet_city_short_info 
*receive_packet_city_short_info_100(struct connection *pc, enum packet_type 
type)
 {
@@ -6251,10 +6251,11 @@
   }
   real_packet->happy = BV_ISSET(fields, 5);
   real_packet->unhappy = BV_ISSET(fields, 6);
-  real_packet->capital = BV_ISSET(fields, 7);
-  real_packet->walls = BV_ISSET(fields, 8);
-  real_packet->occupied = BV_ISSET(fields, 9);
-  if (BV_ISSET(fields, 10)) {
+  if (BV_ISSET(fields, 7)) {
+    DIO_BV_GET(&din, real_packet->improvements);
+  }
+  real_packet->occupied = BV_ISSET(fields, 8);
+  if (BV_ISSET(fields, 9)) {
     {
       int readin;
     
@@ -6324,21 +6325,17 @@
   if(differ) {different++;}
   if(packet->unhappy) {BV_SET(fields, 6);}
 
-  differ = (old->capital != real_packet->capital);
-  if(differ) {different++;}
-  if(packet->capital) {BV_SET(fields, 7);}
-
-  differ = (old->walls != real_packet->walls);
+  differ = !BV_ARE_EQUAL(old->improvements, real_packet->improvements);
   if(differ) {different++;}
-  if(packet->walls) {BV_SET(fields, 8);}
+  if(differ) {BV_SET(fields, 7);}
 
   differ = (old->occupied != real_packet->occupied);
   if(differ) {different++;}
-  if(packet->occupied) {BV_SET(fields, 9);}
+  if(packet->occupied) {BV_SET(fields, 8);}
 
   differ = (old->tile_trade != real_packet->tile_trade);
   if(differ) {different++;}
-  if(differ) {BV_SET(fields, 10);}
+  if(differ) {BV_SET(fields, 9);}
 
   if (different == 0 && !force_send_of_unchanged) {
     return 0;
@@ -6364,10 +6361,11 @@
   }
   /* field 5 is folded into the header */
   /* field 6 is folded into the header */
-  /* field 7 is folded into the header */
+  if (BV_ISSET(fields, 7)) {
+  DIO_BV_PUT(&dout, packet->improvements);
+  }
   /* field 8 is folded into the header */
-  /* field 9 is folded into the header */
-  if (BV_ISSET(fields, 10)) {
+  if (BV_ISSET(fields, 9)) {
     dio_put_uint16(&dout, real_packet->tile_trade);
   }
 
@@ -8977,7 +8975,7 @@
     }
   }
   if (BV_ISSET(fields, 2)) {
-    dio_get_bit_string(&din, real_packet->improvements, 
sizeof(real_packet->improvements));
+    DIO_BV_GET(&din, real_packet->improvements);
   }
 
   clone = fc_malloc(sizeof(*clone));
@@ -9021,7 +9019,7 @@
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 1);}
 
-  differ = (strcmp(old->improvements, real_packet->improvements) != 0);
+  differ = !BV_ARE_EQUAL(old->improvements, real_packet->improvements);
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 2);}
 
@@ -9038,7 +9036,7 @@
     dio_put_uint16(&dout, real_packet->city_id);
   }
   if (BV_ISSET(fields, 2)) {
-    dio_put_bit_string(&dout, real_packet->improvements);
+  DIO_BV_PUT(&dout, packet->improvements);
   }
 
 
@@ -24807,7 +24805,7 @@
 
 #define cmp_packet_ruleset_building_100 cmp_const
 
-BV_DEFINE(packet_ruleset_building_100_fields, 17);
+BV_DEFINE(packet_ruleset_building_100_fields, 18);
 
 static struct packet_ruleset_building 
*receive_packet_ruleset_building_100(struct connection *pc, enum packet_type 
type)
 {
@@ -24952,12 +24950,20 @@
     }
   }
   if (BV_ISSET(fields, 14)) {
-    dio_get_string(&din, real_packet->soundtag, sizeof(real_packet->soundtag));
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->flags = readin;
+    }
   }
   if (BV_ISSET(fields, 15)) {
-    dio_get_string(&din, real_packet->soundtag_alt, 
sizeof(real_packet->soundtag_alt));
+    dio_get_string(&din, real_packet->soundtag, sizeof(real_packet->soundtag));
   }
   if (BV_ISSET(fields, 16)) {
+    dio_get_string(&din, real_packet->soundtag_alt, 
sizeof(real_packet->soundtag_alt));
+  }
+  if (BV_ISSET(fields, 17)) {
     dio_get_string(&din, real_packet->helptext, sizeof(real_packet->helptext));
   }
 
@@ -25098,18 +25104,22 @@
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 13);}
 
-  differ = (strcmp(old->soundtag, real_packet->soundtag) != 0);
+  differ = (old->flags != real_packet->flags);
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 14);}
 
-  differ = (strcmp(old->soundtag_alt, real_packet->soundtag_alt) != 0);
+  differ = (strcmp(old->soundtag, real_packet->soundtag) != 0);
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 15);}
 
-  differ = (strcmp(old->helptext, real_packet->helptext) != 0);
+  differ = (strcmp(old->soundtag_alt, real_packet->soundtag_alt) != 0);
   if(differ) {different++;}
   if(differ) {BV_SET(fields, 16);}
 
+  differ = (strcmp(old->helptext, real_packet->helptext) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 17);}
+
   if (different == 0 && !force_send_of_unchanged) {
     return 0;
   }
@@ -25187,12 +25197,15 @@
     dio_put_uint8(&dout, real_packet->sabotage);
   }
   if (BV_ISSET(fields, 14)) {
-    dio_put_string(&dout, real_packet->soundtag);
+    dio_put_uint16(&dout, real_packet->flags);
   }
   if (BV_ISSET(fields, 15)) {
-    dio_put_string(&dout, real_packet->soundtag_alt);
+    dio_put_string(&dout, real_packet->soundtag);
   }
   if (BV_ISSET(fields, 16)) {
+    dio_put_string(&dout, real_packet->soundtag_alt);
+  }
+  if (BV_ISSET(fields, 17)) {
     dio_put_string(&dout, real_packet->helptext);
   }
 
Index: common/packets_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.h,v
retrieving revision 1.101
diff -u -u -r1.101 packets_gen.h
--- common/packets_gen.h        2 May 2005 08:45:20 -0000       1.101
+++ common/packets_gen.h        4 May 2005 20:17:23 -0000
@@ -202,7 +202,7 @@
   int caravan_shields;
   int last_turns_shield_surplus;
   struct worklist worklist;
-  char improvements[B_LAST+1];
+  bv_imprs improvements;
   enum city_tile_type city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
   bool did_buy;
   bool did_sell;
@@ -222,8 +222,7 @@
   int size;
   bool happy;
   bool unhappy;
-  bool capital;
-  bool walls;
+  bv_imprs improvements;
   bool occupied;
   int tile_trade;
 };
@@ -301,7 +300,7 @@
 struct packet_city_sabotage_list {
   int diplomat_id;
   int city_id;
-  char improvements[B_LAST+1];
+  bv_imprs improvements;
 };
 
 struct packet_player_remove {
@@ -880,6 +879,7 @@
   int build_cost;
   int upkeep;
   int sabotage;
+  int flags;
   char soundtag[MAX_LEN_NAME];
   char soundtag_alt[MAX_LEN_NAME];
   char helptext[MAX_LEN_PACKET];
Index: data/civ1/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ1/buildings.ruleset,v
retrieving revision 1.48
diff -u -u -r1.48 buildings.ruleset
--- data/civ1/buildings.ruleset 18 Apr 2005 06:52:50 -0000      1.48
+++ data/civ1/buildings.ruleset 4 May 2005 20:17:24 -0000
@@ -157,6 +157,7 @@
 [building_city_walls]
 name           = _("City Walls")
 genus           = "Improvement"
+flags          = "VisibleByOthers"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
@@ -408,6 +409,7 @@
 [building_palace]
 name           = _("Palace")
 genus           = "SmallWonder"
+flags          = "SaveSmallWonder"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
Index: data/civ2/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ2/buildings.ruleset,v
retrieving revision 1.52
diff -u -u -r1.52 buildings.ruleset
--- data/civ2/buildings.ruleset 2 May 2005 08:45:20 -0000       1.52
+++ data/civ2/buildings.ruleset 4 May 2005 20:17:24 -0000
@@ -188,6 +188,7 @@
 [building_city_walls]
 name           = _("City Walls")
 genus          = "Improvement"
+flags          = "VisibleByOthers"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
@@ -507,6 +508,7 @@
 [building_palace]
 name           = _("Palace")
 genus          = "SmallWonder"
+flags          = "SaveSmallWonder"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
Index: data/default/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/buildings.ruleset,v
retrieving revision 1.71
diff -u -u -r1.71 buildings.ruleset
--- data/default/buildings.ruleset      18 Apr 2005 23:33:03 -0000      1.71
+++ data/default/buildings.ruleset      4 May 2005 20:17:24 -0000
@@ -37,6 +37,7 @@
 ; build_cost   = production shields required to build
 ; upkeep       = monetary upkeep value
 ; sabotage     = percent chance of diplomat sabotage being successful
+; flags         = special flag strings
 ;
 ; */ <-- avoid gettext warnings
 
@@ -207,6 +208,7 @@
 [building_city_walls]
 name           = _("City Walls")
 genus          = "Improvement"
+flags          = "VisibleByOthers"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
@@ -535,6 +537,7 @@
 [building_palace]
 name           = _("Palace")
 genus          = "SmallWonder"
+flags          = "SaveSmallWonder"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
Index: data/history/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/history/buildings.ruleset,v
retrieving revision 1.23
diff -u -u -r1.23 buildings.ruleset
--- data/history/buildings.ruleset      18 Apr 2005 06:52:51 -0000      1.23
+++ data/history/buildings.ruleset      4 May 2005 20:17:24 -0000
@@ -190,6 +190,7 @@
 [building_city_walls]
 name           = _("City Walls")
 genus           = "Improvement"
+flags          = "VisibleByOthers"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
@@ -516,6 +517,7 @@
 [building_palace]
 name           = _("Palace")
 genus           = "SmallWonder"
+flags          = "SaveSmallWonder"
 reqs   =
     { "type", "name", "range"
       "Tech", "Masonry", "Player"
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.319
diff -u -u -r1.319 citytools.c
--- server/citytools.c  3 May 2005 19:11:00 -0000       1.319
+++ server/citytools.c  4 May 2005 20:17:25 -0000
@@ -693,38 +693,43 @@
 /**************************************************************************
 Create a palace in a random city. Used when the capital was conquered.
 **************************************************************************/
-static void build_free_palace(struct player *pplayer,
-                              const char *const old_capital_name)
+static void build_free_small_wonders(struct player *pplayer,
+                                    const char *const old_capital_name,
+                                    bv_imprs *had_small_wonders)
 {
   int size = city_list_size(pplayer->cities);
-  struct city *pnew_capital;
 
   if (size == 0) {
     /* The last city was removed or transferred to the enemy. R.I.P. */
     return;
   }
 
-  assert(find_palace(pplayer) == NULL);
+  impr_type_iterate(id) {
+    if (BV_ISSET(*had_small_wonders, id)) {
+      struct city *pnew_city;
 
-  pnew_capital = city_list_get(pplayer->cities, myrand(size));
+      assert(find_city_from_small_wonder(pplayer, id) == NULL);
 
-  city_add_improvement(pnew_capital, game.palace_building);
+      pnew_city = city_list_get(pplayer->cities, myrand(size));
 
-  /*
-   * send_player_cities will recalculate all cities and send them to
-   * the client.
-   */
-  send_player_cities(pplayer);
+      city_add_improvement(pnew_city, id);
 
-  notify_player(pplayer, _("You lost your capital %s. A new palace "
-                          "was built in %s."), old_capital_name,
-               pnew_capital->name);
+      /*
+       * send_player_cities will recalculate all cities and send them to
+       * the client.
+       */
+      send_player_cities(pplayer);
 
-  /* 
-   * The enemy want to see the new capital in his intelligence
-   * report. 
-   */
-  send_city_info(NULL, pnew_capital);
+      notify_player(pplayer, _("You lost %s. A new %s was built in %s."),
+                   old_capital_name, get_improvement_name(id),
+                   pnew_city->name);
+      /* 
+       * The enemy want to see the new capital in his intelligence
+       * report. 
+       */
+      send_city_info(NULL, pnew_city);
+    }
+  } impr_type_iterate_end;
 }
 
 /**********************************************************************
@@ -741,7 +746,7 @@
   struct unit_list *old_city_units = unit_list_new();
   struct player *pgiver = city_owner(pcity);
   int old_trade_routes[NUM_TRADEROUTES];
-  bool had_palace = is_capital(pcity);
+  bv_imprs had_small_wonders;
   char old_city_name[MAX_LEN_NAME];
 
   assert(pgiver != ptaker);
@@ -760,9 +765,13 @@
   /* Remove all global improvement effects that this city confers (but
      then restore the local improvement list - we need this to restore the
      global effects for the new city owner) */
+  BV_CLR_ALL(had_small_wonders);
   built_impr_iterate(pcity, i) {
     city_remove_improvement(pcity, i);
-    if (!is_small_wonder(i)) {
+
+    if (is_small_wonder(i)) {
+      BV_SET(had_small_wonders, i);
+    } else {
       pcity->improvements[i] = I_ACTIVE;
     }
   } built_impr_iterate_end;
@@ -879,8 +888,8 @@
 
   /* Build a new palace for free if the player lost her capital and
      savepalace is on. */
-  if (had_palace && game.savepalace) {
-    build_free_palace(pgiver, pcity->name);
+  if (game.savepalace) {
+    build_free_small_wonders(pgiver, pcity->name, &had_small_wonders);
   }
 
   sanity_check_city(pcity);
@@ -1023,11 +1032,16 @@
   int o;
   struct player *pplayer = city_owner(pcity);
   struct tile *ptile = pcity->tile;
-  bool had_palace = is_capital(pcity);
+  bv_imprs had_small_wonders;
   char *city_name = mystrdup(pcity->name);
 
+  BV_CLR_ALL(had_small_wonders);
   built_impr_iterate(pcity, i) {
     city_remove_improvement(pcity, i);
+
+    if (is_small_wonder(i)) {
+      BV_SET(had_small_wonders, i);
+    }
   } built_impr_iterate_end;
 
   /* Rehome units in other cities */
@@ -1130,8 +1144,8 @@
 
   /* Build a new palace for free if the player lost her capital and
      savepalace is on. */
-  if (had_palace && game.savepalace) {
-    build_free_palace(pplayer, city_name);
+  if (game.savepalace) {
+    build_free_small_wonders(pplayer, city_name, &had_small_wonders);
   }
 
   free(city_name);
@@ -1273,13 +1287,6 @@
 
   packet->size = pdcity->size;
 
-  if (pcity && pcity->id == pdcity->id && is_capital(pcity)) {
-    packet->capital = TRUE;
-  } else {
-    packet->capital = FALSE;
-  }
-
-  packet->walls = pdcity->has_walls;
   packet->occupied = pdcity->occupied;
   packet->happy = pdcity->happy;
   packet->unhappy = pdcity->unhappy;
@@ -1289,6 +1296,8 @@
   } else {
     packet->tile_trade = 0;
   }
+
+  packet->improvements = pdcity->improvements;
 }
 
 /**************************************************************************
@@ -1501,7 +1510,7 @@
                  bool dipl_invest)
 {
   int x, y, i;
-  char *p;
+
   packet->id=pcity->id;
   packet->owner=pcity->owner;
   packet->x = pcity->tile->x;
@@ -1565,13 +1574,12 @@
     }
   }
 
-  p = packet->improvements;
-
+  BV_CLR_ALL(packet->improvements);
   impr_type_iterate(i) {
-    *p++ = (city_got_building(pcity, i)) ? '1' : '0';
+    if (city_got_building(pcity, i)) {
+      BV_SET(packet->improvements, i);
+    }
   } impr_type_iterate_end;
-
-  *p = '\0';
 }
 
 /**************************************************************************
@@ -1594,16 +1602,24 @@
   bool occupied =
     (unit_list_size(pcity->tile->units) > 0);
   bool happy = city_happy(pcity), unhappy = city_unhappy(pcity);
- 
+  bv_imprs improvements;
+
+  BV_CLR_ALL(improvements);
+  impr_type_iterate(i) {
+    if (is_improvement_visible(i) && city_got_building(pcity, i)) {
+      BV_SET(improvements, i);
+    }
+  } impr_type_iterate_end;
+
   if (pdcity
       && pdcity->id == pcity->id
       && strcmp(pdcity->name, pcity->name) == 0
       && pdcity->size == pcity->size
-      && pdcity->has_walls == city_got_citywalls(pcity)
       && pdcity->occupied == occupied
       && pdcity->happy == happy
       && pdcity->unhappy == unhappy
-      && pdcity->owner == pcity->owner) {
+      && pdcity->owner == pcity->owner
+      && BV_ARE_EQUAL(pdcity->improvements, improvements)) {
     return FALSE;
   }
 
@@ -1619,11 +1635,11 @@
   }
   sz_strlcpy(pdcity->name, pcity->name);
   pdcity->size = pcity->size;
-  pdcity->has_walls = city_got_citywalls(pcity);
   pdcity->occupied = occupied;
   pdcity->happy = happy;
   pdcity->unhappy = unhappy;
   pdcity->owner = pcity->owner;
+  pdcity->improvements = improvements;
 
   return TRUE;
 }
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.73
diff -u -u -r1.73 diplomats.c
--- server/diplomats.c  2 May 2005 19:05:15 -0000       1.73
+++ server/diplomats.c  4 May 2005 20:17:26 -0000
@@ -206,16 +206,14 @@
                           struct city *pcity)
 {
   struct packet_city_sabotage_list packet;
-  char *p;
 
   /* Send city improvements info to player. */
-  p = packet.improvements;
+  BV_CLR_ALL(packet.improvements);
 
   impr_type_iterate(i) {
-    *p++=city_got_building(pcity,i)?'1':'0';
+    BV_SET(packet.improvements, city_got_building(pcity, i));
   } impr_type_iterate_end;
 
-  *p='\0';
   packet.diplomat_id = pdiplomat->id;
   packet.city_id = pcity->id;
   lsend_packet_city_sabotage_list(player_reply_dest(pplayer), &packet);
Index: server/maphand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.h,v
retrieving revision 1.54
diff -u -u -r1.54 maphand.h
--- server/maphand.h    30 Apr 2005 20:59:50 -0000      1.54
+++ server/maphand.h    4 May 2005 20:17:26 -0000
@@ -29,12 +29,13 @@
   /* Values in this struct are copied using a memcpy, so don't put any
    * pointers in here. */
   int id;
-  bool has_walls;
   bool occupied;
   bool happy, unhappy;
   char name[MAX_LEN_NAME];
   unsigned short size;
   unsigned char owner;
+
+  bv_imprs improvements;
 };
 
 struct player_tile {
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.251
diff -u -u -r1.251 ruleset.c
--- server/ruleset.c    2 May 2005 08:45:23 -0000       1.251
+++ server/ruleset.c    4 May 2005 20:17:27 -0000
@@ -2463,26 +2463,6 @@
 
   section_file_check_unused(file, filename);
   section_file_free(file);
-
-  /*
-   * Hack to allow code that explicitly checks for Palace or City Walls
-   * to work.
-   */
-  game.palace_building = get_building_for_effect(EFT_CAPITAL_CITY);
-  if (game.palace_building == B_LAST) {
-    freelog(LOG_FATAL,
-           /* TRANS: Obscure ruleset error */
-           _("Cannot find any palace building"));
-    exit(EXIT_FAILURE);
-  }
-
-  game.land_defend_building = get_building_for_effect(EFT_LAND_DEFEND);
-  if (game.land_defend_building == B_LAST) {
-    freelog(LOG_FATAL,
-           /* TRANS: Obscure ruleset error */
-           _("Cannot find any land defend building"));
-    exit(EXIT_FAILURE);
-  }
 }
 
 /**************************************************************************
@@ -2758,6 +2738,7 @@
     packet.build_cost = b->build_cost;
     packet.upkeep = b->upkeep;
     packet.sabotage = b->sabotage;
+    packet.flags = b->flags;
     sz_strlcpy(packet.soundtag, b->soundtag);
     sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
 
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.241
diff -u -u -r1.241 savegame.c
--- server/savegame.c   3 May 2005 19:42:48 -0000       1.241
+++ server/savegame.c   4 May 2005 20:17:28 -0000
@@ -2334,7 +2334,9 @@
 The private map for fog of war
 ***********************************************************************/
 static void player_map_load(struct player *plr, int plrno,
-                           struct section_file *file)
+                           struct section_file *file,
+                           char** improvement_order,
+                           int improvement_order_size)
 {
   int i;
 
@@ -2404,6 +2406,8 @@
       for (j = 0; j < i; j++) {
        int nat_x, nat_y;
        struct tile *ptile;
+       int k, id;
+       const char *p;
 
        nat_x = secfile_lookup_int(file, "player%d.dc%d.x", plrno, j);
        nat_y = secfile_lookup_int(file, "player%d.dc%d.y", plrno, j);
@@ -2413,7 +2417,6 @@
        pdcity->id = secfile_lookup_int(file, "player%d.dc%d.id", plrno, j);
        sz_strlcpy(pdcity->name, secfile_lookup_str(file, "player%d.dc%d.name", 
plrno, j));
        pdcity->size = secfile_lookup_int(file, "player%d.dc%d.size", plrno, j);
-       pdcity->has_walls = secfile_lookup_bool(file, 
"player%d.dc%d.has_walls", plrno, j);    
        pdcity->occupied = secfile_lookup_bool_default(file, FALSE,
                                        "player%d.dc%d.occupied", plrno, j);
        pdcity->happy = secfile_lookup_bool_default(file, FALSE,
@@ -2421,6 +2424,25 @@
        pdcity->unhappy = secfile_lookup_bool_default(file, FALSE,
                                        "player%d.dc%d.unhappy", plrno, j);
        pdcity->owner = secfile_lookup_int(file, "player%d.dc%d.owner", plrno, 
j);
+
+       /* Initialise list of improvements */
+       BV_CLR_ALL(pdcity->improvements);
+
+       p = secfile_lookup_str_default(file, NULL,
+                                      "player%d.dc%d.improvements", plrno, j);
+       if (!p) {
+         /* old savegames */
+       } else {
+         for (k = 0; k < improvement_order_size && p[k]; k++) {
+           if (p[k] == '1') {
+             id = find_improvement_by_name_orig(improvement_order[k]);
+             if (id != -1) {
+               BV_SET(pdcity->improvements, id);
+             }
+           }
+         }
+       }
+
        map_get_player_tile(ptile, plr)->city = pdcity;
        alloc_id(pdcity->id);
       }
@@ -3001,6 +3023,7 @@
     if (TRUE) {
       struct dumb_city *pdcity;
       i = 0;
+      char impr_buf[MAX_NUM_ITEMS + 1];
       
       whole_map_iterate(ptile) {
        if ((pdcity = map_get_player_tile(ptile, plr)->city)) {
@@ -3014,8 +3037,8 @@
                             plrno, i);
          secfile_insert_int(file, pdcity->size, "player%d.dc%d.size",
                             plrno, i);
-         secfile_insert_bool(file, pdcity->has_walls,
-                            "player%d.dc%d.has_walls", plrno, i);
+          secfile_insert_bool(file, FALSE,
+                             "player%d.dc%d.has_walls", plrno, i);
          secfile_insert_bool(file, pdcity->occupied,
                              "player%d.dc%d.occupied", plrno, i);
          secfile_insert_bool(file, pdcity->happy,
@@ -3024,6 +3047,18 @@
                              "player%d.dc%d.unhappy", plrno, i);
          secfile_insert_int(file, pdcity->owner, "player%d.dc%d.owner",
                             plrno, i);
+
+         /* Save improvement list as bitvector. Note that improvement order
+          * is saved in savefile.improvement_order.
+          */
+         impr_type_iterate(id) {
+           impr_buf[id] = BV_ISSET(pdcity->improvements, id) ? '1' : '0';
+         } impr_type_iterate_end;
+         impr_buf[game.num_impr_types] = '\0';
+         assert(strlen(impr_buf) < sizeof(impr_buf));
+         secfile_insert_str(file, impr_buf,
+                            "player%d.dc%d.improvements", plrno, i);    
+
          i++;
        }
       } whole_map_iterate_end;
@@ -3612,7 +3647,8 @@
     /* Since the cities must be placed on the map to put them on the
        player map we do this afterwards */
     for(i=0; i<game.nplayers; i++) {
-      player_map_load(&game.players[i], i, file); 
+      player_map_load(&game.players[i], i, file, improvement_order,
+                     improvement_order_size); 
     }
 
     /* We do this here since if the did it in player_load, player 1

[Prev in Thread] Current Thread [Next in Thread]