<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40619 >
The gold upkeep patch (version 2) changes: - give the struct for the list some memory and free all used memory - split the patch in two parts: * the patch * some freelog(LOG_NORMAL,...) debugging messages - correct an error in the definition of the default value - additional comments / explanations - randomly chosen unit to disband The patch was tested with an adapted ruleset (gold upkeep). Matthias
diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_gold/server/cityturn.c freeciv-2.1.99svn.patch_gold_debug/server/cityturn.c --- freeciv-2.1.99svn.patch_gold/server/cityturn.c 2009-01-04 22:08:54.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold_debug/server/cityturn.c 2009-01-04 22:08:03.000000000 +0100 @@ -428,7 +428,6 @@ int gold; gold=pplayer->economic.gold; pplayer->bulbs_last_turn = 0; - /* finances depend on the setting for 'game.info.economicsystem' * 0: finances are check for each city (old system; done in * update_city_activity()) @@ -440,7 +439,11 @@ if (game.info.economicsystem == 1 && pplayer->economic.gold < 0) { /* not enough gold - we have to sell something or even kill some * units (only with gold upkeep!) to get the gold */ + freelog(LOG_NORMAL,"[E:N] %d - %6d (balance:start)", + game.info.economicsystem, pplayer->economic.gold); balance_finances_nation(pplayer); + freelog(LOG_NORMAL,"[E:N] %d - %6d (balance:end)", + game.info.economicsystem, pplayer->economic.gold); } pplayer->ai.prev_gold = gold; @@ -1952,14 +1955,24 @@ update_tech(pplayer, pcity->prod[O_SCIENCE]); /* finances */ + freelog(LOG_NORMAL,"[E:C %s] %d - %6d (before)", city_name(pcity), + game.info.economicsystem, pplayer->economic.gold); pplayer->economic.gold += pcity->prod[O_GOLD]; + freelog(LOG_NORMAL,"[E:C %s] %d - %6d (prod)", city_name(pcity), + game.info.economicsystem, pplayer->economic.gold); pplayer->economic.gold -= pay_for_buildings(pcity); + freelog(LOG_NORMAL,"[E:C %s] %d - %6d (buildings)", city_name(pcity), + game.info.economicsystem, pplayer->economic.gold); pplayer->economic.gold -= pay_for_units(pcity); + freelog(LOG_NORMAL,"[E:C %s] %d - %6d (units)", city_name(pcity), + game.info.economicsystem, pplayer->economic.gold); if (game.info.economicsystem == 0 && pplayer->economic.gold < 0) { /* not enough gold - we have to sell something or even kill some * units (only with gold upkeep!) to get the gold */ balance_finances_city(pplayer, pcity); + freelog(LOG_NORMAL,"[E:C %s] %d - %6d (balance)", city_name(pcity), + game.info.economicsystem, pplayer->economic.gold); } if(city_unhappy(pcity)) {
diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/common/game.h freeciv-2.1.99svn.patch_gold/common/game.h --- freeciv-2.1.99svn.patch_shuffle/common/game.h 2008-12-30 23:29:33.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/common/game.h 2009-01-04 21:54:19.000000000 +0100 @@ -183,6 +183,10 @@ #define GAME_MIN_AIFILL 0 #define GAME_MAX_AIFILL GAME_MAX_MAX_PLAYERS +#define GAME_DEFAULT_ECONOMIC_SYSTEM 0 +#define GAME_MIN_ECONOMIC_SYSTEM 0 +#define GAME_MAX_ECONOMIC_SYSTEM 1 + #define GAME_DEFAULT_FOODBOX 100 #define GAME_MIN_FOODBOX 1 #define GAME_MAX_FOODBOX 10000 diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/common/packets.def freeciv-2.1.99svn.patch_gold/common/packets.def --- freeciv-2.1.99svn.patch_shuffle/common/packets.def 2008-12-30 23:29:33.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/common/packets.def 2009-01-04 21:22:01.000000000 +0100 @@ -389,6 +389,7 @@ UINT8 diplcost, freecost, conquercost; UINT8 angrycitizen; UINT8 techpenalty; + UINT8 economicsystem; UINT32 foodbox; UINT32 shieldbox; UINT32 sciencebox; diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/data/civ1/game.ruleset freeciv-2.1.99svn.patch_gold/data/civ1/game.ruleset --- freeciv-2.1.99svn.patch_shuffle/data/civ1/game.ruleset 2008-12-30 23:29:34.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/data/civ1/game.ruleset 2009-01-04 21:54:25.000000000 +0100 @@ -56,6 +56,17 @@ ; "Fallout" - Nuclear Fallout (distinct from industrial/population). nuke_contamination = "Pollution" +; Parameters used to describe the economic system +; 0: Gold upkeep for buildings and units has to be paid by the each city. +; If there is not enough gold, randomly chosen buildings of the city +; are sold. If there still is not enough gold, units of this city with +; gold upkeep are disbanded. (old system) +; 1: Gold upkeep for buildings and units comes from the overall finances. +; If there is not enough gold first randomly chosen buildings (taking +; into account _all_ cities) are sold, after that units with gold upkeep +; are disbanded. +economicsystem = 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 -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/data/civ2/game.ruleset freeciv-2.1.99svn.patch_gold/data/civ2/game.ruleset --- freeciv-2.1.99svn.patch_shuffle/data/civ2/game.ruleset 2008-12-30 23:29:34.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/data/civ2/game.ruleset 2009-01-04 21:54:28.000000000 +0100 @@ -50,6 +50,17 @@ ; "Fallout" - Nuclear Fallout (distinct from industrial/population). nuke_contamination = "Pollution" +; Parameters used to describe the economic system +; 0: Gold upkeep for buildings and units has to be paid by the each city. +; If there is not enough gold, randomly chosen buildings of the city +; are sold. If there still is not enough gold, units of this city with +; gold upkeep are disbanded. (old system) +; 1: Gold upkeep for buildings and units comes from the overall finances. +; If there is not enough gold first randomly chosen buildings (taking +; into account _all_ cities) are sold, after that units with gold upkeep +; are disbanded. +economicsystem = 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 -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/data/default/game.ruleset freeciv-2.1.99svn.patch_gold/data/default/game.ruleset --- freeciv-2.1.99svn.patch_shuffle/data/default/game.ruleset 2008-12-30 23:29:34.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/data/default/game.ruleset 2009-01-04 21:54:22.000000000 +0100 @@ -68,6 +68,17 @@ ; "Fallout" - Nuclear Fallout (distinct from industrial/population). nuke_contamination = "Fallout" +; Parameters used to describe the economic system +; 0: Gold upkeep for buildings and units has to be paid by the each city. +; If there is not enough gold, randomly chosen buildings of the city +; are sold. If there still is not enough gold, units of this city with +; gold upkeep are disbanded. (old system) +; 1: Gold upkeep for buildings and units comes from the overall finances. +; If there is not enough gold first randomly chosen buildings (taking +; into account _all_ cities) are sold, after that units with gold upkeep +; are disbanded. +economicsystem = 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 -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/server/cityturn.c freeciv-2.1.99svn.patch_gold/server/cityturn.c --- freeciv-2.1.99svn.patch_shuffle/server/cityturn.c 2008-12-25 19:45:49.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/server/cityturn.c 2009-01-04 22:08:54.000000000 +0100 @@ -82,7 +82,18 @@ 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); +static int pay_for_buildings(const struct city *pcity); +static bool sell_buildings(struct player *pplayer, + struct city_improve_list *pcity_improve_sell); +static void balance_finances_nation(struct player *pplayer); +static void balance_finances_city(struct player *pplayer, + struct city *pcity); + +static struct city_improve *create_city_improve(struct city *pcity, + struct impr_type *pimprove); +static void destroy_city_improve(struct city_improve *pcity_improve); +static void destroy_city_improve_list( + struct city_improve_list *pcity_improve_list); static bool disband_city(struct city *pcity); @@ -410,16 +421,28 @@ } /************************************************************************** -... + update all cities of one nation (costs for buildings, unit upkeep, ...) **************************************************************************/ void update_city_activities(struct player *pplayer) { int gold; gold=pplayer->economic.gold; pplayer->bulbs_last_turn = 0; + + /* finances depend on the setting for 'game.info.economicsystem' + * 0: finances are check for each city (old system; done in + * update_city_activity()) + * 1: finances are checked at the end (overall finances) */ city_list_iterate_safe(pplayer->cities, pcity) - update_city_activity(pplayer, pcity); + update_city_activity(pplayer, pcity); city_list_iterate_safe_end; + + if (game.info.economicsystem == 1 && pplayer->economic.gold < 0) { + /* not enough gold - we have to sell something or even kill some + * units (only with gold upkeep!) to get the gold */ + balance_finances_nation(pplayer); + } + pplayer->ai.prev_gold = gold; /* This test include the cost of the units because pay_for_units is called * in update_city_activity */ @@ -1559,24 +1582,178 @@ /************************************************************************** Pay for upkeep costs for all buildings, or sell them. **************************************************************************/ -static void pay_for_buildings(struct player *pplayer, struct city *pcity) +static int pay_for_buildings(const struct city *pcity) { + int gold_needed = 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; +} + +/************************************************************************** + sell buildings to get gold +**************************************************************************/ +static bool sell_buildings(struct player *pplayer, + struct city_improve_list *pcity_improve_sell) +{ + /* randomize the list */ + city_improve_list_shuffle(pcity_improve_sell); + + /* sell buildings from the list */ + city_improve_list_iterate(pcity_improve_sell, pcity_improve) { + if (can_city_sell_building(pcity_improve->pcity, + pcity_improve->pimprove)) { + notify_player(pplayer, city_tile(pcity_improve->pcity), + E_IMP_AUCTIONED, _("Can't afford to maintain %s in " + "%s, building sold!"), + improvement_name_translation(pcity_improve->pimprove), + city_name(pcity_improve->pcity)); + do_sell_building(pplayer, pcity_improve->pcity, + pcity_improve->pimprove); + city_refresh(pcity_improve->pcity); + + /* get the upkeep back */ + pplayer->economic.gold += + city_improvement_upkeep(pcity_improve->pcity, + pcity_improve->pimprove); + + if (pplayer->economic.gold >= 0) { + /* no debts left */ + return TRUE; + } + } + } city_improve_list_iterate_end; + + return FALSE; +} + +/************************************************************************** + balance the gold of a nation by selling some buildings. If this does not + help disband some units which need gold upkeep +**************************************************************************/ +static void balance_finances_nation(struct player *pplayer) +{ + struct city_improve_list *pcity_improve_sell; + pcity_improve_sell = city_improve_list_new(); + + struct unit_list *punit_sell; + punit_sell = unit_list_new(); + + city_list_iterate(pplayer->cities, pcity) { + /* create *a list of all buildings (pcity, pimprove) */ + city_built_iterate(pcity, pimprove) { + if (can_city_sell_building(pcity, pimprove)) { + struct city_improve *pcity_improve = fc_calloc(1, + sizeof(*pcity_improve)); + + pcity_improve->pcity = pcity; + pcity_improve->pimprove = pimprove; + + city_improve_list_append(pcity_improve_sell, pcity_improve); + } + } city_built_iterate_end; + + /* create a list of all units */ + unit_list_iterate(pcity->units_supported, punit) { + unit_list_append(punit_sell, punit); + } unit_list_iterate_end; + } city_list_iterate_end; + + /* try to sell some buildings */ + if (!sell_buildings(pplayer, pcity_improve_sell)) { + /* still not enough gold - disband units */ + sell_units(pplayer, punit_sell); + } + + /* free memory */ + destroy_city_improve_list(pcity_improve_sell); + city_improve_list_free(pcity_improve_sell); + unit_list_free(punit_sell); + + /* should never happen */ + assert(pplayer->economic.gold >= 0); +} + +/************************************************************************** + balance the gold of one city by selling some buildings. If this does not + help disband some units which need gold upkeep +**************************************************************************/ +static void balance_finances_city(struct player *pplayer, + struct city *pcity) +{ + struct city_improve_list *pcity_improve_sell; + pcity_improve_sell = city_improve_list_new(); + + struct unit_list *punit_sell; + punit_sell = unit_list_new(); + + /* create *a list of all buildings (pcity, pimprove) */ + city_built_iterate(pcity, pimprove) { + if (can_city_sell_building(pcity, pimprove)) { + struct city_improve *pcity_improve = create_city_improve(pcity, + pimprove); + city_improve_list_append(pcity_improve_sell, pcity_improve); } } city_built_iterate_end; + + /* create a list of all units */ + unit_list_iterate(pcity->units_supported, punit) { + unit_list_append(punit_sell, punit); + } unit_list_iterate_end; + + /* try to sell some buildings */ + if (!sell_buildings(pplayer, pcity_improve_sell)) { + /* still not enough gold - disband units */ + sell_units(pplayer, punit_sell); + } + + /* free memory */ + destroy_city_improve_list(pcity_improve_sell); + city_improve_list_free(pcity_improve_sell); + unit_list_free(punit_sell); + + /* should never happen */ + assert(pplayer->economic.gold >= 0); +} + +/************************************************************************** + create a struct city_improve +**************************************************************************/ +static struct city_improve *create_city_improve(struct city *pcity, + struct impr_type *pimprove) +{ + struct city_improve *pcity_improve = fc_calloc(1, + sizeof(*pcity_improve)); + + pcity_improve->pcity = pcity; + pcity_improve->pimprove = pimprove; + + return pcity_improve; +} + +/************************************************************************** + destroy a struct city_improve +**************************************************************************/ +static void destroy_city_improve(struct city_improve *pcity_improve) +{ + /* ensure no pointers remain */ + memset(pcity_improve, 0, sizeof(*pcity_improve)); + free(pcity_improve); +} + +/************************************************************************** + destroy all structs city_improve in the corresponding list +**************************************************************************/ +static void destroy_city_improve_list( + struct city_improve_list *pcity_improve_list) +{ + /* destroy all elements of the list */ + city_improve_list_iterate(pcity_improve_list, pcity_improve) { + destroy_city_improve(pcity_improve); + } city_improve_list_iterate_end; } /************************************************************************** @@ -1736,7 +1913,6 @@ static void update_city_activity(struct player *pplayer, struct city *pcity) { struct government *g = government_of_city(pcity); - int saved_id = pcity->id; city_refresh(pcity); @@ -1768,49 +1944,55 @@ return; } - pcity->is_updated=TRUE; + pcity->is_updated = TRUE; - pcity->did_sell=FALSE; + 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)); - } + + /* finances */ + pplayer->economic.gold += pcity->prod[O_GOLD]; + pplayer->economic.gold -= pay_for_buildings(pcity); + pplayer->economic.gold -= pay_for_units(pcity); + + if (game.info.economicsystem == 0 && pplayer->economic.gold < 0) { + /* not enough gold - we have to sell something or even kill some + * units (only with gold upkeep!) to get the gold */ + balance_finances_city(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 { - 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(g)); + handle_player_change_government(pplayer, government_number(g)); + } + sanity_check_city(pcity); } } diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/server/cityturn.h freeciv-2.1.99svn.patch_gold/server/cityturn.h --- freeciv-2.1.99svn.patch_shuffle/server/cityturn.h 2008-12-25 19:45:49.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/server/cityturn.h 2009-01-04 21:33:23.000000000 +0100 @@ -21,6 +21,17 @@ struct conn_list; struct cm_result; +/* (city, improvement) pairs */ +struct city_improve { + struct city *pcity; + struct impr_type *pimprove; +}; + +/* get 'struct city_improve_list' and related functions: */ +#define SPECLIST_TAG city_improve +#define SPECLIST_TYPE struct city_improve +#include "speclist.h" + void city_refresh(struct city *pcity); /* call if city has changed */ void city_refresh_for_player(struct player *pplayer); /* tax/govt changed */ @@ -46,4 +57,10 @@ void advisor_choose_build(struct player *pplayer, struct city *pcity); void nullify_prechange_production(struct city *pcity); + +#define city_improve_list_iterate(city_improve_list, _city_improve) \ + TYPED_LIST_ITERATE(struct city_improve, city_improve_list, \ + _city_improve) +#define city_improve_list_iterate_end LIST_ITERATE_END + #endif /* FC__CITYTURN_H */ diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/server/ruleset.c freeciv-2.1.99svn.patch_gold/server/ruleset.c --- freeciv-2.1.99svn.patch_shuffle/server/ruleset.c 2008-12-30 23:29:34.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/server/ruleset.c 2009-01-04 21:22:01.000000000 +0100 @@ -3016,6 +3016,17 @@ game.info.nuke_contamination = CONTAMINATION_POLLUTION; } + game.info.economicsystem + = secfile_lookup_int_default(&file, GAME_DEFAULT_ECONOMIC_SYSTEM, + "civstyle.economicsystem"); + if (game.info.economicsystem > GAME_MAX_ECONOMIC_SYSTEM + || game.info.economicsystem < GAME_MIN_ECONOMIC_SYSTEM) { + freelog(LOG_ERROR, "Bad value %d for economicsystem. Using default" + "value (%d).", game.info.economicsystem, + GAME_DEFAULT_ECONOMIC_SYSTEM); + game.info.economicsystem = GAME_DEFAULT_ECONOMIC_SYSTEM; + } + 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 -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/server/unittools.c freeciv-2.1.99svn.patch_gold/server/unittools.c --- freeciv-2.1.99svn.patch_shuffle/server/unittools.c 2008-12-25 19:45:49.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/server/unittools.c 2009-01-04 21:22:01.000000000 +0100 @@ -267,44 +267,62 @@ } /*************************************************************************** - Pay the cost of supported units of one city + get the gold needed to pay the cost to support the units of one city ***************************************************************************/ -void pay_for_units(struct player *pplayer, struct city *pcity) +int pay_for_units(const struct city *pcity) { - int potential_gold = 0; + int gold_needed = 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(pcity->units_supported, punit) { + int upkeep[O_COUNT]; + + city_unit_upkeep(punit, upkeep, free_upkeep); + gold_needed += upkeep[O_GOLD]; + } unit_list_iterate_end; + + return gold_needed; +} + +/************************************************************************** + sell units to save gold +**************************************************************************/ +bool sell_units(struct player *pplayer, struct unit_list *punit_sell) +{ + int free_upkeep[O_COUNT]; + + memset(free_upkeep, 0, O_COUNT * sizeof(*free_upkeep)); + + /* randomize the list */ + city_improve_list_shuffle(punit_sell); - unit_list_iterate_safe(pcity->units_supported, punit) { + unit_list_iterate_safe(punit_sell, 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. %s disbanded"), - unit_name_translation(punit)); + if (upkeep[O_GOLD] > 0) { + /* this unit needs gold - disband it */ + notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, + _("Not enough gold. %s 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]; + + /* get the gold back */ + pplayer->economic.gold += upkeep[O_GOLD]; + } + + if (pplayer->economic.gold >= 0) { + /* no debts left */ + return TRUE; } } unit_list_iterate_safe_end; + + return FALSE; } /*************************************************************************** diff -ur -X./freeciv-2.1.99svn15393/diff_ignore freeciv-2.1.99svn.patch_shuffle/server/unittools.h freeciv-2.1.99svn.patch_gold/server/unittools.h --- freeciv-2.1.99svn.patch_shuffle/server/unittools.h 2008-12-25 19:45:49.000000000 +0100 +++ freeciv-2.1.99svn.patch_gold/server/unittools.h 2009-01-04 21:22:01.000000000 +0100 @@ -50,7 +50,8 @@ 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); +int pay_for_units(const struct city *pcity); +bool sell_units(struct player *pplayer, struct unit_list *punit_sell); 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