<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40759 >
version 3:
* remove city_unit_upkeep(); the functionality is provided by
calc_city_units_upkeep()
* additional simplification (common/city.c:city_support)
not tested at all - only something that I checked before going to sleep ...
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//client/packhand.c freeciv-2.1.99svn15584.gold1//client/packhand.c
--- freeciv-2.1.99svn15584.gold//client/packhand.c 2009-04-13 20:57:13.610498460 +0200
+++ freeciv-2.1.99svn15584.gold1//client/packhand.c 2009-04-13 21:56:00.166499236 +0200
@@ -1195,7 +1195,7 @@
bool check_focus = FALSE; /* conservative focus change */
bool moved = FALSE;
bool ret = FALSE;
-
+
punit = player_find_unit_by_id(unit_owner(packet_unit), packet_unit->id);
if (!punit && game_find_unit_by_number(packet_unit->id)) {
/* This means unit has changed owner. We deal with this here
@@ -1406,6 +1406,10 @@
}
}
+ /* update unit upkeep */
+ output_type_iterate(o) {
+ punit->upkeep[o] = packet_unit->upkeep[o];
+ } output_type_iterate_end;
punit->veteran = packet_unit->veteran;
punit->moves_left = packet_unit->moves_left;
punit->fuel = packet_unit->fuel;
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/city.c freeciv-2.1.99svn15584.gold1//common/city.c
--- freeciv-2.1.99svn15584.gold//common/city.c 2009-04-13 20:57:03.182498213 +0200
+++ freeciv-2.1.99svn15584.gold1//common/city.c 2009-04-13 22:45:38.730498560 +0200
@@ -2152,50 +2152,14 @@
}
/**************************************************************************
- Calculate upkeep of a given unit.
-**************************************************************************/
-void city_unit_upkeep(struct unit *punit, int *outputs, int *free_upkeep)
-{
- struct unit_type *ut = unit_type(punit);
- struct player *plr = unit_owner(punit);
-
- assert(punit != NULL && ut != NULL
- && free_upkeep != NULL && outputs != NULL);
- memset(outputs, 0, O_COUNT * sizeof(*outputs));
-
- /* set current upkeep on unit to zero */
-
- output_type_iterate(o) {
- int cost = utype_upkeep_cost(ut, plr, o);
- if (cost > 0) {
- if (free_upkeep[o] > cost) {
- free_upkeep[o] -= cost;
- cost = 0;
- } else {
- cost -= free_upkeep[o];
- free_upkeep[o] = 0;
- }
- outputs[o] = cost;
- }
- } output_type_iterate_end;
-}
-
-/**************************************************************************
Calculate upkeep costs. This builds the pcity->usage[] array as well
as setting some happiness values.
**************************************************************************/
static inline void city_support(struct city *pcity)
{
- int free_upkeep[O_COUNT];
int free_unhappy = get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL);
- output_type_iterate(o) {
- free_upkeep[o] = get_city_output_bonus(pcity, get_output_type(o),
- EFT_UNIT_UPKEEP_FREE_PER_CITY);
- } output_type_iterate_end;
-
/* Clear all usage values. */
- memset(pcity->usage, 0, O_COUNT * sizeof(*pcity->usage));
pcity->martial_law = 0;
pcity->unit_happy_upkeep = 0;
@@ -2222,13 +2186,10 @@
}
unit_list_iterate(pcity->units_supported, this_unit) {
- int upkeep_cost[O_COUNT];
int happy_cost = city_unit_unhappiness(this_unit, &free_unhappy);
- city_unit_upkeep(this_unit, upkeep_cost, free_upkeep);
-
output_type_iterate(o) {
- pcity->usage[o] += upkeep_cost[o];
+ pcity->usage[o] += punit->upkeep[o];
} output_type_iterate_end;
pcity->unit_happy_upkeep += happy_cost;
} unit_list_iterate_end;
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/city.h freeciv-2.1.99svn15584.gold1//common/city.h
--- freeciv-2.1.99svn15584.gold//common/city.h 2009-04-13 20:57:03.186497822 +0200
+++ freeciv-2.1.99svn15584.gold1//common/city.h 2009-04-13 22:45:38.730498560 +0200
@@ -472,7 +472,6 @@
int city_population(const struct city *pcity);
int city_unit_unhappiness(struct unit *punit, int *free_happy);
-void city_unit_upkeep(struct unit *punit, int *outputs, int *free_upkeep);
bool city_happy(const struct city *pcity); /* generally use celebrating instead */
bool city_unhappy(const struct city *pcity); /* anarchy??? */
bool base_city_celebrating(const struct city *pcity);
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/fc_types.h freeciv-2.1.99svn15584.gold1//common/fc_types.h
--- freeciv-2.1.99svn15584.gold//common/fc_types.h 2009-04-13 20:57:03.206498100 +0200
+++ freeciv-2.1.99svn15584.gold1//common/fc_types.h 2009-04-13 21:04:48.062498776 +0200
@@ -75,6 +75,7 @@
enum output_type_id {
O_FOOD, O_SHIELD, O_TRADE, O_GOLD, O_LUXURY, O_SCIENCE, O_LAST
};
+/* num_output_types = O_LAST; see common/city.c */
#define O_COUNT num_output_types
#define O_MAX O_LAST /* Changing this breaks network compatibility. */
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/packets.def freeciv-2.1.99svn15584.gold1//common/packets.def
--- freeciv-2.1.99svn15584.gold//common/packets.def 2009-04-13 20:57:29.806502033 +0200
+++ freeciv-2.1.99svn15584.gold1//common/packets.def 2009-04-13 21:04:48.062498776 +0200
@@ -747,6 +747,7 @@
PLAYER owner;
COORD x,y;
CITY homecity;
+ UINT16 upkeep[O_MAX];
UINT8 veteran;
BOOL ai, paradropped;
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/unit.c freeciv-2.1.99svn15584.gold1//common/unit.c
--- freeciv-2.1.99svn15584.gold//common/unit.c 2009-04-13 20:57:03.158498606 +0200
+++ freeciv-2.1.99svn15584.gold1//common/unit.c 2009-04-13 21:04:48.066498664 +0200
@@ -34,7 +34,6 @@
#include "unit.h"
#include "unitlist.h"
-
/**************************************************************************
bribe unit
investigate
@@ -1373,6 +1372,8 @@
punit->tile = NULL;
punit->homecity = IDENTITY_NUMBER_ZERO;
}
+ /* upkeep will be set each turn within the cityturn loop */
+ memset(punit->upkeep, 0, O_LAST * sizeof(*punit->upkeep));
punit->goto_tile = NULL;
punit->veteran = veteran_level;
/* A unit new and fresh ... */
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//common/unit.h freeciv-2.1.99svn15584.gold1//common/unit.h
--- freeciv-2.1.99svn15584.gold//common/unit.h 2009-04-13 20:57:03.166497823 +0200
+++ freeciv-2.1.99svn15584.gold1//common/unit.h 2009-04-11 12:39:05.000000000 +0200
@@ -142,6 +142,7 @@
struct player *owner; /* Cannot be NULL. */
int id;
int homecity;
+ int upkeep[O_LAST]; /* unit upkeep with regards to the homecity */
int moves_left;
int hp;
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//server/cityturn.c freeciv-2.1.99svn15584.gold1//server/cityturn.c
--- freeciv-2.1.99svn15584.gold//server/cityturn.c 2009-04-13 20:57:29.810498568 +0200
+++ freeciv-2.1.99svn15584.gold1//server/cityturn.c 2009-04-13 22:45:38.734498176 +0200
@@ -93,10 +93,10 @@
#define SPECVEC_TYPE struct cityimpr
#include "specvec.h"
-/* Helper struct for storing a unit with its gold upkeep. */
+/* Helper struct for storing all units with gold upkeep.
+ * Replace this by unit_list? - MaPfa */
struct unitgold {
struct unit *punit;
- int gold_upkeep;
};
#define SPECVEC_TAG unitgold
@@ -501,6 +501,48 @@
}
/**************************************************************************
+ Update upkeep needed for all units supported by the city
+**************************************************************************/
+void calc_city_units_upkeep(const struct city *pcity)
+{
+ int free[O_LAST], upkeep[O_LAST], cost;
+ struct unit_type *ut;
+ struct player *plr;
+
+ if (!pcity || !pcity->units_supported
+ || unit_list_size(pcity->units_supported) < 1) {
+ return;
+ }
+
+ memset(free, 0, O_COUNT * sizeof(*free));
+ output_type_iterate(o) {
+ free[o] = get_city_output_bonus(pcity, get_output_type(o),
+ EFT_UNIT_UPKEEP_FREE_PER_CITY);
+ } output_type_iterate_end;
+
+ /* save the upkeep for all units in the corresponding punit struct */
+ unit_list_iterate(pcity->units_supported, punit) {
+ unit_type *ut = unit_type(punit);
+ player *plr = unit_owner(punit);
+
+ output_type_iterate(o) {
+ cost = utype_upkeep_cost(ut, plr, o);
+ if (cost > 0) {
+ if (free[o] > cost) {
+ free[o] -= cost;
+ cost = 0;
+ } else {
+ cost -= free[o];
+ free[o] = 0;
+ }
+ }
+
+ punit->upkeep[o] = cost;
+ } output_type_iterate_end;
+ } unit_list_iterate_end;
+}
+
+/**************************************************************************
Reduce the city specialists by some (positive) value.
Return the amount of reduction.
**************************************************************************/
@@ -1649,20 +1691,14 @@
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];
+ gold_needed += punit->upkeep[O_GOLD];
} unit_list_iterate_end;
return gold_needed;
@@ -1734,7 +1770,7 @@
while (pplayer->economic.gold < 0 && n > 0) {
r = myrand(n);
punit = units->p[r].punit;
- gold_upkeep = units->p[r].gold_upkeep;
+ gold_upkeep = punit->upkeep[O_GOLD];
notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
_("Not enough gold. %s disbanded"),
@@ -1760,7 +1796,6 @@
struct cityimpr ci;
struct unitgold_vector units;
struct unitgold ug;
- int free[O_COUNT], upkeep[O_COUNT];
if (!pplayer) {
return;
@@ -1783,16 +1818,10 @@
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) {
+ if (punit->upkeep[O_GOLD] > 0) {
ug.punit = punit;
- ug.gold_upkeep = upkeep[O_GOLD];
unitgold_vector_append(&units, &ug);
}
} unit_list_iterate_end;
@@ -1826,7 +1855,6 @@
struct cityimpr ci;
struct unitgold_vector units;
struct unitgold ug;
- int free[O_COUNT], upkeep[O_COUNT];
if (!pcity) {
return;
@@ -1850,16 +1878,10 @@
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) {
+ if (punit->upkeep[O_GOLD] > 0) {
ug.punit = punit;
- ug.gold_upkeep = upkeep[O_GOLD];
unitgold_vector_append(&units, &ug);
}
} unit_list_iterate_end;
@@ -2043,6 +2065,9 @@
pplayer = city_owner(pcity);
gov = government_of_city(pcity);
+ /* update upkeep of suported units */
+ calc_city_units_upkeep(pcity);
+
city_refresh(pcity);
/* Reporting of celebrations rewritten, copying the treatment of disorder below,
Only in freeciv-2.1.99svn15584.gold1//server: cityturn.c.orig
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//server/cityturn.h freeciv-2.1.99svn15584.gold1//server/cityturn.h
--- freeciv-2.1.99svn15584.gold//server/cityturn.h 2009-04-13 20:57:06.042496918 +0200
+++ freeciv-2.1.99svn15584.gold1//server/cityturn.h 2009-04-13 21:18:54.270500838 +0200
@@ -48,5 +48,6 @@
void nullify_prechange_production(struct city *pcity);
void check_city_migrations(struct player *pplayer);
+void calc_city_units_upkeep(const struct city *pcity);
#endif /* FC__CITYTURN_H */
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//server/diplomats.c freeciv-2.1.99svn15584.gold1//server/diplomats.c
--- freeciv-2.1.99svn15584.gold//server/diplomats.c 2009-04-13 20:57:06.054496582 +0200
+++ freeciv-2.1.99svn15584.gold1//server/diplomats.c 2009-04-13 21:45:15.390499956 +0200
@@ -472,6 +472,16 @@
/* This may cause a diplomatic incident */
maybe_cause_incident(DIPLOMAT_BRIBE, pplayer, pvictim, NULL);
+ /* update unit upkeep in the homecity of the victim */
+ if (pvictim->homecity > 0) {
+ /* update unit upkeep */
+ calc_city_units_upkeep(game_find_city_by_number(pvictim->homecity));
+ }
+ /* update unit upkeep in the new homecity */
+ if (pvictim->homecity > 0) {
+ calc_city_units_upkeep(game_find_city_by_number(gained_unit->homecity));
+ }
+
/* Be sure to wipe the converted unit! */
victim_tile = pvictim->tile;
wipe_unit(pvictim);
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//server/unithand.c freeciv-2.1.99svn15584.gold1//server/unithand.c
--- freeciv-2.1.99svn15584.gold//server/unithand.c 2009-04-13 20:57:06.062496638 +0200
+++ freeciv-2.1.99svn15584.gold1//server/unithand.c 2009-04-13 21:32:55.838497178 +0200
@@ -398,11 +398,16 @@
if (old_pcity) {
/* Even if unit is dead, we have to unlink unit pointer (punit). */
unit_list_unlink(old_pcity->units_supported, punit);
+ /* update unit upkeep */
+ calc_city_units_upkeep(old_pcity);
}
if (unit_alive) {
unit_list_prepend(new_pcity->units_supported, punit);
+ /* update unit upkeep */
+ calc_city_units_upkeep(new_pcity);
+
punit->homecity = new_pcity->id;
send_unit_info(unit_owner(punit), punit);
}
diff '--exclude=*svn*' -ur freeciv-2.1.99svn15584.gold//server/unittools.c freeciv-2.1.99svn15584.gold1//server/unittools.c
--- freeciv-2.1.99svn15584.gold//server/unittools.c 2009-04-13 20:57:29.822498512 +0200
+++ freeciv-2.1.99svn15584.gold1//server/unittools.c 2009-04-13 21:52:01.498495489 +0200
@@ -1338,6 +1338,9 @@
- game.info.upgrade_veteran_loss, 0);
}
+ /* update unit upkeep */
+ calc_city_units_upkeep(game_find_city_by_number(punit->homecity));
+
conn_list_do_buffer(pplayer->connections);
unit_refresh_vision(punit);
@@ -1382,6 +1385,8 @@
punit->homecity = 0; /* none */
} else {
punit->homecity = homecity_id;
+ /* update unit upkeep */
+ calc_city_units_upkeep(game_find_city_by_number(homecity_id));
}
if (hp_left >= 0) {
@@ -1579,6 +1584,9 @@
server_remove_unit(punit);
}
+ /* update unit upkeep */
+ calc_city_units_upkeep(game_find_city_by_number(punit->homecity));
+
/* Finally reassign, bounce, or destroy all units that cannot exist at this
* location without transport. */
if (drowning) {
@@ -1827,6 +1835,9 @@
packet->x = punit->tile->x;
packet->y = punit->tile->y;
packet->homecity = punit->homecity;
+ output_type_iterate(o) {
+ packet->upkeep[o] = punit->upkeep[o];
+ } output_type_iterate_end;
packet->veteran = punit->veteran;
packet->type = utype_number(unit_type(punit));
packet->movesleft = punit->moves_left;
_______________________________________________
Freeciv-dev mailing list
[email protected]
https://mail.gna.org/listinfo/freeciv-dev