[Freeciv-Dev] Re: (PR#13539) Fix AI tile effect miscalculation
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13539 >
On Mon, 25 Jul 2005, Jason Short wrote:
> I see the problem now.
Good :-)
> Since aicity hard-codes all the logic inside generic_city_refresh it
> will have to hard-code this too.But this shouldn't be a new function in
> city.c it should just go straight into aicity.c like all the other
> logic.
...
> Also I wouldn't assume that calling generic_city_refresh here will be
> substantially slower.
Calling full generic_city_refresh() will be substantially slower - I
tested this before originally writing this code (although things have
changed in city.c since then).
With some more pre-game analysis of the ruleset we can rule out tile
changes from most buildings, and take a different and faster code path.
Untested patch attached. Does this look better?
- Per
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.231
diff -u -r1.231 aicity.c
--- ai/aicity.c 22 Jul 2005 16:18:04 -0000 1.231
+++ ai/aicity.c 26 Jul 2005 10:38:16 -0000
@@ -132,15 +132,33 @@
}
/**************************************************************************
- Calculates city want from some input values.
+ Calculates city want from some input values. Set id to B_LAST if
+ nothing in the city has changed, and you just want to know the
+ base want of a city.
**************************************************************************/
static inline int city_want(struct player *pplayer, struct city *acity,
- struct ai_data *ai)
+ struct ai_data *ai, int id)
{
int want = 0, prod[O_COUNT], bonus[O_COUNT], waste[O_COUNT], i;
- /* The below calculation mostly duplicates set_city_production(). */
- get_citizen_output(acity, prod); /* this also clears prod[] */
+ if (id != B_LAST && ai->impr_calc[id] == AI_IMPR_CALCULATE_FULL) {
+ bool celebrating = base_city_celebrating(acity);
+
+ /* The below calculation mostly duplicates get_citizen_output().
+ * We do this only for buildings that we know may change tile
+ * outputs. */
+ city_map_checked_iterate(acity->tile, x, y, ptile) {
+ if (acity->city_map[x][y] == C_TILE_WORKER) {
+ output_type_iterate(o) {
+ prod[o] += base_city_get_output_tile(x, y, acity, celebrating, o);
+ } output_type_iterate_end;
+ }
+ } city_map_checked_iterate_end;
+ add_specialist_output(acity, prod);
+ } else {
+ memcpy(prod, acity->citizen_base, O_COUNT * sizeof(*prod));
+ }
+
for (i = 0; i < NUM_TRADEROUTES; i++) {
prod[O_TRADE] += acity->trade_value[i];
}
@@ -205,7 +223,7 @@
/* Stir, then compare notes */
city_range_iterate(pcity, pplayer->cities, ai->impr_range[id], acity) {
- final_want += city_want(pplayer, acity, ai) - acity->ai.worth;
+ final_want += city_want(pplayer, acity, ai, id) - acity->ai.worth;
} city_range_iterate_end;
/* Restore */
@@ -816,7 +834,7 @@
/* First find current worth of cities and cache this. */
city_list_iterate(pplayer->cities, acity) {
- acity->ai.worth = city_want(pplayer, acity, ai);
+ acity->ai.worth = city_want(pplayer, acity, ai, B_LAST);
} city_list_iterate_end;
impr_type_iterate(id) {
Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.74
diff -u -r1.74 aidata.c
--- ai/aidata.c 22 Jul 2005 16:18:04 -0000 1.74
+++ ai/aidata.c 26 Jul 2005 10:38:17 -0000
@@ -88,15 +88,27 @@
case EFT_POLLU_PROD_PCT:
case EFT_OUTPUT_BONUS:
case EFT_OUTPUT_BONUS_2:
+ case EFT_OUTPUT_WASTE_PCT:
+ case EFT_UPKEEP_FREE:
+ requirement_list_iterate(peffect->reqs, preq) {
+ if (preq->source.type == REQ_BUILDING
+ && preq->source.value.building == id) {
+ if (ai->impr_calc[id] != AI_IMPR_CALCULATE_FULL) {
+ ai->impr_calc[id] = AI_IMPR_CALCULATE;
+ }
+ if (preq->range > ai->impr_range[id]) {
+ ai->impr_range[id] = preq->range;
+ }
+ }
+ } requirement_list_iterate_end;
+ break;
case EFT_OUTPUT_ADD_TILE:
case EFT_OUTPUT_PER_TILE:
case EFT_OUTPUT_INC_TILE:
- case EFT_OUTPUT_WASTE_PCT:
- case EFT_UPKEEP_FREE:
requirement_list_iterate(peffect->reqs, preq) {
if (preq->source.type == REQ_BUILDING
&& preq->source.value.building == id) {
- ai->impr_calc[id] = AI_IMPR_CALCULATE;
+ ai->impr_calc[id] = AI_IMPR_CALCULATE_FULL;
if (preq->range > ai->impr_range[id]) {
ai->impr_range[id] = preq->range;
}
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.31
diff -u -r1.31 aidata.h
--- ai/aidata.h 21 Jul 2005 08:12:28 -0000 1.31
+++ ai/aidata.h 26 Jul 2005 10:38:17 -0000
@@ -29,6 +29,7 @@
enum ai_improvement_status {
AI_IMPR_CALCULATE, /* Calculate exactly its effect */
+ AI_IMPR_CALCULATE_FULL, /* Calculate including tile changes */
AI_IMPR_ESTIMATE, /* Estimate its effect using wild guesses */
AI_IMPR_LAST
};
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.359
diff -u -r1.359 city.c
--- common/city.c 25 Jul 2005 21:47:35 -0000 1.359
+++ common/city.c 26 Jul 2005 10:38:19 -0000
@@ -1557,8 +1557,7 @@
Calculate output (gold, science, and luxury) generated by the specialists
of a city. The output[] array is not cleared but is just added to.
****************************************************************************/
-static inline void add_specialist_output(const struct city *pcity,
- int *output)
+void add_specialist_output(const struct city *pcity, int *output)
{
specialist_type_iterate(sp) {
int count = pcity->specialists[sp];
@@ -1572,18 +1571,6 @@
}
/****************************************************************************
- Calculate the base output (all types) of all workers and specialists in
- the city. The output[] array is completely cleared in the process. This
- does not account for output transformations (like trade->(sci,gold,lux))
- or city bonuses (pcity->bonus[]).
-****************************************************************************/
-void get_citizen_output(const struct city *pcity, int *output)
-{
- get_worked_tile_output(pcity, output);
- add_specialist_output(pcity, output);
-}
-
-/****************************************************************************
This function sets all the values in the pcity->bonus[] array. This should
be called near the beginning of generic_city_refresh. It doesn't depend on
anything else in the refresh and doesn't change when workers are moved
@@ -2132,7 +2119,11 @@
set_city_tile_output(pcity); /* Calculate the tile_output[] values. */
city_support(pcity, send_unit_info); /* manage settlers, and units */
}
- get_citizen_output(pcity, pcity->citizen_base); /* Calculate output from
citizens. */
+
+ /* Calculate output from citizens. */
+ get_worked_tile_output(pcity, pcity->citizen_base);
+ add_specialist_output(pcity, pcity->citizen_base);
+
set_city_production(pcity);
citizen_base_mood(pplayer, city_specialists(pcity), &pcity->ppl_happy[0],
&pcity->ppl_content[0], &pcity->ppl_unhappy[0],
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.218
diff -u -r1.218 city.h
--- common/city.h 22 Jul 2005 16:18:05 -0000 1.218
+++ common/city.h 26 Jul 2005 10:38:20 -0000
@@ -352,6 +352,7 @@
const char *get_output_name(Output_type_id output);
struct output_type *get_output_type(Output_type_id output);
Output_type_id find_output_type_by_identifier(const char *id);
+void add_specialist_output(const struct city *pcity, int *output);
/* properties */
@@ -510,7 +511,6 @@
void city_styles_alloc(int num);
void city_styles_free(void);
-void get_citizen_output(const struct city *pcity, int *output);
void add_tax_income(const struct player *pplayer, int trade, int *output);
int get_city_tithes_bonus(const struct city *pcity);
int city_pollution_types(const struct city *pcity, int shield_total,
|
|