Complete.Org: Mailing Lists: Archives: freeciv-ai: January 2006:
[freeciv-ai] Re: [Freeciv-Dev] (PR#12682) AI Ignores Building Effects fo
Home

[freeciv-ai] Re: [Freeciv-Dev] (PR#12682) AI Ignores Building Effects fo

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [freeciv-ai] Re: [Freeciv-Dev] (PR#12682) AI Ignores Building Effects for Tech. Wants
From: "Benedict Adamson" <badamson@xxxxxxxxxxx>
Date: Fri, 20 Jan 2006 10:37:29 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This version of the patch includes amendments as a result of Per's comments.


diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/ai/aicity.c freeciv.PR12682/ai/aicity.c
--- vendor.freeciv.current/ai/aicity.c  2005-12-19 22:41:47.000000000 +0000
+++ freeciv.PR12682/ai/aicity.c 2006-01-20 13:08:12.000000000 +0000
@@ -25,6 +25,7 @@
 #include "fcintl.h"
 #include "game.h"
 #include "government.h"
+#include "improvement.h"
 #include "log.h"
 #include "map.h"
 #include "movement.h"
@@ -57,6 +58,14 @@
 
 #include "aicity.h"
 
+#define SPECVEC_TAG tech
+#define SPECVEC_TYPE Tech_type_id
+#include "specvec.h"
+
+#define SPECVEC_TAG impr
+#define SPECVEC_TYPE Impr_type_id
+#include "specvec.h"
+
 /* Iterate over cities within a certain range around a given city
  * (city_here) that exist within a given city list. */
 #define city_range_iterate(city_here, list, range, city)            \
@@ -240,33 +249,511 @@
 }
 
 /************************************************************************** 
-  Calculate effects. A few base variables:
+  Increase want for a technology because of the value of that technology
+  in providing an improvement effect.
+
+  The input building_want gives the desire for the improvement;
+  the value may be negative for technologies that produce undesirable
+  effects.
+
+  This function must convert from units of 'building want' to 'tech want'.
+  We put this conversion in a function because the 'want' scales are
+  unclear and kludged. Consequently, this conversion might require tweaking.
+**************************************************************************/
+static void want_tech_for_improvement_effect(struct player *pplayer,
+                                            const struct city *pcity,
+                                            const Impr_type_id id,
+                                            Tech_type_id tech,
+                                            int building_want)
+{
+  /* The conversion factor was determined by experiment,
+   * and might need adjustment.
+   */
+  const int tech_want = building_want * pcity->ai.recalc_interval * 14 / 8;
+#if 0
+  /* This logging is relatively expensive,
+   * so activate it only while necessary. */
+  TECH_LOG(LOG_DEBUG, pplayer, tech,
+    "wanted by %s for %s: %d -> %d",
+    pcity->name, get_improvement_name(id),
+    building_want, tech_want);
+#endif
+  pplayer->ai.tech_want[tech] += tech_want;
+}
+
+/************************************************************************** 
+  How desirable is a particular effect for a particular city?
+  Expressed as an adjustment of the base value (v)
+  given the number of cities in range (c).
+**************************************************************************/
+static int improvement_effect_value(struct player *pplayer,
+                                   struct government *gov,
+                                   const struct ai_data *ai,
+                                   const struct city *pcity,
+                                   const bool capital, 
+                                   const struct impr_type *pimpr,
+                                   const struct effect *peffect,
+                                   const int c,
+                                   const int nplayers,
+                                   int v)
+{
+  int amount = peffect->value;
+
+  switch (peffect->type) {
+  /* These (Wonder) effects have already been evaluated in base_want() */
+  case EFT_CAPITAL_CITY:
+  case EFT_UPKEEP_FREE:
+  case EFT_POLLU_POP_PCT:
+  case EFT_POLLU_PROD_PCT:
+  case EFT_OUTPUT_BONUS:
+  case EFT_OUTPUT_BONUS_2:
+  case EFT_OUTPUT_ADD_TILE:
+  case EFT_OUTPUT_INC_TILE:
+  case EFT_OUTPUT_PER_TILE:
+  case EFT_OUTPUT_WASTE:
+  case EFT_OUTPUT_WASTE_BY_DISTANCE:
+  case EFT_OUTPUT_WASTE_PCT:
+  case EFT_SPECIALIST_OUTPUT:
+    break;
+
+  case EFT_CITY_VISION_RADIUS_SQ:
+  case EFT_UNIT_VISION_RADIUS_SQ:
+    /* Wild guess.  "Amount" is the number of tiles (on average) that
+     * will be revealed by the effect.  Note that with an omniscient
+     * AI this effect is actually not useful at all. */
+    v += c * amount;
+    break;
+
+  case EFT_SLOW_DOWN_TIMELINE:
+    /* AI doesn't care about these. */
+    break;
+
+    /* WAG evaluated effects */
+  case EFT_INCITE_COST_PCT:
+    v += c * amount / 100;
+    break;
+  case EFT_MAKE_HAPPY:
+    v += (get_entertainers(pcity) + pcity->ppl_unhappy[4]) * 5 * amount;
+    if (city_list_size(pplayer->cities)
+       > game.info.cityfactor 
+       + get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD)) {
+      v += c * amount; /* offset large empire size */
+    }
+    v += c * amount;
+    break;
+  case EFT_UNIT_RECOVER:
+    /* TODO */
+    break;
+  case EFT_NO_UNHAPPY:
+    v += (get_entertainers(pcity) + pcity->ppl_unhappy[4]) * 30;
+    break;
+  case EFT_FORCE_CONTENT:
+  case EFT_MAKE_CONTENT:
+    if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
+      int factor = 2;
+
+      v += MIN(amount, pcity->ppl_unhappy[4] + get_entertainers(pcity)) * 35;
+
+      /* Try to build wonders to offset empire size unhappiness */
+      if (city_list_size(pplayer->cities) 
+         > game.info.cityfactor 
+         + get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD)) {
+       if (get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD) > 0) {
+         factor += city_list_size(pplayer->cities) 
+           / get_player_bonus(pplayer, EFT_EMPIRE_SIZE_STEP);
+       }
+       factor += 2;
+      }
+      v += factor * c * amount;
+    }
+    break;
+  case EFT_MAKE_CONTENT_MIL_PER:
+    if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
+      v += MIN(pcity->ppl_unhappy[4] + get_entertainers(pcity),
+              amount) * 25;
+      v += MIN(amount, 5) * c;
+    }
+    break;
+  case EFT_MAKE_CONTENT_MIL:
+    if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
+      v += pcity->ppl_unhappy[4] * amount
+        * MAX(unit_list_size(pcity->units_supported), 0) * 2;
+      v += c * MAX(amount + 2, 1);
+    }
+    break;
+  case EFT_TECH_PARASITE:
+    {
+      int turns;
+      int bulbs;
+      int value;
+         
+      if (nplayers <= amount) {
+       break;
+      }
+          
+      turns = 9999;
+      bulbs = 0;
+      players_iterate(aplayer) {
+       int potential = aplayer->bulbs_last_turn
+         + city_list_size(aplayer->cities) + 1;
+       if (tech_exists(pimpr->obsolete_by)) {
+         turns = MIN(turns, 
+                     total_bulbs_required_for_goal(aplayer, pimpr->obsolete_by)
+                     / (potential + 1));
+       }
+       if (players_on_same_team(aplayer, pplayer)) {
+         continue;
+       }
+       bulbs += potential;
+      } players_iterate_end;
+  
+      /* For some number of turns we will be receiving bulbs for free
+       * Bulbs should be amortized properly for each turn.
+       * We use formula for the sum of geometric series:
+       */
+      value = bulbs * (1.0 - pow(1.0 - (1.0 / MORT), turns)) * MORT;
+         
+      value = value  * (100 - game.info.freecost)        
+       * (nplayers - amount) / (nplayers * amount * 100);
+         
+      /* WAG */
+      value /= 3;
+
+      CITY_LOG(LOG_DEBUG, pcity,
+              "%s parasite effect: bulbs %d, turns %d, value %d", 
+              pimpr->name, bulbs, turns, value);
+       
+      v += value;
+      break;
+    }
+  case EFT_GROWTH_FOOD:
+    v += c * 4 + (amount / 7) * pcity->surplus[O_FOOD];
+    break;
+  case EFT_AIRLIFT:
+    /* FIXME: We need some smart algorithm here. The below is 
+     * totally braindead. */
+    v += c + MIN(ai->stats.units.land, 13);
+    break;
+  case EFT_ANY_GOVERNMENT:
+    if (!can_change_to_government(pplayer, ai->goal.govt.gov)) {
+      v += MIN(MIN(ai->goal.govt.val, 65),
+              num_unknown_techs_for_goal(pplayer, ai->goal.govt.req) * 10);
+    }
+    break;
+  case EFT_ENABLE_NUKE:
+    /* Treat nuke as a Cruise Missile upgrade */
+    v += 20 + ai->stats.units.missiles * 5;
+    break;
+  case EFT_ENABLE_SPACE:
+    if (game.info.spacerace) {
+      v += 5;
+      if (ai->diplomacy.production_leader == pplayer) {
+       v += 100;
+      }
+    }
+    break;
+  case EFT_GIVE_IMM_TECH:
+    if (!ai_wants_no_science(pplayer)) {
+      v += amount * (game.info.sciencebox + 1);
+    }
+    break;
+  case EFT_HAVE_EMBASSIES:
+    v += 5 * nplayers;
+    break;
+  case EFT_REVEAL_CITIES:
+  case EFT_NO_ANARCHY:
+    break;  /* Useless for AI */
+  case EFT_NO_SINK_DEEP:
+    v += 15 + ai->stats.units.triremes * 5;
+    break;
+  case EFT_NUKE_PROOF:
+    if (ai->threats.nuclear) {
+      v += pcity->size * unit_list_size(pcity->tile->units) * (capital + 1)
+       * amount / 100;
+    }
+    break;
+  case EFT_REVEAL_MAP:
+    if (!ai->explore.land_done || !ai->explore.sea_done) {
+      v += 10;
+    }
+    break;
+  case EFT_SIZE_UNLIMIT:
+    /* Note we look up the SIZE_UNLIMIT again right below.  This could
+     * be avoided... */
+    if (get_city_bonus(pcity, EFT_SIZE_UNLIMIT) == 0) {
+      amount = 20; /* really big city */
+    }
+    /* there not being a break here is deliberate, mind you */
+  case EFT_SIZE_ADJ:
+    if (get_city_bonus(pcity, EFT_SIZE_UNLIMIT) == 0) {
+      const int aqueduct_size = get_city_bonus(pcity, EFT_SIZE_ADJ);
+
+      if (!city_can_grow_to(pcity, pcity->size + 1)) {
+       v += pcity->surplus[O_FOOD] * ai->food_priority * amount;
+       if (pcity->size == aqueduct_size) {
+         v += 30 * pcity->surplus[O_FOOD];
+       }
+      }
+      v += c * amount * 4 / aqueduct_size;
+    }
+    break;
+  case EFT_SS_STRUCTURAL:
+  case EFT_SS_COMPONENT:
+  case EFT_SS_MODULE:
+    if (game.info.spacerace
+       /* If someone has started building spaceship already or
+        * we have chance to win a spacerace */
+       && (ai->diplomacy.spacerace_leader
+           || ai->diplomacy.production_leader == pplayer)) {
+      v += 95;
+    }
+    break;
+  case EFT_SPY_RESISTANT:
+    /* Uhm, problem: City Wall has -50% here!! */
+    break;
+  case EFT_MOVE_BONUS:
+    /* FIXME: check other reqs (e.g., unitclass) */
+    v += (8 * v * amount + ai->stats.units.land
+         + ai->stats.units.sea + ai->stats.units.air);
+    break;
+  case EFT_UNIT_NO_LOSE_POP:
+    v += unit_list_size(pcity->tile->units) * 2;
+    break;
+  case EFT_HP_REGEN:
+    /* FIXME: check other reqs (e.g., unitclass) */
+    v += (5 * c + ai->stats.units.land
+         + ai->stats.units.sea + ai->stats.units.air);
+    break;
+  case EFT_VETERAN_COMBAT:
+    /* FIXME: check other reqs (e.g., unitclass) */
+    v += (2 * c + ai->stats.units.land + ai->stats.units.sea
+         + ai->stats.units.air);
+    break;
+  case EFT_VETERAN_BUILD:
+    /* FIXME: check other reqs (e.g., unitclass, unitflag) */
+    v += (3 * c + ai->stats.units.land + ai->stats.units.sea
+         + ai->stats.units.air);
+    break;
+  case EFT_UPGRADE_UNIT:
+    v += ai->stats.units.upgradeable;
+    if (amount == 1) {
+      v *= 2;
+    } else if (amount == 2) {
+      v *= 3;
+    } else {
+      v *= 4;
+    }
+    break;
+  case EFT_DEFEND_BONUS:
+    if (ai_handicap(pplayer, H_DEFENSIVE)) {
+      v += amount / 10; /* make AI slow */
+    }
+    if (is_ocean(tile_get_terrain(pcity->tile))) {
+      v += ai->threats.ocean[-tile_get_continent(pcity->tile)]
+       ? amount/5 : amount/20;
+    } else {
+      adjc_iterate(pcity->tile, tile2) {
+       if (is_ocean(tile_get_terrain(tile2))) {
+         if (ai->threats.ocean[-tile_get_continent(tile2)]) {
+           v += amount/5;
+           break;
+         }
+       }
+      } adjc_iterate_end;
+    }
+    v += (amount/20 + ai->threats.invasions - 1) * c; /* for wonder */
+    if (ai->threats.continent[pcity->tile->continent]
+       || capital
+       || (ai->threats.invasions
+           && is_water_adjacent_to_tile(pcity->tile))) {
+      if (ai->threats.continent[pcity->tile->continent]) {
+       v += amount;
+      } else {
+       v += amount / (!ai->threats.igwall ? (15 - capital * 5) : 15);
+      }
+    }
+    break;
+  case EFT_NO_INCITE:
+    if (get_city_bonus(pcity, EFT_NO_INCITE) <= 0) {
+      v += MAX((game.info.diplchance * 2 
+               - game.info.incite_total_factor) / 2
+              - game.info.incite_improvement_factor * 5
+              - game.info.incite_unit_factor * 5, 0);
+    }
+    break;
+  case EFT_GAIN_AI_LOVE:
+    players_iterate(aplayer) {
+      if (aplayer->ai.control) {
+       if (ai_handicap(pplayer, H_DEFENSIVE)) {
+         v += amount / 10;
+       } else {
+         v += amount / 20;
+       }
+      }
+    } players_iterate_end;
+    break;
+  /* Currently not supported for building AI - wait for modpack users */
+  case EFT_UNHAPPY_FACTOR:
+  case EFT_UPKEEP_FACTOR:
+  case EFT_UNIT_UPKEEP_FREE_PER_CITY:
+  case EFT_CIVIL_WAR_CHANCE:
+  case EFT_EMPIRE_SIZE_MOD:
+  case EFT_EMPIRE_SIZE_STEP:
+  case EFT_MAX_RATES:
+  case EFT_MARTIAL_LAW_EACH:
+  case EFT_MARTIAL_LAW_MAX:
+  case EFT_RAPTURE_GROW:
+  case EFT_UNBRIBABLE_UNITS:
+  case EFT_REVOLUTION_WHEN_UNHAPPY:
+  case EFT_HAS_SENATE:
+  case EFT_INSPIRE_PARTISANS:
+  case EFT_HAPPINESS_TO_GOLD:
+  case EFT_FANATICS:
+  case EFT_NO_DIPLOMACY:
+  case EFT_OUTPUT_PENALTY_TILE:
+  case EFT_OUTPUT_INC_TILE_CELEBRATE:
+  case EFT_TRADE_REVENUE_BONUS:
+    break;
+  case EFT_LAST:
+    freelog(LOG_ERROR, "Bad effect type.");
+    break;
+  }
+
+  return v;
+}
+
+/************************************************************************** 
+  Increase the degree to which we want to meet a set of requirements,
+  because they will enable construction of an improvement
+  with desirable effects.
+
+  v is the desire for the improvement.
+
+  Returns whether all the requirements are met.
+**************************************************************************/
+static bool adjust_wants_for_reqs(struct player *pplayer,
+                                  struct city *pcity, 
+                                  struct impr_type *pimpr,
+                                  const int v)
+{
+  bool all_met = TRUE;
+  int n_needed_techs = 0;
+  int n_needed_improvements = 0;
+  struct tech_vector needed_techs;
+  struct impr_vector needed_improvements;
+
+  tech_vector_init(&needed_techs);
+  impr_vector_init(&needed_improvements);
+
+  requirement_vector_iterate(&pimpr->reqs, preq) {
+    const bool active = is_req_active(pplayer, pcity, pimpr,
+                                      NULL, NULL, NULL, NULL, preq);
+    if (preq->source.type == REQ_TECH && !active) {
+      /* Found a missing technology requirement for this improvement. */
+      tech_vector_append(&needed_techs, &preq->source.value.tech);
+    } else if (preq->source.type == REQ_BUILDING && !active) {
+      /* Found a missing improvement requirement for this improvement.
+       * For example, in the default ruleset a city must have a Library
+       * before it can have a University. */
+      impr_vector_append(&needed_improvements, &preq->source.value.building);
+    }
+    all_met = all_met && active;
+  } requirement_vector_iterate_end;
+
+  /* If v is negative, the improvement is not worth building,
+   * but there is no need to punish research of the technologies
+   * that would make it available.
+   */
+  n_needed_techs = tech_vector_size(&needed_techs);
+  if (0 < v && 0 < n_needed_techs) {
+    /* Because we want this improvements,
+     * we want the techs that will make it possible */
+    const int dv = v / n_needed_techs;
+    int t;
+
+    for (t = 0; t < n_needed_techs; t++) {
+      want_tech_for_improvement_effect(pplayer, pcity, pimpr->index,
+                                       *tech_vector_get(&needed_techs, t), dv);
+    }
+  }
+
+  /* If v is negative, the improvement is not worth building,
+   * but there is no need to punish building the improvements
+   * that would make it available.
+   */
+  n_needed_improvements = impr_vector_size(&needed_improvements);
+  if (0 < v && 0 < n_needed_improvements) {
+    /* Because we want this improvement,
+     * we want the improvements that will make it possible */
+    const int dv = v / (n_needed_improvements * 4); /* WAG */
+    int i;
+
+    for (i = 0; i < n_needed_improvements; i++) {
+      struct impr_type *needed_impr = get_improvement_type(
+                                        *impr_vector_get(&needed_improvements,
+                                                         i));
+      /* TODO: increase the want for the needed_impr,
+       * if we can build it now */
+      /* Recurse */
+      (void)adjust_wants_for_reqs(pplayer, pcity, needed_impr, dv);
+    }
+  }
+
+  /* TODO: use a similar method to increase wants for governments
+   * that will make this improvement possible? */
+
+  tech_vector_free(&needed_techs);
+  impr_vector_free(&needed_improvements);
+
+  return all_met;
+}
+
+/************************************************************************** 
+  Calculate effects of possible improvements and extra effects of existing
+  improvements. Consequently adjust the desirability of those improvements
+  or the technologies that would make them possible.
+
+  This function may (indeed, should) be called even for improvements that a 
city
+  already has, or can not (yet) build. For existing improvements,
+  it will discourage research of technologies that would make the improvement
+  obsolete or reduce its effectiveness, and encourages technologies that would
+  improve its effectiveness. For improvements that the city can not yet build
+  it will encourage research of the techs and building of the improvements
+  that will make the improvement possible.
+
+  A complexity is that there are two sets of requirements to consider:
+  the requirements for the building itself, and the requirements for
+  the effects for the building.
+
+  A few base variables:
     c - number of cities we have in current range
     u - units we have of currently affected type
     v - the want for the improvement we are considering
 
   This function contains a whole lot of WAGs. We ignore cond_* for now,
-  thinking that one day we may fulfill the cond_s anyway. In general, we
+  thinking that one day we may fulfil the cond_s anyway. In general, we
   first add bonus for city improvements, then for wonders.
 
   IDEA: Calculate per-continent aggregates of various data, and use this
   for wonders below for better wonder placements.
 **************************************************************************/
-static void adjust_building_want_by_effects(struct city *pcity, 
-                                            Impr_type_id id)
+static void adjust_wants_by_effects1(struct player *pplayer,
+                                     struct city *pcity, 
+                                     struct impr_type *pimpr,
+                                     const bool already)
 {
-  struct player *pplayer = city_owner(pcity);
-  struct impr_type *pimpr = get_improvement_type(id);
   int v = 0;
   int cities[REQ_RANGE_LAST];
   int nplayers = game.info.nplayers - game.info.nbarbarians;
   struct ai_data *ai = ai_data_get(pplayer);
-  struct tile *ptile = pcity->tile;
   bool capital = is_capital(pcity);
+  bool can_build = TRUE;
+  struct government *gov = get_gov_pplayer(pplayer);
   struct req_source source = {
     .type = REQ_BUILDING,
-    .value = {.building = id}
+    .value = {.building = pimpr->index}
   };
+  const bool is_coinage = impr_flag(pimpr->index, IF_GOLD);
 
   /* Remove team members from the equation */
   players_iterate(aplayer) {
@@ -277,409 +764,157 @@
     }
   } players_iterate_end;
 
-  if (impr_flag(id, IF_GOLD)) {
+  if (is_coinage) {
     /* Since coinage contains some entirely spurious ruleset values,
-     * we need to return here with some spurious want. */
-    pcity->ai.building_want[id] = TRADE_WEIGHTING;
-    return;
+     * we need to hard-code a sensible want.
+     * We must otherwise handle the special IF_GOLD improvement
+     * like the others, so the AI will research techs that make it available,
+     * for rulesets that do not provide it from the start.
+     */
+    v += TRADE_WEIGHTING;
+  } else {
+    /* Base want is calculated above using a more direct approach. */
+    v += base_want(pplayer, pcity, pimpr->index);
+    if (v != 0) {
+      CITY_LOG(LOG_DEBUG, pcity, "%s base_want is %d (range=%d)", 
+               pimpr->name, v, ai->impr_range[pimpr->index]);
+    }
   }
 
-  /* Base want is calculated above using a more direct approach. */
-  v += base_want(pplayer, pcity, id);
-  if (v != 0) {
-    CITY_LOG(LOG_DEBUG, pcity, "%s base_want is %d (range=%d)", 
-             get_improvement_name(id), v, ai->impr_range[id]);
+  if (!is_coinage) {
+    /* Adjust by building cost */
+    /* FIXME: ought to reduce by upkeep cost and amortise by building cost */
+    v -= (impr_build_shield_cost(pimpr->index)
+         / (pcity->surplus[O_SHIELD] * 10 + 1));
   }
 
   /* Find number of cities per range.  */
   cities[REQ_RANGE_PLAYER] = city_list_size(pplayer->cities);
   cities[REQ_RANGE_WORLD] = cities[REQ_RANGE_PLAYER]; /* kludge. */
 
-  cities[REQ_RANGE_CONTINENT] = ai->stats.cities[ptile->continent];
+  cities[REQ_RANGE_CONTINENT] = ai->stats.cities[pcity->tile->continent];
 
   cities[REQ_RANGE_CITY] = 1;
   cities[REQ_RANGE_LOCAL] = 0;
 
   effect_list_iterate(get_req_source_effects(&source), peffect) {
-    struct requirement *mypreq;
-    bool useful;
+    struct requirement *mypreq = NULL;
+    bool active = TRUE;
+    int n_needed_techs = 0;
+    struct tech_vector needed_techs;
 
     if (is_effect_disabled(pplayer, pcity, pimpr,
                           NULL, NULL, NULL, NULL,
                           peffect)) {
-      CITY_LOG(LOG_DEBUG, pcity, "%s has a disabled effect: %s", 
-               get_improvement_name(id), effect_type_name(peffect->type));
       continue;
     }
 
-    mypreq = NULL;
-    useful = TRUE;
+    tech_vector_init(&needed_techs);
+
     requirement_list_iterate(peffect->reqs, preq) {
       /* Check if all the requirements for the currently evaluated effect
        * are met, except for having the building that we are evaluating. */
       if (preq->source.type == REQ_BUILDING
-         && preq->source.value.building == id) {
+         && preq->source.value.building == pimpr->index) {
        mypreq = preq;
         continue;
       }
       if (!is_req_active(pplayer, pcity, pimpr, NULL, NULL, NULL, NULL,
                         preq)) {
-       useful = FALSE;
-       break;
+       active = FALSE;
+       if (preq->source.type == REQ_TECH) {
+         /* This missing requirement is a missing tech requirement.
+          * This will be for some additional effect
+          * (For example, in the default ruleset, Mysticism increases
+          * the effect of Temples). */
+          tech_vector_append(&needed_techs, &preq->source.value.tech);
+       }
       }
     } requirement_list_iterate_end;
 
-    if (useful) {
-      int amount = peffect->value, c = cities[mypreq->range];
-
-      switch (peffect->type) {
-      /* These have already been evaluated in base_want() */
-      case EFT_CAPITAL_CITY:
-      case EFT_UPKEEP_FREE:
-      case EFT_POLLU_POP_PCT:
-      case EFT_POLLU_PROD_PCT:
-      case EFT_OUTPUT_BONUS:
-      case EFT_OUTPUT_BONUS_2:
-      case EFT_OUTPUT_ADD_TILE:
-      case EFT_OUTPUT_INC_TILE:
-      case EFT_OUTPUT_PER_TILE:
-      case EFT_OUTPUT_WASTE:
-      case EFT_OUTPUT_WASTE_BY_DISTANCE:
-      case EFT_OUTPUT_WASTE_PCT:
-      case EFT_SPECIALIST_OUTPUT:
-         break;
-
-      case EFT_CITY_VISION_RADIUS_SQ:
-      case EFT_UNIT_VISION_RADIUS_SQ:
-       /* Wild guess.  "Amount" is the number of tiles (on average) that
-        * will be revealed by the effect.  Note that with an omniscient
-        * AI this effect is actually not useful at all. */
-       v += c * amount;
-       break;
-
-      case EFT_SLOW_DOWN_TIMELINE:
-       /* AI doesn't care about these. */
-       break;
-
-       /* WAG evaluated effects */
-       case EFT_INCITE_COST_PCT:
-         v += c * amount / 100;
-         break;
-       case EFT_MAKE_HAPPY:
-         v += (get_entertainers(pcity) + pcity->ppl_unhappy[4]) * 5 * amount;
-          if (city_list_size(pplayer->cities)
-                > game.info.cityfactor 
-                  + get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD)) {
-            v += c * amount; /* offset large empire size */
-          }
-          v += c * amount;
-         break;
-       case EFT_UNIT_RECOVER:
-         /* TODO */
-         break;
-       case EFT_NO_UNHAPPY:
-         v += (get_entertainers(pcity) + pcity->ppl_unhappy[4]) * 30;
-         break;
-       case EFT_FORCE_CONTENT:
-       case EFT_MAKE_CONTENT:
-         if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
-            int factor = 2;
-
-           v += MIN(amount, pcity->ppl_unhappy[4] + get_entertainers(pcity)) * 
35;
-
-            /* Try to build wonders to offset empire size unhappiness */
-            if (city_list_size(pplayer->cities) 
-                > game.info.cityfactor 
-                  + get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD)) {
-              if (get_player_bonus(pplayer, EFT_EMPIRE_SIZE_MOD) > 0) {
-                factor += city_list_size(pplayer->cities) 
-                          / get_player_bonus(pplayer, EFT_EMPIRE_SIZE_STEP);
-              }
-              factor += 2;
-            }
-           v += factor * c * amount;
-         }
-         break;
-       case EFT_MAKE_CONTENT_MIL_PER:
-          if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
-           v += MIN(pcity->ppl_unhappy[4] + get_entertainers(pcity),
-                    amount) * 25;
-           v += MIN(amount, 5) * c;
-         }
-         break;
-       case EFT_MAKE_CONTENT_MIL:
-          if (get_city_bonus(pcity, EFT_NO_UNHAPPY) <= 0) {
-           v += pcity->ppl_unhappy[4] * amount
-             * MAX(unit_list_size(pcity->units_supported), 0) * 2;
-           v += c * MAX(amount + 2, 1);
-         }
-         break;
-       case EFT_TECH_PARASITE:
-       {
-         int turns;
-         int bulbs;
-         int value;
-         
-         if (nplayers <= amount) {
-           break;
-         }
-          
-         turns = 9999;
-         bulbs = 0;
-         players_iterate(aplayer) {
-           int potential = aplayer->bulbs_last_turn
-                           + city_list_size(aplayer->cities) + 1;
-           if (tech_exists(pimpr->obsolete_by)) {
-             turns = MIN(turns, 
-               total_bulbs_required_for_goal(aplayer, pimpr->obsolete_by)
-               / (potential + 1));
-           }
-           if (players_on_same_team(aplayer, pplayer)) {
-             continue;
-           }
-           bulbs += potential;
-         } players_iterate_end;
-  
-         /* For some number of turns we will be receiving bulbs for free
-          * Bulbs should be amortized properly for each turn.
-          * We use formula for the sum of geometric series:
-          */
-         value = bulbs * (1.0 - pow(1.0 - (1.0 / MORT), turns)) * MORT;
-         
-         value = value  * (100 - game.info.freecost)     
-                 * (nplayers - amount) / (nplayers * amount * 100);
-         
-         /* WAG */
-         value /= 3;
-
-          CITY_LOG(LOG_DEBUG, pcity,
-                  "%s parasite effect: bulbs %d, turns %d, value %d", 
-                   get_improvement_name(id), bulbs, turns, value);
-       
-         v += value;
-         break;
+    n_needed_techs = tech_vector_size(&needed_techs);
+    if (active || n_needed_techs) {
+      const int v1 = improvement_effect_value(pplayer, gov, ai,
+                                             pcity, capital, 
+                                             pimpr, peffect,
+                                             cities[mypreq->range],
+                                             nplayers, v);
+      /* v1 could be negative (the effect could be undesirable),
+       * although it is usually positive.
+       * For example, in the default ruleset, Communism decreases the
+       * effectiveness of a Cathedral. */
+
+      if (active) {
+       v = v1;
+      } else { /* n_needed_techs */
+       /* We might want the technology that will enable this
+        * (additional) effect.
+        * The better the effect, the more we want the technology.
+        * Use (v1 - v) rather than v1 in case there are multiple
+        * effects that have technology requirements and to eliminate the
+        * 'base' effect of the building.
+         * We are more interested in (additional) effects that enhance
+        * buildings we already have.
+        */
+        const int a = already? 5: 4; /* WAG */
+        const int dv = (v1 - v) * a / (4 * n_needed_techs);
+       int t;
+       for (t = 0; t < n_needed_techs; t++) {
+         want_tech_for_improvement_effect(pplayer, pcity, pimpr->index,
+                                           *tech_vector_get(&needed_techs, t),
+                                           dv);
        }
-       case EFT_GROWTH_FOOD:
-         v += c * 4 + (amount / 7) * pcity->surplus[O_FOOD];
-         break;
-       case EFT_AIRLIFT:
-         /* FIXME: We need some smart algorithm here. The below is 
-          * totally braindead. */
-         v += c + MIN(ai->stats.units.land, 13);
-         break;
-       case EFT_ANY_GOVERNMENT:
-         if (!can_change_to_government(pplayer, ai->goal.govt.gov)) {
-           v += MIN(MIN(ai->goal.govt.val, 65),
-               num_unknown_techs_for_goal(pplayer, ai->goal.govt.req) * 10);
-         }
-         break;
-       case EFT_ENABLE_NUKE:
-         /* Treat nuke as a Cruise Missile upgrade */
-         v += 20 + ai->stats.units.missiles * 5;
-         break;
-       case EFT_ENABLE_SPACE:
-         if (game.info.spacerace) {
-           v += 5;
-           if (ai->diplomacy.production_leader == pplayer) {
-             v += 100;
-           }
-         }
-         break;
-       case EFT_GIVE_IMM_TECH:
-         if (!ai_wants_no_science(pplayer)) {
-           v += amount * (game.info.sciencebox + 1);
-          }
-         break;
-       case EFT_HAVE_EMBASSIES:
-         v += 5 * nplayers;
-         break;
-       case EFT_REVEAL_CITIES:
-       case EFT_NO_ANARCHY:
-         break;  /* Useless for AI */
-       case EFT_NO_SINK_DEEP:
-         v += 15 + ai->stats.units.triremes * 5;
-         break;
-       case EFT_NUKE_PROOF:
-         if (ai->threats.nuclear) {
-           v += pcity->size * unit_list_size(ptile->units) * (capital + 1)
-                * amount / 100;
-         }
-         break;
-       case EFT_REVEAL_MAP:
-         if (!ai->explore.land_done || !ai->explore.sea_done) {
-           v += 10;
-         }
-         break;
-       case EFT_SIZE_UNLIMIT:
-         /* Note we look up the SIZE_UNLIMIT again right below.  This could
-          * be avoided... */
-         if (get_city_bonus(pcity, EFT_SIZE_UNLIMIT) == 0) {
-           amount = 20; /* really big city */
-         }
-         /* there not being a break here is deliberate, mind you */
-       case EFT_SIZE_ADJ:
-         if (get_city_bonus(pcity, EFT_SIZE_UNLIMIT) == 0) {
-           const int aqueduct_size = get_city_bonus(pcity, EFT_SIZE_ADJ);
-
-           if (!city_can_grow_to(pcity, pcity->size + 1)) {
-             v += pcity->surplus[O_FOOD] * ai->food_priority * amount;
-             if (pcity->size == aqueduct_size) {
-               v += 30 * pcity->surplus[O_FOOD];
-             }
-           }
-           v += c * amount * 4 / aqueduct_size;
-         }
-         break;
-       case EFT_SS_STRUCTURAL:
-       case EFT_SS_COMPONENT:
-       case EFT_SS_MODULE:
-         if (game.info.spacerace
-             /* If someone has started building spaceship already or
-              * we have chance to win a spacerace */
-             && (ai->diplomacy.spacerace_leader
-                 || ai->diplomacy.production_leader == pplayer)) {
-           v += 95;
-         }
-         break;
-       case EFT_SPY_RESISTANT:
-         /* Uhm, problem: City Wall has -50% here!! */
-         break;
-       case EFT_MOVE_BONUS:
-         /* FIXME: check other reqs (e.g., unitclass) */
-         v += (8 * v * amount + ai->stats.units.land
-               + ai->stats.units.sea + ai->stats.units.air);
-         break;
-       case EFT_UNIT_NO_LOSE_POP:
-         v += unit_list_size(ptile->units) * 2;
-         break;
-       case EFT_HP_REGEN:
-         /* FIXME: check other reqs (e.g., unitclass) */
-         v += (5 * c + ai->stats.units.land
-               + ai->stats.units.sea + ai->stats.units.air);
-         break;
-       case EFT_VETERAN_COMBAT:
-         /* FIXME: check other reqs (e.g., unitclass) */
-         v += (2 * c + ai->stats.units.land + ai->stats.units.sea
-               + ai->stats.units.air);
-         break;
-       case EFT_VETERAN_BUILD:
-         /* FIXME: check other reqs (e.g., unitclass, unitflag) */
-         v += (3 * c + ai->stats.units.land + ai->stats.units.sea
-               + ai->stats.units.air);
-         break;
-       case EFT_UPGRADE_UNIT:
-         v += ai->stats.units.upgradeable;
-         if (amount == 1) {
-           v *= 2;
-         } else if (amount == 2) {
-           v *= 3;
-         } else {
-           v *= 4;
-         }
-         break;
-       case EFT_DEFEND_BONUS:
-         if (ai_handicap(pplayer, H_DEFENSIVE)) {
-           v += amount / 10; /* make AI slow */
-         }
-         if (is_ocean(tile_get_terrain(pcity->tile))) {
-           v += ai->threats.ocean[-tile_get_continent(pcity->tile)]
-                ? amount/5 : amount/20;
-         } else {
-           adjc_iterate(pcity->tile, tile2) {
-             if (is_ocean(tile_get_terrain(tile2))) {
-               if (ai->threats.ocean[-tile_get_continent(tile2)]) {
-                 v += amount/5;
-                 break;
-               }
-             }
-           } adjc_iterate_end;
-         }
-         v += (amount/20 + ai->threats.invasions - 1) * c; /* for wonder */
-         if (ai->threats.continent[ptile->continent]
-             || capital
-             || (ai->threats.invasions
-                 && is_water_adjacent_to_tile(pcity->tile))) {
-           if (ai->threats.continent[ptile->continent]) {
-             v += amount;
-           } else {
-             v += amount / (!ai->threats.igwall ? (15 - capital * 5) : 15);
-           }
-         }
-         break;
-       case EFT_NO_INCITE:
-         if (get_city_bonus(pcity, EFT_NO_INCITE) <= 0) {
-           v += MAX((game.info.diplchance * 2 
-                      - game.info.incite_total_factor) / 2
-               - game.info.incite_improvement_factor * 5
-               - game.info.incite_unit_factor * 5, 0);
-         }
-         break;
-       case EFT_GAIN_AI_LOVE:
-         players_iterate(aplayer) {
-           if (aplayer->ai.control) {
-             if (ai_handicap(pplayer, H_DEFENSIVE)) {
-               v += amount / 10;
-             } else {
-               v += amount / 20;
-             }
-           }
-         } players_iterate_end;
-         break;
-        /* Currently not supported for building AI - wait for modpack users */
-        case EFT_UNHAPPY_FACTOR:
-        case EFT_UPKEEP_FACTOR:
-        case EFT_UNIT_UPKEEP_FREE_PER_CITY:
-        case EFT_CIVIL_WAR_CHANCE:
-        case EFT_EMPIRE_SIZE_MOD:
-        case EFT_EMPIRE_SIZE_STEP:
-        case EFT_MAX_RATES:
-        case EFT_MARTIAL_LAW_EACH:
-        case EFT_MARTIAL_LAW_MAX:
-        case EFT_RAPTURE_GROW:
-        case EFT_UNBRIBABLE_UNITS:
-        case EFT_REVOLUTION_WHEN_UNHAPPY:
-        case EFT_HAS_SENATE:
-        case EFT_INSPIRE_PARTISANS:
-        case EFT_HAPPINESS_TO_GOLD:
-        case EFT_FANATICS:
-        case EFT_NO_DIPLOMACY:
-        case EFT_OUTPUT_PENALTY_TILE:
-        case EFT_OUTPUT_INC_TILE_CELEBRATE:
-       case EFT_TRADE_REVENUE_BONUS:
-          break;
-       case EFT_LAST:
-         freelog(LOG_ERROR, "Bad effect type.");
-         break;
       }
     }
-  } effect_list_iterate_end;
-
-  /* Reduce want if building gets obsoleted soon */
-  if (tech_exists(pimpr->obsolete_by)) {
-    v -= v / MAX(1, num_unknown_techs_for_goal(pplayer, pimpr->obsolete_by));
-  }
 
-  /* Adjust by building cost */
-  v -= (impr_build_shield_cost(pimpr->index)
-       / (pcity->surplus[O_SHIELD] * 10 + 1));
+    tech_vector_free(&needed_techs);
+  } effect_list_iterate_end;
 
-  /* Would it mean losing shields? */
-  if ((pcity->production.is_unit 
-       || (is_wonder(pcity->production.value) 
-           && !is_wonder(id))
-       || (!is_wonder(pcity->production.value)
-           && is_wonder(id)))
-      && pcity->turn_last_built != game.info.turn) {
-    v -= (pcity->shield_stock / 2) * (SHIELD_WEIGHTING / 2);
-  }
+  if (already && tech_exists(pimpr->obsolete_by)) {
+    /* Discourage research of the technology that would make this building
+     * obsolete. The bigger the desire for this building, the more
+     * we want to discourage the technology. */
+    want_tech_for_improvement_effect(pplayer, pcity, pimpr->index,
+                                    pimpr->obsolete_by, -v);
+  } else if (!already) {
+    /* Increase the want for technologies that will enable
+     * construction of this improvement, if necessary.
+     */
+    const bool all_met = adjust_wants_for_reqs(pplayer, pcity, pimpr, v);
+    can_build = can_build && all_met;
+  }
+
+  if (is_coinage && can_build) {
+    /* Could have a negative want for coinage,
+     * if we have some stock in a building already. */
+    pcity->ai.building_want[pimpr->index] += v;
+  } else if (!already && can_build) {
+    /* Convert the base 'want' into a building want
+     * by applying various adjustments */
+
+    /* Would it mean losing shields? */
+    if ((pcity->production.is_unit 
+         || (is_wonder(pcity->production.value) && !is_wonder(pimpr->index))
+          || (!is_wonder(pcity->production.value) && is_wonder(pimpr->index)))
+        && pcity->turn_last_built != game.info.turn) {
+      v -= (pcity->shield_stock / 2) * (SHIELD_WEIGHTING / 2);
+    }
+
+    /* Reduce want if building gets obsoleted soon */
+    if (tech_exists(pimpr->obsolete_by)) {
+      v -= v / MAX(1, num_unknown_techs_for_goal(pplayer, pimpr->obsolete_by));
+    }
+
+    /* Are we wonder city? Try to avoid building non-wonders very much. */
+    if (pcity->id == ai->wonder_city && !is_wonder(pimpr->index)) {
+      v /= 5;
+    }
 
-  /* Are we wonder city? Try to avoid building non-wonders very much. */
-  if (pcity->id == ai->wonder_city && !is_wonder(id)) {
-    v /= 5;
+    /* Set */
+    pcity->ai.building_want[pimpr->index] += v;
   }
-
-  /* Set */
-  pcity->ai.building_want[id] = v;
+  /* Else we either have the improvement already,
+   * or we can not build it (yet) */
 }
 
 /**************************************************************************
@@ -794,6 +1029,106 @@
 }
 
 /************************************************************************** 
+  Whether the AI should calculate the building wants for this city
+  this turn, ahead of schedule.
+
+  Always recalculate if the city just finished building,
+  so we can make a sensible choice for the next thing to build.
+  Perhaps the improvement we were building has become obsolete,
+  or a different player built the Great Wonder we were building.
+**************************************************************************/
+static bool should_force_recalc(struct city *pcity)
+{
+  return city_built_last_turn(pcity) ||
+        (!pcity->production.is_unit
+         && !impr_flag(pcity->production.value, IF_GOLD)
+         && !can_eventually_build_improvement(pcity, pcity->production.value));
+}
+
+/************************************************************************** 
+  Calculate how much an AI player should want to build particular
+  improvements, because of the effects of those improvements, and
+  increase the want for technologies that will enable buildings with
+  desirable effects.
+**************************************************************************/
+static void adjust_wants_by_effects(struct player *pplayer,
+                                    struct city *wonder_city)
+{
+  /* Clear old building wants.
+   * Do this separately from the iteration over improvement types
+   * because each iteration could actually update more than one improvement,
+   * if improvements have improvements as requirements.
+   */
+  city_list_iterate(pplayer->cities, pcity) {
+    if (pplayer->ai.control && pcity->ai.next_recalc <= game.info.turn) {
+      /* Do a scheduled recalculation this turn */
+      impr_type_iterate(id) {
+        pcity->ai.building_want[id] = 0;
+      } impr_type_iterate_end;
+    } else if (pplayer->ai.control && should_force_recalc(pcity)) {
+      /* Do an emergency recalculation this turn. */
+      pcity->ai.recalc_interval = pcity->ai.next_recalc - game.info.turn;
+      pcity->ai.next_recalc = game.info.turn;
+
+      impr_type_iterate(id) {
+        pcity->ai.building_want[id] = 0;
+      } impr_type_iterate_end;
+    }
+  } city_list_iterate_end;
+
+  impr_type_iterate(id) {
+    /* Handle coinage specially because you can never complete coinage */
+    const bool is_coinage = impr_flag(id, IF_GOLD);
+    if (is_coinage || can_player_eventually_build_improvement(pplayer, id)) {
+      const bool is_wonder_impr = is_wonder(id);
+      struct impr_type *pimpr = get_improvement_type(id);
+
+      city_list_iterate(pplayer->cities, pcity) {
+        if (pcity != wonder_city && is_wonder_impr) {
+          /* Only wonder city should build wonders! */
+          pcity->ai.building_want[id] = 0;
+        } else if ((!is_coinage
+                    && !can_eventually_build_improvement(pcity, id))
+                   || is_building_replaced(pcity, id)) {
+          /* Don't consider impossible or redundant buildings */
+          pcity->ai.building_want[id] = 0;
+        } else if (pplayer->ai.control
+                   && pcity->ai.next_recalc <= game.info.turn) {
+          /* Building wants vary relatively slowly, so not worthwhile
+           * recalculating them every turn.
+           * We DO want to calculate (tech) wants because of buildings
+           * we already have. */
+          const bool already = city_got_building(pcity, id);
+
+          adjust_wants_by_effects1(pplayer, pcity, pimpr, already);
+
+          assert(!(already && 0 < pcity->ai.building_want[id]));
+        } else if (city_got_building(pcity, id)) {
+          /* Never want to build something we already have. */
+          pcity->ai.building_want[id] = 0;
+        }
+        /* else wait until a later turn */
+      } city_list_iterate_end;
+    } else {
+      /* An impossible improvement */
+      city_list_iterate(pplayer->cities, pcity) {
+        pcity->ai.building_want[id] = 0;
+      } city_list_iterate_end;
+    }
+  } impr_type_iterate_end;
+
+#if 0
+  /* This logging is relatively expensive, so activate only if necessary */
+  city_list_iterate(pplayer->cities, pcity) {
+    impr_type_iterate(id) {
+      CITY_LOG(LOG_DEBUG, pcity, "want to build %s with %d", 
+               get_improvement_name(id), pcity->ai.building_want[id]);
+    } impr_type_iterate_end;
+  } city_list_iterate_end;
+#endif
+}
+
+/************************************************************************** 
   Prime pcity->ai.building_want[]
 **************************************************************************/
 void ai_manage_buildings(struct player *pplayer)
@@ -872,39 +1207,15 @@
     acity->ai.worth = city_want(pplayer, acity, ai, B_LAST);
   } city_list_iterate_end;
 
-  impr_type_iterate(id) {
-    if (!can_player_build_improvement(pplayer, id)
-        || improvement_obsolete(pplayer, id)) {
-      continue;
-    }
-    city_list_iterate(pplayer->cities, pcity) {
-      if (pcity != wonder_city && is_wonder(id)) {
-        /* Only wonder city should build wonders! */
-        continue;
-      }
-      if (pplayer->ai.control && pcity->ai.next_recalc > game.info.turn) {
-        continue; /* do not recalc yet */
-      } else {
-        pcity->ai.building_want[id] = 0; /* do recalc */
-      }
-      if (city_got_building(pcity, id)
-          || !can_build_improvement(pcity, id)
-          || is_building_replaced(pcity, id)) {
-        continue; /* Don't build redundant buildings */
-      }
-      adjust_building_want_by_effects(pcity, id);
-      CITY_LOG(LOG_DEBUG, pcity, "want to build %s with %d", 
-               get_improvement_name(id), pcity->ai.building_want[id]);
-    } city_list_iterate_end;
-  } impr_type_iterate_end;
+  adjust_wants_by_effects(pplayer, wonder_city);
 
   /* Reset recalc counter */
   city_list_iterate(pplayer->cities, pcity) {
     if (pcity->ai.next_recalc <= game.info.turn) {
       /* This will spread recalcs out so that no one turn end is 
        * much longer than others */
-      pcity->ai.next_recalc = game.info.turn + myrand(RECALC_SPEED) 
-                              + RECALC_SPEED;
+      pcity->ai.recalc_interval = myrand(RECALC_SPEED) + RECALC_SPEED;
+      pcity->ai.next_recalc = game.info.turn + pcity->ai.recalc_interval;
     }
   } city_list_iterate_end;
 }
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/common/city.c freeciv.PR12682/common/city.c
--- vendor.freeciv.current/common/city.c        2005-12-19 22:41:45.000000000 
+0000
+++ freeciv.PR12682/common/city.c       2006-01-20 13:08:10.000000000 +0000
@@ -2439,6 +2439,7 @@
   pcity->ai.invasion = 0;
   pcity->ai.bcost = 0;
   pcity->ai.attack = 0;
+  pcity->ai.recalc_interval = 1;
   pcity->ai.next_recalc = 0;
 
   memset(pcity->surplus, 0, O_COUNT * sizeof(*pcity->surplus));
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/common/city.h freeciv.PR12682/common/city.h
--- vendor.freeciv.current/common/city.h        2005-12-19 22:41:45.000000000 
+0000
+++ freeciv.PR12682/common/city.h       2006-01-20 13:08:10.000000000 +0000
@@ -160,7 +160,11 @@
 
 struct ai_city {
   /* building desirabilities - easiest to handle them here -- Syela */
-  int building_want[B_LAST];    /* not sure these will always be < 256 */
+  /* The units of building_want are output
+   * (shields/gold/luxuries) multiplied by a priority
+   * (SHIELD_WEIGHTING, etc or ai->shields_priority, etc)
+   */
+  int building_want[B_LAST];
 
   unsigned int danger;          /* danger to be compared to assess_defense */
   bool diplomat_threat;         /* enemy diplomat or spy is near the city */
@@ -194,7 +198,9 @@
                       * all units coming to kill us. */
 
   int worth; /* Cache city worth here, sum of all weighted incomes */
-  int next_recalc; /* Only recalc every Nth turn */
+  /* Only recalc every Nth turn: */
+  int recalc_interval; /* Use for weighting values calculated every Nth turn */
+  int next_recalc;
 };
 
 struct city {
diff -ruN -Xvendor.freeciv.current/diff_ignore 
vendor.freeciv.current/common/player.h freeciv.PR12682/common/player.h
--- vendor.freeciv.current/common/player.h      2005-12-19 22:41:45.000000000 
+0000
+++ freeciv.PR12682/common/player.h     2006-01-20 13:08:11.000000000 +0000
@@ -100,6 +100,7 @@
   int prev_gold;
   int maxbuycost;
   int est_upkeep; /* estimated upkeep of buildings in cities */
+  /* The units of tech_want seem to be shields */
   int tech_want[A_LAST+1];
   int handicap;                        /* sum of enum handicap_type */
   int skill_level;             /* 0-10 value for save/load/display */

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