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

> [book - Tue Feb 10 02:58:11 2009]:
> 
> > [matthias.pfaffer...@mapfa.de - Sun Jan 04 22:03:07 2009]:
> > 
> > The gold upkeep patch (version 2)
> 
> I have made some adjustments to your patch and attached
> it as version 3.

Version 4 updated for latest trunk sources.


-----------------------------------------------------------------------
あの城には金の手を持つ男が住んでいるそうです。
 common/game.h             |    4 +
 common/packets.def        |    1 +
 data/civ1/game.ruleset    |   12 ++
 data/civ2/game.ruleset    |   12 ++
 data/default/game.ruleset |   12 ++
 server/cityturn.c         |  459 +++++++++++++++++++++++++++++++++++++--------
 server/ruleset.c          |   11 +
 server/unittools.c        |   42 ----
 server/unittools.h        |    1 -
 9 files changed, 435 insertions(+), 119 deletions(-)

diff --git a/common/game.h b/common/game.h
index e39bc05..94a1b25 100644
--- a/common/game.h
+++ b/common/game.h
@@ -183,6 +183,10 @@ bool setting_class_is_changeable(enum sset_class class);
 #define GAME_MIN_AIFILL              0
 #define GAME_MAX_AIFILL              GAME_MAX_MAX_PLAYERS
 
+#define GAME_DEFAULT_GOLD_UPKEEP_STYLE 0
+#define GAME_MIN_GOLD_UPKEEP_STYLE     0
+#define GAME_MAX_GOLD_UPKEEP_STYLE     1
+
 #define GAME_DEFAULT_FOODBOX         100
 #define GAME_MIN_FOODBOX             1
 #define GAME_MAX_FOODBOX             10000
diff --git a/common/packets.def b/common/packets.def
index 4a83f79..e5642c6 100644
--- a/common/packets.def
+++ b/common/packets.def
@@ -443,6 +443,7 @@ PACKET_GAME_INFO=15; sc
   UINT8 init_vis_radius_sq;
   BOOL pillage_select;
   UINT8 nuke_contamination;
+  UINT8 gold_upkeep_style;
   UINT8 granary_food_ini[MAX_GRANARY_INIS];
   UINT8 granary_num_inis;
   UINT8 granary_food_inc;
diff --git a/data/civ1/game.ruleset b/data/civ1/game.ruleset
index f4c785d..762d2e8 100644
--- a/data/civ1/game.ruleset
+++ b/data/civ1/game.ruleset
@@ -56,6 +56,18 @@ pillage_select		= 0
 ;   "Fallout"   - Nuclear Fallout (distinct from industrial/population).
 nuke_contamination	= "Pollution"
 
+; Method of paying unit and improvement gold upkeep
+; 0 - The player's total gold must be non-negative after paying upkeep
+;     costs associated with each city. If for any city the player's gold
+;     is negative, random buildings in the city are sold off. If the gold
+;     is still negative, then supported units with gold upkeep are
+;     disbanded.
+; 1 - Gold upkeep for all buildings and units is paid in a lump sum after
+;     all cities have been processed. If the player does not have enough
+;     gold, random buildings from random cities are sold. If still more
+;     gold is needed, then random units with gold upkeep are disbanded.
+gold_upkeep_style = 0
+
 ; Parameters used to generalize the calculation of city granary size:
 ;   if city_size <= num_inis:
 ;     city_granary_size = (granary_food_ini[city_size] * foodbox / 100)
diff --git a/data/civ2/game.ruleset b/data/civ2/game.ruleset
index f822bf1..92a4361 100644
--- a/data/civ2/game.ruleset
+++ b/data/civ2/game.ruleset
@@ -50,6 +50,18 @@ pillage_select		= 1
 ;   "Fallout"   - Nuclear Fallout (distinct from industrial/population).
 nuke_contamination	= "Pollution"
 
+; Method of paying unit and improvement gold upkeep
+; 0 - The player's total gold must be non-negative after paying upkeep
+;     costs associated with each city. If for any city the player's gold
+;     is negative, random buildings in the city are sold off. If the gold
+;     is still negative, then supported units with gold upkeep are
+;     disbanded.
+; 1 - Gold upkeep for all buildings and units is paid in a lump sum after
+;     all cities have been processed. If the player does not have enough
+;     gold, random buildings from random cities are sold. If still more
+;     gold is needed, then random units with gold upkeep are disbanded.
+gold_upkeep_style = 0
+
 ; Parameters used to generalize the calculation of city granary size:
 ;   if city_size <= num_inis:
 ;     city_granary_size = (granary_food_ini[city_size] * foodbox / 100)
diff --git a/data/default/game.ruleset b/data/default/game.ruleset
index a0e19b3..86fbc2d 100644
--- a/data/default/game.ruleset
+++ b/data/default/game.ruleset
@@ -68,6 +68,18 @@ pillage_select		= 1
 ;   "Fallout"   - Nuclear Fallout (distinct from industrial/population).
 nuke_contamination	= "Fallout"
 
+; Method of paying unit and improvement gold upkeep
+; 0 - The player's total gold must be non-negative after paying upkeep
+;     costs associated with each city. If for any city the player's gold
+;     is negative, random buildings in the city are sold off. If the gold
+;     is still negative, then supported units with gold upkeep are
+;     disbanded.
+; 1 - Gold upkeep for all buildings and units is paid in a lump sum after
+;     all cities have been processed. If the player does not have enough
+;     gold, random buildings from random cities are sold. If still more
+;     gold is needed, then random units with gold upkeep are disbanded.
+gold_upkeep_style = 0
+
 ; Parameters used to generalize the calculation of city granary size:
 ;   if city_size <= num_inis:
 ;     city_granary_size = (granary_food_ini[city_size] * foodbox / 100)
diff --git a/server/cityturn.c b/server/cityturn.c
index d3230e4..b517d2b 100644
--- a/server/cityturn.c
+++ b/server/cityturn.c
@@ -82,12 +82,40 @@ static void upgrade_building_prod(struct city *pcity);
 static struct unit_type *unit_upgrades_to(struct city *pcity,
 					  struct unit_type *id);
 static void upgrade_unit_prod(struct city *pcity);
-static void pay_for_buildings(struct player *pplayer, struct city *pcity);
+
+/* Helper struct for associating a building to a city. */
+struct cityimpr {
+  struct city *pcity;
+  struct impr_type *pimprove;
+};
+
+#define SPECVEC_TAG cityimpr
+#define SPECVEC_TYPE struct cityimpr
+#include "specvec.h"
+
+/* Helper struct for storing a unit with its gold upkeep. */
+struct unitgold {
+  struct unit *punit;
+  int gold_upkeep;
+};
+
+#define SPECVEC_TAG unitgold
+#define SPECVEC_TYPE struct unitgold
+#include "specvec.h"
+
+static int city_total_impr_gold_upkeep(const struct city *pcity);
+static int city_total_unit_gold_upkeep(const struct city *pcity);
+static bool sell_random_buildings(struct player *pplayer,
+                                  struct cityimpr_vector *imprs);
+static bool sell_random_units(struct player *pplayer,
+                              struct unitgold_vector *units);
+static void city_balance_treasury(struct city *pcity);
+static void player_balance_treasury(struct player *pplayer);
 
 static bool disband_city(struct city *pcity);
 
 static void define_orig_production_values(struct city *pcity);
-static void update_city_activity(struct player *pplayer, struct city *pcity);
+static void update_city_activity(struct city *pcity);
 static void nullify_caravan_and_disband_plus(struct city *pcity);
 
 static float city_migration_score(const struct city *pcity);
@@ -414,27 +442,62 @@ void send_city_turn_notifications(struct conn_list *dest, struct city *pcity)
 }
 
 /**************************************************************************
-...
+  Update all cities of one nation (costs for buildings, unit upkeep, ...).
 **************************************************************************/
 void update_city_activities(struct player *pplayer)
 {
-  int gold;
-  gold=pplayer->economic.gold;
+  int n, gold;
+
+  assert(pplayer != NULL);
+  assert(pplayer->cities != NULL);
+
+  n = city_list_size(pplayer->cities);
+  gold = pplayer->economic.gold;
   pplayer->bulbs_last_turn = 0;
-  city_list_iterate_safe(pplayer->cities, pcity)
-     update_city_activity(pplayer, pcity);
-  city_list_iterate_safe_end;
+
+  if (n > 0) {
+    struct city *cities[n];
+    int i = 0, r;
+
+    city_list_iterate(pplayer->cities, pcity) {
+      cities[i++] = pcity;
+    } city_list_iterate_end;
+
+    /* How gold upkeep is handled depends on the setting
+     * 'game.info.gold_upkeep_style':
+     * 0 - Each city tries to balance its upkeep individually
+     *     (this is done in update_city_activity()).
+     * 1 - The nation as a whole balances the treasury. */
+
+    /* Iterate over cities in a random order. */
+    while (i > 0) {
+      r = myrand(i);
+      update_city_activity(cities[r]);
+      cities[r] = cities[--i];
+    }
+
+    if (game.info.gold_upkeep_style == 1 && pplayer->economic.gold < 0) {
+      player_balance_treasury(pplayer);
+    }
+
+    /* Should not happen. */
+    assert(pplayer->economic.gold >= 0);
+  }
+
   pplayer->ai.prev_gold = gold;
-  /* This test include the cost of the units because pay_for_units is called
-   * in update_city_activity */
+  /* This test includes the cost of the units because
+   * units are paid for in update_city_activity(). */
   if (gold - (gold - pplayer->economic.gold) * 3 < 0) {
     notify_player(pplayer, NULL, E_LOW_ON_FUNDS,
-		     _("WARNING, we're LOW on FUNDS sire."));  
+                  _("WARNING, we're LOW on FUNDS sire."));
+  }
+
+#if 0
+  /* Uncomment to unbalance the game, like in civ1 (CLG). */
+  if (pplayer->got_tech && pplayer->research->researched > 0) {
+    pplayer->research->researched = 0;
   }
-    /* uncomment to unbalance the game, like in civ1 (CLG)
-      if (pplayer->got_tech && pplayer->research->researched > 0)    
-        pplayer->research->researched=0;
-    */
+#endif
 }
 
 /**************************************************************************
@@ -1561,26 +1624,257 @@ static bool city_build_stuff(struct player *pplayer, struct city *pcity)
 }
 
 /**************************************************************************
-  Pay for upkeep costs for all buildings, or sell them.
+  Returns the total amount of gold needed to pay for all buildings in the
+  city.
 **************************************************************************/
-static void pay_for_buildings(struct player *pplayer, struct city *pcity)
+static int city_total_impr_gold_upkeep(const struct city *pcity)
 {
+  int gold_needed = 0;
+
+  if (!pcity) {
+    return 0;
+  }
+
   city_built_iterate(pcity, pimprove) {
-    if (can_city_sell_building(pcity, pimprove)) {
-      int upkeep = city_improvement_upkeep(pcity, pimprove);
+      gold_needed += city_improvement_upkeep(pcity, pimprove);
+  } city_built_iterate_end;
 
-      if (pplayer->economic.gold - upkeep < 0) {
-	notify_player(pplayer, pcity->tile, E_IMP_AUCTIONED,
-			 _("Can't afford to maintain %s in %s, "
-			   "building sold!"),
-			 improvement_name_translation(pimprove),
-			 city_name(pcity));
-	do_sell_building(pplayer, pcity, pimprove);
-	city_refresh(pcity);
-      } else
-        pplayer->economic.gold -= upkeep;
+  return gold_needed;
+}
+
+/***************************************************************************
+  Get the total amount of gold needed to pay upkeep costs for all supported
+  units of the city. Takes into account EFT_UNIT_UPKEEP_FREE_PER_CITY.
+***************************************************************************/
+static int city_total_unit_gold_upkeep(const struct city *pcity)
+{
+  int gold_needed = 0;
+  int free[O_COUNT], upkeep[O_COUNT];
+
+  if (!pcity || !pcity->units_supported
+      || unit_list_size(pcity->units_supported) < 1) {
+    return 0;
+  }
+
+  memset(free, 0, O_COUNT * sizeof(*free));
+  free[O_GOLD] = get_city_output_bonus(pcity, get_output_type(O_GOLD),
+                                       EFT_UNIT_UPKEEP_FREE_PER_CITY);
+
+  unit_list_iterate(pcity->units_supported, punit) {
+    city_unit_upkeep(punit, upkeep, free);
+    gold_needed += upkeep[O_GOLD];
+  } unit_list_iterate_end;
+
+  return gold_needed;
+}
+
+/**************************************************************************
+  Randomly sell buildings from the given vector until the player has
+  a non-negative amount of gold left in the treasury. Returns TRUE if
+  enough buildings were sold to pay the deficit.
+
+  NB: It is assumed that gold upkeep for the buildings has already been
+  paid this turn, hence when a building is sold its upkeep is given back
+  to the player.
+  NB: The contents of 'imprs' are usually mangled by this function.
+  NB: It is assumed that all buildings in 'imprs' can be sold.
+**************************************************************************/
+static bool sell_random_buildings(struct player *pplayer,
+                                  struct cityimpr_vector *imprs)
+{
+  struct city *pcity;
+  struct impr_type *pimprove;
+  int n, r;
+
+  assert(pplayer != NULL);
+
+  n = imprs ? cityimpr_vector_size(imprs) : 0;
+  while (pplayer->economic.gold < 0 && n > 0) {
+    r = myrand(n);
+    pcity = imprs->p[r].pcity;
+    pimprove = imprs->p[r].pimprove;
+
+    notify_player(pplayer, city_tile(pcity), E_IMP_AUCTIONED,
+                  _("Can't afford to maintain %s in %s, building sold!"),
+                  improvement_name_translation(pimprove),
+                  city_name(pcity));
+
+    do_sell_building(pplayer, pcity, pimprove);
+    city_refresh(pcity);
+
+    /* Get back the gold upkeep that was already paid this turn. */
+    pplayer->economic.gold += city_improvement_upkeep(pcity, pimprove);
+
+    imprs->p[r] = imprs->p[--n];
+  }
+
+  return pplayer->economic.gold >= 0;
+}
+
+/**************************************************************************
+  Randomly "sell" units from the given vector until the player has a
+  a non-negative amount of gold left in the treasury. Returns TRUE if
+  enough units were sold to pay the deficit.
+
+  NB: It is assumed that gold upkeep for the units has already been paid
+  this turn, hence when a unit is "sold" its upkeep is given back to the
+  player.
+  NB: The contents of 'units' are usually mangled by this function.
+  NB: It is assumed that all units in 'units' have positive gold upkeep.
+**************************************************************************/
+static bool sell_random_units(struct player *pplayer,
+                              struct unitgold_vector *units)
+{
+  struct unit *punit;
+  int gold_upkeep, n, r;
+
+  assert(pplayer != NULL);
+
+  n = units ? unitgold_vector_size(units) : 0;
+  while (pplayer->economic.gold < 0 && n > 0) {
+    r = myrand(n);
+    punit = units->p[r].punit;
+    gold_upkeep = units->p[r].gold_upkeep;
+
+    notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
+                  _("Not enough gold. %s disbanded"),
+                  unit_name_translation(punit));
+    wipe_unit(punit);
+
+    /* Get the upkeep gold back. */
+    pplayer->economic.gold += gold_upkeep;
+
+    units->p[r] = units->p[--n];
+  }
+
+  return pplayer->economic.gold >= 0;
+}
+
+/**************************************************************************
+  Balance the gold of a nation by selling some random buildings. If this
+  does not help, then disband some units which need gold upkeep.
+**************************************************************************/
+static void player_balance_treasury(struct player *pplayer)
+{
+  struct cityimpr_vector imprs;
+  struct cityimpr ci;
+  struct unitgold_vector units;
+  struct unitgold ug;
+  int free[O_COUNT], upkeep[O_COUNT];
+
+  if (!pplayer) {
+    return;
+  }
+
+  cityimpr_vector_init(&imprs);
+  unitgold_vector_init(&units);
+
+  city_list_iterate(pplayer->cities, pcity) {
+    city_built_iterate(pcity, pimprove) {
+      if (can_city_sell_building(pcity, pimprove)) {
+        ci.pcity = pcity;
+        ci.pimprove = pimprove;
+        cityimpr_vector_append(&imprs, &ci);
+      }
+    } city_built_iterate_end;
+  } city_list_iterate_end;
+
+  if (sell_random_buildings(pplayer, &imprs)) {
+    goto CLEANUP;
+  }
+
+  memset(free, 0, O_COUNT * sizeof(*free));
+
+  city_list_iterate(pplayer->cities, pcity) {
+    free[O_GOLD] = get_city_output_bonus(pcity, get_output_type(O_GOLD),
+                                         EFT_UNIT_UPKEEP_FREE_PER_CITY);
+    unit_list_iterate(pcity->units_supported, punit) {
+      city_unit_upkeep(punit, upkeep, free);
+      if (upkeep[O_GOLD] > 0) {
+        ug.punit = punit;
+        ug.gold_upkeep = upkeep[O_GOLD];
+        unitgold_vector_append(&units, &ug);
+      }
+    } unit_list_iterate_end;
+  } city_list_iterate_end;
+
+  if (sell_random_units(pplayer, &units)) {
+    goto CLEANUP;
+  }
+
+  /* If we get here it means the player has
+   * negative gold. This should never happen. */
+  die("Player cannot have negative gold.");
+
+CLEANUP:
+  cityimpr_vector_free(&imprs);
+  unitgold_vector_free(&units);
+}
+
+/**************************************************************************
+  Balance the gold of one city by randomly selling some buildings. If this
+  does not help, randomly disband some units which need gold upkeep.
+
+  NB: This function adds the gold upkeep of disbanded units back to the
+  player's gold. Hence it assumes that this gold was previously taken
+  from the player (i.e. in update_city_activity()).
+**************************************************************************/
+static void city_balance_treasury(struct city *pcity)
+{
+  struct player *pplayer;
+  struct cityimpr_vector imprs;
+  struct cityimpr ci;
+  struct unitgold_vector units;
+  struct unitgold ug;
+  int free[O_COUNT], upkeep[O_COUNT];
+
+  if (!pcity) {
+    return;
+  }
+
+  pplayer = city_owner(pcity);
+  cityimpr_vector_init(&imprs);
+  unitgold_vector_init(&units);
+
+  /* Create a vector of all buildings that can be sold. */
+  city_built_iterate(pcity, pimprove) {
+    if (can_city_sell_building(pcity, pimprove)) {
+      ci.pcity = pcity;
+      ci.pimprove = pimprove;
+      cityimpr_vector_append(&imprs, &ci);
     }
   } city_built_iterate_end;
+
+  /* Try to sell some buildings. */
+  if (sell_random_buildings(pplayer, &imprs)) {
+    goto CLEANUP;
+  }
+
+  memset(free, 0, O_COUNT * sizeof(*free));
+  free[O_GOLD] = get_city_output_bonus(pcity, get_output_type(O_GOLD),
+                                       EFT_UNIT_UPKEEP_FREE_PER_CITY);
+
+  /* Create a vector of all supported units with gold upkeep. */
+  unit_list_iterate(pcity->units_supported, punit) {
+    city_unit_upkeep(punit, upkeep, free);
+    if (upkeep[O_GOLD] > 0) {
+      ug.punit = punit;
+      ug.gold_upkeep = upkeep[O_GOLD];
+      unitgold_vector_append(&units, &ug);
+    }
+  } unit_list_iterate_end;
+
+  /* Still not enough gold, so try "selling" some units. */
+  if (sell_random_units(pplayer, &units)) {
+    goto CLEANUP;
+  }
+
+  /* If we get here the player has negative gold, but hopefully
+   * another city will be able to pay the deficit, so continue. */
+
+CLEANUP:
+  cityimpr_vector_free(&imprs);
+  unitgold_vector_free(&units);
 }
 
 /**************************************************************************
@@ -1737,16 +2031,25 @@ void nullify_prechange_production(struct city *pcity)
 /**************************************************************************
  Called every turn, at end of turn, for every city.
 **************************************************************************/
-static void update_city_activity(struct player *pplayer, struct city *pcity)
+static void update_city_activity(struct city *pcity)
 {
-  struct government *g = government_of_city(pcity);
-  int saved_id = pcity->id;
+  struct player *pplayer;
+  struct government *gov;
+
+  if (!pcity) {
+    return;
+  }
+
+  pplayer = city_owner(pcity);
+  gov = government_of_city(pcity);
 
   city_refresh(pcity);
 
-  /* reporting of celebrations rewritten, copying the treatment of disorder below,
+  /* Reporting of celebrations rewritten, copying the treatment of disorder below,
      with the added rapture rounds count.  991219 -- Jing */
   if (city_build_stuff(pplayer, pcity)) {
+    int saved_id;
+
     if (city_celebrating(pcity)) {
       pcity->rapture++;
       if (pcity->rapture == 1) {
@@ -1760,61 +2063,65 @@ static void update_city_activity(struct player *pplayer, struct city *pcity)
                       _("Celebrations canceled in %s."),
                       city_name(pcity));
       }
-      pcity->rapture=0;
+      pcity->rapture = 0;
     }
-    pcity->was_happy=city_happy(pcity);
+    pcity->was_happy = city_happy(pcity);
 
     /* City population updated here, after the rapture stuff above. --Jing */
-    {
-      int id=pcity->id;
-      city_populate(pcity);
-      if(!player_find_city_by_id(pplayer, id))
-	return;
+    saved_id = pcity->id;
+    city_populate(pcity);
+    if (!player_find_city_by_id(pplayer, saved_id)) {
+      return;
     }
 
-    pcity->is_updated=TRUE;
-
-    pcity->did_sell=FALSE;
+    pcity->is_updated = TRUE;
+    pcity->did_sell = FALSE;
     pcity->did_buy = FALSE;
     pcity->airlift = get_city_bonus(pcity, EFT_AIRLIFT);
     update_tech(pplayer, pcity->prod[O_SCIENCE]);
-    pplayer->economic.gold+=pcity->prod[O_GOLD];
-    pay_for_units(pplayer, pcity);
-    if (city_exist(saved_id)) {
-      pay_for_buildings(pplayer, pcity);
-
-      if(city_unhappy(pcity)) { 
-        pcity->anarchy++;
-        if (pcity->anarchy == 1) {
-          notify_player(pplayer, pcity->tile, E_CITY_DISORDER,
-                        _("Civil disorder in %s."),
-                        city_name(pcity));
-        } else {
-          notify_player(pplayer, pcity->tile, E_CITY_DISORDER,
-                        _("CIVIL DISORDER CONTINUES in %s."),
-                        city_name(pcity));
-        }
+
+    /* Update the treasury. */
+    pplayer->economic.gold += pcity->prod[O_GOLD];
+    pplayer->economic.gold -= city_total_impr_gold_upkeep(pcity);
+    pplayer->economic.gold -= city_total_unit_gold_upkeep(pcity);
+
+    if (game.info.gold_upkeep_style == 0 && pplayer->economic.gold < 0) {
+      /* Not enough gold - we have to sell some buildings, and if that
+       * is not enough, disband units with gold upkeep. */
+      city_balance_treasury(pcity);
+    }
+
+    if (city_unhappy(pcity)) {
+      pcity->anarchy++;
+      if (pcity->anarchy == 1) {
+        notify_player(pplayer, pcity->tile, E_CITY_DISORDER,
+                      _("Civil disorder in %s."),
+                      city_name(pcity));
       } else {
-        if (pcity->anarchy != 0) {
-          notify_player(pplayer, pcity->tile, E_CITY_NORMAL,
-                        _("Order restored in %s."),
-                        city_name(pcity));
-        }
-        pcity->anarchy = 0;
+        notify_player(pplayer, pcity->tile, E_CITY_DISORDER,
+                      _("CIVIL DISORDER CONTINUES in %s."),
+                      city_name(pcity));
       }
-      check_pollution(pcity);
-
-      send_city_info(NULL, pcity);
-      if (pcity->anarchy>2 
-          && get_player_bonus(pplayer, EFT_REVOLUTION_WHEN_UNHAPPY) > 0) {
-        notify_player(pplayer, pcity->tile, E_ANARCHY,
-                      _("The people have overthrown your %s, "
-                        "your country is in turmoil."),
-                      government_name_translation(g));
-        handle_player_change_government(pplayer, government_number(g));
+    } else {
+      if (pcity->anarchy != 0) {
+        notify_player(pplayer, pcity->tile, E_CITY_NORMAL,
+                      _("Order restored in %s."),
+                      city_name(pcity));
       }
-      sanity_check_city(pcity);
+      pcity->anarchy = 0;
     }
+    check_pollution(pcity);
+
+    send_city_info(NULL, pcity);
+    if (pcity->anarchy > 2
+        && get_player_bonus(pplayer, EFT_REVOLUTION_WHEN_UNHAPPY) > 0) {
+      notify_player(pplayer, pcity->tile, E_ANARCHY,
+                    _("The people have overthrown your %s, "
+                      "your country is in turmoil."),
+                    government_name_translation(gov));
+      handle_player_change_government(pplayer, government_number(gov));
+    }
+    sanity_check_city(pcity);
   }
 }
 
diff --git a/server/ruleset.c b/server/ruleset.c
index 8137bdb..eba64a3 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -3025,6 +3025,17 @@ static void load_ruleset_game(void)
     game.info.nuke_contamination = CONTAMINATION_POLLUTION;
   }
 
+  game.info.gold_upkeep_style
+    = secfile_lookup_int_default(&file, GAME_DEFAULT_GOLD_UPKEEP_STYLE,
+                                 "civstyle.gold_upkeep_style");
+  if (game.info.gold_upkeep_style > GAME_MAX_GOLD_UPKEEP_STYLE
+      || game.info.gold_upkeep_style < GAME_MIN_GOLD_UPKEEP_STYLE) {
+    freelog(LOG_ERROR, "Bad value %d for gold_upkeep_style. Using default"
+            "value (%d).", game.info.gold_upkeep_style,
+            GAME_DEFAULT_GOLD_UPKEEP_STYLE);
+    game.info.gold_upkeep_style = GAME_DEFAULT_GOLD_UPKEEP_STYLE;
+  }
+
   food_ini = secfile_lookup_int_vec(&file, &game.info.granary_num_inis, 
 				    "civstyle.granary_food_ini");
   if (game.info.granary_num_inis > MAX_GRANARY_INIS) {
diff --git a/server/unittools.c b/server/unittools.c
index 2617cf5..1ca18c3 100644
--- a/server/unittools.c
+++ b/server/unittools.c
@@ -267,48 +267,6 @@ static void do_upgrade_effects(struct player *pplayer)
 }
 
 /***************************************************************************
-  Pay the cost of supported units of one city
-***************************************************************************/
-void pay_for_units(struct player *pplayer, struct city *pcity)
-{
-  int potential_gold = 0;
-  int free_upkeep[O_COUNT];
-
-  memset(free_upkeep, 0, O_COUNT * sizeof(*free_upkeep));
-  free_upkeep[O_GOLD] = get_city_output_bonus(pcity, get_output_type(O_GOLD),
-                                              EFT_UNIT_UPKEEP_FREE_PER_CITY);
-
-  city_built_iterate(pcity, pimprove) {
-    if (can_city_sell_building(pcity, pimprove)) {
-      potential_gold += impr_sell_gold(pimprove);
-    }
-  } city_built_iterate_end;
-
-  unit_list_iterate_safe(pcity->units_supported, punit) {
-    int upkeep[O_COUNT];
-
-    city_unit_upkeep(punit, upkeep, free_upkeep);
-
-    if (pplayer->economic.gold + potential_gold < upkeep[O_GOLD]) {
-      /* We cannot upkeep this unit any longer and selling off city
-       * improvements will not help so we will have to disband */
-      assert(pplayer->economic.gold + potential_gold >= 0);
-
-      notify_player(pplayer, NULL, E_UNIT_LOST_MISC,
-                    _("Not enough gold to pay upkeep "
-                      "for %s. Unit disbanded."),
-                    unit_name_translation(punit));
-      wipe_unit(punit);
-    } else {
-      /* Gold can get negative here as city improvements will be sold
-       * afterwards to balance our budget. FIXME: Should units with gold 
-       * upkeep give gold when they are disbanded? */
-      pplayer->economic.gold -= upkeep[O_GOLD];
-    }
-  } unit_list_iterate_safe_end;
-}
-
-/***************************************************************************
   1. Do Leonardo's Workshop upgrade if applicable.
 
   2. Restore/decrease unit hitpoints.
diff --git a/server/unittools.h b/server/unittools.h
index 744bb69..fe0b022 100644
--- a/server/unittools.h
+++ b/server/unittools.h
@@ -50,7 +50,6 @@ int get_unit_vision_at(struct unit *punit, struct tile *ptile,
 		       enum vision_layer vlayer);
 void unit_refresh_vision(struct unit *punit);
 void unit_list_refresh_vision(struct unit_list *punitlist);
-void pay_for_units(struct player *pplayer, struct city *pcity);
 void bounce_unit(struct unit *punit, bool verbose);
 
 /* creation/deletion/upgrading */
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to