Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2005:
[Freeciv-Dev] Re: (PR#13539) Fix AI tile effect miscalculation
Home

[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]
To: jdorje@xxxxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#13539) Fix AI tile effect miscalculation
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Tue, 26 Jul 2005 03:40:37 -0700
Reply-to: bugs@xxxxxxxxxxx

<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,

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