Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] (PR#9961) Re: effects
Home

[Freeciv-Dev] (PR#9961) Re: effects

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9961) Re: effects
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 5 Sep 2004 18:15:19 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=9961 >

Mike Kaufman wrote:

> in find_source_building() why do you check for !is_wonder(*pbldg) ?
> I think this is wrong. I should look for non-wonder buildings first, but after
> that search the wonders. This shouldn't cost much.

Maybe.  The problem is this is really an AI function, it just has to be 
in effects.c because it accesses static data.  I renamed it 
ai_find_source_building (nobody else should use it!) and left it at that.

> "Returns the number buildings of a certain type in a continent"
> s/in/on/

Yes.

> rename targets_in_range()

I renamed it to count_targets_in_range.  But I don't think that's 
exactly what it does?

> I can stand no longer. in eff_redundant():
> s/group that exists wins/group that exists takes precedence/
> same for the comments in the rulesets.

OK.  But I found no such comments in the rulesets.

> The comment for eff_reqs_active() should read:
> "Check the requirements for the effect to see if it is active."

OK.

> in the comment of eff_eventually_active() 
> s/deps/reqs/

OK.

> rename eff_eventually_active() to is_eff_active_for_target()?
> maybe, in any case 'eventually' needs to be removed as it communicates
> future time rather than lack of range check.

I renamed it as is_effect_useful().

> rename eff_active() -> is_eff_active()

OK.  I also booleanized some other boolean functions.

> in get_effect_value(), rename the parameter 'eff' to 'type' or something.

effect_type

> eff_redundant(), eff_reqs_active(), eff_eventually_active() and 
> eff_active() rename parameter 'id' to 'building' as you did in
> targets_in_range()

I also renamed "eff" as "peffect".  And added explanations of the 
parameters.

> in aicity.c:adjust_building_want_by_effects(), 
>   cities[EFR_LAST] is cached in ai_data. Use that instead.
> 
> in aicity.c:108
> add a comment there saying something like: iterate over each
>           effect for the building type, etc
> 
> in the header to ai_manage_buildings() a TODO: RECALC_SPEED should be
>           configurable to ai difficulty
> 
> aicity.c:893
> -       && i != B_CITY /* selling city walls is really, really dumb -- Syela 
> */
> -       && (wonder_replacement(pcity, i) || 
> building_unwanted(city_owner(pcity), i))) {
> +       && !building_has_effect(i, EFT_LAND_DEFEND)
> +             /* selling city walls is really, really dumb -- Syela */
> +       && (building_replaced(pcity, i)
> +        || building_unwanted(city_owner(pcity), i))) {
> 
> don't like this. If it's obsolete, then it has no effect and never will.
> $$ is better. Are there other assumptions (or lack thereof) made here?

AI stuff: I didn't touch this.  But Per changed a lot of the AI code so 
they may be obsolete.

> city.c:can_build_improvement() 
> The comment is wrong. We aren't talking about units here.

Fixed.

> can_build_improvement() and can_eventually_build_improvement() return FALSE
> rather than 0. Change comment

No doubt a holdover from before we had booleans.

> can_build_improvement_direct(), can_build_improvement(), 
> can_eventually_build_improvement() should be in improvement.c

Probably, but the effect patch doesn't need to move it.

> in improvement_upkeep()
> 
>   if (improvement_types[i].upkeep <= 
>       get_city_bonus(pcity, EFT_UPKEEP_FREE))
> 
> can go on one line.

No it can't.  It's one character too long ;-).

> city.c:563
> the government comment here makes less sense now.

Rewritten (it still mentions government).

> base_get_shields_tile():
>  get_city_tile_bonus(pcity, ptile, EFT_PROD_PER_TILE); is missing.

Yep.  I also moved EFT_FOOD_PER_TILE in get_city_food_bonus so it 
follows the sames tructure as the other two (previously FOOD_PER_TILE 
was applied earlier).

> city.c:set_pollution(). This is wrong.

How so?

If you have recycling center and hydro/hoover/nuclear, you only get /5 
to your pollution instead of /6.  This is hard or impossible to fix, and 
probably isn't a big deal.

I did make a minor fix in case EFT_POLLU_POP_PCT was > 100%.  We don't 
want mod to be negative in that case.

> city.c:2516
>    pcity->luxury_bonus = 100;
>    pcity->tax_bonus = 100;
> +  pcity->luxury_bonus = 100;
>    pcity->science_bonus = 100;
> redundant

Yes.  There's another duplicate luxury calc below that I also removed.

> combat.c:305,306, indent properly

OK.

> game.c:372 initialize spaceshipparts in the declaration

This code has changed; the complaint is obsolete.

> improvement.c:130 this is dangerous. what happens if the building has 
> multiple effects. This must be noted in the documentation.

I wrote about it in README.effects. (In fact the space parts weren't 
documented here at all since I changed them.)

> improvement.c:556
> s/N.B. Unlike effects, we do not have/N.B. We do not need/

Sure...

> improvement.h: why do you have stuff aboe the #includes?

Removed.

> player.c:407 README.effects needs to note that a "value" for this effect
> does nothing (or alter this to reflect what it _does_ say in README.effects
> which would be better)

Modified README.effects.  I agree that the value should be made a 
percentage.  But I didn't do this.

> unit.c:57 line wrapping...

I couldn't find anything.

> rulesets: "eff" should be replaced by "name"

I agree.  Done.

> there needs to to commentary for the effect groups.

Vasco, can you make some?

> Also, what happens if I put a -2 instead of 4 for Size_Adj. Correct behavior?

I assume it reduces the max size of the city.  This is correct.  In SMAC 
one of the nations has this effect.

> I'm not happy that you make *_Defend a multiplier rather than a percentage.
> That's too coarse-grained.

I agree.  Done (but I didn't edit the ai code).

> ditto for Growth Food

Also done.  This was just a little uglier.  Someone should check the logic.

> ditto for Pollu_Prod_Pct, which makes even less sense considering the name.
> review all Pollu_Prod_Pct.

I didn't change this one.  I think it needs to be renamed.

We can't make it a percentage.  Recycle reduces pollution by 66% and 
clean power by 50%.  But these don't combine to 116% as they would if we 
made it a "normal" percentage.

The way it is now recycle gets a value of 2 and clean power a value of 
5.  Each of them works fine individually.  But if you combine them 
you'll get /= 5 instead of /= 6.  Not too big a problem.

> The mass_transit number for Pollu_Pop_Pct is incongruous.

100%?  Why?

> is this intentional:
> -       "Unit_Vet_Combat", "Player", 100, "Land"
> +    { "eff", "range", "value"
> +      "Land_Veteran", "Player"
> +      "Land_Regen", "Player"
> +      "Land_Vet_Combat", "Player", 50

I removed Land_Regen from Sun Tzu's in history/default/civ2 rulesets. 
It seems to be clearly wrong.

The logic for Land_Vet_Combat seems to be a bit backwards.  I think the 
Land_Vet_Combat value is correct for the current rules.  But the value 
in civ2 ruleset was wrong.

> citytools.c:642
>   pcity->improvements[game.palace_building] = I_NONE;
>                                            ^ ^

ok...

> cityturn.c:310 probably should be: 
> get_current_construction_bonus(pcity, EFT_GROWTH_FOOD) >= 100

The check is

        && get_current_construction_bonus(pcity, EFT_GROWTH_FOOD) > 0

which I think is correct.  If we are building granary (bonus=50) then we 
(may) want to throttle.

> cityturn.c:443 should be:
>   } else if (find_source_building(powner, EFT_SIZE_ADJ)
>              || find_source_building(powner, EFT_SIZE_UNLIMIT)) {
>       notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQUEDUCT,
>                        _("Game: %s needs an improvement to grow any 
> further."),
>                        pcity->name);
>   } else {
>       notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQUEDUCT,
>                        _("Game: %s can grow no further."), pcity->name);
>   }

This code shouldn't use find_source_building.  It does need to be better 
before we can have fully generalized rulesets.  But it should be okay 
for now.  Note that [ai_]find_source_building doesn't return a boolean 
so your code is quite wrong.

> and then cityturn.c:460,461 is wrong.

> same issue for cityturn.c:530 and 540

I have no idea what code you mean.  Line numbers change you know.

> cityturn.c:751 the variable 'id' really isn't needed. fold into notify.

OK.  I renamed id2 as upgrades_to

> cityturn.c:759 extra space before comma

Yah.

> overarching comment you use get_current_construction_bonus() in conditionals
> and the answer might be negative, which as I recall is not defined.

All checks now do a direct comparison > 0.

> cityturn.c:943 mod can share the line with .name

Picky, aren't we?

> diplomats.c:759 comment makes no sense anymore.

Is "subvertable" a word?

> diplomats.c:1034  I don't like this at all. We should be able to specify a
> percentage.

> diplomats.c:1122 ditto 

For EFT_SPY_RESISTANT, yes.  This bonus is given defensively in 
diplomatic combat as well as to protect buildings.  The former should be 
a different effect (EFT_SPY_DEFEND) but I didn't make that.

> gotohand.c:989 see above on multipliers vs. percentages.

Yep.

> plrhand.c:do_tech_parasite_effect() why aren't we naming the building?

Because we don't know what building it is.  We can find out but it will 
take some work.

> plrhand.c:903 is this right?

I assume you mean this on line 935:

-  if (player_owns_active_govchange_wonder(pplayer)) {
+  if (get_player_bonus(pplayer, EFT_NO_ANARCHY) > 0) {

why wouldn't it be right?

> ruleset.c:load_ruleset_buildings() some lines wrapping issues.

Some fixed (there may be more).

> settlers.c:877 see EFT_GROWTH_FOOD above.

Yes.

> unittools.c:do_upgrade_effects()
> there are problems here as you assign an int to a bool.
> I see you choose to ignore the AMOUNT spec...
> you are missing the upgrade step effects.
> int candidate_to_upgrade=-1; spacing
> i=0 spacing, or initialize it in the declaration.
> for the ALL_LEAP, you need not go through the candidate selection process.

This is ugly.  But I solved it ;-).  I removed all four effects and 
replaced them with one EFT_UNIT_UPGRADE.  The amount specifies the 
number to be ugpraded.  Really, even having an amount here is 
unnecessary for the current level of generalization.

> unittools.c:496 line wrap.

?

> doc/README.effects needs to be updated.

I fixed the problems I noticed (and the ones I changed above).  Someone 
will have to review it eventually.

In addition to the above changes, Per made a bunch of improvements to 
the AI code.  These are merged in with my patch.  They include changes 
to the prototypes of city_pollution and city_gold_surplus.  The patch is 
about 100k bigger now because of all the AI changes.  I will guarantee 
there are bugs.

jason

? data/diff
Index: ai/advdomestic.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
retrieving revision 1.118
diff -u -r1.118 advdomestic.c
--- ai/advdomestic.c    31 Aug 2004 15:52:46 -0000      1.118
+++ ai/advdomestic.c    6 Sep 2004 01:11:02 -0000
@@ -39,883 +39,6 @@
 
 #include "advdomestic.h"
 
-/**************************************************************************
-  Calculate desire for land defense. First look for potentially hostile 
-  cities on our continent, indicating danger of being attacked by land. 
-  Then check if we are on the shoreline because we want to stop invasions
-  too - but only if a non-allied player has started using sea units yet. 
-  If they are slow to go on the offensive, we should expand or attack.
-
-  Returns a base value of desire for land defense building.
-
-  FIXME: We should have a concept of "oceans" just like we do for
-  continents. Too many times I've seen the AI build destroyers and 
-  coastal defences in inlands cities with a small pond adjacent. - Per
-**************************************************************************/
-static int ai_eval_threat_land(struct player *pplayer, struct city *pcity)
-{
-  struct ai_data *ai = ai_data_get(pplayer);
-  Continent_id continent;
-  bool vulnerable;
-
-  /* make easy AI dumb */
-  if (ai_handicap(pplayer, H_DEFENSIVE)) {
-    return 40;
-  }
-
-  continent = map_get_continent(pcity->x, pcity->y);
-  vulnerable = ai->threats.continent[continent]
-               || city_got_building(pcity, B_PALACE)
-               || (ai->threats.invasions
-                   && is_water_adjacent_to_tile(pcity->x, pcity->y));
-
-  return vulnerable ? TRADE_WEIGHTING + 2 : 1; /* trump coinage, and sam */
-}
-
-/**************************************************************************
-  Calculate desire for coastal defence building.
-**************************************************************************/
-static int ai_eval_threat_sea(struct player *pplayer, struct city *pcity)
-{
-  struct ai_data *ai = ai_data_get(pplayer);
-
-  /* make easy AI stay dumb */
-  if (ai_handicap(pplayer, H_DEFENSIVE)) {
-    return 40;
-  }
-
-  /* trump coinage, and wall, and sam */
-  if (is_ocean(map_get_terrain(pcity->x, pcity->y))) {
-    return ai->threats.ocean[-map_get_continent(pcity->x, pcity->y)]
-           ? TRADE_WEIGHTING + 3 : 1;
-  } else {
-    adjc_iterate(pcity->x, pcity->y, x2, y2) {
-      if (is_ocean(map_get_terrain(x2, y2))) {
-        Continent_id ocean_number = map_get_continent(x2, y2);
-
-        if (ai->threats.ocean[-ocean_number]) {
-          return TRADE_WEIGHTING + 3;
-        }
-      }
-    } adjc_iterate_end;
-  }
-  return 1;
-}
-
-/**************************************************************************
-  Calculate desire for air defence building.
-**************************************************************************/
-static int ai_eval_threat_air(struct player *pplayer, struct city *pcity)
-{
-  struct ai_data *ai = ai_data_get(pplayer);
-  Continent_id continent;
-  bool vulnerable;
-
-  /* make easy AI dumber */
-  if (ai_handicap(pplayer, H_DEFENSIVE)) {
-    return 50;
-  }
-
-  continent = map_get_continent(pcity->x, pcity->y);
-  vulnerable = ai->threats.air
-               && (ai->threats.continent[continent]
-                   || is_water_adjacent_to_tile(pcity->x, pcity->y) 
-                   || city_got_building(pcity, B_PALACE));
-
-  return vulnerable ? TRADE_WEIGHTING + 1 : 1; /* trump coinage */
-}
-
-/**************************************************************************
-  Calculate need for nuclear defence. Look for players capable of building
-  nuclear weapons. Capable of building, not has, because at this stage in
-  the game we can get nukes and use nukes faster than we can manage to
-  build SDIs. We also look if players _have_ nukes, and increase our
-  want for SDIs correspondingly. Lastly, we check if we are in a strategic
-  position (ie near water or on a continent with non-allied cities).
-**************************************************************************/
-static int ai_eval_threat_nuclear(struct player *pplayer, struct city *pcity)
-{
-  struct ai_data *ai = ai_data_get(pplayer);
-  Continent_id continent;
-  int vulnerable = 1;
-
-  /* make easy AI really dumb, like it was before */
-  if (ai_handicap(pplayer, H_DEFENSIVE)) {
-    return 50;
-  }
-
-  /* No non-allied player has nuclear capability yet. */
-  if (ai->threats.nuclear == 0) { return 0; }
-
-  continent = map_get_continent(pcity->x, pcity->y);
-  if (ai->threats.continent[continent]
-      || is_water_adjacent_to_tile(pcity->x, pcity->y)
-      || city_got_building(pcity, B_PALACE)) {
-    vulnerable++;
-  }
-
-  /* 15 is just a new magic number, which will be +15 if we are
-     in a vulnerable spot, and +15 if someone we are not allied
-     with really have built nukes. This might be overkill, but
-     at least it is not as bad as it used to be. */
-  return ((ai->threats.nuclear + vulnerable) * 15);
-}
-
-/**************************************************************************
-  Calculate desire for missile defence.
-**************************************************************************/
-static int ai_eval_threat_missile(struct player *pplayer, struct city *pcity)
-{
-  struct ai_data *ai = ai_data_get(pplayer);
-  Continent_id continent = map_get_continent(pcity->x, pcity->y);
-  bool vulnerable = is_water_adjacent_to_tile(pcity->x, pcity->y)
-                    || ai->threats.continent[continent]
-                    || city_got_building(pcity, B_PALACE);
-
-  /* Only build missile defence if opponent builds them, and we are in
-     a vulnerable spot. Trump coinage but not wall or coastal. */
-  return (ai->threats.missile && vulnerable) ? TRADE_WEIGHTING + 1 : 1;
-}
-
-/**************************************************************************
-Returns the value (desire to build it) of the improvement for keeping
-of order in the city.
-
-Improvements which increase happiness have two benefits. They can prevent
-cities from falling into disorder, and free the population changed into elvis
-specialists (so you can work tiles with value like tileval with them).  Happy
-is number of people the improvement would make happy.
-
-This function lets you decide if the happiness improvement such as the Temple,
-Cathedral or WoW is worth the cost of the elvises keeping your citizens content
-or the cost of the potential disorder (basically how much citizens would be
-unhappy * SADVAL).
-
-Note that an elvis citizen is a parasite. The fewer you have, the more
-food/prod/trade your city produces.
-**************************************************************************/
-static int impr_happy_val(struct city *pcity, int happy, int tileval)
-{
-  /* How much one rebeling citizen counts - 16 is debatable value */
-#define SADVAL 16
-  /* Number of elvises in the city */
-  int elvis = pcity->specialists[SP_ELVIS];
-  /* Raw number of unhappy people */
-  int sad = pcity->ppl_unhappy[0];
-  /* Final number of content people */
-  int content = pcity->ppl_content[4];
-  /* Resulting value */
-  int value = 0;
-
-  /* Count people made happy by luxury as content. */
-  if (pcity->ppl_content[1] < pcity->ppl_content[0])
-    content += pcity->ppl_content[0] - pcity->ppl_content[1];
-
-  /* If units are making us unhappy, count that too. */
-  sad += pcity->ppl_unhappy[3] - pcity->ppl_unhappy[2];
-  /* Angry citizens have to be counted double, as you have to first make them
-   * unhappy and then content. */
-  sad += pcity->ppl_angry[0] * 2;
-  
-  freelog(LOG_DEBUG, "In %s, unh[0] = %d, unh[4] = %d, sad = %d",
-         pcity->name, pcity->ppl_unhappy[0], pcity->ppl_unhappy[4], sad);
-
-  /* The cost of the elvises. */
-  while (happy > 0 && elvis > 0) { happy--; elvis--; value += tileval; }
-  /* The cost of the rebels. */
-  while (happy > 0 && sad > 0) { happy--; sad--; value += SADVAL; }
-  
-  /* Desperately seeking Colosseum - we need happy improvements urgently. */
-  if (city_unhappy(pcity))
-    value += SADVAL * (sad + content);
-  
-  /* Usage of (happy && content) led to a lack of foresight, especially
-   * re: Chapel -- Syela */
-  while (happy > 0) { happy--; value += SADVAL; }
-  
-  freelog(LOG_DEBUG, "%s: %d elvis %d sad %d content %d size %d val",
-         pcity->name, pcity->specialists[SP_ELVIS], pcity->ppl_unhappy[4],
-         pcity->ppl_content[4], pcity->size, value);
-
-  return value;
-#undef SADVAL
-}
-
-/**************************************************************************
-Return a weighted value for a city's Ocean tiles
-(i.e. based on the total number and number actively worked).
-**************************************************************************/
-static int ocean_workers(struct city *pcity)
-{
-  int i = 0;
-
-  city_map_checked_iterate(pcity->x, pcity->y, cx, cy, mx, my) {
-    if (is_ocean(map_get_terrain(mx, my))) {
-      /* This is a kluge; wasn't getting enough harbors because often
-       * everyone was stuck farming grassland. */
-      i++;
-
-      if (is_worker_here(pcity, cx, cy))
-       i++;
-    }
-  } city_map_checked_iterate_end;
-  
-  return i / 2;
-}
-
-/**************************************************************************
-Number of road tiles actively worked.
-**************************************************************************/
-static int road_trade(struct city *pcity)
-{
-  int i = 0;
-
-  city_map_checked_iterate(pcity->x, pcity->y, cx, cy, mx, my) {
-    if (map_has_special(mx, my, S_ROAD)
-       && is_worker_here(pcity, cx, cy))
-      i++;
-  } city_map_checked_iterate_end;
-
-  return i; 
-}
-
-/**************************************************************************
-Number of farmland tiles actively worked.
-**************************************************************************/
-static int farmland_food(struct city *pcity)
-{
-  int i = 0;
-
-  city_map_checked_iterate(pcity->x, pcity->y, cx, cy, mx, my) {
-    if (map_has_special(mx, my, S_FARMLAND)
-       && is_worker_here(pcity, cx, cy))
-      i++;
-  } city_map_checked_iterate_end;
-
-  return i; 
-}
-
-/**************************************************************************
-Pollution benefit or cost of given improvement.
-
-Positive return value: less pollution if this improvement would be built
-Negative return value: more pollution if this improvement would be built
-Bigger absolute value means greater effect, naturally.
-**************************************************************************/
-static int pollution_benefit(struct player *pplayer, struct city *pcity,
-                            Impr_Type_id impr_type)
-{
-  /* Generated pollution */
-  int pollution = 0;
-  /* Production bonus of improvement */
-  int prodbonus = 0;
-  /* How seriously we should take it */
-  int weight;
-  /* Pollution cost */
-  int cost = 0;
-
-  /* Count total production of worked tiles, that's base of pollution value. */
-  city_map_iterate(x, y) {
-    if (get_worker_city(pcity, x, y) == C_TILE_WORKER) {
-      pollution += city_get_shields_tile(x, y, pcity);
-    }
-  } city_map_iterate_end;
-
-  /* Count production bonuses generated by various buildings. */
-  if (city_got_building(pcity, B_FACTORY) || impr_type == B_FACTORY) {
-    prodbonus += 50;
-    if (city_got_building(pcity, B_MFG) || impr_type == B_MFG) {
-      prodbonus *= 2;
-    }
-  }
-
-  /* Count bonuses for that production bonuses ;-). */
-  if (city_affected_by_wonder(pcity, B_HOOVER) || impr_type == B_HOOVER ||
-      city_got_building(pcity, B_POWER) || impr_type == B_POWER ||
-      city_got_building(pcity, B_HYDRO) || impr_type == B_HYDRO ||
-      city_got_building(pcity, B_NUCLEAR) || impr_type == B_NUCLEAR) {
-    prodbonus = (prodbonus * 3) / 2;
-  }
-  
-  /* And now apply the bonuses. */
-  pollution = pollution * (prodbonus + 100) / 100;
-
-  /* Count buildings which reduce the pollution. */
-  if (city_got_building(pcity, B_RECYCLING) || impr_type == B_RECYCLING)
-    pollution /= 3;
-  
-  else if (city_got_building(pcity, B_HYDRO) || impr_type == B_HYDRO ||
-           city_affected_by_wonder(pcity, B_HOOVER) || impr_type == B_HOOVER ||
-           city_got_building(pcity, B_NUCLEAR) || impr_type == B_NUCLEAR)
-    pollution /= 2;
-
-  /* Count technologies which affect the pollution. */
-  if (! city_got_building(pcity, B_MASS) && impr_type != B_MASS) {
-    pollution += (num_known_tech_with_flag(pplayer,
-                                          TF_POPULATION_POLLUTION_INC) *
-                 pcity->size) / 4;
-  }
-  
-  /* Heuristic? */
-  pollution -= 20;
-  if (pollution < 0) pollution = 0;
-  
-  weight = (POLLUTION_WEIGHTING + pplayer->ai.warmth) * 64;
-  
-  /* Base is cost of actual pollution. */
-  
-  if (pcity->pollution > 0) {
-    int amortized = amortize(weight, 100 / pcity->pollution);
-    
-    cost = ((amortized * weight) / (MAX(1, weight - amortized))) / 64;
-    
-    freelog(LOG_DEBUG, "City: %s, Pollu: %d, cost: %d, Id: %d, P: %d",
-           pcity->name, pcity->pollution, cost, impr_type, pollution);
-  }
-  
-  /* Subtract cost of future pollution. */
-  
-  if (pollution > 0) {
-    int amortized = amortize(weight, 100 / pollution);
-  
-    cost -= ((amortized * weight) / (MAX(1, weight - amortized))) / 64;
-  }
-  
-  return cost;
-}
-
-/****************************************************************************
-  Return TRUE if the given wonder is already being built by pcity owner in
-  another city (if so we probably don't want to build it here, although
-  we may want to start building it and switch later).
-****************************************************************************/
-static bool built_elsewhere(struct city *pcity, Impr_Type_id wonder)
-{
-  city_list_iterate(city_owner(pcity)->cities, acity) {
-    if (pcity != acity && !acity->is_building_unit
-       && pcity->currently_building == wonder) {
-      return TRUE;
-    }
-  } city_list_iterate_end;
-
-  return FALSE;
-}
-
-/**************************************************************************
-  Returns the city_tile_value of the worst tile worked by pcity 
-  (not including the city center).  Returns 0 if no tiles are worked.
-**************************************************************************/
-static int worst_worker_tile_value(struct city *pcity)
-{
-  int worst = 0;
-
-  city_map_iterate(x, y) {
-    if (is_city_center(x, y)) {
-      continue;
-    }
-    if (get_worker_city(pcity, x, y) == C_TILE_WORKER) {
-      int tmp = city_tile_value(pcity, x, y, 0, 0);
-
-      if (tmp < worst || worst == 0) {
-       worst = tmp;
-      }
-    }
-  } city_map_iterate_end;
-
-  return worst;
-}
-
-/**************************************************************************
-  Get city_tile_value of best unused tile available to pcity.  Returns
-  0 if no tiles are available.
-**************************************************************************/
-static int best_free_tile_value(struct city *pcity)
-{
-  int best = 0;
-
-  city_map_iterate(x, y) {
-    if (get_worker_city(pcity, x, y) == C_TILE_EMPTY) {
-      int tmp = city_tile_value(pcity, x, y, 0, 0);
-      
-      if (tmp > best) {
-       best = tmp;
-      }
-    }
-  } city_map_iterate_end;
-  
-  return best;
-}
-
-/**************************************************************************
-  Returns the amount of food consumed by pcity's units.
-**************************************************************************/
-static int settler_eats(struct city *pcity)
-{
-  struct government *gov = get_gov_pcity(pcity);
-  int free_food = citygov_free_food(pcity, gov);
-  int eat = 0;
-
-  unit_list_iterate(pcity->units_supported, this_unit) {
-    int food_cost = utype_food_cost(unit_type(this_unit), gov);
-
-    adjust_city_free_cost(&free_food, &food_cost);
-    if (food_cost > 0) {
-      eat += food_cost;
-    }
-  } unit_list_iterate_end;
-
-  return eat;
-}
-
-/**************************************************************************
-  Evaluate the current desirability of all city improvements for the given 
-  city to update pcity->ai.building_want.
-**************************************************************************/
-void ai_eval_buildings(struct city *pcity)
-{
-  struct government *g = get_gov_pcity(pcity);
-  struct player *pplayer = city_owner(pcity);
-  int bar, est_food, food, grana, hunger, needpower;
-  int tprod, prod, sci, tax, t, val, wwtv;
-  int j, k;
-  int values[B_LAST];
-  int nplayers = game.nplayers 
-                 - team_count_members_alive(pplayer->team);
-
-  /* --- initialize control parameters --- */
-  t = pcity->ai.trade_want;  /* trade_weighting */
-  sci = (pcity->trade_prod * pplayer->economic.science + 50) / 100;
-  tax = pcity->trade_prod - sci;
-
-  /* better might be a longterm weighted average, this is a quick-n-dirty fix 
-  -- Syela */
-  sci = ((sci + pcity->trade_prod) * t)/2;
-  tax = ((tax + pcity->trade_prod) * t)/2;
-  /* don't need libraries!! */
-  if (ai_wants_no_science(pplayer)) {
-    sci = 0;
-  }
-
-  est_food = (2 * pcity->specialists[SP_SCIENTIST]
-             + 2 * pcity->specialists[SP_TAXMAN]
-             + pcity->food_surplus);
-  prod = 
-    (pcity->shield_prod * SHIELD_WEIGHTING * 100) / city_shield_bonus(pcity);
-  needpower = (city_got_building(pcity, B_MFG) ? 2 :
-              (city_got_building(pcity, B_FACTORY) ? 1 : 0));
-  val = best_free_tile_value(pcity);
-  wwtv = worst_worker_tile_value(pcity);
-
-  /* because the benefit doesn't come immediately, and to stop stupidity   */
-  /* the AI used to really love granaries for nascent cities, which is OK  */
-  /* as long as they aren't rated above Settlers and Laws is above Pottery */
-  /* -- Syela */
-  grana = MAX(2, pcity->size);
-  food  = food_weighting(grana);
-  grana = food_weighting(grana + 1);
-  hunger = 1;
-  j = (pcity->size * 2) + settler_eats(pcity) - pcity->food_prod;
-  if (j >= 0
-      && pcity->specialists[SP_SCIENTIST] <= 0
-      && pcity->specialists[SP_TAXMAN] <= 0) {
-    hunger += j + 1;
-  }
-
-  /* rationale: barracks effectively doubles prod if building military units */
-  /* if half our production is military, effective gain is 1/2 city prod     */
-  bar = ((!pcity->is_building_unit && pcity->currently_building == B_SUNTZU)
-      || built_elsewhere(pcity, B_SUNTZU)) ? 1 : 0;
-  j = 0; k = 0, tprod = 0;
-  city_list_iterate(pplayer->cities, acity) {
-    k++;
-    tprod += acity->shield_prod;
-    if (acity->is_building_unit) {
-      if (!unit_type_flag(acity->currently_building, F_NONMIL) 
-       && unit_types[acity->currently_building].move_type == LAND_MOVING)
-        j += prod;
-      else 
-      if (unit_type_flag(acity->currently_building, F_HELP_WONDER) && bar != 0)
-       j += prod;                              /* this also stops flip-flops */
-    } else 
-      if (acity->currently_building == B_BARRACKS   /* this stops flip-flops */
-       || acity->currently_building == B_BARRACKS2
-       || acity->currently_building == B_BARRACKS3
-       || acity->currently_building == B_SUNTZU)
-       j += prod;
-  } city_list_iterate_end;
-  bar = j > 0 ? j / k : 0;
-
-  /* --- clear to initialize values ... and go --- */
-  memset(values, 0, sizeof(values));
-
-  /* Buildings first, values are used in Wonder section next */
-  impr_type_iterate(id) {
-    if ( is_wonder(id) 
-      || !can_build_improvement(pcity, id))
-      continue;
-
-    switch (id) {
-    
-    /* food/growth production */
-    case B_AQUEDUCT:
-    case B_SEWER:
-      /* Aqueducts and Sewers are similar */
-      k = (id == B_AQUEDUCT ? game.aqueduct_size : game.sewer_size);
-      if (pcity->size >= k-1 && est_food > 0) {
-        /* need it to grow, but don't force */
-        j = ((city_happy(pcity) || pcity->size > k) ? -100 : -66);
-      }
-      else {
-        /* how long (== how much food) till we grow big enough? 
-         * j = num_pop_rollover * biggest_granary_size - current_food */
-        j = (k+1) - MIN(k, pcity->size);
-       j *= city_granary_size(MAX(k, pcity->size));
-        j-= pcity->food_stock;
-  
-        /* value = some odd factors / food_required */
-        j = (k+1) * food * est_food * game.foodbox / MAX(1, j);
-      }
-      values[id] = j;
-      break;
-    case B_GRANARY:
-      if (improvement_variant(B_PYRAMIDS) != 0
-          || !built_elsewhere(pcity, B_PYRAMIDS))
-        values[id] = grana * pcity->food_surplus;
-      break;
-    case B_HARBOUR:
-      values[id] = ocean_workers(pcity) * food * hunger;
-      break;
-    case B_SUPERMARKET:
-      if (player_knows_techs_with_flag(pplayer, TF_FARMLAND))
-        values[id] = farmland_food(pcity) * food * hunger;
-      break;
-  
-    /* science production */
-    case B_RESEARCH:
-      if (built_elsewhere(pcity, B_SETI))
-        break;
-    case B_UNIVERSITY:
-    case B_LIBRARY:
-      values[id] = sci/2;
-      break;
-  
-    /* happiness generation - trade production */
-    case B_MARKETPLACE:
-    case B_BANK:
-    case B_STOCK:
-      values[id] = (tax + 3 * pcity->specialists[SP_TAXMAN]
-                   + pcity->specialists[SP_ELVIS] * wwtv) / 2;
-      break;
-    case B_SUPERHIGHWAYS:
-      values[id] = road_trade(pcity) * t;
-      break;
-    case B_CAPITAL:
-      values[id] = TRADE_WEIGHTING; /* a kind of default */
-      break;
-  
-    /* unhappiness relief */
-    case B_TEMPLE:
-      values[id] = impr_happy_val(pcity, get_temple_power(pcity), val);
-      break;
-    case B_CATHEDRAL:
-      if (improvement_variant(B_MICHELANGELO) == 1 
-          || !built_elsewhere(pcity, B_MICHELANGELO))
-        values[id]= impr_happy_val(pcity, get_cathedral_power(pcity), val);
-      else
-      if (tech_exists(game.rtech.cathedral_plus)
-        && get_invention(pplayer, game.rtech.cathedral_plus) != TECH_KNOWN)
-        values[id]= impr_happy_val(pcity, 4, val) - impr_happy_val(pcity, 3, 
val);
-      break;
-    case B_COLOSSEUM:
-      values[id] = impr_happy_val(pcity, get_colosseum_power(pcity), val);
-      break;
-    case B_COURTHOUSE:
-      if (g->corruption_level == 0) {
-        values[id] += impr_happy_val(pcity, 1, val);
-      } else {
-        /* The use of TRADE_WEIGHTING here is deliberate, since
-         * t is corruption modified. */
-        values[id] = (pcity->corruption * TRADE_WEIGHTING) / 2;
-      }
-      break;
-    
-    /* shield production and pollution */
-    case B_OFFSHORE:  /* ignoring pollu. FIX? */
-      values[B_OFFSHORE] = ocean_workers(pcity) * SHIELD_WEIGHTING;
-      break;
-    case B_FACTORY:
-    case B_MFG:
-      values[id] = 
-        (( city_got_building(pcity, B_HYDRO)
-        || city_got_building(pcity, B_NUCLEAR)
-        || city_got_building(pcity, B_POWER)
-        || city_affected_by_wonder(pcity, B_HOOVER))
-        ?  (prod * 3)/4 : prod/2) 
-        + pollution_benefit(pplayer, pcity, id);
-      break;
-    case B_HYDRO: 
-    case B_NUCLEAR: 
-    case B_POWER: 
-      if ( !city_got_building(pcity, B_HYDRO)
-        && !city_got_building(pcity, B_NUCLEAR)
-        && !city_got_building(pcity, B_POWER)
-        && !city_affected_by_wonder(pcity, B_HOOVER))
-        values[id] = (needpower*prod)/4 + pollution_benefit(pplayer, pcity, 
id);
-      break;
-    case B_MASS:
-    case B_RECYCLING:
-      values[id] = pollution_benefit(pplayer, pcity, id);
-      break;
-  
-    /* defense/protection */
-    case B_BARRACKS:
-    case B_BARRACKS2:
-    case B_BARRACKS3:
-      if (!built_elsewhere(pcity, B_SUNTZU)) 
-        values[id] = bar;
-      break;
-  
-    /* military advisor will deal with CITY and PORT */
-  
-    /* old wall code depended on danger, was a CPU hog and didn't really work 
-     * anyway. It was so stupid, AI wouldn't start building walls until it was 
-     * in danger and it would have no chance to finish them before it was too 
-     * late */
-    case B_CITY:
-      /* if (!built_elsewhere(pcity, B_WALL)) was counterproductive -- Syela */
-      values[id] = ai_eval_threat_land(pplayer, pcity);
-      break;
-    case B_COASTAL:
-      values[id] = ai_eval_threat_sea(pplayer, pcity);
-      break;
-    case B_SAM:
-      values[id] = ai_eval_threat_air(pplayer, pcity);
-      break;
-    case B_SDI:
-      values[B_SDI] = MAX(ai_eval_threat_nuclear(pplayer, pcity),
-                       ai_eval_threat_missile(pplayer, pcity));
-      break;
-  
-    /* spaceship production */
-    case B_SCOMP:
-      if ((game.spacerace)
-        && pplayer->spaceship.components < NUM_SS_COMPONENTS) 
-        values[id] = -90;
-      break;
-    case B_SMODULE:
-      if ((game.spacerace)
-        && pplayer->spaceship.modules < NUM_SS_MODULES) 
-        values[id] = -90;
-      break;
-    case B_SSTRUCTURAL:
-      if ((game.spacerace)
-        && pplayer->spaceship.structurals < NUM_SS_STRUCTURALS)
-        values[id] = -80;
-      break;
-    default:
-      /* ignored: AIRPORT, PALACE, and POLICE and the rest. -- Syela*/
-      break;
-    } /* end switch */
-  } impr_type_iterate_end;
-
-  /* Miscellaneous building values */
-  if ( values[B_COLOSSEUM] == 0
-    && tech_exists(game.rtech.colosseum_plus)
-    && get_invention(pplayer, game.rtech.colosseum_plus) != TECH_KNOWN)
-    values[B_COLOSSEUM] = 
-      impr_happy_val(pcity, 4, val) - impr_happy_val(pcity, 3, val);
-    
-  /* Wonders */
-  impr_type_iterate(id) {
-    if (!is_wonder(id) 
-      || !can_build_improvement(pcity, id)
-      || wonder_obsolete(id)
-      || !is_wonder_useful(id)) 
-      continue;
-
-    switch (id) {
-    case B_ASMITHS:
-      impr_type_iterate(id2) {
-        if (city_got_building(pcity, id2)
-          && improvement_upkeep(pcity, id2) == 1)
-          values[id] += t;
-      } impr_type_iterate_end;
-      break;
-    case B_COLLOSSUS:
-      /* probably underestimates the value */
-      values[id] = (pcity->size + 1) * t;
-      break;
-    case B_COPERNICUS:
-      values[id] = sci/2;
-      break;
-    case B_CURE:
-      values[id] = impr_happy_val(pcity, 1, val);
-      break;
-    case B_DARWIN:
-      /* this is a one-time boost, not constant */
-      values[id] = ((total_bulbs_required(pplayer) * 2 + game.researchcost) * 
t 
-                 - pplayer->research.bulbs_researched * t) / MORT;
-      break;
-    case B_GREAT:
-      /* basically (100 - freecost)% of a free tech per 2 turns */
-      values[id] = (total_bulbs_required(pplayer) * (100 - game.freecost) * t
-                 * (nplayers - 2)) / (nplayers * 2 * 100);
-      break;
-    case B_WALL:
-      if (!city_got_citywalls(pcity)) {
-        /* allowing B_CITY when B_WALL exists, 
-         * don't like B_WALL when B_CITY exists. */
-        /* was 40, which led to the AI building WALL, not being able to build 
-         * CITY, someone learning Metallurgy, and the AI collapsing.  
-         * I hate the WALL. -- Syela */
-        values[B_WALL] = 1; /* WAG */
-      }
-      break;
-    case B_HANGING:
-      /* will add the global effect to this. */
-      values[id] = impr_happy_val(pcity, 3, val)
-                 - impr_happy_val(pcity, 1, val);
-      break;
-    case B_HOOVER:
-      if (!city_got_building(pcity, B_HYDRO)
-        && !city_got_building(pcity, B_NUCLEAR)) {
-        values[id] = (city_got_building(pcity, B_POWER) ? 0 :
-          (needpower * prod)/4) + pollution_benefit(pplayer, pcity, B_HOOVER);
-      }
-      break;
-    case B_ISAAC:
-      values[id] = sci;
-      break;
-    case B_LEONARDO:
-      unit_list_iterate(pcity->units_supported, punit) {
-        Unit_Type_id unit_id = can_upgrade_unittype(pplayer, punit->type);
-        if (unit_id >= 0) {
-          /* this is probably wrong -- Syela */
-          j = 8 * unit_upgrade_price(pplayer, punit->type, unit_id);
-          values[id] = MAX(values[id], j);
-        }
-      } unit_list_iterate_end;
-      break;
-    case B_BACH:
-      values[id] = impr_happy_val(pcity, 2, val);
-      break;
-    case B_RICHARDS:
-      /* ignoring pollu, I don't think it matters here -- Syela */
-      values[id] = (pcity->size + 1) * SHIELD_WEIGHTING;
-      break;
-    case B_MICHELANGELO:
-      /* Note: Mich not built, so get_cathedral_power() doesn't include 
-       * its effect. */
-      if (improvement_variant(B_MICHELANGELO) == 0
-        && !city_got_building(pcity, B_CATHEDRAL)) {
-        /* Assumes Mich will act as the Cath that is not in this city. */
-        values[id] = impr_happy_val(pcity, get_cathedral_power(pcity), val);
-      }
-      else
-      if (improvement_variant(B_MICHELANGELO)==1
-        && city_got_building(pcity, B_CATHEDRAL)) {
-        /* Assumes Mich doubles the power of the Cath that is in this city. */
-        values[id] = impr_happy_val(pcity, get_cathedral_power(pcity), val);
-      }
-      break;
-    case B_ORACLE:
-      /* The following is probably wrong if B_ORACLE req is
-       * not the same as game.rtech.temple_plus (was A_MYSTICISM) --dwp */
-      if (!city_got_building(pcity, B_TEMPLE)) {
-        if (get_invention(pplayer, game.rtech.temple_plus) != TECH_KNOWN) {
-          /* The += has nothing to do with oracle, 
-           * just the tech_Want of mysticism! */
-          values[id] = impr_happy_val(pcity, 2, val) 
-                     - impr_happy_val(pcity, 1, val);
-          values[id]+= impr_happy_val(pcity, 2, val)
-                     - impr_happy_val(pcity, 1, val);
-        }
-      } else {
-        if (get_invention(pplayer, game.rtech.temple_plus) != TECH_KNOWN) {
-          /* The += has nothing to do with oracle, 
-           * just the tech_Want of mysticism! */
-          values[id] = impr_happy_val(pcity, 4, val) 
-                     - impr_happy_val(pcity, 1, val);
-          values[id]+= impr_happy_val(pcity, 2, val)
-                     - impr_happy_val(pcity, 1, val);
-        }
-        else
-          values[id] = impr_happy_val(pcity, 2, val);
-      }
-      break;
-    case B_PYRAMIDS:
-      if (improvement_variant(B_PYRAMIDS)==0
-        && !city_got_building(pcity, B_GRANARY)) {
-        /* different tech req's */
-        values[id] = food * pcity->food_surplus;
-      }
-      break;
-    case B_SETI:
-      if (!city_got_building(pcity, B_RESEARCH))
-        values[id] = sci/2;
-      break;
-    case B_SHAKESPEARE:
-      values[id] = impr_happy_val(pcity, pcity->size, val);
-      break;
-    case B_SUNTZU:
-      values[id] = bar;
-      break;
-    case B_WOMENS:
-      unit_list_iterate(pcity->units_supported, punit) {
-       if (punit->unhappiness != 0) {
-         values[id] += t * 2;
-       }
-      } unit_list_iterate_end;
-      break;
-    case B_APOLLO:
-      if (game.spacerace) {
-        values[id] = values[B_CAPITAL] + 1; /* trump coinage and defenses */
-      }
-      break;
-    case B_UNITED:
-      values[id] = values[B_CAPITAL] + 4; /* trump coinage and defenses */
-      break;
-    case B_LIGHTHOUSE:
-      values[id] = values[B_CAPITAL] + 4; /* trump coinage and defenses */
-      break;
-    case B_MAGELLAN:
-      values[id] = values[B_CAPITAL] + 4; /* trump coinage and defenses */
-      break;
-    default:
-       /* also, MAGELLAN is special cased in ai_manage_buildings() */
-       /* ignoring MANHATTAN and STATUE */
-      break;
-    } /* end switch */
-  } impr_type_iterate_end;
-
-  /* Final massage */
-  impr_type_iterate(id) {
-    if (values[id] >= 0) {
-      if (!is_wonder(id)) {
-        /* trying to buy fewer improvements */
-        values[id]-= improvement_upkeep(pcity, id) * t;
-        values[id] = (values[id] <= 0 
-          ? 0 : (values[id] * SHIELD_WEIGHTING * 100) / MORT);
-      } else {
-        /* bias against wonders when total production is small */
-        values[id] *= (tprod < 50 ? 100/(50-tprod): 100);
-      }
-
-      /* handle H_PROD here? -- Syela */
-      j = impr_build_shield_cost(id);
-      pcity->ai.building_want[id] = values[id] / j;
-    } else {
-      pcity->ai.building_want[id] = -values[id];
-    }
-
-    if (values[id] != 0) 
-      CITY_LOG(LOG_DEBUG, pcity, "ai_eval_buildings: wants %s with desire %d.",
-               get_improvement_name(id), pcity->ai.building_want[id]);
-  } impr_type_iterate_end;
-
-  return;
-}
-
 /***************************************************************************
  * Evaluate the need for units (like caravans) that aid wonder construction.
  * If another city is building wonder and needs help but pplayer is not
Index: ai/advdomestic.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.h,v
retrieving revision 1.7
diff -u -r1.7 advdomestic.h
--- ai/advdomestic.h    3 Sep 2004 04:22:36 -0000       1.7
+++ ai/advdomestic.h    6 Sep 2004 01:11:02 -0000
@@ -21,6 +21,5 @@
 void ai_eval_threat_done(struct player *pplayer);
 void domestic_advisor_choose_build(struct player *pplayer, struct city *pcity,
                                   struct ai_choice *choice);
-void ai_eval_buildings(struct city *pcity);
 
 #endif  /* FC__ADVDOMESTIC_H */
Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.172
diff -u -r1.172 advmilitary.c
--- ai/advmilitary.c    2 Sep 2004 14:53:08 -0000       1.172
+++ ai/advmilitary.c    6 Sep 2004 01:11:02 -0000
@@ -323,8 +323,12 @@
   }
 
   danger = unit_att_rating(punit);
-  if (sailing && city_got_building(pcity, B_COASTAL)) danger /= 2;
-  if (is_air_unit(punit) && city_got_building(pcity, B_SAM)) danger /= 2;
+  if (sailing && get_city_bonus(pcity, EFT_SEA_DEFEND) > 0) {
+    danger /= 2;
+  }
+  if (is_air_unit(punit) && get_city_bonus(pcity, EFT_AIR_DEFEND) > 0) {
+    danger /= 2;
+  }
 
   return danger;
 }
@@ -437,7 +441,7 @@
 static unsigned int assess_danger(struct city *pcity)
 {
   int i;
-  unsigned int danger[5];
+  int danger[5], defender[4];
   struct player *pplayer = city_owner(pcity);
   bool pikemen = FALSE;
   unsigned int urgency = 0;
@@ -547,17 +551,32 @@
     urgency += 10;
   }
 
-  ai_reevaluate_building(pcity, &pcity->ai.building_want[B_CITY],
-                         urgency, danger[1], assess_defense(pcity));
-  ai_reevaluate_building(pcity, &pcity->ai.building_want[B_COASTAL],
-                         urgency, danger[2], 
-                         assess_defense_igwall(pcity));
-  ai_reevaluate_building(pcity, &pcity->ai.building_want[B_SAM],
-                         urgency, danger[3], 
-                         assess_defense_igwall(pcity));
-  ai_reevaluate_building(pcity, &pcity->ai.building_want[B_SDI],
-                         urgency, danger[4], 
-                         assess_defense_igwall(pcity));
+  /* HACK: This needs changing if multiple improvements provide
+   * this effect. */
+  defender[0] = ai_find_source_building(pplayer, EFT_LAND_DEFEND);
+  defender[1] = ai_find_source_building(pplayer, EFT_SEA_DEFEND);
+  defender[2] = ai_find_source_building(pplayer, EFT_AIR_DEFEND);
+  defender[3] = ai_find_source_building(pplayer, EFT_MISSILE_DEFEND);
+
+  if (defender[0] != B_LAST) {
+    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender[0]],
+       urgency, danger[1], assess_defense(pcity));
+  }
+  if (defender[1] != B_LAST) {
+    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender[1]],
+       urgency, danger[2], 
+       assess_defense_igwall(pcity));
+  }
+  if (defender[2] != B_LAST) {
+    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender[2]],
+       urgency, danger[3], 
+       assess_defense_igwall(pcity));
+  }
+  if (defender[3] != B_LAST) {
+    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender[3]],
+       urgency, danger[4], 
+       assess_defense_igwall(pcity));
+  }
 
   pcity->ai.danger = danger[0];
   pcity->ai.urgency = urgency;
@@ -799,9 +818,9 @@
             !can_build_unit_direct(pcity, unit_types[unit_type].obsoleted_by))
         && unit_types[unit_type].attack_strength > 0 /* or we'll get SIGFPE */
         && move_type == orig_move_type) {
-      /* TODO: Case for B_AIRPORT. -- Raahul */
+      /* TODO: Case for Airport. -- Raahul */
       int will_be_veteran = (move_type == LAND_MOVING
-                             || player_knows_improvement_tech(pplayer, 
B_PORT));
+         || ai_find_source_building(pplayer, EFT_SEA_VETERAN) != B_LAST);
       /* Cost (shield equivalent) of gaining these techs. */
       /* FIXME? Katvrr advises that this should be weighted more heavily in big
        * danger. */
@@ -1148,6 +1167,7 @@
 {
   enum unit_move_type move_type;
   struct player *pplayer = city_owner(pcity);
+  Impr_Type_id id;
 
   /* Sanity */
   if (!is_unit_choice_type(choice->choice)) return;
@@ -1155,36 +1175,25 @@
   if (do_make_unit_veteran(pcity, choice->choice)) return;
 
   move_type = get_unit_type(choice->choice)->move_type;
-  if (improvement_variant(B_BARRACKS)==1) {
-    /* Barracks will work for all units! */
-    move_type = LAND_MOVING;
-  }
-
   switch(move_type) {
   case LAND_MOVING:
-    if (player_knows_improvement_tech(pplayer, B_BARRACKS3)) {
-      choice->choice = B_BARRACKS3;
-      choice->type = CT_BUILDING;
-    } else if (player_knows_improvement_tech(pplayer, B_BARRACKS2)) {
-      choice->choice = B_BARRACKS2;
-      choice->type = CT_BUILDING;
-    } else if (player_knows_improvement_tech(pplayer, B_BARRACKS)) {
-      choice->choice = B_BARRACKS;
+    if ((id = ai_find_source_building(pplayer, EFT_LAND_VETERAN)) != B_LAST) {
+      choice->choice = id;
       choice->type = CT_BUILDING;
     }
     break;
   case SEA_MOVING:
-    if (player_knows_improvement_tech(pplayer, B_PORT)) {
-      choice->choice = B_PORT;
+    if ((id = ai_find_source_building(pplayer, EFT_SEA_VETERAN)) != B_LAST) {
+      choice->choice = id;
       choice->type = CT_BUILDING;
     }
     break;
   case HELI_MOVING:
   case AIR_MOVING:
-    if (player_knows_improvement_tech(pplayer, B_AIRPORT)
-        && pcity->shield_surplus > impr_build_shield_cost(B_AIRPORT) / 10) {
+    if ((id = ai_find_source_building(pplayer, EFT_AIR_VETERAN)) != B_LAST
+        && pcity->shield_surplus > impr_build_shield_cost(id) / 10) {
       /* Only build this if we have really high production */
-      choice->choice = B_AIRPORT;
+      choice->choice = id;
       choice->type = CT_BUILDING;
     }
     break;
@@ -1223,6 +1232,7 @@
   /* Otherwise no need to defend yet */
   if (pcity->ai.danger != 0) { 
     int num_defenders = unit_list_size(&ptile->units);
+    int land_id, sea_id, air_id;
 
     /* First determine the danger.  It is measured in percents of our 
      * defensive strength, capped at 200 + urgency */
@@ -1248,40 +1258,50 @@
      * 2. (80 - pcity->shield_stock) * 2 below is hardcoded price of walls */
     /* We will build walls if we can and want and (have "enough" defenders or
      * can just buy the walls straight away) */
-    if (pcity->ai.building_want[B_CITY] != 0 && our_def != 0 
-        && can_build_improvement(pcity, B_CITY)
+
+    /* HACK: This needs changing if multiple improvements provide
+     * this effect. */
+    land_id = ai_find_source_building(pplayer, EFT_LAND_DEFEND);
+    sea_id = ai_find_source_building(pplayer, EFT_SEA_DEFEND);
+    air_id = ai_find_source_building(pplayer, EFT_AIR_DEFEND);
+
+    if (land_id != B_LAST
+       && pcity->ai.building_want[land_id] != 0 && our_def != 0 
+        && can_build_improvement(pcity, land_id)
         && (danger < 101 || num_defenders > 1
             || (pcity->ai.grave_danger == 0 
                 && pplayer->economic.gold > (80 - pcity->shield_stock) * 2)) 
         && ai_fuzzy(pplayer, TRUE)) {
       /* NB: great wall is under domestic */
-      choice->choice = B_CITY;
+      choice->choice = land_id;
       /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[B_CITY];
+      choice->want = pcity->ai.building_want[land_id];
       if (urgency == 0 && choice->want > 100) {
         choice->want = 100;
       }
       choice->type = CT_BUILDING;
 
-    } else if (pcity->ai.building_want[B_COASTAL] != 0 && our_def != 0 
-               && can_build_improvement(pcity, B_COASTAL) 
+    } else if (sea_id != B_LAST
+              && pcity->ai.building_want[sea_id] != 0 && our_def != 0 
+               && can_build_improvement(pcity, sea_id) 
                && (danger < 101 || num_defenders > 1) 
                && ai_fuzzy(pplayer, TRUE)) {
-      choice->choice = B_COASTAL;
+      choice->choice = sea_id;
       /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[B_COASTAL];
+      choice->want = pcity->ai.building_want[sea_id];
       if (urgency == 0 && choice->want > 100) {
         choice->want = 100;
       }
       choice->type = CT_BUILDING;
 
-    } else if (pcity->ai.building_want[B_SAM] != 0 && our_def != 0 
-               && can_build_improvement(pcity, B_SAM) 
+    } else if (air_id != B_LAST
+              && pcity->ai.building_want[air_id] != 0 && our_def != 0 
+               && can_build_improvement(pcity, air_id) 
                && (danger < 101 || num_defenders > 1) 
                && ai_fuzzy(pplayer, TRUE)) {
-      choice->choice = B_SAM;
+      choice->choice = air_id;
       /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[B_SAM];
+      choice->want = pcity->ai.building_want[air_id];
       if (urgency == 0 && choice->want > 100) {
         choice->want = 100;
       }
@@ -1291,7 +1311,7 @@
       /* Consider building defensive units units */
       process_defender_want(pplayer, pcity, danger, choice);
       if (urgency == 0 && unit_types[choice->choice].defense_strength == 1) {
-        if (city_got_barracks(pcity)) {
+        if (get_city_bonus(pcity, EFT_LAND_REGEN) > 0) {
           /* unlikely */
           choice->want = MIN(49, danger);
         } else {
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.162
diff -u -r1.162 aicity.c
--- ai/aicity.c 4 Sep 2004 19:28:18 -0000       1.162
+++ ai/aicity.c 6 Sep 2004 01:11:03 -0000
@@ -20,6 +20,7 @@
 
 #include "city.h"
 #include "combat.h"
+#include "effects.h"
 #include "events.h"
 #include "fcintl.h"
 #include "game.h"
@@ -28,6 +29,7 @@
 #include "map.h"
 #include "packets.h"
 #include "player.h"
+#include "rand.h"
 #include "shared.h"
 #include "support.h"
 #include "unit.h"
@@ -75,7 +77,7 @@
            - pcity->ppl_unhappy[4] * ai->unhappy_priority
            - pcity->ppl_angry[4] * ai->angry_priority
            - pcity->pollution * ai->pollution_priority);
-  
+
   if (pcity->food_surplus < 0 || pcity->shield_surplus < 0) {
     /* The city is unmaintainable, it can't be good */
     i = MIN(i, 0);
@@ -83,90 +85,434 @@
 
   return i;
 }
-     
+
+/**************************************************************************
+  Calculates want for some buildings by actually adding the building and
+  measuring the effect.
+**************************************************************************/
+static int base_want(struct player *pplayer, struct city *pcity, 
+                     Impr_Type_id id)
+{
+  struct ai_data *ai = ai_data_get(pplayer);
+  int final_want = 0;
+  Continent_id continent = map_get_continent(pcity->x, pcity->y);
+  struct city *capital = find_palace(pplayer);
+
+  if (ai->impr_calc[id] == AI_IMPR_ESTIMATE) {
+    return 0; /* Nothing to calculate here. */
+  }
+
+  /* First calculate current worth */
+  city_list_iterate(pplayer->cities, acity) {
+    if ((ai->impr_range[id] == EFR_CITY && acity == pcity)
+        || (ai->impr_range[id] == EFR_LOCAL && acity == pcity)
+        || (ai->impr_range[id] == EFR_CONTINENT
+            && map_get_continent(acity->x, acity->y) == continent)
+        || (ai->impr_range[id] == EFR_PLAYER)) {
+      int food, trade, shields, lux, sci, tax, want = 0;
+
+      get_food_trade_shields(acity, &food, &trade, &shields);
+      get_tax_income(pplayer, trade, &sci, &lux, &tax);
+
+      want += food * ai->food_priority;
+      want += ((shields * get_city_shield_bonus(acity)) / 100) 
+              * ai->shield_priority;
+      want -= city_pollution(acity, shields) * ai->pollution_priority;
+      want += ((lux * get_city_luxury_bonus(acity)) / 100)
+              * ai->luxury_priority;
+      want += ((sci * get_city_science_bonus(acity)) / 100)
+              * ai->science_priority;
+      want += ((city_gold_surplus(acity, tax) 
+                * get_city_tax_bonus(acity)) / 100)
+              * ai->gold_priority;
+      acity->ai.worth = want;
+    }
+  } city_list_iterate_end;
+
+  /* Add the improvement */
+  city_add_improvement(pcity, id);
+
+  /* Stir, then compare notes */
+  city_list_iterate(pplayer->cities, acity) {
+    if ((ai->impr_range[id] == EFR_CITY && acity == pcity)
+        || (ai->impr_range[id] == EFR_LOCAL && acity == pcity)
+        || (ai->impr_range[id] == EFR_CONTINENT
+            && map_get_continent(acity->x, acity->y) == continent)
+        || (ai->impr_range[id] == EFR_PLAYER)) {
+      int food, trade, shields, lux, sci, tax, want = 0;
+
+      get_food_trade_shields(acity, &food, &trade, &shields);
+      get_tax_income(pplayer, trade, &sci, &lux, &tax);
+      want += food * ai->food_priority;
+      want += ((shields * get_city_shield_bonus(acity)) / 100) 
+              * ai->shield_priority;
+      want -= city_pollution(acity, shields) * ai->pollution_priority;
+      want += ((lux * get_city_luxury_bonus(acity)) / 100)
+              * ai->luxury_priority;
+      want += ((sci * get_city_science_bonus(acity)) / 100)
+              * ai->science_priority;
+      want += ((city_gold_surplus(acity, tax) 
+                * get_city_tax_bonus(acity)) / 100)
+              * ai->gold_priority;
+      final_want += want - acity->ai.worth;
+    }
+  } city_list_iterate_end;
+
+  /* Restore */
+  city_remove_improvement(pcity, id);
+
+  /* Ensure that we didn't inadvertantly move our palace */
+  if (find_palace(pplayer) != capital) {
+    city_add_improvement(capital, get_building_for_effect(EFT_CAPITAL_CITY));
+  }
+
+  return final_want;
+}
+
 /************************************************************************** 
-...
+  Calculate effects. 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
+  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)
+{
+  struct player *pplayer = city_owner(pcity);
+  struct impr_type *pimpr = get_improvement_type(id);
+  int v = 0;
+  int cities[EFR_LAST];
+  int nplayers = game.nplayers
+                 - team_count_members_alive(pplayer->team);
+  struct ai_data *ai = ai_data_get(pplayer);
+  struct tile *ptile = map_get_tile(pcity->x, pcity->y);
+  bool capital = is_capital(pcity);
+  struct government *gov = get_gov_pplayer(pplayer);
+
+  /* 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, calc=%d)", 
+             get_improvement_name(id), v, ai->impr_range[id], 
ai->impr_calc[id]);
+  }
+
+  /* Find number of cities per range.  */
+  cities[EFR_PLAYER] = city_list_size(&pplayer->cities);
+  cities[EFR_WORLD] = cities[EFR_PLAYER]; /* kludge. */
+
+  cities[EFR_CONTINENT] = 0;
+  city_list_iterate(pplayer->cities, acity) {
+    if (map_get_tile(acity->x, acity->y)->continent == ptile->continent)
+      cities[EFR_CONTINENT]++;
+  } city_list_iterate_end;
+
+  cities[EFR_CITY] = 1;
+  cities[EFR_LOCAL] = 0;
+
+  /* Calculate desire value. */
+  effect_type_vector_iterate(get_building_effect_types(id), ptype) {
+    effect_list_iterate(*get_building_effects(id, *ptype), peff) {
+      if (is_effect_useful(TARGET_BUILDING, pplayer, pcity, id,
+                          NULL, id, peff)) {
+       int amount = peff->value, c = cities[peff->range];
+
+       switch (*ptype) {
+          /* TODO */
+         case EFT_INCITE_DIST_ADJ:
+         case EFT_INCITE_DIST_PCT:
+         case EFT_MAKE_CONTENT_MIL_PER:
+         case EFT_MAKE_HAPPY:
+         case EFT_UNIT_RECOVER:
+         case EFT_FORCE_CONTENT_PCT:
+         case EFT_MAKE_CONTENT_PCT:
+         case EFT_SEA_VET_COMBAT:
+         case EFT_AIR_VET_COMBAT:
+            break;
+
+          /* These have already been evaluated in base_want() */
+         case EFT_LUXURY_PCT:
+         case EFT_SCIENCE_PCT:
+         case EFT_TAX_PCT:
+          case EFT_CAPITAL_CITY:
+         case EFT_UPKEEP_FREE:
+         case EFT_POLLU_POP_PCT:
+         case EFT_POLLU_PROD_PCT:
+         case EFT_TRADE_PER_TILE:
+         case EFT_PROD_TO_GOLD:
+         case EFT_TRADE_INC_TILE:
+         case EFT_FOOD_BONUS:
+         case EFT_FOOD_PCT:
+         case EFT_FOOD_INC_TILE:
+         case EFT_POLLU_ADJ:
+         case EFT_POLLU_PCT:
+         case EFT_POLLU_POP_ADJ:
+         case EFT_POLLU_PROD_ADJ:
+         case EFT_TRADE_ADD_TILE:
+         case EFT_TRADE_BONUS:
+         case EFT_TRADE_PCT:
+         case EFT_NO_UPKEEP:
+         case EFT_PROD_PCT:
+         case EFT_PROD_INC_TILE:
+         case EFT_PROD_PER_TILE:
+         case EFT_PROD_ADD_TILE:
+         case EFT_FOOD_PER_TILE:
+         case EFT_FOOD_ADD_TILE:
+         case EFT_PROD_BONUS:
+          case EFT_TAX_BONUS:
+          case EFT_SCIENCE_BONUS:
+         case EFT_LUXURY_BONUS:
+          case EFT_CORRUPT_PCT:
+          case EFT_WASTE_PCT:
+           break;
+
+          /* WAG evaluated effects */
+         case EFT_NO_UNHAPPY:
+            v += (pcity->specialists[SP_ELVIS] + pcity->ppl_unhappy[0]) * 3;
+            break;
+         case EFT_FORCE_CONTENT:
+           if (!government_has_flag(gov, G_NO_UNHAPPY_CITIZENS)) {
+             v += (pcity->ppl_unhappy[0] + pcity->specialists[SP_ELVIS]) * 3;
+             v += 5 * c;
+           }
+           break;
+         case EFT_MAKE_CONTENT:
+           if (!government_has_flag(gov, G_NO_UNHAPPY_CITIZENS)) {
+             v += pcity->ppl_unhappy[0] * amount;
+             v += amount * c;
+           }
+           break;
+         case EFT_MAKE_CONTENT_MIL:
+           if (!government_has_flag(gov, G_NO_UNHAPPY_CITIZENS)) {
+             v += pcity->ppl_unhappy[4] * amount
+               * MAX(unit_list_size(&pcity->units_supported)
+                   - gov->free_happy, 0) * 2;
+             v += c * MAX(amount + 2 - gov->free_happy, 1);
+           }
+           break;
+         case EFT_TECH_PARASITE:
+           v += (total_bulbs_required(pplayer) * (100 - game.freecost)
+               * (nplayers - amount)) / (nplayers * amount * 100);
+           break;
+         case EFT_GROWTH_FOOD:
+           v += c * 4 + 25;
+           break;
+         case EFT_AIRLIFT:
+           v += c + ai->stats.units[UCL_LAND];
+           break;
+         case EFT_ANY_GOVERNMENT:
+           if (!can_change_to_government(pplayer, ai->goal.govt.idx)) {
+             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[UCL_MISSILE] * 5;
+           break;
+         case EFT_ENABLE_SPACE:
+           if (game.spacerace) {
+             v += 50;
+           }
+           break;
+         case EFT_GIVE_IMM_TECH:
+           v += ((total_bulbs_required(pplayer) * amount 
+                 + game.researchcost)
+               * TRADE_WEIGHTING - pplayer->research.bulbs_researched 
+               * TRADE_WEIGHTING) / MORT;
+           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.triremes * 5;
+           break;
+         case EFT_NUKE_PROOF:
+           if (ai->threats.nuclear) {
+             v += pcity->size * unit_list_size(&ptile->units) * (capital + 1);
+           }
+           break;
+         case EFT_REVEAL_MAP:
+           if (!ai->explore.land_done || !ai->explore.sea_done) {
+             v += 10;
+           }
+           break;
+         case EFT_SIZE_UNLIMIT:
+           amount = 20; /* really big city */
+           /* there not being a break here is deliberate, mind you */
+         case EFT_SIZE_ADJ: 
+           if (city_can_grow_to(pcity, pcity->size + 1)) {
+             v += pcity->food_surplus * ai->food_priority * amount / 10;
+           }
+           v += c * amount / game.aqueduct_size;
+           break;
+         case EFT_SS_STRUCTURAL:
+         case EFT_SS_COMPONENT:
+         case EFT_SS_MODULE:
+           if (game.spacerace && ai->diplomacy.strategy == WIN_SPACE) {
+             v += 95;
+           }
+           break;
+         case EFT_SPY_RESISTANT:
+           /* Uhm, problem: City Wall has -50% here!! */
+           break;
+         case EFT_SEA_MOVE:
+           v += ai->stats.units[UCL_SEA] * 8 * amount;
+           break;
+         case EFT_UNIT_NO_LOSE_POP:
+           v += unit_list_size(&(ptile->units)) * 2;
+           break;
+         case EFT_LAND_REGEN:
+           v += 15 * c + ai->stats.units[UCL_LAND] * 3;
+           break;
+         case EFT_SEA_REGEN:
+           v += 15 * c + ai->stats.units[UCL_SEA] * 3;
+           break;
+         case EFT_AIR_REGEN:
+           v += 15 * c + ai->stats.units[UCL_AIR] * 3;
+           break;
+         case EFT_LAND_VET_COMBAT:
+           v += 2 * c + ai->stats.units[UCL_LAND] * 2;
+           break;
+         case EFT_LAND_VETERAN:
+           v += 5 * c + ai->stats.units[UCL_LAND];
+           break;
+         case EFT_SEA_VETERAN:
+           v += 5 * c + ai->stats.units[UCL_SEA];
+           break;
+         case EFT_AIR_VETERAN:
+           v += 5 * c + ai->stats.units[UCL_AIR];
+           break;
+         case EFT_UPGRADE_UNIT:
+           v += ai->stats.units[UCL_LAST];
+           if (amount == 1) {
+             v *= 2;
+           } else if (amount == 2) {
+             v *= 3;
+           } else {
+             v *= 4;
+           }
+           break;
+         case EFT_SEA_DEFEND:
+           if (ai_handicap(pplayer, H_DEFENSIVE)) {
+             v += amount * 10; /* make AI slow */
+           }
+            if (is_ocean(map_get_terrain(pcity->x, pcity->y))) {
+              v += ai->threats.ocean[-map_get_continent(pcity->x, pcity->y)]
+                   ? amount * 8 : amount;
+            } else {
+              adjc_iterate(pcity->x, pcity->y, x2, y2) {
+                if (is_ocean(map_get_terrain(x2, y2))) {
+                  if (ai->threats.ocean[-map_get_continent(x2, y2)]) {
+                    v += 8 * amount;
+                  }
+                }
+              } adjc_iterate_end;
+            }
+           v += (amount + ai->threats.invasions - 1) * c; /* for wonder */
+           if (capital && ai->threats.invasions) {
+             v += amount * 10; /* defend capital! */
+           }
+           break;
+         case EFT_AIR_DEFEND:
+           if (ai_handicap(pplayer, H_DEFENSIVE)) {
+             v += amount * 15; /* make AI slow */
+           }
+           v += (ai->threats.air && ai->threats.continent[ptile->continent]) 
+             ? amount * 5 + amount * c : c;
+           break;
+         case EFT_MISSILE_DEFEND:
+           if (ai->threats.missile
+               && (ai->threats.continent[ptile->continent] || capital)) {
+             v += amount * 5 + (amount - 1) * c;
+           }
+           break;
+         case EFT_LAND_DEFEND:
+           if (ai_handicap(pplayer, H_DEFENSIVE)) {
+             v += amount * 10; /* make AI slow */
+           }
+           if (ai->threats.continent[ptile->continent]
+               || capital
+               || (ai->threats.invasions
+                 && is_water_adjacent_to_tile(pcity->x, pcity->y))) {
+             v += !ai->threats.igwall ? 15 + (capital * amount * 5) : 10;
+           }
+           v += (1 + ai->threats.invasions + !ai->threats.igwall) * c;
+           break;
+         case EFT_NO_INCITE:
+           if (!government_has_flag(gov, G_UNBRIBABLE)) {
+             v += MAX((game.diplchance * 2 - game.incite_cost.total_factor) / 2
+                 - game.incite_cost.improvement_factor * 5
+                 - game.incite_cost.unit_factor * 5, 0);
+           }
+           break;
+         case EFT_LAST:
+           freelog(LOG_ERROR, "Bad effect type.");
+           break;
+       }
+      }
+    } effect_list_iterate_end;
+  } effect_type_vector_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 -= pimpr->build_cost / (pcity->shield_surplus * 10 + 1);
+
+  /* Set */
+  pcity->ai.building_want[id] = v;
+}
+
+/************************************************************************** 
+  Prime pcity->ai.building_want[]
 **************************************************************************/
 static void ai_manage_buildings(struct player *pplayer)
-{ /* we have just managed all our cities but not chosen build for them yet */
-  struct government *g = get_gov_pplayer(pplayer);
-  Tech_Type_id j;
-  int values[B_LAST], leon = 0;
-  bool palace = FALSE;
-  int corr = 0;
-  memset(values, 0, sizeof(values));
-  memset(pplayer->ai.tech_want, 0, sizeof(pplayer->ai.tech_want));
-
-  if (find_palace(pplayer) || g->corruption_level == 0) palace = TRUE;
-  city_list_iterate(pplayer->cities, pcity)
-    ai_eval_buildings(pcity);
-    if (!palace) corr += pcity->corruption * 8;
-    impr_type_iterate(i) {
-      if (pcity->ai.building_want[i] > 0) values[i] += 
pcity->ai.building_want[i];
-    } impr_type_iterate_end;
-
-    if (pcity->ai.building_want[B_LEONARDO] > leon)
-      leon = pcity->ai.building_want[B_LEONARDO];
-  city_list_iterate_end;
-
-/* this is a weird place to iterate a units list! */
-  unit_list_iterate(pplayer->units, punit)
-    if (is_sailing_unit(punit))
-      values[B_MAGELLAN] +=
-         unit_build_shield_cost(punit->type) * 2 * SINGLE_MOVE /
-         unit_type(punit)->move_rate;
-  unit_list_iterate_end;
-  values[B_MAGELLAN] *= 100 * SHIELD_WEIGHTING;
-  values[B_MAGELLAN] /= (MORT * impr_build_shield_cost(B_MAGELLAN));
-
-  /* This is a weird place to put tech advice */
-  /* This was: > G_DESPOTISM; should maybe remove test, depending
-   * on new government evaluation etc, but used for now for
-   * regression testing --dwp */
-  if (g->index != game.default_government
-      && g->index != game.government_when_anarchy) {
-    impr_type_iterate(i) {
-      j = improvement_types[i].tech_req;
-      if (get_invention(pplayer, j) != TECH_KNOWN)
-        pplayer->ai.tech_want[j] += values[i];
-      /* if it is a bonus tech double it's value since it give a free
-        tech */
-      if (game.global_advances[j] == 0 && tech_flag(j, TF_BONUS_TECH))
-       pplayer->ai.tech_want[j] *= 2;
-      /* this probably isn't right -- Syela */
-      /* since it assumes that the next tech is as valuable as the
-        current -- JJCogliati */
-    } impr_type_iterate_end;
-  } /* tired of researching pottery when we need to learn Republic!! -- Syela 
*/
-
-
-  city_list_iterate(pplayer->cities, pcity)
-    pcity->ai.building_want[B_MAGELLAN] = values[B_MAGELLAN];
-    pcity->ai.building_want[B_ASMITHS] = values[B_ASMITHS];
-    pcity->ai.building_want[B_CURE] = values[B_CURE];
-    pcity->ai.building_want[B_HANGING] += values[B_CURE];
-    pcity->ai.building_want[B_WALL] = values[B_WALL];
-    pcity->ai.building_want[B_HOOVER] = values[B_HOOVER];
-    pcity->ai.building_want[B_BACH] = values[B_BACH];
-/* yes, I know that HOOVER and BACH should be continent-only not global */
-    pcity->ai.building_want[B_MICHELANGELO] = values[B_MICHELANGELO];
-    pcity->ai.building_want[B_ORACLE] = values[B_ORACLE];
-    pcity->ai.building_want[B_PYRAMIDS] = values[B_PYRAMIDS];
-    pcity->ai.building_want[B_SETI] = values[B_SETI];
-    pcity->ai.building_want[B_SUNTZU] = values[B_SUNTZU];
-    pcity->ai.building_want[B_WOMENS] = values[B_WOMENS];
-    pcity->ai.building_want[B_LEONARDO] = leon; /* hopefully will fix */
-    pcity->ai.building_want[B_PALACE] = corr; /* urgent enough? */
-  city_list_iterate_end;
-
-  city_list_iterate(pplayer->cities, pcity) /* wonder-kluge */
-    impr_type_iterate(i) {
-      if (!pcity->is_building_unit && is_wonder(i) &&
-          is_wonder(pcity->currently_building))
-       /* this should encourage completion of wonders, I hope! -- Syela */
-        pcity->ai.building_want[i] += pcity->shield_stock / 2;
-    } impr_type_iterate_end;
-  city_list_iterate_end;
+/* TODO:  RECALC_SPEED should be configurable to ai difficulty. -kauf  */
+#define RECALC_SPEED 5
+{
+  impr_type_iterate(id) {
+    if (!can_player_build_improvement(pplayer, id)
+        || improvement_obsolete(pplayer, id)) {
+      continue;
+    }
+    city_list_iterate(pplayer->cities, pcity) {
+      if (pcity->ai.next_recalc > game.turn) {
+        continue; /* do not recalc yet */
+      } else {
+        pcity->ai.building_want[id] = 0; /* do recalc */
+      }
+      if (city_got_building(pcity, id)
+          || pcity->shield_surplus == 0
+          || !can_build_improvement(pcity, id)
+          || improvement_redundant(pplayer, pcity, id, FALSE)) {
+        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;
+
+  /* Reset recalc counter */
+  city_list_iterate(pplayer->cities, pcity) {
+    if (pcity->ai.next_recalc <= game.turn) {
+      /* This will spread recalcs out so that no one turn end is 
+       * much longer than others */
+      pcity->ai.next_recalc = game.turn + myrand(RECALC_SPEED) + RECALC_SPEED;
+    }
+  } city_list_iterate_end;
 }
 
 /*************************************************************************** 
@@ -296,8 +642,8 @@
     if (best_role_unit(pcity, F_TRADE_ROUTE) != U_LAST) {
       pcity->ai.choice.choice = best_role_unit(pcity, F_TRADE_ROUTE);
       pcity->ai.choice.type = CT_NONMIL;
-    } else if (can_build_improvement(pcity, B_CAPITAL)) {
-      pcity->ai.choice.choice = B_CAPITAL;
+    } else if (can_build_improvement(pcity, game.default_building)) {
+      pcity->ai.choice.choice = game.default_building;
       pcity->ai.choice.type = CT_BUILDING;
     } else if (best_role_unit(pcity, F_SETTLERS) != U_LAST) {
       pcity->ai.choice.choice = best_role_unit(pcity, F_SETTLERS);
@@ -355,7 +701,8 @@
 static void try_to_sell_stuff(struct player *pplayer, struct city *pcity)
 {
   impr_type_iterate(id) {
-    if (can_sell_building(pcity, id) && id != B_CITY) {
+    if (can_sell_building(pcity, id)
+       && !building_has_effect(id, EFT_LAND_DEFEND)) {
 /* selling walls to buy defenders is counterproductive -- Syela */
       really_handle_city_sell(pplayer, pcity, id);
       break;
@@ -488,7 +835,7 @@
 
     if (bestchoice.type != CT_BUILDING
         && unit_type_flag(bestchoice.choice, F_CITIES)) {
-      if (!city_got_effect(pcity, B_GRANARY) 
+      if (get_city_bonus(pcity, EFT_GROWTH_FOOD) == 0
           && pcity->size == 1
           && city_granary_size(pcity->size)
              > pcity->food_stock + pcity->food_surplus) {
@@ -607,7 +954,7 @@
 static bool building_unwanted(struct player *plr, Impr_Type_id i)
 {
   return (ai_wants_no_science(plr)
-         && (i == B_LIBRARY || i == B_UNIVERSITY || i == B_RESEARCH));
+          && building_has_effect(i, EFT_SCIENCE_BONUS));
 }
 
 /**************************************************************************
@@ -619,9 +966,10 @@
 
   built_impr_iterate(pcity, i) {
     if(!is_wonder(i) 
-       && i != B_CITY /* selling city walls is really, really dumb -- Syela */
+       && !building_has_effect(i, EFT_LAND_DEFEND)
+             /* selling city walls is really, really dumb -- Syela */
        && (building_replaced(pcity, i)
-          || building_unwanted(city_owner(pcity), i))) {
+        || building_unwanted(city_owner(pcity), i))) {
       do_sell_building(pplayer, pcity, i);
       notify_player_ex(pplayer, pcity->x, pcity->y, E_IMP_SOLD,
                       _("Game: %s is selling %s (not needed) for %d."), 
Index: ai/aicity.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.h,v
retrieving revision 1.24
diff -u -r1.24 aicity.h
--- ai/aicity.h 3 Sep 2004 04:22:36 -0000       1.24
+++ ai/aicity.h 6 Sep 2004 01:11:03 -0000
@@ -15,15 +15,14 @@
 
 #include "fc_types.h"
 #include "unit.h"              /* enum unit_move_type */
+#include "city.h"
+#include "aidata.h"
 
 struct ai_choice;
-struct ai_data;
-
-int ai_eval_calc_city(struct city *pcity, struct ai_data *ai);
 
 void ai_manage_cities(struct player *pplayer);
 
-enum ai_city_task { AICITY_NONE, AICITY_TECH, AICITY_TAX, AICITY_PROD};
-/* These are not used (well, except AICITY_NONE)  --dwp */
+Unit_Type_id ai_choose_defender_versus(struct city *pcity, Unit_Type_id v);
+int ai_eval_calc_city(struct city *pcity, struct ai_data *ai);
 
 #endif  /* FC__AICITY_H */
Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.37
diff -u -r1.37 aidata.c
--- ai/aidata.c 2 Sep 2004 20:51:48 -0000       1.37
+++ ai/aidata.c 6 Sep 2004 01:11:03 -0000
@@ -1,389 +1,484 @@
-/********************************************************************** 
- Freeciv - Copyright (C) 2002 - The Freeciv Project
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "aisupport.h"
-#include "city.h"
-#include "game.h"
-#include "government.h"
-#include "log.h"
-#include "map.h"
-#include "mem.h"
-#include "unit.h"
-
-#include "citytools.h"
-#include "diplhand.h"
-#include "maphand.h"
-#include "settlers.h"
-#include "unittools.h"
-
-#include "advdiplomacy.h"
-#include "advmilitary.h"
-#include "aicity.h"
-#include "aiferry.h"
-#include "aihand.h"
-#include "ailog.h"
-#include "aitools.h"
-#include "aiunit.h"
-
-#include "aidata.h"
-
-static struct ai_data aidata[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
-
-/**************************************************************************
-  Make and cache lots of calculations needed for other functions.
-
-  Note: We use map.num_continents here rather than pplayer->num_continents
-  because we are omniscient and don't care about such trivialities as who
-  can see what.
-
-  FIXME: We should try to find the lowest common defence strength of our
-  defending units, and ignore enemy units that are incapable of harming 
-  us, instead of just checking attack strength > 1.
-**************************************************************************/
-void ai_data_turn_init(struct player *pplayer) 
-{
-  struct ai_data *ai = &aidata[pplayer->player_no];
-  int i, nuke_units = num_role_units(F_NUCLEAR);
-  bool danger_of_nukes = FALSE;
-  int ally_strength = -1;
-  struct player *ally_strongest = NULL;
-
-  /*** Threats ***/
-
-  ai->num_continents    = map.num_continents;
-  ai->num_oceans        = map.num_oceans;
-  ai->threats.continent = fc_calloc(ai->num_continents + 1, sizeof(bool));
-  ai->threats.invasions = FALSE;
-  ai->threats.air       = FALSE;
-  ai->threats.nuclear   = 0; /* none */
-  ai->threats.ocean     = fc_calloc(ai->num_oceans + 1, sizeof(bool));
-
-  players_iterate(aplayer) {
-    if (!is_player_dangerous(pplayer, aplayer)) {
-      continue;
-    }
-
-    /* The idea is that if there aren't any hostile cities on
-     * our continent, the danger of land attacks is not big
-     * enough to warrant city walls. Concentrate instead on 
-     * coastal fortresses and hunting down enemy transports. */
-    city_list_iterate(aplayer->cities, acity) {
-      Continent_id continent = map_get_continent(acity->x, acity->y);
-      ai->threats.continent[continent] = TRUE;
-    } city_list_iterate_end;
-
-    unit_list_iterate(aplayer->units, punit) {
-      if (is_sailing_unit(punit)) {
-        /* If the enemy has not started sailing yet, or we have total
-         * control over the seas, don't worry, keep attacking. */
-        if (is_ground_units_transport(punit)) {
-          ai->threats.invasions = TRUE;
-        }
-
-        /* The idea is that while our enemies don't have any offensive
-         * seaborne units, we don't have to worry. Go on the offensive! */
-        if (unit_type(punit)->attack_strength > 1) {
-         if (is_ocean(map_get_terrain(punit->x, punit->y))) {
-           Continent_id continent = map_get_continent(punit->x, punit->y);
-           ai->threats.ocean[-continent] = TRUE;
-         } else {
-           adjc_iterate(punit->x, punit->y, x2, y2) {
-             if (is_ocean(map_get_terrain(x2, y2))) {
-               Continent_id continent = map_get_continent(x2, y2);
-               ai->threats.ocean[-continent] = TRUE;
-             }
-           } adjc_iterate_end;
-         }
-        } 
-        continue;
-      }
-
-      /* The next idea is that if our enemies don't have any offensive
-       * airborne units, we don't have to worry. Go on the offensive! */
-      if ((is_air_unit(punit) || is_heli_unit(punit))
-           && unit_type(punit)->attack_strength > 1) {
-        ai->threats.air = TRUE;
-      }
-
-      /* If our enemy builds missiles, worry about missile defence. */
-      if (unit_flag(punit, F_MISSILE)
-          && unit_type(punit)->attack_strength > 1) {
-        ai->threats.missile = TRUE;
-      }
-
-      /* If he builds nukes, worry a lot. */
-      if (unit_flag(punit, F_NUCLEAR)) {
-        danger_of_nukes = TRUE;
-      }
-    } unit_list_iterate_end;
-
-    /* Check for nuke capability */
-    for (i = 0; i < nuke_units; i++) {
-      Unit_Type_id nuke = get_role_unit(F_NUCLEAR, i);
-      if (can_player_build_unit_direct(aplayer, nuke)) { 
-        ai->threats.nuclear = 1;
-      }
-    }
-  } players_iterate_end;
-
-  /* Increase from fear to terror if opponent actually has nukes */
-  if (danger_of_nukes) ai->threats.nuclear++; /* sum of both fears */
-
-  /*** Exploration ***/
-
-  ai->explore.land_done = TRUE;
-  ai->explore.sea_done = TRUE;
-  ai->explore.continent = fc_calloc(ai->num_continents + 1, sizeof(bool));
-  ai->explore.ocean = fc_calloc(ai->num_oceans + 1, sizeof(bool));
-  whole_map_iterate(x, y) {
-    struct tile *ptile = map_get_tile(x, y);
-    Continent_id continent = map_get_continent(x, y);
-
-    if (is_ocean(ptile->terrain)) {
-      if (ai->explore.sea_done && ai_handicap(pplayer, H_TARGETS) 
-          && !map_is_known(x, y, pplayer)) {
-       /* We're not done there. */
-        ai->explore.sea_done = FALSE;
-        ai->explore.ocean[-continent] = TRUE;
-      }
-      /* skip rest, which is land only */
-      continue;
-    }
-    if (ai->explore.continent[ptile->continent]) {
-      /* we don't need more explaining, we got the point */
-      continue;
-    }
-    if (map_has_special(x, y, S_HUT) 
-        && (!ai_handicap(pplayer, H_HUTS)
-             || map_is_known(x, y, pplayer))) {
-      ai->explore.land_done = FALSE;
-      ai->explore.continent[continent] = TRUE;
-      continue;
-    }
-    if (ai_handicap(pplayer, H_TARGETS) && !map_is_known(x, y, pplayer)) {
-      /* this AI must explore */
-      ai->explore.land_done = FALSE;
-      ai->explore.continent[continent] = TRUE;
-    }
-  } whole_map_iterate_end;
-
-  /*** Statistics ***/
-
-  ai->stats.workers = fc_calloc(ai->num_continents + 1, sizeof(int));
-  ai->stats.cities = fc_calloc(ai->num_continents + 1, sizeof(int));
-  ai->stats.average_production = 0;
-  city_list_iterate(pplayer->cities, pcity) {
-    ai->stats.cities[(int)map_get_continent(pcity->x, pcity->y)]++;
-    ai->stats.average_production += pcity->shield_surplus;
-  } city_list_iterate_end;
-  ai->stats.average_production /= MAX(1, city_list_size(&pplayer->cities));
-  BV_CLR_ALL(ai->stats.diplomat_reservations);
-  unit_list_iterate(pplayer->units, punit) {
-    struct tile *ptile = map_get_tile(punit->x, punit->y);
-
-    if (!is_ocean(ptile->terrain) && unit_flag(punit, F_SETTLERS)) {
-      ai->stats.workers[(int)map_get_continent(punit->x, punit->y)]++;
-    }
-    if (unit_flag(punit, F_DIPLOMAT) && punit->ai.ai_role == AIUNIT_ATTACK) {
-      /* Heading somewhere on a mission, reserve target. */
-      struct city *pcity = map_get_city(goto_dest_x(punit),
-                                       goto_dest_y(punit));;
-      if (pcity) {
-        BV_SET(ai->stats.diplomat_reservations, pcity->id);
-      }
-    }
-  } unit_list_iterate_end;
-  aiferry_init_stats(pplayer);
-
-  /*** Diplomacy ***/
-
-  if (pplayer->ai.control && !is_barbarian(pplayer)) {
-    ai_diplomacy_calculate(pplayer, ai);
-  }
-
-  /* Question: What can we accept as the reputation of a player before
-   * we start taking action to prevent us from being suckered?
-   * Answer: Very little. */
-  ai->diplomacy.acceptable_reputation =
-           GAME_DEFAULT_REPUTATION -
-           GAME_DEFAULT_REPUTATION / 4;
-
-  /* Set per-player variables. We must set all players, since players 
-   * can be created during a turn, and we don't want those to have 
-   * invalid values. */
-  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
-    struct player *aplayer = get_player(i);
-
-    ai->diplomacy.player_intel[i].is_allied_with_enemy = NULL;
-    ai->diplomacy.player_intel[i].at_war_with_ally = NULL;
-    ai->diplomacy.player_intel[i].is_allied_with_ally = NULL;
-
-    /* Determine who is the leader of our alliance. That is,
-     * whoever has the more cities. */
-    if (pplayers_allied(pplayer, aplayer)
-        && city_list_size(&aplayer->cities) > ally_strength) {
-      ally_strength = city_list_size(&aplayer->cities);
-      ally_strongest = aplayer;
-    }
-
-    players_iterate(check_pl) {
-      if (check_pl == pplayer
-          || check_pl == aplayer
-          || !check_pl->is_alive) {
-        continue;
-      }
-      if (pplayers_allied(aplayer, check_pl)
-          && pplayer_get_diplstate(pplayer, check_pl)->type == DS_WAR) {
-       ai->diplomacy.player_intel[i].is_allied_with_enemy = check_pl;
-      }
-      if (pplayers_allied(pplayer, check_pl)
-          && pplayer_get_diplstate(aplayer, check_pl)->type == DS_WAR) {
-        ai->diplomacy.player_intel[i].at_war_with_ally = check_pl;
-      }
-      if (pplayers_allied(aplayer, check_pl)
-          && pplayers_allied(pplayer, check_pl)) {
-        ai->diplomacy.player_intel[i].is_allied_with_ally = check_pl;
-      }
-    } players_iterate_end;
-  }
-  if (ally_strongest != ai->diplomacy.alliance_leader) {
-    ai->diplomacy.alliance_leader = ally_strongest;
-  }
-  ai->diplomacy.spacerace_leader = player_leading_spacerace();
-
-  /*** Priorities ***/
-
-  /* NEVER set these to zero! Weight values are usually multiplied by 
-   * these values, so be careful with them. They are used in city 
-   * and government calculations, and food and shields should be 
-   * slightly bigger because we only look at surpluses there. They
-   * are all WAGs. */
-  ai->food_priority = FOOD_WEIGHTING;
-  ai->shield_priority = SHIELD_WEIGHTING;
-  if (ai_wants_no_science(pplayer)) {
-    ai->luxury_priority = TRADE_WEIGHTING;
-    ai->science_priority = 1;
-  } else {
-    ai->luxury_priority = 1;
-    ai->science_priority = TRADE_WEIGHTING;
-  }
-  ai->gold_priority = TRADE_WEIGHTING;
-  ai->happy_priority = 1;
-  ai->unhappy_priority = TRADE_WEIGHTING; /* danger */
-  ai->angry_priority = TRADE_WEIGHTING * 3; /* grave danger */
-  ai->pollution_priority = POLLUTION_WEIGHTING;
-
-  ai_best_government(pplayer);
-
-  /*** Interception engine ***/
-
-  /* We are tracking a unit if punit->ai.cur_pos is not NULL. If we
-   * are not tracking, start tracking by setting cur_pos. If we are, 
-   * fill prev_pos with previous cur_pos. This way we get the 
-   * necessary coordinates to calculate a probably trajectory. */
-  players_iterate(aplayer) {
-    if (!aplayer->is_alive || aplayer == pplayer) {
-      continue;
-    }
-    unit_list_iterate(aplayer->units, punit) {
-      if (!punit->ai.cur_pos) {
-        /* Start tracking */
-        punit->ai.cur_pos = &punit->ai.cur_struct;
-        punit->ai.prev_pos = NULL;
-      } else {
-        punit->ai.prev_struct = punit->ai.cur_struct;
-        punit->ai.prev_pos = &punit->ai.prev_struct;
-      }
-      punit->ai.cur_pos->x = punit->x;
-      punit->ai.cur_pos->y = punit->y;
-    } unit_list_iterate_end;
-  } players_iterate_end;
-}
-
-/**************************************************************************
-  Clean up our mess.
-**************************************************************************/
-void ai_data_turn_done(struct player *pplayer)
-{
-  struct ai_data *ai = &aidata[pplayer->player_no];
-
-  free(ai->explore.ocean);     ai->explore.ocean = NULL;
-  free(ai->explore.continent); ai->explore.continent = NULL;
-  free(ai->threats.continent); ai->threats.continent = NULL;
-  free(ai->stats.workers);     ai->stats.workers = NULL;
-  free(ai->stats.cities);      ai->stats.cities = NULL;
-}
-
-/**************************************************************************
-  Return a pointer to our data
-**************************************************************************/
-struct ai_data *ai_data_get(struct player *pplayer)
-{
-  struct ai_data *ai = &aidata[pplayer->player_no];
-
-  if (ai->num_continents != map.num_continents
-      || ai->num_oceans != map.num_oceans) {
-    /* we discovered more continents, recalculate! */
-    ai_data_turn_done(pplayer);
-    ai_data_turn_init(pplayer);
-  }
-  return ai;
-}
-
-/**************************************************************************
-  Initialize with sane values.
-**************************************************************************/
-void ai_data_init(struct player *pplayer)
-{
-  struct ai_data *ai = &aidata[pplayer->player_no];
-  int i;
-
-  ai->govt_reeval = 0;
-  ai->government_want = fc_calloc(game.government_count + 1, sizeof(int));
-
-  ai->diplomacy.target = NULL;
-  ai->diplomacy.strategy = WIN_OPEN;
-  ai->diplomacy.timer = 0;
-  ai->diplomacy.countdown = 0;
-  ai->diplomacy.love_coeff = 4; /* 4% */
-  ai->diplomacy.love_incr = 4;
-  ai->diplomacy.req_love_for_peace = 8;
-  ai->diplomacy.req_love_for_alliance = 16;
-  ai->diplomacy.req_love_for_ceasefire = 0;
-  ai->diplomacy.alliance_leader = pplayer;
-
-  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
-    ai->diplomacy.player_intel[i].spam = i % 5; /* pseudorandom */
-    ai->diplomacy.player_intel[i].distance = 1;
-    ai->diplomacy.player_intel[i].ally_patience = 0;
-    pplayer->ai.love[i] = 1;
-    ai->diplomacy.player_intel[i].asked_about_peace = 0;
-    ai->diplomacy.player_intel[i].asked_about_alliance = 0;
-    ai->diplomacy.player_intel[i].asked_about_ceasefire = 0;
-    ai->diplomacy.player_intel[i].warned_about_space = 0;
-  }
-}
-
-/**************************************************************************
-  Deinitialize data
-**************************************************************************/
-void ai_data_done(struct player *pplayer)
-{
-  struct ai_data *ai = &aidata[pplayer->player_no];
-
-  free(ai->government_want);
-}
+/********************************************************************** 
+ Freeciv - Copyright (C) 2002 - The Freeciv Project
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "aisupport.h"
+#include "city.h"
+#include "effects.h"
+#include "game.h"
+#include "government.h"
+#include "log.h"
+#include "map.h"
+#include "mem.h"
+#include "unit.h"
+
+#include "citytools.h"
+#include "diplhand.h"
+#include "maphand.h"
+#include "settlers.h"
+#include "unittools.h"
+
+#include "advdiplomacy.h"
+#include "advmilitary.h"
+#include "aicity.h"
+#include "aiferry.h"
+#include "aihand.h"
+#include "ailog.h"
+#include "aitools.h"
+#include "aiunit.h"
+
+#include "aidata.h"
+
+static struct ai_data aidata[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+
+/**************************************************************************
+  Precalculates some important data about the improvements in the game
+  that we use later in ai/aicity.c.  We mark improvements as 'calculate'
+  if we want to run a full test on them, as 'estimate' if we just want
+  to do some guesses on them, or as 'unused' is they are useless to us.
+  Then we find the largest range of calculatable effects in the
+  improvement and record it for later use.
+**************************************************************************/
+static void ai_data_city_impr_calc(struct player *pplayer, struct ai_data *ai)
+{
+  int count[AI_IMPR_LAST];
+
+  memset(count, 0, sizeof(count));
+
+  impr_type_iterate(id) {
+    ai->impr_calc[id] = AI_IMPR_ESTIMATE;
+
+    /* Find largest extension */
+    effect_type_vector_iterate(get_building_effect_types(id), ptype) {
+      switch (*ptype) {
+#if 0
+      /* TODO */
+      case EFT_FORCE_CONTENT:
+      case EFT_FORCE_CONTENT_PCT:
+      case EFT_MAKE_CONTENT:
+      case EFT_MAKE_CONTENT_MIL:
+      case EFT_MAKE_CONTENT_MIL_PER:
+      case EFT_MAKE_CONTENT_PCT:
+      case EFT_MAKE_HAPPY:
+#endif
+      case EFT_LUXURY_BONUS:
+      case EFT_LUXURY_PCT:
+      case EFT_SCIENCE_BONUS:
+      case EFT_SCIENCE_PCT:
+      case EFT_TAX_BONUS:
+      case EFT_TAX_PCT:
+      case EFT_CAPITAL_CITY:
+      case EFT_CORRUPT_PCT:
+      case EFT_FOOD_ADD_TILE:
+      case EFT_FOOD_BONUS:
+      case EFT_FOOD_PCT:
+      case EFT_FOOD_INC_TILE:
+      case EFT_FOOD_PER_TILE:
+      case EFT_POLLU_ADJ:
+      case EFT_POLLU_PCT:
+      case EFT_POLLU_POP_ADJ:
+      case EFT_POLLU_POP_PCT:
+      case EFT_POLLU_PROD_ADJ:
+      case EFT_POLLU_PROD_PCT:
+      case EFT_PROD_ADD_TILE:
+      case EFT_PROD_BONUS:
+      case EFT_PROD_PCT:
+      case EFT_PROD_INC_TILE:
+      case EFT_PROD_PER_TILE:
+      case EFT_TRADE_ADD_TILE:
+      case EFT_TRADE_BONUS:
+      case EFT_TRADE_PCT:
+      case EFT_TRADE_INC_TILE:
+      case EFT_TRADE_PER_TILE:
+      case EFT_UPKEEP_FREE:
+      effect_list_iterate(*get_building_effects(id, *ptype), peff) {
+        ai->impr_calc[id] = AI_IMPR_CALCULATE;
+        if (peff->range > ai->impr_range[id]) {
+          ai->impr_range[id] = peff->range;
+        }
+      } effect_list_iterate_end;
+      break;
+      default:
+      /* Nothing! */
+      break;
+      }
+    } effect_type_vector_iterate_end;
+    
+  } impr_type_iterate_end;
+}
+
+/**************************************************************************
+  Analyze rulesets. Must be run after rulesets after loaded, unlike
+  _init, which must be run before savegames are loaded, which is usually
+  before rulesets.
+**************************************************************************/
+void ai_data_analyze_rulesets(struct player *pplayer)
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+
+freelog(LOG_NORMAL, "yep, ran");
+  ai_data_city_impr_calc(pplayer, ai);
+}
+
+/**************************************************************************
+  Make and cache lots of calculations needed for other functions.
+
+  Note: We use map.num_continents here rather than pplayer->num_continents
+  because we are omniscient and don't care about such trivialities as who
+  can see what.
+
+  FIXME: We should try to find the lowest common defence strength of our
+  defending units, and ignore enemy units that are incapable of harming 
+  us, instead of just checking attack strength > 1.
+**************************************************************************/
+void ai_data_turn_init(struct player *pplayer) 
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+  int i, nuke_units = num_role_units(F_NUCLEAR);
+  bool danger_of_nukes = FALSE;
+  int ally_strength = -1;
+  struct player *ally_strongest = NULL;
+
+  /*** Threats ***/
+
+  ai->num_continents    = map.num_continents;
+  ai->num_oceans        = map.num_oceans;
+  ai->threats.continent = fc_calloc(ai->num_continents + 1, sizeof(bool));
+  ai->threats.invasions = FALSE;
+  ai->threats.air       = FALSE;
+  ai->threats.nuclear   = 0; /* none */
+  ai->threats.ocean     = fc_calloc(ai->num_oceans + 1, sizeof(bool));
+  ai->threats.igwall    = FALSE;
+
+  players_iterate(aplayer) {
+    if (!is_player_dangerous(pplayer, aplayer)) {
+      continue;
+    }
+
+    /* The idea is that if there aren't any hostile cities on
+     * our continent, the danger of land attacks is not big
+     * enough to warrant city walls. Concentrate instead on 
+     * coastal fortresses and hunting down enemy transports. */
+    city_list_iterate(aplayer->cities, acity) {
+      Continent_id continent = map_get_continent(acity->x, acity->y);
+      ai->threats.continent[continent] = TRUE;
+    } city_list_iterate_end;
+
+    unit_list_iterate(aplayer->units, punit) {
+      if (unit_flag(punit, F_IGWALL)) {
+        ai->threats.igwall = TRUE;
+      }
+
+      if (is_sailing_unit(punit)) {
+        /* If the enemy has not started sailing yet, or we have total
+         * control over the seas, don't worry, keep attacking. */
+        if (is_ground_units_transport(punit)) {
+          ai->threats.invasions = TRUE;
+        }
+
+        /* The idea is that while our enemies don't have any offensive
+         * seaborne units, we don't have to worry. Go on the offensive! */
+        if (unit_type(punit)->attack_strength > 1) {
+         if (is_ocean(map_get_terrain(punit->x, punit->y))) {
+           Continent_id continent = map_get_continent(punit->x, punit->y);
+           ai->threats.ocean[-continent] = TRUE;
+         } else {
+           adjc_iterate(punit->x, punit->y, x2, y2) {
+             if (is_ocean(map_get_terrain(x2, y2))) {
+               Continent_id continent = map_get_continent(x2, y2);
+               ai->threats.ocean[-continent] = TRUE;
+             }
+           } adjc_iterate_end;
+         }
+        } 
+        continue;
+      }
+
+      /* The next idea is that if our enemies don't have any offensive
+       * airborne units, we don't have to worry. Go on the offensive! */
+      if ((is_air_unit(punit) || is_heli_unit(punit))
+           && unit_type(punit)->attack_strength > 1) {
+        ai->threats.air = TRUE;
+      }
+
+      /* If our enemy builds missiles, worry about missile defence. */
+      if (unit_flag(punit, F_MISSILE)
+          && unit_type(punit)->attack_strength > 1) {
+        ai->threats.missile = TRUE;
+      }
+
+      /* If he builds nukes, worry a lot. */
+      if (unit_flag(punit, F_NUCLEAR)) {
+        danger_of_nukes = TRUE;
+      }
+    } unit_list_iterate_end;
+
+    /* Check for nuke capability */
+    for (i = 0; i < nuke_units; i++) {
+      Unit_Type_id nuke = get_role_unit(F_NUCLEAR, i);
+      if (can_player_build_unit_direct(aplayer, nuke)) { 
+        ai->threats.nuclear = 1;
+      }
+    }
+  } players_iterate_end;
+
+  /* Increase from fear to terror if opponent actually has nukes */
+  if (danger_of_nukes) ai->threats.nuclear++; /* sum of both fears */
+
+  /*** Exploration ***/
+
+  ai->explore.land_done = TRUE;
+  ai->explore.sea_done = TRUE;
+  ai->explore.continent = fc_calloc(ai->num_continents + 1, sizeof(bool));
+  ai->explore.ocean = fc_calloc(ai->num_oceans + 1, sizeof(bool));
+  whole_map_iterate(x, y) {
+    struct tile *ptile = map_get_tile(x, y);
+    Continent_id continent = map_get_continent(x, y);
+
+    if (is_ocean(ptile->terrain)) {
+      if (ai->explore.sea_done && ai_handicap(pplayer, H_TARGETS) 
+          && !map_is_known(x, y, pplayer)) {
+       /* We're not done there. */
+        ai->explore.sea_done = FALSE;
+        ai->explore.ocean[-continent] = TRUE;
+      }
+      /* skip rest, which is land only */
+      continue;
+    }
+    if (ai->explore.continent[ptile->continent]) {
+      /* we don't need more explaining, we got the point */
+      continue;
+    }
+    if (map_has_special(x, y, S_HUT) 
+        && (!ai_handicap(pplayer, H_HUTS)
+             || map_is_known(x, y, pplayer))) {
+      ai->explore.land_done = FALSE;
+      ai->explore.continent[continent] = TRUE;
+      continue;
+    }
+    if (ai_handicap(pplayer, H_TARGETS) && !map_is_known(x, y, pplayer)) {
+      /* this AI must explore */
+      ai->explore.land_done = FALSE;
+      ai->explore.continent[continent] = TRUE;
+    }
+  } whole_map_iterate_end;
+
+  /*** Statistics ***/
+
+  ai->stats.workers = fc_calloc(ai->num_continents + 1, sizeof(int));
+  ai->stats.cities = fc_calloc(ai->num_continents + 1, sizeof(int));
+  ai->stats.average_production = 0;
+  city_list_iterate(pplayer->cities, pcity) {
+    ai->stats.cities[(int)map_get_continent(pcity->x, pcity->y)]++;
+    ai->stats.average_production += pcity->shield_surplus;
+  } city_list_iterate_end;
+  ai->stats.average_production /= MAX(1, city_list_size(&pplayer->cities));
+  BV_CLR_ALL(ai->stats.diplomat_reservations);
+  unit_list_iterate(pplayer->units, punit) {
+    struct tile *ptile = map_get_tile(punit->x, punit->y);
+
+    if (!is_ocean(ptile->terrain) && unit_flag(punit, F_SETTLERS)) {
+      ai->stats.workers[(int)map_get_continent(punit->x, punit->y)]++;
+    }
+    if (unit_flag(punit, F_DIPLOMAT) && punit->ai.ai_role == AIUNIT_ATTACK) {
+      /* Heading somewhere on a mission, reserve target. */
+      struct city *pcity = map_get_city(goto_dest_x(punit),
+                                       goto_dest_y(punit));;
+      if (pcity) {
+        BV_SET(ai->stats.diplomat_reservations, pcity->id);
+      }
+    }
+  } unit_list_iterate_end;
+  aiferry_init_stats(pplayer);
+
+  /*** Diplomacy ***/
+
+  if (pplayer->ai.control && !is_barbarian(pplayer)) {
+    ai_diplomacy_calculate(pplayer, ai);
+  }
+
+  /* Question: What can we accept as the reputation of a player before
+   * we start taking action to prevent us from being suckered?
+   * Answer: Very little. */
+  ai->diplomacy.acceptable_reputation =
+           GAME_DEFAULT_REPUTATION -
+           GAME_DEFAULT_REPUTATION / 4;
+
+  /* Set per-player variables. We must set all players, since players 
+   * can be created during a turn, and we don't want those to have 
+   * invalid values. */
+  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+    struct player *aplayer = get_player(i);
+
+    ai->diplomacy.player_intel[i].is_allied_with_enemy = NULL;
+    ai->diplomacy.player_intel[i].at_war_with_ally = NULL;
+    ai->diplomacy.player_intel[i].is_allied_with_ally = NULL;
+
+    /* Determine who is the leader of our alliance. That is,
+     * whoever has the more cities. */
+    if (pplayers_allied(pplayer, aplayer)
+        && city_list_size(&aplayer->cities) > ally_strength) {
+      ally_strength = city_list_size(&aplayer->cities);
+      ally_strongest = aplayer;
+    }
+
+    players_iterate(check_pl) {
+      if (check_pl == pplayer
+          || check_pl == aplayer
+          || !check_pl->is_alive) {
+        continue;
+      }
+      if (pplayers_allied(aplayer, check_pl)
+          && pplayer_get_diplstate(pplayer, check_pl)->type == DS_WAR) {
+       ai->diplomacy.player_intel[i].is_allied_with_enemy = check_pl;
+      }
+      if (pplayers_allied(pplayer, check_pl)
+          && pplayer_get_diplstate(aplayer, check_pl)->type == DS_WAR) {
+        ai->diplomacy.player_intel[i].at_war_with_ally = check_pl;
+      }
+      if (pplayers_allied(aplayer, check_pl)
+          && pplayers_allied(pplayer, check_pl)) {
+        ai->diplomacy.player_intel[i].is_allied_with_ally = check_pl;
+      }
+    } players_iterate_end;
+  }
+  if (ally_strongest != ai->diplomacy.alliance_leader) {
+    ai->diplomacy.alliance_leader = ally_strongest;
+  }
+  ai->diplomacy.spacerace_leader = player_leading_spacerace();
+
+  /*** Priorities ***/
+
+  /* NEVER set these to zero! Weight values are usually multiplied by 
+   * these values, so be careful with them. They are used in city 
+   * and government calculations, and food and shields should be 
+   * slightly bigger because we only look at surpluses there. They
+   * are all WAGs. */
+  ai->food_priority = FOOD_WEIGHTING;
+  ai->shield_priority = SHIELD_WEIGHTING;
+  if (ai_wants_no_science(pplayer)) {
+    ai->luxury_priority = TRADE_WEIGHTING;
+    ai->science_priority = 1;
+  } else {
+    ai->luxury_priority = 1;
+    ai->science_priority = TRADE_WEIGHTING;
+  }
+  ai->gold_priority = TRADE_WEIGHTING;
+  ai->happy_priority = 1;
+  ai->unhappy_priority = TRADE_WEIGHTING; /* danger */
+  ai->angry_priority = TRADE_WEIGHTING * 3; /* grave danger */
+  ai->pollution_priority = POLLUTION_WEIGHTING;
+
+  ai_best_government(pplayer);
+
+  /*** Interception engine ***/
+
+  /* We are tracking a unit if punit->ai.cur_pos is not NULL. If we
+   * are not tracking, start tracking by setting cur_pos. If we are, 
+   * fill prev_pos with previous cur_pos. This way we get the 
+   * necessary coordinates to calculate a probably trajectory. */
+  players_iterate(aplayer) {
+    if (!aplayer->is_alive || aplayer == pplayer) {
+      continue;
+    }
+    unit_list_iterate(aplayer->units, punit) {
+      if (!punit->ai.cur_pos) {
+        /* Start tracking */
+        punit->ai.cur_pos = &punit->ai.cur_struct;
+        punit->ai.prev_pos = NULL;
+      } else {
+        punit->ai.prev_struct = punit->ai.cur_struct;
+        punit->ai.prev_pos = &punit->ai.prev_struct;
+      }
+      punit->ai.cur_pos->x = punit->x;
+      punit->ai.cur_pos->y = punit->y;
+    } unit_list_iterate_end;
+  } players_iterate_end;
+}
+
+/**************************************************************************
+  Clean up our mess.
+**************************************************************************/
+void ai_data_turn_done(struct player *pplayer)
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+
+  free(ai->explore.ocean);     ai->explore.ocean = NULL;
+  free(ai->explore.continent); ai->explore.continent = NULL;
+  free(ai->threats.continent); ai->threats.continent = NULL;
+  free(ai->stats.workers);     ai->stats.workers = NULL;
+  free(ai->stats.cities);      ai->stats.cities = NULL;
+}
+
+/**************************************************************************
+  Return a pointer to our data
+**************************************************************************/
+struct ai_data *ai_data_get(struct player *pplayer)
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+
+  if (ai->num_continents != map.num_continents
+      || ai->num_oceans != map.num_oceans) {
+    /* we discovered more continents, recalculate! */
+    ai_data_turn_done(pplayer);
+    ai_data_turn_init(pplayer);
+  }
+  return ai;
+}
+
+/**************************************************************************
+  Initialize with sane values.
+**************************************************************************/
+void ai_data_init(struct player *pplayer)
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+  int i;
+
+  ai->govt_reeval = 0;
+  ai->government_want = fc_calloc(game.government_count + 1, sizeof(int));
+
+  ai->diplomacy.target = NULL;
+  ai->diplomacy.strategy = WIN_OPEN;
+  ai->diplomacy.timer = 0;
+  ai->diplomacy.countdown = 0;
+  ai->diplomacy.love_coeff = 4; /* 4% */
+  ai->diplomacy.love_incr = 4;
+  ai->diplomacy.req_love_for_peace = 8;
+  ai->diplomacy.req_love_for_alliance = 16;
+  ai->diplomacy.req_love_for_ceasefire = 0;
+  ai->diplomacy.alliance_leader = pplayer;
+
+  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+    ai->diplomacy.player_intel[i].spam = i % 5; /* pseudorandom */
+    ai->diplomacy.player_intel[i].distance = 1;
+    ai->diplomacy.player_intel[i].ally_patience = 0;
+    pplayer->ai.love[i] = 1;
+    ai->diplomacy.player_intel[i].asked_about_peace = 0;
+    ai->diplomacy.player_intel[i].asked_about_alliance = 0;
+    ai->diplomacy.player_intel[i].asked_about_ceasefire = 0;
+    ai->diplomacy.player_intel[i].warned_about_space = 0;
+  }
+}
+
+/**************************************************************************
+  Deinitialize data
+**************************************************************************/
+void ai_data_done(struct player *pplayer)
+{
+  struct ai_data *ai = &aidata[pplayer->player_no];
+
+  free(ai->government_want);
+}
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.16
diff -u -r1.16 aidata.h
--- ai/aidata.h 3 Sep 2004 04:22:36 -0000       1.16
+++ ai/aidata.h 6 Sep 2004 01:11:03 -0000
@@ -26,6 +26,12 @@
  * start of every turn. 
  */
 
+enum ai_improvement_status {
+  AI_IMPR_CALCULATE, /* Calculate exactly its effect */
+  AI_IMPR_ESTIMATE,  /* Estimate its effect using wild guesses */
+  AI_IMPR_LAST
+};
+
 enum winning_strategy {
   WIN_OPEN,     /* still undetermined */
   WIN_WAR,      /* we have no other choice than to crush all opposition */
@@ -50,6 +56,10 @@
 
 BV_DEFINE(bv_id, MAX_NUM_ID);
 struct ai_data {
+  /* Precalculated info about city improvements */
+  enum ai_improvement_status impr_calc[MAX_NUM_ITEMS];
+  enum effect_range impr_range[MAX_NUM_ITEMS];
+
   /* AI diplomacy and opinions on other players */
   struct {
     int acceptable_reputation;
@@ -75,6 +85,7 @@
     bool air;         /* check for non-allied offensive aircraft */
     bool missile;     /* check for non-allied missiles */
     int nuclear;      /* nuke check: 0=no, 1=capability, 2=built */
+    bool igwall;      /* enemies have igwall units */
   } threats;
 
   /* Keeps track of which continents are fully explored already */
@@ -88,6 +99,8 @@
   /* This struct is used for statistical unit building, eg to ensure
    * that we don't build too few or too many units of a given type. */
   struct {
+    int triremes;
+    int units[UCL_LAST + 1]; /* no. units by class */
     int *workers;     /* cities to workers on continent*/
     int *cities;      /* number of cities on continent */
     int passengers;   /* number of passengers waiting for boats */
@@ -132,8 +145,8 @@
 
 void ai_data_init(struct player *pplayer);
 void ai_data_done(struct player *pplayer);
+void ai_data_analyze_rulesets(struct player *pplayer);
 
 struct ai_data *ai_data_get(struct player *pplayer);
 
-
 #endif
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.38
diff -u -r1.38 aidiplomat.c
--- ai/aidiplomat.c     29 Aug 2004 17:54:13 -0000      1.38
+++ ai/aidiplomat.c     6 Sep 2004 01:11:03 -0000
@@ -173,11 +173,8 @@
     }
     incite_cost = city_incite_cost(pplayer, acity);
     if (HOSTILE_PLAYER(pplayer, ai, city_owner(acity))
-        && !city_got_building(acity, B_PALACE)
-        && !government_has_flag(get_gov_pplayer(city_owner(acity)),
-                                G_UNBRIBABLE)
-        && (incite_cost <
-            pplayer->economic.gold - pplayer->ai.est_upkeep)) {
+        && (incite_cost < INCITE_IMPOSSIBLE_COST)
+        && (incite_cost < pplayer->economic.gold - pplayer->ai.est_upkeep)) {
       /* incite gain (FIXME: we should count wonders too but need to
          cache that somehow to avoid CPU hog -- Per) */
       gain_incite = acity->food_prod * FOOD_WEIGHTING
@@ -345,11 +342,9 @@
       continue; 
     }
 
-    can_incite = !(city_got_building(acity, B_PALACE)
-                   || government_has_flag(get_gov_pplayer(aplayer), 
-                                          G_UNBRIBABLE));
-
     incite_cost = city_incite_cost(pplayer, acity);
+    can_incite = (incite_cost < INCITE_IMPOSSIBLE_COST);
+
     dipldef = (count_diplomats_on_tile(acity->x, acity->y) > 0);
     /* Three actions to consider:
      * 1. establishing embassy OR
Index: ai/aiexplorer.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiexplorer.c,v
retrieving revision 1.3
diff -u -r1.3 aiexplorer.c
--- ai/aiexplorer.c     26 Aug 2004 22:22:03 -0000      1.3
+++ ai/aiexplorer.c     6 Sep 2004 01:11:04 -0000
@@ -110,7 +110,7 @@
    */
   if ((likely_ocean(x, y, pplayer) < 50) || 
       is_likely_coastline(x, y, pplayer) ||
-      (player_owns_active_wonder(pplayer, B_LIGHTHOUSE))) {
+      get_player_bonus(pplayer, EFT_NO_SINK_DEEP) > 0) {
     return FALSE;
   } else {
     return TRUE;
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.122
diff -u -r1.122 aitools.c
--- ai/aitools.c        2 Sep 2004 14:58:23 -0000       1.122
+++ ai/aitools.c        6 Sep 2004 01:11:04 -0000
@@ -793,8 +793,6 @@
                                     struct government *g)
 {
   int free_happy;
-  bool have_police;
-  int variant;
   int unhap = 0;
 
   /* bail out now if happy_cost is 0 */
@@ -803,14 +801,10 @@
   }
   
   free_happy  = citygov_free_happy(pcity, g);
-  have_police = city_got_effect(pcity, B_POLICE);
-  variant = improvement_variant(B_WOMENS);
 
-  if (variant == 0 && have_police) {
-    /* ??  This does the right thing for normal Republic and Democ -- dwp */
-    free_happy += g->unit_happy_cost_factor;
-  }
-  
+  /* ??  This does the right thing for normal Republic and Democ -- dwp */
+  free_happy += get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL);
+
   unit_list_iterate(pcity->units_supported, punit) {
     int happy_cost = utype_happy_cost(unit_type(punit), g);
 
@@ -830,7 +824,7 @@
       continue;
     }
 
-    if (variant == 1 && have_police) {
+    if (get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL_PER) > 0) {
       happy_cost--;
     }
     adjust_city_free_cost(&free_happy, &happy_cost);
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.334
diff -u -r1.334 aiunit.c
--- ai/aiunit.c 1 Sep 2004 11:47:25 -0000       1.334
+++ ai/aiunit.c 6 Sep 2004 01:11:04 -0000
@@ -1734,14 +1734,12 @@
       city_list_iterate(aplayer->cities, pcity) {
         if (ground) {
           cur = WARMAP_COST(pcity->x, pcity->y);
-          if (city_got_building(pcity, B_BARRACKS)
-              || city_got_building(pcity, B_BARRACKS2)
-              || city_got_building(pcity, B_BARRACKS3)) {
+          if (get_city_bonus(pcity, EFT_LAND_REGEN) > 0) {
             cur /= 3;
           }
         } else {
           cur = WARMAP_SEACOST(pcity->x, pcity->y);
-          if (city_got_building(pcity, B_PORT)) {
+          if (get_city_bonus(pcity, EFT_SEA_REGEN) > 0) {
             cur /= 3;
           }
         }
Index: client/cityrepdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/cityrepdata.c,v
retrieving revision 1.35
diff -u -r1.35 cityrepdata.c
--- client/cityrepdata.c        4 Sep 2004 18:39:38 -0000       1.35
+++ client/cityrepdata.c        6 Sep 2004 01:11:04 -0000
@@ -274,7 +274,7 @@
   static char buf[32];
   int goldie;
 
-  goldie = city_gold_surplus(pcity);
+  goldie = city_gold_surplus(pcity, pcity->tax_total);
   my_snprintf(buf, sizeof(buf), "%s%d/%d/%d",
              (goldie < 0) ? "-" : (goldie > 0) ? "+" : "",
              (goldie < 0) ? (-goldie) : goldie,
@@ -286,11 +286,11 @@
 static const char *cr_entry_gold(const struct city *pcity)
 {
   static char buf[8];
-  int income = city_gold_surplus(pcity);
+  int income = city_gold_surplus(pcity, pcity->tax_total);
   if (income > 0) {
     my_snprintf(buf, sizeof(buf), "+%d", income);
   } else {
-    my_snprintf(buf, sizeof(buf), "%3d", city_gold_surplus(pcity));
+    my_snprintf(buf, sizeof(buf), "%3d", city_gold_surplus(pcity, 
pcity->tax_total));
   }
   return buf;
 }
Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.138
diff -u -r1.138 climisc.c
--- client/climisc.c    3 Sep 2004 01:21:03 -0000       1.138
+++ client/climisc.c    6 Sep 2004 01:11:04 -0000
@@ -713,7 +713,7 @@
   impr_type_iterate(id) {
     bool can_build = can_player_build_improvement(game.player_ptr, id);
     bool can_eventually_build =
-       could_player_eventually_build_improvement(game.player_ptr, id);
+       can_player_eventually_build_improvement(game.player_ptr, id);
 
     /* If there's a city, can the city build the improvement? */
     if (pcity) {
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.74
diff -u -r1.74 helpdata.c
--- client/helpdata.c   4 Sep 2004 21:11:46 -0000       1.74
+++ client/helpdata.c   6 Sep 2004 01:11:04 -0000
@@ -507,7 +507,8 @@
   assert(buf);
   buf[0] = '\0';
 
-  if (which == B_MANHATTEN && num_role_units(F_NUCLEAR) > 0) {
+  if (building_has_effect(which, EFT_ENABLE_NUKE)
+      && num_role_units(F_NUCLEAR) > 0) {
     Unit_Type_id u;
     Tech_Type_id t;
 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.400
diff -u -r1.400 packhand.c
--- client/packhand.c   31 Aug 2004 04:40:48 -0000      1.400
+++ client/packhand.c   6 Sep 2004 01:11:05 -0000
@@ -699,10 +699,10 @@
                            ARRAY_SIZE(pcity->improvements));
   }
 
-  update_improvement_from_packet(pcity, B_PALACE, packet->capital,
-                                 &need_effect_update);
-  update_improvement_from_packet(pcity, B_CITY, packet->walls,
-                                 &need_effect_update);
+  update_improvement_from_packet(pcity, game.palace_building,
+                                packet->capital, &need_effect_update);
+  update_improvement_from_packet(pcity, game.land_defend_building,
+                                packet->walls, &need_effect_update);
 
   if (city_is_new) {
     init_worklist(&pcity->worklist);
@@ -1367,6 +1367,20 @@
   game.nuclearwinter=pinfo->nuclearwinter;
   game.cooling=pinfo->cooling;
   if (!can_client_change_view()) {
+    /*
+     * Hack to allow code that explicitly checks for Palace or City Walls
+     * to work.
+     */
+    game.palace_building = get_building_for_effect(EFT_CAPITAL_CITY);
+    if (game.palace_building == B_LAST) {
+      freelog(LOG_FATAL, "Cannot find any palace building");
+    }
+
+    game.land_defend_building = get_building_for_effect(EFT_LAND_DEFEND);
+    if (game.land_defend_building == B_LAST) {
+      freelog(LOG_FATAL, "Cannot find any land defend building");
+    }
+
     improvement_status_init(game.improvements,
                            ARRAY_SIZE(game.improvements));
 
@@ -2155,6 +2169,8 @@
   tilespec_free_city_tiles(game.styles_count);
   ruleset_data_free();
 
+  ruleset_cache_init();
+
   game.aqueduct_size = packet->aqueduct_size;
   game.sewer_size = packet->sewer_size;
   game.add_to_size_limit = packet->add_to_size_limit;
@@ -2194,6 +2210,8 @@
     mystrlcpy(team_get_by_id(i)->name, packet->team_name[i],
               MAX_LEN_NAME);
   }
+
+  game.default_building = packet->default_building;
 }
 
 /**************************************************************************
@@ -2328,12 +2346,6 @@
   T(equiv_repl, equiv_repl_count, B_LAST);
 #undef T
 
-  b->effect = fc_malloc(sizeof(*b->effect) * (p->effect_count + 1));
-  for (i = 0; i < p->effect_count; i++) {
-    b->effect[i] = p->effect[i];
-  }
-  b->effect[p->effect_count].type = EFT_LAST;
-
 #ifdef DEBUG
   if(p->id == game.num_impr_types-1) {
     impr_type_iterate(id) {
@@ -2384,75 +2396,6 @@
       freelog(LOG_DEBUG, "  upkeep      %2d", b->upkeep);
       freelog(LOG_DEBUG, "  sabotage   %3d", b->sabotage);
       freelog(LOG_DEBUG, "  effect...");
-      for (inx = 0; b->effect[inx].type != EFT_LAST; inx++) {
-       char buf[1024], *ptr;
-       ptr = buf;
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " %d/%s",
-                   b->effect[inx].type,
-                   effect_type_name(b->effect[inx].type));
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " range=%d/%s",
-                   b->effect[inx].range,
-                   effect_range_name(b->effect[inx].range));
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " amount=%d",
-                   b->effect[inx].amount);
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " survives=%d",
-                   b->effect[inx].survives);
-       ptr = strchr(ptr, '\0');
-       freelog(LOG_DEBUG, "   %2d. %s", inx, buf);
-       ptr = buf;
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " cond_bldg=%d/%s",
-                   b->effect[inx].cond_bldg,
-                   (b->effect[inx].cond_bldg == B_LAST) ?
-                   "Uncond." :
-                   improvement_types[b->effect[inx].cond_bldg].name);
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " cond_gov=%d/%s",
-                   b->effect[inx].cond_gov,
-                   (b->effect[inx].cond_gov == game.government_count) ?
-                   "Uncond." :
-                   get_government_name(b->effect[inx].cond_gov));
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " cond_adv=%d/%s",
-                   b->effect[inx].cond_adv,
-                   (b->effect[inx].cond_adv == A_NONE) ?
-                   "Uncond." :
-                   (b->effect[inx].cond_adv == A_LAST) ?
-                   "Never" :
-                   advances[b->effect[inx].cond_adv].name);
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " cond_eff=%d/%s",
-                   b->effect[inx].cond_eff,
-                   (b->effect[inx].cond_eff == EFT_LAST) ?
-                   "Uncond." :
-                   effect_type_name(b->effect[inx].cond_eff));
-       ptr = strchr(ptr, '\0');
-       freelog(LOG_DEBUG, "       %s", buf);
-       ptr = buf;
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " aff_unit=%d/%s",
-                   b->effect[inx].aff_unit,
-                   (b->effect[inx].aff_unit == UCL_LAST) ?
-                   "All" :
-                   unit_class_name(b->effect[inx].aff_unit));
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " aff_terr=%d/%s",
-                   b->effect[inx].aff_terr,
-                   (b->effect[inx].aff_terr == T_NONE) ? "None"
-                   : ((b->effect[inx].aff_terr == T_UNKNOWN) ? "All"
-                      : get_terrain_name(b->effect[inx].aff_terr)));
-       ptr = strchr(ptr, '\0');
-       my_snprintf(ptr, sizeof(buf)-(ptr-buf), " aff_spec=%04X/%s",
-                   b->effect[inx].aff_spec,
-                   (b->effect[inx].aff_spec == 0) ?
-                   "None" :
-                   (b->effect[inx].aff_spec == S_ALL) ?
-                   "All" :
-                   get_special_name(b->effect[inx].aff_spec));
-       ptr = strchr(ptr, '\0');
-       freelog(LOG_DEBUG, "       %s", buf);
-      }
       freelog(LOG_DEBUG, "  variant     %2d", b->variant);     /* FIXME: 
remove when gen-impr obsoletes */
       freelog(LOG_DEBUG, "  helptext    %s", b->helptext);
     } impr_type_iterate_end;
@@ -2975,3 +2918,30 @@
 {
   freelog(LOG_VERBOSE, "server shutdown");
 }
+
+/**************************************************************************
+  Add group data to ruleset cache.  
+**************************************************************************/
+void handle_ruleset_cache_group(struct packet_ruleset_cache_group *packet)
+{
+  struct effect_group *pgroup;
+  int i;
+
+  pgroup = effect_group_new(packet->name);
+
+  for (i = 0; i < packet->num_elements; i++) {
+    effect_group_add(pgroup, packet->improvements[i],
+                 packet->ranges[i], packet->survives[i]);
+  }
+}
+
+/**************************************************************************
+  Add effect data to ruleset cache.  
+**************************************************************************/
+void handle_ruleset_cache_effect(struct packet_ruleset_cache_effect *packet)
+{
+  ruleset_cache_add(packet->id, packet->eff, packet->range, packet->survives,
+                   packet->value, packet->req, packet->arg,
+                   packet->group);
+}
+
Index: client/text.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/text.c,v
retrieving revision 1.9
diff -u -r1.9 text.c
--- client/text.c       13 Aug 2004 15:26:50 -0000      1.9
+++ client/text.c       6 Sep 2004 01:11:06 -0000
@@ -711,34 +711,18 @@
 const char *get_happiness_buildings(const struct city *pcity)
 {
   int faces = 0;
-  struct government *g = get_gov_pcity(pcity);
+  struct building_vector sources;
   INIT;
 
   add_line(_("Buildings: "));
-  if (city_got_building(pcity, B_TEMPLE)) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_TEMPLE));
-  }
-  if (city_got_building(pcity, B_COURTHOUSE) && g->corruption_level == 0) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_COURTHOUSE));
-  }
-  if (city_got_building(pcity, B_COLOSSEUM)) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_COLOSSEUM));
-  }
-  if (faces > 2) {
-    /* Hack to get wrapping right. */
-    add(_("\n              "));
-  }
-  if (city_got_effect(pcity, B_CATHEDRAL)) {
+
+  sources = get_city_bonus_sources(pcity, EFT_MAKE_CONTENT);
+  building_vector_iterate(&sources, pbldg) {
     faces++;
-    add("%s", get_improvement_name(B_CATHEDRAL));
-    if (!city_got_building(pcity, B_CATHEDRAL)) {
-      add(_("(%s)"), get_improvement_name(B_MICHELANGELO));
-    }
-    add(_(". "));
-  }
+    add(_("%s. "), get_improvement_name(*pbldg));
+  } building_vector_iterate_end;
+  building_vector_free(&sources);
+
   if (faces == 0) {
     add(_("None. "));
   }
@@ -752,31 +736,31 @@
 const char *get_happiness_wonders(const struct city *pcity)
 {
   int faces = 0;
+  struct building_vector sources;
   INIT;
 
   add_line(_("Wonders: "));
 
-  if (city_affected_by_wonder(pcity, B_HANGING)) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_HANGING));
-  }
-  if (city_affected_by_wonder(pcity, B_BACH)) {
+  sources = get_city_bonus_sources(pcity, EFT_MAKE_HAPPY);
+  building_vector_iterate(&sources, pbldg) {
     faces++;
-    add(_("%s. "), get_improvement_name(B_BACH));
-  }
-  /* hack for eliminating gtk_set_line_wrap() -mck */
-  if (faces > 1) {
-    /* sizeof("Wonders: ") */
-    add(_("\n              "));
-  }
-  if (city_affected_by_wonder(pcity, B_SHAKESPEARE)) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_SHAKESPEARE));
-  }
-  if (city_affected_by_wonder(pcity, B_CURE)) {
-    faces++;
-    add(_("%s. "), get_improvement_name(B_CURE));
-  }
+    add(_("%s. "), get_improvement_name(*pbldg));
+  } building_vector_iterate_end;
+  building_vector_free(&sources);
+
+  sources = get_city_bonus_sources(pcity, EFT_FORCE_CONTENT);
+  building_vector_iterate(&sources, pbldg) {
+    faces++;
+    add(_("%s. "), get_improvement_name(*pbldg));
+  } building_vector_iterate_end;
+  building_vector_free(&sources);
+
+  sources = get_city_bonus_sources(pcity, EFT_NO_UNHAPPY);
+  building_vector_iterate(&sources, pbldg) {
+    faces++;
+    add(_("%s. "), get_improvement_name(*pbldg));
+  } building_vector_iterate_end;
+  building_vector_free(&sources);
 
   if (faces == 0) {
     add(_("None. "));
Index: client/gui-gtk/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/citydlg.c,v
retrieving revision 1.185
diff -u -r1.185 citydlg.c
--- client/gui-gtk/citydlg.c    17 Jul 2004 05:53:20 -0000      1.185
+++ client/gui-gtk/citydlg.c    6 Sep 2004 01:11:06 -0000
@@ -1696,7 +1696,7 @@
   my_snprintf(buf[TRADE], sizeof(buf[TRADE]), "%2d (%+2d)",
              pcity->trade_prod + pcity->corruption, pcity->trade_prod);
   my_snprintf(buf[GOLD], sizeof(buf[GOLD]), "%2d (%+2d)",
-             pcity->tax_total, city_gold_surplus(pcity));
+             pcity->tax_total, city_gold_surplus(pcity, pcity->tax_total));
   my_snprintf(buf[LUXURY], sizeof(buf[LUXURY]), "%2d      ",
              pcity->luxury_total);
 
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/citydlg.c,v
retrieving revision 1.90
diff -u -r1.90 citydlg.c
--- client/gui-gtk-2.0/citydlg.c        17 Jul 2004 05:53:20 -0000      1.90
+++ client/gui-gtk-2.0/citydlg.c        6 Sep 2004 01:11:06 -0000
@@ -1318,7 +1318,7 @@
   my_snprintf(buf[TRADE], sizeof(buf[TRADE]), "%2d (%+2d)",
              pcity->trade_prod + pcity->corruption, pcity->trade_prod);
   my_snprintf(buf[GOLD], sizeof(buf[GOLD]), "%2d (%+2d)",
-             pcity->tax_total, city_gold_surplus(pcity));
+             pcity->tax_total, city_gold_surplus(pcity, pcity->tax_total));
   my_snprintf(buf[LUXURY], sizeof(buf[LUXURY]), "%2d      ",
              pcity->luxury_total);
 
Index: client/gui-mui/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/citydlg.c,v
retrieving revision 1.80
diff -u -r1.80 citydlg.c
--- client/gui-mui/citydlg.c    20 Jul 2004 16:27:07 -0000      1.80
+++ client/gui-mui/citydlg.c    6 Sep 2004 01:11:07 -0000
@@ -1810,7 +1810,7 @@
   settextf(info->food_text, "%2d (%+2d)", pcity->food_prod, 
pcity->food_surplus);
   settextf(info->shield_text, "%2d (%+2d)", pcity->shield_prod + 
pcity->shield_waste, pcity->shield_surplus);
   settextf(info->trade_text, "%2d (%+2d)", pcity->trade_prod + 
pcity->corruption, pcity->trade_prod);
-  settextf(info->gold_text, "%2d (%+2d)", pcity->tax_total, 
city_gold_surplus(pcity));
+  settextf(info->gold_text, "%2d (%+2d)", pcity->tax_total, 
city_gold_surplus(pcity, pcity->tax_total));
   settextf(info->luxury_text, "%2d", pcity->luxury_total);
   settextf(info->science_text, "%2d", pcity->science_total);
 
Index: client/gui-sdl/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/citydlg.c,v
retrieving revision 1.44
diff -u -r1.44 citydlg.c
--- client/gui-sdl/citydlg.c    23 Jun 2004 23:08:55 -0000      1.44
+++ client/gui-sdl/citydlg.c    6 Sep 2004 01:11:07 -0000
@@ -2965,7 +2965,7 @@
   /* ================================================================= */
   /* gold label */
   my_snprintf(cBuf, sizeof(cBuf), _("Gold: %d (%d) per turn"),
-             city_gold_surplus(pCity), pCity->tax_total);
+             city_gold_surplus(pCity, pcity->tax_total), pCity->tax_total);
 
   copy_chars_to_string16(pStr, cBuf);
   pStr->fgcol = *get_game_colorRGB(COLOR_STD_CITY_GOLD);
@@ -2980,7 +2980,7 @@
   FREESURFACE(pBuf);
 
   /* draw coins */
-  count = city_gold_surplus(pCity);
+  count = city_gold_surplus(pCity, pcity->tax_total);
   if (count) {
 
     if (count > 0) {
@@ -3012,7 +3012,7 @@
 
   /* upkeep label */
   my_snprintf(cBuf, sizeof(cBuf), _("Upkeep : %d"), pCity->tax_total -
-             city_gold_surplus(pCity));
+             city_gold_surplus(pCity, pcity->tax_total));
 
   copy_chars_to_string16(pStr, cBuf);
   pStr->fgcol = *get_game_colorRGB(COLOR_STD_CITY_UNKEEP);
@@ -3027,7 +3027,7 @@
   FREESURFACE(pBuf);
 
   /* draw upkeep */
-  count = city_gold_surplus(pCity);
+  count = city_gold_surplus(pCity, pcity->tax_total);
   if (pCity->tax_total - count) {
 
     dest.x = pWindow->size.x + 423;
Index: client/gui-sdl/cityrep.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/cityrep.c,v
retrieving revision 1.14
diff -u -r1.14 cityrep.c
--- client/gui-sdl/cityrep.c    25 Feb 2004 20:09:51 -0000      1.14
+++ client/gui-sdl/cityrep.c    6 Sep 2004 01:11:07 -0000
@@ -386,7 +386,7 @@
     add_to_gui_list(MAX_ID - pCity->id, pBuf);
             
     /* ----------- */
-    my_snprintf(cBuf, sizeof(cBuf), "%d", city_gold_surplus(pCity));
+    my_snprintf(cBuf, sizeof(cBuf), "%d", city_gold_surplus(pCity, 
pcity->tax_total));
     pStr = create_str16_from_char(cBuf, 10);
     pStr->style |= SF_CENTER;
     pStr->fgcol = *get_game_colorRGB(COLOR_STD_CITY_GOLD);
@@ -974,7 +974,7 @@
             
   /* gold surplus */
   pWidget = pWidget->prev;
-  my_snprintf(cBuf, sizeof(cBuf), "%d", city_gold_surplus(pCity));
+  my_snprintf(cBuf, sizeof(cBuf), "%d", city_gold_surplus(pCity, 
pcity->tax_total));
   copy_chars_to_string16(pWidget->string16, cBuf);
     
   /* science income */
Index: client/gui-win32/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/citydlg.c,v
retrieving revision 1.81
diff -u -r1.81 citydlg.c
--- client/gui-win32/citydlg.c  18 Jul 2004 04:50:23 -0000      1.81
+++ client/gui-win32/citydlg.c  6 Sep 2004 01:11:08 -0000
@@ -459,7 +459,7 @@
   struct city *pcity=pdialog->pcity;
   my_snprintf(buf, sizeof(buf),
              _("Gold:    %2d (%+2d)\nLuxury:  %2d\nScience: %2d"),
-             pcity->tax_total, city_gold_surplus(pcity),
+             pcity->tax_total, city_gold_surplus(pcity, pcity->tax_total),
              pcity->luxury_total,
              pcity->science_total);      
   SetWindowText(pdialog->output_area[0],buf);
Index: client/gui-xaw/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/citydlg.c,v
retrieving revision 1.120
diff -u -r1.120 citydlg.c
--- client/gui-xaw/citydlg.c    27 Jul 2004 17:53:37 -0000      1.120
+++ client/gui-xaw/citydlg.c    6 Sep 2004 01:11:08 -0000
@@ -271,7 +271,7 @@
   if (pdialog) {
     pcity=pdialog->pcity;
     goldtotal=pcity->tax_total;
-    goldsurplus=city_gold_surplus(pcity);
+    goldsurplus=city_gold_surplus(pcity, pcity->tax_total);
     luxtotal=pcity->luxury_total;
     scitotal=pcity->science_total;
   }
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.241
diff -u -r1.241 city.c
--- common/city.c       4 Sep 2004 19:28:19 -0000       1.241
+++ common/city.c       6 Sep 2004 01:11:09 -0000
@@ -263,54 +263,6 @@
 }
 
 /**************************************************************************
-  Returns TRUE if a building is replaced.  To be replaced, all its effects
-  must be redundant.
-**************************************************************************/
-bool building_replaced(const struct city *pcity, Impr_Type_id id)
-{
-  if(is_wonder(id)) return FALSE;
-  switch (id) {
-  case B_BARRACKS:
-  case B_BARRACKS2:
-  case B_BARRACKS3:
-    if (city_affected_by_wonder(pcity, B_SUNTZU))
-      return TRUE;
-    break;
-  case B_GRANARY:
-    if (improvement_variant(B_PYRAMIDS)==0
-       && city_affected_by_wonder(pcity, B_PYRAMIDS))
-      return TRUE;
-    break;
-  case B_CATHEDRAL:
-    if (improvement_variant(B_MICHELANGELO)==0
-       && city_affected_by_wonder(pcity, B_MICHELANGELO))
-      return TRUE;
-    break;
-  case B_CITY:  
-    if (city_affected_by_wonder(pcity, B_WALL))
-      return TRUE;
-    break;
-  case B_HYDRO:
-  case B_POWER:
-  case B_NUCLEAR:
-    if (city_affected_by_wonder(pcity, B_HOOVER))
-      return TRUE;
-    break;
-  case B_POLICE:
-    if (city_affected_by_wonder(pcity, B_WOMENS))
-      return TRUE;
-    break;
-  case B_RESEARCH:
-    if (city_affected_by_wonder(pcity, B_SETI))
-      return TRUE;
-    break;
-  default:
-    break;
-  }
-  return FALSE;
-}
-
-/**************************************************************************
   Return the extended name of the building.
 **************************************************************************/
 const char *get_impr_name_ex(const struct city *pcity, Impr_Type_id id)
@@ -399,13 +351,12 @@
 }
 
 /**************************************************************************
- Will this city ever be able to build this improvement?
- Doesn't check for building prereqs
+  Return whether given city can build given improvement, ignoring whether
+  improvement is obsolete.
 **************************************************************************/
-bool can_eventually_build_improvement(const struct city *pcity, Impr_Type_id 
id)
+bool can_build_improvement_direct(const struct city *pcity, Impr_Type_id id)
 {
-  /* also does an improvement_exists() */
-  if (!could_player_eventually_build_improvement(city_owner(pcity),id)) {
+  if (!can_player_build_improvement_direct(city_owner(pcity), id)) {
     return FALSE;
   }
 
@@ -413,7 +364,7 @@
     return FALSE;
   }
 
-  if (!city_has_terr_spec_gate(pcity,id)) {
+  if (!city_has_terr_spec_gate(pcity, id)) {
     return FALSE;
   }
 
@@ -421,29 +372,34 @@
 }
 
 /**************************************************************************
-  Can this improvement get built in this city by the player who owns it?
+  Return whether given city can build given building; returns FALSE if
+  the building is obsolete.
 **************************************************************************/
 bool can_build_improvement(const struct city *pcity, Impr_Type_id id)
-{
-  struct player *p = city_owner(pcity);
-  struct impr_type *impr = get_improvement_type(id);
-
-  if (!improvement_exists(id)) {
+{  
+  if (!can_build_improvement_direct(pcity, id)) {
     return FALSE;
   }
-  if (!player_knows_improvement_tech(p, id)) {
+  if (improvement_obsolete(city_owner(pcity), id)) {
     return FALSE;
   }
+  return TRUE;
+}
 
-  if (!can_eventually_build_improvement(pcity, id)) {
+/**************************************************************************
+  Return whether player can eventually build given improvement in the city;
+  returns 0 if improvement can never possibly be built in this city.
+**************************************************************************/
+bool can_eventually_build_improvement(const struct city *pcity,
+                                     Impr_Type_id id)
+{
+  /* Can the _player_ ever build this improvement? */
+  if (!can_player_eventually_build_improvement(city_owner(pcity), id)) {
     return FALSE;
   }
 
-  /* The building pre req */
-  if (impr->bldg_req != B_LAST) {
-    if (!city_got_building(pcity, impr->bldg_req)) {
-      return FALSE;
-    }
+  if (!city_has_terr_spec_gate(pcity, id)) {
+    return FALSE;
   }
 
   return TRUE;
@@ -552,11 +508,11 @@
     return 0;
   if (is_wonder(i))
     return 0;
-  if (improvement_types[i].upkeep == 1 &&
-      city_affected_by_wonder(pcity, B_ASMITHS)) 
+  if (improvement_types[i].upkeep
+      <= get_city_bonus(pcity, EFT_UPKEEP_FREE)) {
     return 0;
-  if (government_has_flag(get_gov_pcity(pcity), G_CONVERT_TITHES_TO_MONEY)
-      && (i == B_TEMPLE || i == B_COLOSSEUM || i == B_CATHEDRAL)) {
+  }
+  if (get_building_bonus(pcity, i, EFT_NO_UPKEEP) > 0) {
     return 0;
   }
   
@@ -574,6 +530,7 @@
 {
   enum tile_special_type spec_t = map_get_special(map_x, map_y);
   Terrain_type_id tile_t = map_get_terrain(map_x, map_y);
+  struct tile *ptile = map_get_tile(map_x, map_y);
   int s;
 
   if (contains_special(spec_t, S_SPECIAL_1)) {
@@ -597,17 +554,16 @@
     int before_penalty = (is_celebrating ? g->celeb_shields_before_penalty
                          : g->shields_before_penalty);
 
-    if (city_affected_by_wonder(pcity, B_RICHARDS)) {
-      s++;
-    }
-    if (is_ocean(tile_t) && city_got_building(pcity, B_OFFSHORE)) {
-      s++;
-    }
+    s += get_city_tile_bonus(pcity, ptile, EFT_PROD_ADD_TILE);
 
-    /* government shield bonus & penalty */
+    /* Government & effect shield bonus/penalty. */
     if (s > 0) {
       s += (is_celebrating ? g->celeb_shield_bonus : g->shield_bonus);
+      s += get_city_tile_bonus(pcity, ptile, EFT_PROD_INC_TILE);
     }
+
+    s += (s * get_city_tile_bonus(pcity, ptile, EFT_PROD_PER_TILE)) / 100;
+
     if (before_penalty > 0 && s > before_penalty) {
       s--;
     }
@@ -679,6 +635,7 @@
 {
   enum tile_special_type spec_t = map_get_special(map_x, map_y);
   Terrain_type_id tile_t = map_get_terrain(map_x, map_y);
+  struct tile *ptile = map_get_tile(map_x, map_y);
   int t;
 
   if (contains_special(spec_t, S_SPECIAL_1)) {
@@ -692,50 +649,46 @@
   if (contains_special(spec_t, S_RIVER) && !is_ocean(tile_t)) {
     t += terrain_control.river_trade_incr;
   }
+
   if (contains_special(spec_t, S_ROAD)) {
     t += get_tile_type(tile_t)->road_trade_incr;
   }
-  if (t > 0) {
-    if (contains_special(spec_t, S_RAILROAD)) {
-      t += (t * terrain_control.rail_trade_bonus) / 100;
-    }
-
-    /* Civ1 specifically documents that Railroad trade increase is before 
-     * Democracy/Republic [government in general now -- SKi] bonus  -AJS */
-    if (pcity) {
-      struct government *g = get_gov_pcity(pcity);
-      int before_penalty = (is_celebrating ? g->celeb_trade_before_penalty
-                           : g->trade_before_penalty);
 
-      if (t > 0) {
-       t += (is_celebrating ? g->celeb_trade_bonus : g->trade_bonus);
-      }
+  if (contains_special(spec_t, S_RAILROAD)) {
+    t += (t * terrain_control.rail_trade_bonus) / 100;
+  }
 
-      if (city_affected_by_wonder(pcity, B_COLLOSSUS)) {
-       t++;
-      }
+  /* Civ1 specifically documents that Railroad trade increase is before 
+   * Democracy/Republic [government in general now -- SKi] bonus  -AJS */
+  if (pcity) {
+    struct government *g = get_gov_pcity(pcity);
+    int before_penalty = (is_celebrating ? g->celeb_trade_before_penalty
+                         : g->trade_before_penalty);
 
-      if (contains_special(spec_t, S_ROAD)
-         && city_got_building(pcity, B_SUPERHIGHWAYS)) {
-       t += (t * terrain_control.road_superhighway_trade_bonus) / 100;
-      }
+    t += get_city_tile_bonus(pcity, ptile, EFT_TRADE_ADD_TILE);
 
-      /* government trade penalty -- SKi */
-      if (before_penalty > 0 && t > before_penalty) {
-       t--;
-      }
+    if (t > 0) {
+      t += (is_celebrating ? g->celeb_trade_bonus : g->trade_bonus);
+      t += get_city_bonus(pcity, EFT_TRADE_INC_TILE);
     }
 
-    if (contains_special(spec_t, S_POLLUTION)) {
-      /* The trade here is dirty */
-      t -= (t * terrain_control.pollution_trade_penalty) / 100;
-    }
+    t += (t * get_city_tile_bonus(pcity, ptile, EFT_TRADE_PER_TILE)) / 100;
 
-    if (contains_special(spec_t, S_FALLOUT)) {
-      t -= (t * terrain_control.fallout_trade_penalty) / 100;
+    /* government trade penalty -- SKi */
+    if (before_penalty > 0 && t > before_penalty) {
+      t--;
     }
   }
 
+  if (contains_special(spec_t, S_POLLUTION)) {
+    /* The trade here is dirty */
+    t -= (t * terrain_control.pollution_trade_penalty) / 100;
+  }
+
+  if (contains_special(spec_t, S_FALLOUT)) {
+    t -= (t * terrain_control.fallout_trade_penalty) / 100;
+  }
+
   if (pcity && is_city_center(city_x, city_y)) {
     t = MAX(t, game.rgame.min_city_center_trade);
   }
@@ -793,36 +746,38 @@
   const enum tile_special_type spec_t = map_get_special(map_x, map_y);
   const Terrain_type_id tile_t = map_get_terrain(map_x, map_y);
   struct tile_type *type = get_tile_type(tile_t);
+  struct tile tile;
   int f;
   const bool auto_water = (pcity && is_city_center(city_x, city_y)
                           && tile_t == type->irrigation_result
                           && terrain_control.may_irrigate);
 
-  if (contains_special(spec_t, S_SPECIAL_1)) {
-    f = get_tile_type(tile_t)->food_special_1;
-  } else if (contains_special(spec_t, S_SPECIAL_2)) {
-    f = get_tile_type(tile_t)->food_special_2;
-  } else {
-    f = get_tile_type(tile_t)->food;
-  }
+  /* create dummy tile which has the city center bonuses. */
+  tile.terrain = tile_t;
+  tile.special = spec_t;
 
-  if (contains_special(spec_t, S_IRRIGATION) || auto_water) {
+  if (auto_water) {
     /* The center tile is auto-irrigated. */
-    f += type->irrigation_food_incr;
+    tile.special |= S_IRRIGATION;
 
-    /* Farmland only affects cities with supermarkets.  The center tile is
-     * auto-irrigated. */
-    if (pcity
-       && (contains_special(spec_t, S_FARMLAND)
-           || (auto_water
-               && player_knows_techs_with_flag(city_owner(pcity),
-                                               TF_FARMLAND)))
-       && city_got_building(pcity, B_SUPERMARKET)) {
-      f += (f * terrain_control.farmland_supermarket_food_bonus) / 100;
+    if (player_knows_techs_with_flag(city_owner(pcity), TF_FARMLAND)) {
+      tile.special |= S_FARMLAND;
     }
   }
 
-  if (contains_special(spec_t, S_RAILROAD)) {
+  if (contains_special(tile.special, S_SPECIAL_1)) {
+    f = type->food_special_1;
+  } else if (contains_special(tile.special, S_SPECIAL_2)) {
+    f = type->food_special_2;
+  } else {
+    f = type->food;
+  }
+
+  if (contains_special(tile.special, S_IRRIGATION)) {
+    f += type->irrigation_food_incr;
+  }
+
+  if (contains_special(tile.special, S_RAILROAD)) {
     f += (f * terrain_control.rail_food_bonus) / 100;
   }
 
@@ -831,23 +786,25 @@
     int before_penalty = (is_celebrating ? g->celeb_food_before_penalty
                          : g->food_before_penalty);
 
-    if (is_ocean(tile_t) && city_got_building(pcity, B_HARBOUR)) {
-      f++;
-    }
+    f += get_city_tile_bonus(pcity, &tile, EFT_FOOD_ADD_TILE);
 
     if (f > 0) {
       f += (is_celebrating ? g->celeb_food_bonus : g->food_bonus);
+      f += get_city_bonus(pcity, EFT_FOOD_INC_TILE);
     }
+
+    f += (f * get_city_tile_bonus(pcity, &tile, EFT_FOOD_PER_TILE) / 100);
+
     if (before_penalty > 0 && f > before_penalty) {
       f--;
     }
   }
 
-  if (contains_special(spec_t, S_POLLUTION)) {
+  if (contains_special(tile.special, S_POLLUTION)) {
     /* The food here is yucky */
     f -= (f * terrain_control.pollution_food_penalty) / 100;
   }
-  if (contains_special(spec_t, S_FALLOUT)) {
+  if (contains_special(tile.special, S_FALLOUT)) {
     f -= (f * terrain_control.fallout_food_penalty) / 100;
   }
 
@@ -1094,7 +1051,7 @@
   Calculate amount of gold remaining in city after paying for buildings 
   and units.
 *************************************************************************/
-int city_gold_surplus(const struct city *pcity)
+int city_gold_surplus(const struct city *pcity, int tax_total)
 {
   int cost = 0;
 
@@ -1106,17 +1063,7 @@
     cost += punit->upkeep_gold;
   } unit_list_iterate_end;
 
-  return pcity->tax_total-cost;
-}
-
-/**************************************************************************
- Whether a city has an improvement, or the same effect via a wonder.
- (The Impr_Type_id should be an improvement, not a wonder.)
- Note also: city_got_citywalls(), and server/citytools:city_got_barracks()
-**************************************************************************/
-bool city_got_effect(const struct city *pcity, Impr_Type_id id)
-{
-  return city_got_building(pcity, id) || building_replaced(pcity, id);
+  return tax_total - cost;
 }
 
 /**************************************************************************
@@ -1125,7 +1072,7 @@
 **************************************************************************/
 bool is_capital(const struct city *pcity)
 {
-  return city_got_building(pcity, B_PALACE);
+  return (get_city_bonus(pcity, EFT_CAPITAL_CITY) != 0);
 }
 
 /**************************************************************************
@@ -1133,80 +1080,7 @@
 **************************************************************************/
 bool city_got_citywalls(const struct city *pcity)
 {
-  if (city_got_building(pcity, B_CITY))
-    return TRUE;
-  return (city_affected_by_wonder(pcity, B_WALL));
-}
-
-/**************************************************************************
-  Return TRUE if the wonder's effect applies to this city.  This is only
-  used for some wonder checks; others are done manually.
-**************************************************************************/
-bool city_affected_by_wonder(const struct city *pcity, Impr_Type_id id)
-{
-  struct city *tmp;
-  if (!improvement_exists(id))
-    return FALSE;
-  if (!is_wonder(id) || wonder_obsolete(id))
-    return FALSE;
-  if (city_got_building(pcity, id))
-    return TRUE;
-  
-  /* For Manhatten it can be owned by anyone, and it doesn't matter
-   * whether it is destroyed or not.
-   *
-   * (The same goes for Apollo, with respect to building spaceship parts,
-   * but not for getting the map effect.  This function only returns true
-   * for Apollo for the owner of a non-destroyed Apollo; for building
-   * spaceship parts just check (game.global_wonders[id] != 0).
-   * (Actually, this function is not currently used for either Manhatten
-   * or Apollo.))
-   *
-   * Otherwise the player who owns the city needs to have it to
-   * get the effect.
-   */
-  if (id==B_MANHATTEN) 
-    return (game.global_wonders[id] != 0);
-  
-  tmp = player_find_city_by_id(city_owner(pcity), game.global_wonders[id]);
-  if (!tmp)
-    return FALSE;
-  switch (id) {
-  case B_ASMITHS:
-  case B_APOLLO:
-  case B_CURE:
-  case B_GREAT:
-  case B_WALL:
-  case B_HANGING:
-  case B_ORACLE:
-  case B_UNITED:
-  case B_WOMENS:
-  case B_DARWIN:
-  case B_LIGHTHOUSE:
-  case B_MAGELLAN:
-  case B_MICHELANGELO:
-  case B_SETI:
-  case B_PYRAMIDS:
-  case B_LIBERTY:
-  case B_SUNTZU:
-    return TRUE;
-  case B_ISAAC:
-  case B_COPERNICUS:
-  case B_SHAKESPEARE:
-  case B_COLLOSSUS:
-  case B_RICHARDS:
-    return FALSE;
-  case B_HOOVER:
-  case B_BACH:
-    if (improvement_variant(id)==1) {
-      return (map_get_continent(tmp->x, tmp->y) ==
-             map_get_continent(pcity->x, pcity->y));
-    } else {
-      return TRUE;
-    }
-  default:
-    return FALSE;
-  }
+  return (get_city_bonus(pcity, EFT_LAND_DEFEND) > 0);
 }
 
 /**************************************************************************
@@ -1547,10 +1421,14 @@
 ****************************************************************************/
 bool city_can_grow_to(const struct city *pcity, int pop_size)
 {
-  return (pop_size <= game.aqueduct_size
-         || (pop_size <= game.sewer_size
-             && city_got_building(pcity, B_AQUEDUCT))
-         || city_got_building(pcity, B_SEWER));
+  if (get_city_bonus(pcity, EFT_SIZE_UNLIMIT) > 0) {
+    return TRUE;
+  } else {
+    int max_size;
+                                                                               
+    max_size = game.aqueduct_size + get_city_bonus(pcity, EFT_SIZE_ADJ);
+    return (pop_size <= max_size);
+  }
 }
 
 /**************************************************************************
@@ -1693,23 +1571,7 @@
 **************************************************************************/
 int get_city_shield_bonus(const struct city *pcity)
 {
-  int shield_bonus = 100;
-
-  if (city_got_building(pcity, B_FACTORY)) {
-    shield_bonus += 50;
-    if (city_got_building(pcity, B_MFG)) {
-      shield_bonus += 50;
-    }
-
-    if (city_affected_by_wonder(pcity, B_HOOVER) ||
-       city_got_building(pcity, B_POWER) ||
-       city_got_building(pcity, B_HYDRO) ||
-       city_got_building(pcity, B_NUCLEAR)) {
-      shield_bonus = 100 + (3 * (shield_bonus - 100)) / 2;
-    }
-  }
-
-  return shield_bonus;
+  return (100 + get_city_bonus(pcity, EFT_PROD_BONUS));
 }
 
 /**************************************************************************
@@ -1717,19 +1579,7 @@
 **************************************************************************/
 int get_city_tax_bonus(const struct city *pcity)
 {
-  int tax_bonus = 100;
-
-  if (city_got_building(pcity, B_MARKETPLACE)) {
-    tax_bonus += 50;
-    if (city_got_building(pcity, B_BANK)) {
-      tax_bonus += 50;
-      if (city_got_building(pcity, B_STOCK)) {
-       tax_bonus += 50;
-      }
-    }
-  }
-
-  return tax_bonus;
+  return (100 + get_city_bonus(pcity, EFT_TAX_BONUS));
 }
 
 /**************************************************************************
@@ -1737,8 +1587,7 @@
 **************************************************************************/
 int get_city_luxury_bonus(const struct city *pcity)
 {
-  /* Currently the luxury bonus is equivalent to the tax bonus. */
-  return get_city_tax_bonus(pcity);
+  return (100 + get_city_bonus(pcity, EFT_LUXURY_BONUS));
 }
 
 /**************************************************************************
@@ -1754,16 +1603,8 @@
     return 0;
   }
 
-  if (city_got_building(pcity, B_TEMPLE))
-    tithes_bonus += get_temple_power(pcity);
-  if (city_got_building(pcity, B_COLOSSEUM))
-    tithes_bonus += get_colosseum_power(pcity);
-  if (city_got_effect(pcity, B_CATHEDRAL))
-    tithes_bonus += get_cathedral_power(pcity);
-  if (city_affected_by_wonder(pcity, B_BACH))
-    tithes_bonus += 2;
-  if (city_affected_by_wonder(pcity, B_CURE))
-    tithes_bonus += 1;
+  tithes_bonus += get_city_bonus(pcity, EFT_MAKE_CONTENT);
+  tithes_bonus += get_city_bonus(pcity, EFT_FORCE_CONTENT);
 
   return tithes_bonus;
 }
@@ -1773,23 +1614,10 @@
 **************************************************************************/
 int get_city_science_bonus(const struct city *pcity)
 {
-  int science_bonus = 100;
+  int science_bonus;
+
+  science_bonus = 100 + get_city_bonus(pcity, EFT_SCIENCE_BONUS);
 
-  if (city_got_building(pcity, B_LIBRARY)) {
-    science_bonus += 50;
-    if (city_got_building(pcity, B_UNIVERSITY)) {
-      science_bonus += 50;
-    }
-    if (city_got_effect(pcity, B_RESEARCH)) {
-      science_bonus += 50;
-    }
-  }
-  if (city_affected_by_wonder(pcity, B_COPERNICUS)) {
-    science_bonus += 50;
-  }
-  if (city_affected_by_wonder(pcity, B_ISAAC)) {
-    science_bonus += 100;
-  }
   if (government_has_flag(get_gov_pcity(pcity), G_REDUCED_RESEARCH)) {
     science_bonus /= 2;
   }
@@ -1861,12 +1689,14 @@
 
 /**************************************************************************
   Modify the incomes according to various buildings.
+
+  Note this does not set trade.  That's been done already.
 **************************************************************************/
 static void add_buildings_effect(struct city *pcity)
 {
   /* this is the place to set them */
-  pcity->luxury_bonus = get_city_luxury_bonus(pcity);
   pcity->tax_bonus = get_city_tax_bonus(pcity);
+  pcity->luxury_bonus = get_city_luxury_bonus(pcity);
   pcity->science_bonus = get_city_science_bonus(pcity);
   pcity->shield_bonus = get_city_shield_bonus(pcity);
 
@@ -1999,21 +1829,11 @@
 **************************************************************************/
 static inline void citizen_content_buildings(struct city *pcity)
 {
-  struct government *g = get_gov_pcity(pcity);
   int faces = 0;
   happy_copy(pcity, 1);
 
-  if (city_got_building(pcity, B_TEMPLE)) {
-    faces += get_temple_power(pcity);
-  }
-  if (city_got_building(pcity, B_COURTHOUSE) && g->corruption_level == 0) {
-    faces++;
-  }
+  faces += get_city_bonus(pcity, EFT_MAKE_CONTENT);
 
-  if (city_got_building(pcity, B_COLOSSEUM))
-    faces += get_colosseum_power(pcity);
-  if (city_got_effect(pcity, B_CATHEDRAL))
-    faces += get_cathedral_power(pcity);
   /* make people content (but not happy):
      get rid of angry first, then make unhappy content. */
   while (faces > 0 && pcity->ppl_angry[2] > 0) {
@@ -2033,14 +1853,13 @@
 **************************************************************************/
 static inline void citizen_happy_wonders(struct city *pcity)
 {
-  int bonus = 0;
+  int bonus = 0, mod;
 
   happy_copy(pcity, 3);
 
-  if (city_affected_by_wonder(pcity, B_HANGING)) {
-    bonus += 1;
-    if (city_got_building(pcity, B_HANGING))
-      bonus += 2;
+  if ((mod = get_city_bonus(pcity, EFT_MAKE_HAPPY)) > 0) {
+    bonus += mod;
+
     while (bonus > 0 && pcity->ppl_content[4] > 0) {
       pcity->ppl_content[4]--;
       pcity->ppl_happy[4]++;
@@ -2049,10 +1868,9 @@
          will let it make unhappy content */
     }
   }
-  if (city_affected_by_wonder(pcity, B_BACH))
-    bonus += 2;
-  if (city_affected_by_wonder(pcity, B_CURE))
-    bonus += 1;
+
+  bonus += get_city_bonus(pcity, EFT_FORCE_CONTENT);
+
   /* get rid of angry first, then make unhappy content */
   while (bonus > 0 && pcity->ppl_angry[4] > 0) {
     pcity->ppl_angry[4]--;
@@ -2065,7 +1883,7 @@
     bonus--;
   }
 
-  if (city_affected_by_wonder(pcity, B_SHAKESPEARE)) {
+  if (get_city_bonus(pcity, EFT_NO_UNHAPPY) > 0) {
     pcity->ppl_content[4] += pcity->ppl_unhappy[4] + pcity->ppl_angry[4];
     pcity->ppl_unhappy[4] = 0;
     pcity->ppl_angry[4] = 0;
@@ -2092,28 +1910,25 @@
 }
 
 /**************************************************************************
-  Calculate pollution.
+  Calculate pollution for the city.  The shield_total must be passed in
+  (most callers will want to pass pcity->shield_prod).
 **************************************************************************/
-static inline void set_pollution(struct city *pcity)
+int city_pollution(struct city *pcity, int shield_total)
 {
   struct player *pplayer = city_owner(pcity);
+  int mod, pollution = shield_total;
 
-  pcity->pollution = pcity->shield_prod;
-  if (city_got_building(pcity, B_RECYCLING)) {
-    pcity->pollution /= 3;
-  } else if (city_got_building(pcity, B_HYDRO) ||
-            city_affected_by_wonder(pcity, B_HOOVER) ||
-            city_got_building(pcity, B_NUCLEAR)) {
-    pcity->pollution /= 2;
-  }
-
-  if (!city_got_building(pcity, B_MASS)) {
-    pcity->pollution += (pcity->size *
-                        num_known_tech_with_flag
-                        (pplayer, TF_POPULATION_POLLUTION_INC)) / 4;
-  }
+  mod = get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
+  if (mod > 0) {
+    pollution /= mod;
+  }
+  mod = (pcity->size *
+      num_known_tech_with_flag(pplayer, TF_POPULATION_POLLUTION_INC)) / 4;
+  mod -= mod * get_city_bonus(pcity, EFT_POLLU_POP_PCT) / 100;
+  pollution += MAX(mod, 0);
+  pollution = MAX(0, pollution - 20);
 
-  pcity->pollution = MAX(0, pcity->pollution - 20);
+  return pollution;
 }
 
 /**************************************************************************
@@ -2174,18 +1989,13 @@
 {
   struct government *g = get_gov_pcity(pcity);
 
-  bool have_police = city_got_effect(pcity, B_POLICE);
-  int variant = improvement_variant(B_WOMENS);
-
   int free_happy = citygov_free_happy(pcity, g);
   int free_shield = citygov_free_shield(pcity, g);
   int free_food = citygov_free_food(pcity, g);
   int free_gold = citygov_free_gold(pcity, g);
 
-  if (variant == 0 && have_police) {
-    /* ??  This does the right thing for normal Republic and Democ -- dwp */
-    free_happy += g->unit_happy_cost_factor;
-  }
+  /* ??  This does the right thing for normal Republic and Democ -- dwp */
+  free_happy += get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL);
 
   happy_copy(pcity, 2);
 
@@ -2257,7 +2067,8 @@
        happy_cost = 0;
       }
     }
-    if (happy_cost > 0 && variant == 1 && have_police) {
+    if (happy_cost > 0
+       && get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL_PER) > 0) {
       happy_cost--;
     }
 
@@ -2317,7 +2128,7 @@
   citizen_happy_size(pcity);
   set_tax_income(pcity);       /* calc base luxury, tax & bulbs */
   add_buildings_effect(pcity); /* marketplace, library wonders.. */
-  set_pollution(pcity);
+  pcity->pollution = city_pollution(pcity, pcity->shield_prod);
   citizen_happy_luxury(pcity); /* with our new found luxuries */
   citizen_content_buildings(pcity);    /* temple cathedral colosseum */
   city_support(pcity, send_unit_info); /* manage settlers, and units */
@@ -2402,10 +2213,7 @@
   /* Now calculate the final corruption.  Ordered to reduce integer
    * roundoff errors. */
   val = trade * MAX(dist, 1) * g->corruption_level;
-  if (city_got_building(pcity, B_COURTHOUSE) ||
-      city_got_building(pcity, B_PALACE)) {
-    val /= 2;
-  }
+  val -= (val * get_city_bonus(pcity, EFT_CORRUPT_PCT)) / 100;
   val /= 100 * 100; /* Level is a % multiplied by 100 */
   val = CLIP(trade_penalty, val, trade);
   return val;
@@ -2441,10 +2249,8 @@
   val = shields * MAX(dist, 1) * g->waste_level;
   val /= 100 * 100; /* Level is a % multiplied by 100 */
 
-  if (city_got_building(pcity, B_COURTHOUSE)
-      || city_got_building(pcity, B_PALACE)) {
-    val /= 2;
-  }
+  val -= (val * get_city_bonus(pcity, EFT_WASTE_PCT)) / 100;
+
   val = CLIP(shield_penalty, val, shields);
   return val;
 }
@@ -2464,49 +2270,6 @@
 }
 
 /**************************************************************************
-  Return the power (pacifying effect) of temples in the city.
-**************************************************************************/
-int get_temple_power(const struct city *pcity)
-{
-  struct player *p = city_owner(pcity);
-  int power = 1;
-  if (get_invention(p, game.rtech.temple_plus) == TECH_KNOWN)
-    power = 2;
-  if (city_affected_by_wonder(pcity, B_ORACLE))
-    power *= 2;
-  return power;
-}
-
-/**************************************************************************
-  Return the power (pacifying effect) of cathedrals in the city.
-**************************************************************************/
-int get_cathedral_power(const struct city *pcity)
-{
-  struct player *p = city_owner(pcity);
-  int power = 3;
-  if (get_invention(p, game.rtech.cathedral_minus /*A_COMMUNISM */ ) ==
-      TECH_KNOWN) power--;
-  if (get_invention(p, game.rtech.cathedral_plus /*A_THEOLOGY */ ) ==
-      TECH_KNOWN) power++;
-  if (improvement_variant(B_MICHELANGELO) == 1
-      && city_affected_by_wonder(pcity, B_MICHELANGELO))
-    power *= 2;
-  return power;
-}
-
-/**************************************************************************
-  Return the power (pacifying effect) of colosseums in the city.
-**************************************************************************/
-int get_colosseum_power(const struct city *pcity)
-{
-  struct player *p = city_owner(pcity);
-  int power = 3;
-  if (get_invention(p, game.rtech.colosseum_plus /*A_ELECTRICITY */ ) ==
-      TECH_KNOWN) power++;
-  return power;
-}
-
-/**************************************************************************
  Adds an improvement (and its effects) to a city, and sets the global
  arrays if the improvement has effects and/or an equiv_range that
  extend outside of the city.
@@ -2644,7 +2407,7 @@
       pcity->currently_building = u;
     } else {
       pcity->is_building_unit = FALSE;
-      pcity->currently_building = B_CAPITAL;
+      pcity->currently_building = game.default_building;
     }
   }
   pcity->turn_founded = game.turn;
@@ -2673,6 +2436,7 @@
   pcity->ai.invasion = 0;
   pcity->ai.bcost = 0;
   pcity->ai.attack = 0;
+  pcity->ai.next_recalc = 0;
 
   pcity->corruption = 0;
   pcity->shield_waste = 0;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.159
diff -u -r1.159 city.h
--- common/city.h       4 Sep 2004 19:28:19 -0000       1.159
+++ common/city.h       6 Sep 2004 01:11:09 -0000
@@ -206,6 +206,9 @@
   int invasion; /* who's coming to kill us, for attack co-ordination */
   int attack, bcost; /* This is also for invasion - total power and value of
                       * 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 */
 };
 
 struct city {
@@ -254,7 +257,7 @@
   int currently_building;
   
   Impr_Status improvements[B_LAST];
-  
+
   struct worklist worklist;
 
   enum city_tile_type city_map[CITY_MAP_SIZE][CITY_MAP_SIZE];
@@ -346,7 +349,7 @@
 
 struct player *city_owner(const struct city *pcity);
 int city_population(const struct city *pcity);
-int city_gold_surplus(const struct city *pcity);
+int city_gold_surplus(const struct city *pcity, int tax_total);
 int city_buy_cost(const struct city *pcity);
 bool city_happy(const struct city *pcity);  /* generally use celebrating 
instead */
 bool city_unhappy(const struct city *pcity);                /* anarchy??? */
@@ -358,15 +361,15 @@
 
 bool city_has_terr_spec_gate(const struct city *pcity, Impr_Type_id id); 
 int improvement_upkeep(const struct city *pcity, Impr_Type_id i); 
+bool can_build_improvement_direct(const struct city *pcity, Impr_Type_id id);
 bool can_build_improvement(const struct city *pcity, Impr_Type_id id);
-bool can_eventually_build_improvement(const struct city *pcity, Impr_Type_id 
id);
+bool can_eventually_build_improvement(const struct city *pcity,
+                                     Impr_Type_id id);
 bool can_build_unit(const struct city *pcity, Unit_Type_id id);
 bool can_build_unit_direct(const struct city *pcity, Unit_Type_id id);
 bool can_eventually_build_unit(const struct city *pcity, Unit_Type_id id);
 bool city_can_use_specialist(const struct city *pcity, enum specialist_type 
type);
 bool city_got_building(const struct city *pcity,  Impr_Type_id id); 
-bool city_affected_by_wonder(const struct city *pcity, Impr_Type_id id);
-bool city_got_effect(const struct city *pcity, Impr_Type_id id);
 bool is_capital(const struct city *pcity);
 bool city_got_citywalls(const struct city *pcity);
 bool building_replaced(const struct city *pcity, Impr_Type_id id);
@@ -483,9 +486,6 @@
 int city_corruption(const struct city *pcity, int trade);
 int city_waste(const struct city *pcity, int shields);
 int city_specialists(const struct city *pcity);                 /* 
elv+tax+scie */
-int get_temple_power(const struct city *pcity);
-int get_cathedral_power(const struct city *pcity);
-int get_colosseum_power(const struct city *pcity);
 int get_city_tax_bonus(const struct city *pcity);
 int get_city_luxury_bonus(const struct city *pcity);
 int get_city_shield_bonus(const struct city *pcity);
@@ -507,6 +507,7 @@
 void get_tax_income(struct player *pplayer, int trade, int *sci,
                     int *lux, int *tax);
 int get_city_tithes_bonus(const struct city *pcity);
+int city_pollution(struct city *pcity, int shield_total);
 
 /*
  * Iterates over all improvements which are built in the given city.
Index: common/combat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.c,v
retrieving revision 1.45
diff -u -r1.45 combat.c
--- common/combat.c     25 Aug 2004 18:24:19 -0000      1.45
+++ common/combat.c     6 Sep 2004 01:11:09 -0000
@@ -301,9 +301,9 @@
 **************************************************************************/
 bool unit_really_ignores_citywalls(struct unit *punit)
 {
-  return unit_ignores_citywalls(punit)
-    || is_air_unit(punit)
-    || (is_sailing_unit(punit) && !(improvement_variant(B_CITY)==1));
+  return (unit_ignores_citywalls(punit)
+         || is_air_unit(punit)
+         || is_sailing_unit(punit));
 }
 
 /**************************************************************************
@@ -322,7 +322,9 @@
   square_iterate(x, y, 2, x1, y1) {
     struct city *pcity = map_get_city(x1, y1);
     if (pcity && (!pplayers_allied(city_owner(pcity), owner))
-       && city_got_building(pcity, B_SDI)) return pcity;
+       && get_city_bonus(pcity, EFT_NUKE_PROOF) > 0) {
+      return pcity;
+    }
   } square_iterate_end;
 
   return NULL;
@@ -406,6 +408,7 @@
                                  int defensepower, bool fortified)
 {
   struct city *pcity = map_get_city(x, y);
+  int mod;
 
   if (unit_type_exists(att_type)) {
     if (unit_type_flag(def_type, F_PIKEMEN)
@@ -419,24 +422,23 @@
     }
          
     if (is_air_unittype(att_type) && pcity) {
-      if (city_got_building(pcity, B_SAM)) {
-       defensepower *= 2;
+      if ((mod = get_city_bonus(pcity, EFT_AIR_DEFEND)) > 0) {
+       defensepower = defensepower * (100 + mod) / 100;
       }
-      if (city_got_building(pcity, B_SDI)
+      if ((mod = get_city_bonus(pcity, EFT_MISSILE_DEFEND)) > 0
          && unit_type_flag(att_type, F_MISSILE)) {
-       defensepower *= 2;
+       defensepower = defensepower * (100 + mod) / 100;
       }
     } else if (is_water_unit(att_type) && pcity) {
-      if (city_got_building(pcity, B_COASTAL)) {
-       defensepower *= 2;
+      if ((mod = get_city_bonus(pcity, EFT_SEA_DEFEND)) > 0) {
+       defensepower = defensepower * (100 + mod) / 100;
       }
     }
     if (!unit_type_flag(att_type, F_IGWALL)
-       && (is_ground_unittype(att_type) || is_heli_unittype(att_type)
-           || (improvement_variant(B_CITY) == 1
-               && is_water_unit(att_type))) && pcity
-       && city_got_citywalls(pcity)) {
-      defensepower *= 3;
+       && (is_ground_unittype(att_type) || is_heli_unittype(att_type))
+        && pcity
+        && (mod = get_city_bonus(pcity, EFT_LAND_DEFEND)) > 0) {
+      defensepower = defensepower * (100 + mod) / 100;
     }
 
     if (unit_type_flag(att_type, F_FIGHTER) && is_heli_unittype(def_type)) {
Index: common/dataio.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/dataio.c,v
retrieving revision 1.12
diff -u -r1.12 dataio.c
--- common/dataio.c     2 Sep 2004 22:01:51 -0000       1.12
+++ common/dataio.c     6 Sep 2004 01:11:09 -0000
@@ -711,33 +711,3 @@
   dio_put_uint16(dout, pds->contact_turns_left);
   dio_put_uint8(dout, pds->has_reason_to_cancel);
 }
-
-void dio_get_effect(struct data_in *din, struct impr_effect *peffect)
-{
-  dio_get_uint8(din, (int *) &(peffect->type));
-  dio_get_uint8(din, (int *) &(peffect->range));
-  dio_get_sint16(din, &peffect->amount);
-  dio_get_uint8(din, &peffect->survives);
-  dio_get_uint8(din, (int *) &peffect->cond_bldg);
-  dio_get_uint8(din, &peffect->cond_gov);
-  dio_get_uint8(din, &peffect->cond_adv);
-  dio_get_uint8(din, (int *) &(peffect->cond_eff));
-  dio_get_uint8(din, (int *) &(peffect->aff_unit));
-  dio_get_sint16(din, (int *) &(peffect->aff_terr));
-  dio_get_uint16(din, (int *) &(peffect->aff_spec));
-}
-
-void dio_put_effect(struct data_out *dout, const struct impr_effect *peffect)
-{
-  dio_put_uint8(dout, peffect->type);
-  dio_put_uint8(dout, peffect->range);
-  dio_put_sint16(dout, peffect->amount);
-  dio_put_uint8(dout, peffect->survives);
-  dio_put_uint8(dout, peffect->cond_bldg);
-  dio_put_uint8(dout, peffect->cond_gov);
-  dio_put_uint8(dout, peffect->cond_adv);
-  dio_put_uint8(dout, peffect->cond_eff);
-  dio_put_uint8(dout, peffect->aff_unit);
-  dio_put_sint16(dout, peffect->aff_terr);
-  dio_put_uint16(dout, peffect->aff_spec);
-}
Index: common/dataio.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/dataio.h,v
retrieving revision 1.6
diff -u -r1.6 dataio.h
--- common/dataio.h     2 Jun 2004 19:47:41 -0000       1.6
+++ common/dataio.h     6 Sep 2004 01:11:09 -0000
@@ -17,7 +17,6 @@
 
 struct worklist;
 struct player_diplstate;
-struct impr_effect;
 
 struct data_in {
   const void *src;
@@ -71,7 +70,6 @@
 void dio_get_tech_list(struct data_in *din, int *dest);
 void dio_get_worklist(struct data_in *din, struct worklist *pwl);
 void dio_get_diplstate(struct data_in *din, struct player_diplstate *pds);
-void dio_get_effect(struct data_in *din, struct impr_effect *peffect);
 
 void dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value);
 void dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value);
@@ -100,8 +98,6 @@
 void dio_put_worklist(struct data_out *dout, const struct worklist *pwl);
 void dio_put_diplstate(struct data_out *dout,
                       const struct player_diplstate *pds);
-void dio_put_effect(struct data_out *dout,
-                   const struct impr_effect *peffect);
 
 void dio_put_uint8_vec8(struct data_out *dout, int *values, int stop_value);
 void dio_put_uint16_vec8(struct data_out *dout, int *values, int stop_value);
Index: common/effects.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.c,v
retrieving revision 1.8
diff -u -r1.8 effects.c
--- common/effects.c    4 Sep 2004 20:19:51 -0000       1.8
+++ common/effects.c    6 Sep 2004 01:11:09 -0000
@@ -1,5 +1,5 @@
 /********************************************************************** 
- Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+ Freeciv - Copyright (C) 2004 - The Freeciv Team
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
@@ -15,25 +15,30 @@
 #endif
 
 #include <assert.h>
+#include <ctype.h>
+#include <string.h>
 
+#include "city.h"
 #include "effects.h"
 #include "game.h"
 #include "government.h"
 #include "improvement.h"
+#include "log.h"
 #include "map.h"
 #include "mem.h"
+#include "packets.h"
+#include "player.h"
 #include "support.h"
 #include "tech.h"
 #include "shared.h" /* ARRAY_SIZE */
-
-
+ 
 /* Names of effect ranges.
  * (These must correspond to enum effect_range_id in effects.h.)
  * do not change these unless you know what you're doing! */
 static const char *effect_range_names[] = {
   "Local",
   "City",
-  "Island",
+  "Continent",
   "Player",
   "World"
 };
@@ -41,20 +46,14 @@
 /* Names of effect types.
  * (These must correspond to enum effect_type_id in effects.h.) */
 static const char *effect_type_names[] = {
-  "Adv_Parasite",
+  "Tech_Parasite",
   "Airlift",
   "Any_Government",
-  "Barb_Attack",
-  "Barb_Defend",
-  "Building_Cost",
-  "Building_Cost_Pct",
   "Capital_City",
-  "Capital_Exists",
-  "Corrupt_Adj",
   "Corrupt_Pct",
+  "Waste_Pct",
   "Enable_Nuke",
   "Enable_Space",
-  "Enemy_Peaceful",
   "Food_Add_Tile",
   "Food_Bonus",
   "Food_Pct",
@@ -62,10 +61,9 @@
   "Food_Per_Tile",
   "Force_Content",
   "Force_Content_Pct",
-  "Give_Imm_Adv",
+  "Give_Imm_Tech",
   "Growth_Food",
   "Have_Embassies",
-  "Improve_Rep",
   "Luxury_Bonus",
   "Luxury_Pct",
   "Make_Content",
@@ -73,7 +71,6 @@
   "Make_Content_Mil_Per",
   "Make_Content_Pct",
   "Make_Happy",
-  "May_Declare_War",
   "No_Anarchy",
   "No_Sink_Deep",
   "Nuke_Proof",
@@ -91,13 +88,11 @@
   "Prod_To_Gold",
   "Reveal_Cities",
   "Reveal_Map",
-  "Revolt_Dist_Adj",
-  "Revolt_Dist_Pct",
+  "Incite_Dist_Adj",
+  "Incite_Dist_Pct",
   "Science_Bonus",
   "Science_Pct",
   "Size_Unlimit",
-  "Slow_Nuke_Winter",
-  "Slow_Global_Warm",
   "SS_Structural",
   "SS_Component",
   "SS_Module",
@@ -109,24 +104,28 @@
   "Trade_Pct",
   "Trade_Inc_Tile",
   "Trade_Per_Tile",
-  "Trade_Route_Pct",
-  "Unit_Attack",
-  "Unit_Attack_Firepower",
-  "Unit_Cost",
-  "Unit_Cost_Pct",
-  "Unit_Defend",
-  "Unit_Defend_Firepower",
-  "Unit_Move",
+  "Sea_Move",
   "Unit_No_Lose_Pop",
   "Unit_Recover",
-  "Unit_Repair",
-  "Unit_Vet_Combat",
-  "Unit_Veteran",
-  "Upgrade_One_Step",
-  "Upgrade_One_Leap",
-  "Upgrade_All_Step",
-  "Upgrade_All_Leap",
-  "Upkeep_Free"
+  "Upgrade_Unit",
+  "Upkeep_Free",
+  "No_Unhappy",
+  "Land_Veteran",
+  "Sea_Veteran",
+  "Air_Veteran",
+  "Land_Vet_Combat",
+  "Sea_Vet_Combat",
+  "Air_Vet_Combat",
+  "Land_Regen",
+  "Sea_Regen",
+  "Air_Regen",
+  "Land_Defend",
+  "Sea_Defend",
+  "Air_Defend",
+  "Missile_Defend",
+  "Size_Adj",
+  "No_Upkeep",
+  "No_Incite"
 };
 
 /**************************************************************************
@@ -187,33 +186,505 @@
 const char *effect_type_name(enum effect_type id)
 {
   assert(ARRAY_SIZE(effect_type_names) == EFT_LAST);
+  assert(id >= 0 && id < EFT_LAST);
+  return effect_type_names[id];
+}
+
+/**************************************************************************
+  The code creates a ruleset cache on ruleset load. This constant cache
+  is used to speed up effects queries. There is no further memory
+  allocation or de-allocation by any of the code after cache creation.
+
+  Since the cache is constant, the server only needs to send effects data to
+  the client upon connect. It also means that an AI can do fast searches in
+  the effects space by trying the possible combinations of addition or
+  removal of buildings with the effects it cares about, like is done in the
+  existing code.
+
+
+  To know how much a target is being affected, simply use the convenience
+  functions:
+
+  * get_player_bonus
+  * get_city_bonus
+  * get_city_tile_bonus
+  * get_building_bonus
+
+  These functions require as arguments the target and the effect type to be
+  queried.
+
+  Source buildings are unique and at a well known place in the
+  data structures. This allows lots of optimizations in the code.
+
+
+  === Future extensions:
+  The uniqueness aspect of a source is not as important as it being in a
+  well known place. Since a wonder is in a well known place, i.e.
+  game.global_wonders[], it is easy to find out if something is affected by
+  it or not.
+
+  This could easily be extended by generalizing it to these arrays:
+    game.impr[], pplayer->impr[], pisland->impr[], pcity->impr[].
+
+  Which would store the number of buildings of that type present by game,
+  player, island or city. A similar, game wide only array would be kept
+  for surviving effects.
+
+  This should enable basic support for small wonders and satellites.
+
+  Since this means one always knows where to look for a source, we
+  can have very fast queries on effects that will scale well with complex
+  effects.
+**************************************************************************/
+
+static const char *req_type_names[] = {
+  "None",
+  "Tech",
+  "Gov",
+  "Building",
+  "Special",
+  "Terrain"
+};
+
+struct effect_group_element {
+  Impr_Type_id improvement;
+  enum effect_range range;
+  bool survives;
+};
+
+#define SPECLIST_TAG effect_group_element
+#define SPECLIST_TYPE struct effect_group_element
+#include "speclist.h"
+
+#define effect_group_element_list_iterate(list, elt) \
+  TYPED_LIST_ITERATE(struct effect_group_element, list, elt)
+#define effect_group_element_list_iterate_end  LIST_ITERATE_END
+
+struct effect_group {
+  char *name;
+  int id;
+  struct effect_group_element_list elements;
+};
+
+#define SPECLIST_TAG effect_group
+#define SPECLIST_TYPE struct effect_group
+#include "speclist.h"
+
+#define effect_group_list_iterate(list, pgroup) \
+  TYPED_LIST_ITERATE(struct effect_group, list, pgroup)
+#define effect_group_list_iterate_end  LIST_ITERATE_END
+
+/**************************************************************************
+  Ruleset cache. The cache is created during ruleset loading and the data
+  is organized to enable fast queries.
+**************************************************************************/
+static struct {
+  struct {
+    /* This cache shows for each effect, which buildings provide it. */
+    struct building_vector buildings;
+
+    /* This array provides a full list of the effects of this type provided
+     * by each building.  (It's not really a cache, it's the real data.) */
+    struct effect_list buckets[B_LAST];
+  } effects[EFT_LAST];
+
+  /* This cache shows for each building, which effect types it provides. */
+  struct {
+    struct effect_type_vector types;
+  } buildings[B_LAST];
+} ruleset_cache;
+
+static struct effect_group_list groups;
+static int next_group_id;
+
+
+/**************************************************************************
+  Get a vector of buildings which grant the effect type.
+**************************************************************************/
+static struct building_vector *get_buildings_with_effect(enum effect_type e)
+{
+  return &ruleset_cache.effects[e].buildings;
+}
+
+/**************************************************************************
+  Get a list of effects of a type granted by a building.
+**************************************************************************/
+struct effect_list *get_building_effects(Impr_Type_id building,
+                                        enum effect_type effect)
+{
+  return &ruleset_cache.effects[effect].buckets[building];
+}
+
+/**************************************************************************
+  Get a vector of effects types granted by a building.
+**************************************************************************/
+struct effect_type_vector *get_building_effect_types(Impr_Type_id id)
+{
+  return &ruleset_cache.buildings[id].types;
+}
+
+
+/**************************************************************************
+  Get requirements type from string.
+**************************************************************************/
+enum req_type req_type_from_str(const char *str)
+{
+  enum req_type id;
+
+  for (id = 1; id < ARRAY_SIZE(req_type_names); id++) {
+    if (0 == mystrcasecmp(req_type_names[id], str)) {
+      return id;
+    }
+  }
+
+  return REQ_LAST;
+}
+
+/**************************************************************************
+  Create a new effects group.
+**************************************************************************/
+struct effect_group *effect_group_new(const char *name)
+{
+  struct effect_group *group;
+
+  group = fc_malloc(sizeof(*group));
+  group->name = mystrdup(name);
+  group->id = next_group_id++;
+  effect_group_element_list_init(&group->elements);
+
+  effect_group_list_insert_back(&groups, group);
+  return group;
+}
+
+/**************************************************************************
+  Add a new building to an existing effects group.
+**************************************************************************/
+void effect_group_add(struct effect_group *group, Impr_Type_id id,
+                     enum effect_range range, bool survives)
+{
+  struct effect_group_element *elt;
+
+  elt = fc_malloc(sizeof(*elt));
+  elt->improvement = id;
+  elt->range = range;
+  elt->survives = survives;
+
+  effect_group_element_list_insert_back(&group->elements, elt);
+}
+
+/**************************************************************************
+  Find the id of an effects group by name.
+**************************************************************************/
+int find_effect_group(const char *name)
+{
+  int i = 0;
+
+  effect_group_list_iterate(groups, pgroup) {
+    if (0 == mystrcasecmp(pgroup->name, name)) {
+      return i;
+    }
+    i++;
+  } effect_group_list_iterate_end;
+
+  return -1;
+}
+
+/**************************************************************************
+  Initialize ruleset cache.
+**************************************************************************/
+void ruleset_cache_init(void)
+{
+  int i, j;
+
+  assert(ARRAY_SIZE(req_type_names) == REQ_LAST);
 
-  if (id < EFT_LAST) {
-    return effect_type_names[id];
+  effect_group_list_init(&groups);
+  next_group_id = 0;
+
+  for (i = 0; i < ARRAY_SIZE(ruleset_cache.buildings); i++) {
+    effect_type_vector_init(get_building_effect_types(i));
+  }
+
+  for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
+    building_vector_init(get_buildings_with_effect(i));
+
+    for (j = 0; j < ARRAY_SIZE(ruleset_cache.effects[i].buckets); j++) {
+      effect_list_init(get_building_effects(j, i));
+    }
+  }
+}
+
+/**************************************************************************
+  Free the ruleset cache.
+**************************************************************************/
+void ruleset_cache_free(void)
+{
+  int i, j;
+
+  for (i = 0; i < ARRAY_SIZE(ruleset_cache.buildings); i++) {
+    effect_type_vector_free(get_building_effect_types(i));
+  }
+
+  for (i = 0; i < ARRAY_SIZE(ruleset_cache.effects); i++) {
+    building_vector_free(get_buildings_with_effect(i));
+
+    for (j = 0; j < ARRAY_SIZE(ruleset_cache.effects[i].buckets); j++) {
+      effect_list_unlink_all(get_building_effects(j, i));
+    }
+  }
+}
+
+/**************************************************************************
+  Parse effect requirement.
+**************************************************************************/
+int parse_effect_requirement(Impr_Type_id id, enum req_type type,
+                            const char *arg)
+{
+  bool problem;
+  int data;
+  struct government *pgov;
+
+  switch (type) {
+    case REQ_NONE:
+      problem = FALSE;
+      data = 0;
+      break;
+    case REQ_TECH:
+      problem = (A_LAST == (data = find_tech_by_name(arg)));
+      break;
+    case REQ_GOV:
+       if (!(pgov = find_government_by_name(arg))) {
+         problem = TRUE;
+       } else {
+         problem = FALSE;
+         data = pgov->index;
+       }
+      break;
+    case REQ_BUILDING:
+      problem = (B_LAST == (data = find_improvement_by_name(arg)));
+      break;
+    case REQ_SPECIAL:
+      problem = (S_NO_SPECIAL == (data = get_special_by_name(arg)));
+      break;
+    case REQ_TERRAIN:
+      problem = (T_UNKNOWN == (data = get_terrain_by_name(arg)));
+      break;
+    default:
+      freelog(LOG_ERROR, "for %s: unimplemented requirement type '%d'",
+             get_improvement_name(id), type);
+      return -1;
+  }
+
+  if (problem) {
+    freelog(LOG_ERROR, "for %s: bad requirement data '%s'",
+           get_improvement_name(id), arg);
+    return -1;
   } else {
-    return NULL;
+    return data;
+  }
+}
+
+/**************************************************************************
+  Add effect to ruleset cache.
+**************************************************************************/
+void ruleset_cache_add(Impr_Type_id id, enum effect_type eff,
+                      enum effect_range range, bool survives,
+                      int value,
+                      enum req_type req, int arg, int group)
+{
+  struct effect *peff;
+
+  peff = fc_malloc(sizeof(*peff));
+
+  peff->range = range;
+  peff->survives = survives;
+  peff->value = value;
+
+  peff->req.type = req;
+
+  switch (req) {
+    case REQ_NONE:
+      break;
+    case REQ_TECH:
+       peff->req.value.tech = arg;
+      break;
+    case REQ_GOV:
+       peff->req.value.gov = arg;
+      break;
+    case REQ_BUILDING:
+       peff->req.value.building = arg;
+      break;
+    case REQ_SPECIAL:
+       peff->req.value.special = arg;
+      break;
+    case REQ_TERRAIN:
+       peff->req.value.terrain = arg;
+      break;
+    case REQ_LAST:
+      assert(0);
+      break;
+  }
+
+  effect_list_insert_back(get_building_effects(id, eff), peff);
+
+  if (group >= 0) {
+    peff->group = effect_group_list_get(&groups, group);
+  } else {
+    peff->group = NULL;
+  }
+
+  /* Add improvement type to the effect's buildings vector. */
+  {
+    struct building_vector *vec;
+    Impr_Type_id *pbldg;
+
+    vec = get_buildings_with_effect(eff);
+
+    if (!(pbldg = building_vector_get(vec, -1)) || *pbldg != id) {
+      building_vector_append(vec, &id);
+    }
+  }
+
+  /* Add effect type to the building's effect types vector. */
+  {
+    struct effect_type_vector *vec;
+    bool exists = FALSE;
+
+    vec = get_building_effect_types(id);
+
+    effect_type_vector_iterate(vec, ptype) {
+      if (*ptype == eff) {
+       exists = TRUE;
+       break;
+      }
+    } effect_type_vector_iterate_end;
+
+    if (!exists) {
+      effect_type_vector_append(vec, &eff);
+    }
   }
 }
 
 /**************************************************************************
-  Return TRUE iff the two effects are equal.
+  Send the ruleset cache groups data.
 **************************************************************************/
-bool are_effects_equal(const struct impr_effect *const peff1,
-                      const struct impr_effect *const peff2)
+static void send_ruleset_cache_groups(struct conn_list *dest)
 {
-#define T(name) if(peff1->name!=peff2->name) return FALSE;
-  T(type);
-  T(range);
-  T(amount);
-  T(survives);
-  T(cond_bldg);
-  T(cond_gov);
-  T(cond_adv);
-  T(cond_eff);
-  T(aff_unit);
-  T(aff_terr);
-  T(aff_spec);
-  return TRUE;
+  struct packet_ruleset_cache_group packet;
+  int i;
+
+  effect_group_list_iterate(groups, pgroup) {
+    sz_strlcpy(packet.name, pgroup->name);
+
+    packet.num_elements = effect_group_element_list_size(&pgroup->elements);
+    for (i = 0; i < packet.num_elements; i++) {
+      struct effect_group_element *elt;
+
+      elt = effect_group_element_list_get(&pgroup->elements, i);
+      packet.improvements[i] = elt->improvement;
+      packet.ranges[i] = elt->range;
+      packet.survives[i] = elt->survives;
+    }
+
+    lsend_packet_ruleset_cache_group(dest, &packet);
+  } effect_group_list_iterate_end;
+}
+
+/**************************************************************************
+  Send the ruleset cache effects data.
+**************************************************************************/
+static void send_ruleset_cache_effects(struct conn_list *dest)
+{
+  struct packet_ruleset_cache_effect packet;
+  enum effect_type eff;
+
+  for (eff = 0; eff < EFT_LAST; eff++) {
+    packet.eff = eff;
+
+    building_vector_iterate(get_buildings_with_effect(eff), id) {
+      packet.id = *id;
+
+      effect_list_iterate(*get_building_effects(*id, eff), peff) {
+       packet.range = peff->range;
+       packet.survives = peff->survives;
+        packet.value = peff->value;
+       packet.req = peff->req.type;
+
+       if (peff->group) {
+         packet.group = peff->group->id;
+       } else {
+         packet.group = -1;
+       }
+
+       switch (packet.req) {
+         case REQ_NONE:
+           packet.arg = 0;
+           break;
+         case REQ_TECH:
+           packet.arg = peff->req.value.tech;
+           break;
+         case REQ_GOV:
+           packet.arg = peff->req.value.gov;
+           break;
+         case REQ_BUILDING:
+           packet.arg = peff->req.value.building;
+           break;
+         case REQ_SPECIAL:
+           packet.arg = peff->req.value.special;
+           break;
+         case REQ_TERRAIN:
+           packet.arg = peff->req.value.terrain;
+           break;
+         case REQ_LAST:
+           assert(0);
+           break;
+       }
+
+       lsend_packet_ruleset_cache_effect(dest, &packet);
+      } effect_list_iterate_end;
+    } building_vector_iterate_end;
+  }
+}
+
+/**************************************************************************
+  Send the ruleset cache data over the network.
+**************************************************************************/
+void send_ruleset_cache(struct conn_list *dest)
+{
+  send_ruleset_cache_groups(dest);
+  send_ruleset_cache_effects(dest);
+}
+
+/**************************************************************************
+  Returns a buildable, non-obsolete building that can provide the effect.
+
+  Note: this function is an inefficient hack to be used by the old AI.  It
+  will never find wonders, since that's not what the AI wants.
+**************************************************************************/
+Impr_Type_id ai_find_source_building(struct player *plr,
+                                    enum effect_type effect_type)
+{
+  /* FIXME: this just returns the first building. it should return the best
+   * building instead. */
+  building_vector_iterate(get_buildings_with_effect(effect_type), pbldg) {
+    if (can_player_build_improvement(plr, *pbldg)
+       && !improvement_obsolete(plr, *pbldg)
+       && !is_wonder(*pbldg)) {
+      return *pbldg;
+    }
+  } building_vector_iterate_end;
+  return B_LAST;
+}
+
+/**************************************************************************
+  Get a building which grants this effect. Returns B_LAST if there is none.
+**************************************************************************/
+Impr_Type_id get_building_for_effect(enum effect_type eff)
+{
+  building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+    return *pbldg;
+  } building_vector_iterate_end;
+  return B_LAST;
 }
 
 /**************************************************************************
@@ -223,62 +694,430 @@
   giving the exact bonus.  Finding the exact bonus requires knowing the
   effect range and may take longer.  This function should only be used
   in situations where the range doesn't matter.
+**************************************************************************/
+bool building_has_effect(Impr_Type_id id, enum effect_type effect)
+{
+  return (effect_list_size(get_building_effects(id, effect)) > 0);
+}
+
+/**************************************************************************
+  Returns the number of total world buildings (this includes buildings
+  that have been destroyed).
+**************************************************************************/
+static int num_world_buildings_total(Impr_Type_id id)
+{
+  if (is_wonder(id) && game.global_wonders[id] != 0) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+/**************************************************************************
+  Returns the number of buildings of a certain type in the world.
+**************************************************************************/
+static int num_world_buildings(Impr_Type_id id)
+{
+  if (is_wonder(id) && find_city_by_id(game.global_wonders[id])) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+/**************************************************************************
+  Returns the number of buildings of a certain type owned by plr.
+**************************************************************************/
+static int num_player_buildings(const struct player *plr, Impr_Type_id id)
+{
+  if (is_wonder(id) && player_find_city_by_id(plr, game.global_wonders[id])) {
+    return 1;
+  } else { 
+    return 0;
+  }
+}
+
+/**************************************************************************
+  Returns the number of buildings of a certain type on a continent.
+**************************************************************************/
+static int num_continent_buildings(const struct player *plr, int continent,
+                                  Impr_Type_id id)
+{
+  if (is_wonder(id)) {
+    struct city *tmp;
 
-  TODO:
-    1.  This function does not access the effect data directly; instead
-        it just associates the effect with a building.
-    2.  Only a few effects are supported.
-**************************************************************************/
-bool building_has_effect(Impr_Type_id building, enum effect_type effect)
-{
-  switch (effect) {
-  case EFT_PROD_TO_GOLD:
-    return building == B_CAPITAL;
-  case EFT_SS_STRUCTURAL:
-    return building == B_SSTRUCTURAL;
-  case EFT_SS_COMPONENT:
-    return building == B_SCOMP;
-  case EFT_SS_MODULE:
-    return building == B_SMODULE;
-  default:
-    break;
+    tmp = player_find_city_by_id(plr, game.global_wonders[id]);
+    if (tmp && map_get_continent(tmp->x, tmp->y) == continent) {
+      return 1;
+    }
+  }  
+  return 0;
+}
+
+/**************************************************************************
+  Returns the number of buildings of a certain type in a city.
+**************************************************************************/
+static int num_city_buildings(const struct city *pcity, Impr_Type_id id)
+{
+  return (city_got_building(pcity, id) ? 1 : 0);
+}
+
+/**************************************************************************
+  Is this target possible for the range involved?
+  e.g. you can only affect a player target with something of at least
+  player range.
+**************************************************************************/
+static bool is_target_possible(enum target_type target,
+                              enum effect_range range)
+{
+  switch (target) {
+  case TARGET_PLAYER:
+    return (range >= EFR_PLAYER);
+  case TARGET_CITY:
+    return (range >= EFR_CITY);
+  case TARGET_BUILDING:
+    return (range >= EFR_LOCAL);
   }
   assert(0);
   return FALSE;
 }
 
 /**************************************************************************
+  How many targets (player, city, building) are in range of the source
+  building?
+**************************************************************************/
+static int count_targets_in_range(enum target_type target,
+                                const struct player *plr,
+                                const struct city *pcity,
+                                Impr_Type_id building,
+                                enum effect_range range, bool survives,
+                                Impr_Type_id source)
+{
+  if (!is_target_possible(target, range)) {
+    return 0;
+  }
+
+  if (improvement_obsolete(plr, source)) {
+    return 0;
+  }
+
+  if (survives) {
+    if (range == EFR_WORLD) {
+      return num_world_buildings_total(source);
+    } else {
+      return 0;
+    }
+  }
+
+  switch (range) {
+    case EFR_WORLD:
+      return num_world_buildings(source);
+    case EFR_PLAYER:
+      return num_player_buildings(plr, source);
+    case EFR_CONTINENT:
+      {
+       int continent;
+
+       continent = map_get_continent(pcity->x, pcity->y);
+
+       return num_continent_buildings(plr, continent, source);
+      }
+    case EFR_CITY:
+      return num_city_buildings(pcity, source);
+    case EFR_LOCAL:
+      if (building == source) {
+       return num_city_buildings(pcity, source);
+      } else {
+       return 0;
+      }
+    default:
+      return 0;
+  }
+}
+
+/**************************************************************************
+  Is the effect from the source building redundant on the given target
+  (i.e. are its effects replaced by other sources in the group)?
+
+  target gives the type of the target
+  (plr,pcity,building) gives the exact target
+  source is the source of the effect
+  peffect is the exact effect
+**************************************************************************/
+static bool is_effect_redundant(enum target_type target,
+                               const struct player *plr,
+                               const struct city *pcity,
+                               Impr_Type_id building,
+                               Impr_Type_id source,
+                               const struct effect *peffect)
+{
+  if (peffect->group) {
+    /* If there is more than one building in the same effects "group", then
+     * only the first one that exists can be active. */
+    effect_group_element_list_iterate(peffect->group->elements, elt) {
+      if (elt->improvement == source) {
+       return FALSE;
+      } else {
+       if (count_targets_in_range(target, plr, pcity, building, elt->range,
+                                  elt->survives, elt->improvement) > 0) {
+         return TRUE;
+       }
+      }
+    } effect_group_element_list_iterate_end;
+  }
+  return FALSE;
+}
+
+/**************************************************************************
+  Checks the requirements of the effect to see if it is active on the
+  given target. (If the requirements are not met the effect should be
+  ignored.)
+
+  target gives the type of the target
+  (plr,pcity,building,ptile) give the exact target
+  source gives the source of the effect
+  peffect gives the exact effect value
+**************************************************************************/
+static bool are_effect_reqs_active(enum target_type target,
+                                  const struct player *plr,
+                                  const struct city *pcity,
+                                  Impr_Type_id building,
+                                  const struct tile *ptile,
+                                  Impr_Type_id source,
+                                  const struct effect *peffect)
+{
+  bool active = FALSE;
+
+  switch (peffect->req.type) {
+    case REQ_NONE:
+      active = TRUE;
+      break;
+    case REQ_TECH:
+      active = plr && (get_invention(plr, peffect->req.value.tech)
+                      == TECH_KNOWN);
+      break;
+    case REQ_GOV:
+      active = plr && (plr->government == peffect->req.value.gov);
+      break;
+    case REQ_BUILDING:
+      active = (count_targets_in_range(target, plr, pcity, building,
+                                      EFR_CITY, FALSE,
+                                      peffect->req.value.building) > 0);
+      break;
+    case REQ_SPECIAL:
+      active = ptile && tile_has_special(ptile, peffect->req.value.special);
+      break;
+    case REQ_TERRAIN:
+      active = ptile && (ptile->terrain == peffect->req.value.terrain);
+      break;
+    case REQ_LAST:
+      assert(0);
+      break;
+  }
+
+  return active;
+}
+
+/**************************************************************************
+  Can the effect from the source building be active at a certain target
+  (player, city or building)?
+
+  Don't do range checks for the actual source being tested, only for
+  requirements.
+
+  target gives the type of the target
+  (plr,pcity,building,ptile) give the exact target
+  source gives the source of the effect
+  peffect gives the exact effect value
+**************************************************************************/
+bool is_effect_useful(enum target_type target, const struct player *plr,
+                     const struct city *pcity, Impr_Type_id building,
+                     const struct tile *ptile, Impr_Type_id source,
+                     const struct effect *peffect)
+{
+  if (is_effect_redundant(target, plr, pcity, building, source, peffect)) {
+    return FALSE;
+  }
+  return are_effect_reqs_active(target, plr, pcity, building,
+                               ptile, source, peffect);
+}
+
+/**************************************************************************
+  Is the effect from the source building active at a certain target (player,
+  city or building)?
+
+  target gives the type of the target
+  (plr,pcity,building,ptile) give the exact target
+  source gives the source of the effect
+  peffect gives the exact effect value
+**************************************************************************/
+static bool is_effect_active(enum target_type target,
+                            const struct player *plr,
+                            const struct city *pcity,
+                            Impr_Type_id building,
+                            const struct tile *ptile,
+                            Impr_Type_id source,
+                            const struct effect *peffect)
+{
+  if (count_targets_in_range(target, plr, pcity, building, peffect->range,
+                            peffect->survives, source) == 0) {
+    return FALSE;
+  }
+  return is_effect_useful(target, plr, pcity, building,
+                         ptile, source, peffect);
+}
+
+/**************************************************************************
+  Returns TRUE if a building is replaced.  To be replaced, all its effects
+  must be redundant.
+**************************************************************************/
+bool building_replaced(const struct city *pcity, Impr_Type_id id)
+{
+  bool equivs_present = FALSE;
+
+  effect_type_vector_iterate(get_building_effect_types(id), ptype) {
+    effect_list_iterate(*get_building_effects(id, *ptype), peff) {
+      if (!is_effect_redundant(TARGET_BUILDING, city_owner(pcity), pcity, id,
+                              id, peff)) {
+       return FALSE;
+      }
+      if (peff->group) {
+       equivs_present = TRUE;
+      }
+    } effect_list_iterate_end;
+  } effect_type_vector_iterate_end;
+  return equivs_present;
+}
+
+/**************************************************************************
+  Get the total value of one source building's effect type.  This is 
+  necessary since one building may have multiple effects of one type.
+**************************************************************************/
+static int get_effect_value(enum target_type target,
+                           const struct player *plr,
+                           const struct city *pcity,
+                           Impr_Type_id id,
+                           const struct tile *ptile,
+                           Impr_Type_id source,
+                           enum effect_type effect_type)
+{
+  int value = 0;
+
+  effect_list_iterate(*get_building_effects(source, effect_type), peffect) {
+    if (is_effect_active(target, plr, pcity, id, ptile, source, peffect)) {
+      value += peffect->value;
+    }
+  } effect_list_iterate_end;
+
+  return value;
+}
+
+/**************************************************************************
+  Returns the effect bonus for any target.
+
+  The target type is given by 'target'.  The effect type is given by
+  'effect'.  The other parameters give information about the target.
+**************************************************************************/
+static int get_target_bonus(enum target_type target,
+                           enum effect_type effect,
+                           const struct player *pplayer,
+                           const struct city *pcity,
+                           Impr_Type_id building,
+                           const struct tile *ptile)
+{
+  int bonus = 0;
+
+  building_vector_iterate(get_buildings_with_effect(effect), pbldg) {
+    bonus += get_effect_value(target, pplayer, pcity, building, ptile,
+                             *pbldg, effect);
+  } building_vector_iterate_end;
+
+  return bonus;
+}
+
+/**************************************************************************
+  Returns the effect bonus for a player.
+**************************************************************************/
+int get_player_bonus(const struct player *pplayer, enum effect_type effect)
+{
+  return get_target_bonus(TARGET_PLAYER, effect,
+                         pplayer, NULL, B_LAST, NULL);
+}
+
+/**************************************************************************
+  Returns the effect bonus at a city.
+**************************************************************************/
+int get_city_bonus(const struct city *pcity, enum effect_type effect)
+{
+  return get_target_bonus(TARGET_CITY, effect,
+                         city_owner(pcity), pcity, B_LAST, NULL);
+}
+
+/**************************************************************************
+  Returns the effect bonus at a city tile.
+**************************************************************************/
+int get_city_tile_bonus(const struct city *pcity, const struct tile *ptile,
+                       enum effect_type effect)
+{
+  return get_target_bonus(TARGET_CITY, effect,
+                         city_owner(pcity), pcity, B_LAST, ptile);
+}
+
+/**************************************************************************
+  Returns the effect bonus at a building.
+**************************************************************************/
+int get_building_bonus(const struct city *pcity, Impr_Type_id id,
+                      enum effect_type effect)
+{
+  return get_target_bonus(TARGET_BUILDING, effect,
+                         city_owner(pcity), pcity, id, NULL);
+}
+
+/**************************************************************************
+  Returns the effect sources of this type currently active at the city.
+**************************************************************************/
+struct building_vector get_city_bonus_sources(const struct city *pcity,
+                                             enum effect_type effect)
+{
+  struct player *plr = city_owner(pcity);
+  struct building_vector res;
+
+  building_vector_init(&res);
+
+  building_vector_iterate(get_buildings_with_effect(effect), pbldg) {
+    if (get_effect_value(TARGET_CITY, plr, pcity,
+                        B_LAST, NULL, *pbldg, effect) > 0) {
+      building_vector_append(&res, pbldg);
+    }
+  } building_vector_iterate_end;
+
+  return res;
+}
+
+/**************************************************************************
   Returns the effect bonus the currently-in-construction-item will provide.
 
   Note this is not called get_current_production_bonus because that would
   be confused with EFT_PROD_BONUS.
-
-  TODO:
-    1.  This function does not access the effect data directly; instead
-        it just associates the effect with a building.
-    2.  Only a few effects are supported.
 **************************************************************************/
 int get_current_construction_bonus(const struct city *pcity,
                                   enum effect_type effect)
 {
-  if (pcity->is_building_unit) {
-    return 0; /* No effects for units. */
-  }
+  if (!pcity->is_building_unit) {
+    Impr_Type_id id;
+    int power = 0;
+
+    id = pcity->currently_building;
+
+    effect_list_iterate(*get_building_effects(id, effect), peffect) {
+      if (is_effect_useful(TARGET_BUILDING, city_owner(pcity),
+                                  pcity, id, NULL, id, peffect)) {
+       power += peffect->value;
+      }
+    } effect_list_iterate_end;
 
-  switch (effect) {
-  case EFT_PROD_TO_GOLD:
-    return (pcity->currently_building == B_CAPITAL) ? 1 : 0;
-  case EFT_SS_STRUCTURAL:
-    return (pcity->currently_building == B_SSTRUCTURAL) ? 1 : 0;
-  case EFT_SS_COMPONENT:
-    return (pcity->currently_building == B_SCOMP) ? 1 : 0;
-  case EFT_SS_MODULE:
-    return (pcity->currently_building == B_SMODULE) ? 1 : 0;
-  default:
-    /* All others unsupported. */
-    break;
+    return power;
   }
 
-  assert(0);
   return 0;
 }
Index: common/effects.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.h,v
retrieving revision 1.6
diff -u -r1.6 effects.h
--- common/effects.h    4 Sep 2004 20:19:51 -0000       1.6
+++ common/effects.h    6 Sep 2004 01:11:09 -0000
@@ -13,11 +13,10 @@
 #ifndef FC__EFFECTS_H
 #define FC__EFFECTS_H
 
-struct impr_effect;
-
 #include "shared.h"            /* bool */
 
 #include "fc_types.h"
+#include "tech.h"
 #include "terrain.h"
 
 /* Range of effects (used in equiv_range and effect.range fields)
@@ -25,7 +24,7 @@
 enum effect_range {
   EFR_LOCAL,
   EFR_CITY,
-  EFR_ISLAND,
+  EFR_CONTINENT,
   EFR_PLAYER,
   EFR_WORLD,
   EFR_LAST   /* keep this last */
@@ -34,20 +33,14 @@
 /* Type of effects. (Used in effect.type field)
  * These must correspond to effect_type_names[] in effects.c. */
 enum effect_type {
-  EFT_ADV_PARASITE,
+  EFT_TECH_PARASITE,
   EFT_AIRLIFT,
   EFT_ANY_GOVERNMENT,
-  EFT_BARB_ATTACK,
-  EFT_BARB_DEFEND,
-  EFT_BUILDING_COST,
-  EFT_BUILDING_COST_PCT,
   EFT_CAPITAL_CITY,
-  EFT_CAPITAL_EXISTS,
-  EFT_CORRUPT_ADJ,
   EFT_CORRUPT_PCT,
+  EFT_WASTE_PCT,
   EFT_ENABLE_NUKE,
   EFT_ENABLE_SPACE,
-  EFT_ENEMY_PEACEFUL,
   EFT_FOOD_ADD_TILE,
   EFT_FOOD_BONUS,
   EFT_FOOD_PCT,
@@ -55,10 +48,9 @@
   EFT_FOOD_PER_TILE,
   EFT_FORCE_CONTENT,
   EFT_FORCE_CONTENT_PCT,
-  EFT_GIVE_IMM_ADV,
+  EFT_GIVE_IMM_TECH,
   EFT_GROWTH_FOOD,
   EFT_HAVE_EMBASSIES,
-  EFT_IMPROVE_REP,
   EFT_LUXURY_BONUS,
   EFT_LUXURY_PCT,
   EFT_MAKE_CONTENT,
@@ -66,7 +58,6 @@
   EFT_MAKE_CONTENT_MIL_PER,
   EFT_MAKE_CONTENT_PCT,
   EFT_MAKE_HAPPY,
-  EFT_MAY_DECLARE_WAR,
   EFT_NO_ANARCHY,
   EFT_NO_SINK_DEEP,
   EFT_NUKE_PROOF,
@@ -84,13 +75,11 @@
   EFT_PROD_TO_GOLD,
   EFT_REVEAL_CITIES,
   EFT_REVEAL_MAP,
-  EFT_REVOLT_DIST_ADJ,
-  EFT_REVOLT_DIST_Pct,
+  EFT_INCITE_DIST_ADJ,
+  EFT_INCITE_DIST_PCT,
   EFT_SCIENCE_BONUS,
   EFT_SCIENCE_PCT,
   EFT_SIZE_UNLIMIT,
-  EFT_SLOW_NUKE_WINTER,
-  EFT_SLOW_GLOBAL_WARM,
   EFT_SS_STRUCTURAL,
   EFT_SS_COMPONENT,
   EFT_SS_MODULE,
@@ -102,40 +91,158 @@
   EFT_TRADE_PCT,
   EFT_TRADE_INC_TILE,
   EFT_TRADE_PER_TILE,
-  EFT_TRADE_ROUTE_PCT,
-  EFT_UNIT_ATTACK,
-  EFT_UNIT_ATTACK_FIREPOWER,
-  EFT_UNIT_COST,
-  EFT_UNIT_COST_PCT,
-  EFT_UNIT_DEFEND,
-  EFT_UNIT_DEFEND_FIREPOWER,
-  EFT_UNIT_MOVE,
+  EFT_SEA_MOVE,
   EFT_UNIT_NO_LOSE_POP,
   EFT_UNIT_RECOVER,
-  EFT_UNIT_REPAIR,
-  EFT_UNIT_VET_COMBAT,
-  EFT_UNIT_VETERAN,
-  EFT_UPGRADE_ONE_STEP,
-  EFT_UPGRADE_ONE_LEAP,
-  EFT_UPGRADE_ALL_STEP,
-  EFT_UPGRADE_ALL_LEAP,
+  EFT_UPGRADE_UNIT,
   EFT_UPKEEP_FREE,
+  EFT_NO_UNHAPPY,
+  EFT_LAND_VETERAN,
+  EFT_SEA_VETERAN,
+  EFT_AIR_VETERAN,
+  EFT_LAND_VET_COMBAT,
+  EFT_SEA_VET_COMBAT,
+  EFT_AIR_VET_COMBAT,
+  EFT_LAND_REGEN,
+  EFT_SEA_REGEN,
+  EFT_AIR_REGEN,
+  EFT_LAND_DEFEND,
+  EFT_SEA_DEFEND,
+  EFT_AIR_DEFEND,
+  EFT_MISSILE_DEFEND,
+  EFT_SIZE_ADJ,
+  EFT_NO_UPKEEP,
+  EFT_NO_INCITE,
   EFT_LAST     /* keep this last */
 };
 
-#define EFT_ALL EFT_LAST
-
 /* lookups */
 enum effect_range effect_range_from_str(const char *str);
 const char *effect_range_name(enum effect_range id);
 enum effect_type effect_type_from_str(const char *str);
 const char *effect_type_name(enum effect_type id);
 
-bool are_effects_equal(const struct impr_effect *const peff1,
-                      const struct impr_effect *const peff2);
+/* Typedefs. */
+#define effect_list_iterate(list, peff) \
+  TYPED_LIST_ITERATE(struct effect, list, peff)
+#define effect_list_iterate_end  LIST_ITERATE_END
+
+#define SPECVEC_TAG building
+#define SPECVEC_TYPE Impr_Type_id
+#include "specvec.h"
+
+#define building_vector_iterate(vector, pbldg) \
+  TYPED_VECTOR_ITERATE(Impr_Type_id, vector, pbldg)
+#define building_vector_iterate_end  VECTOR_ITERATE_END
+
+#define SPECVEC_TAG effect_type
+#define SPECVEC_TYPE enum effect_type
+#include "specvec.h"
+
+#define effect_type_vector_iterate(vector, ptype) \
+  TYPED_VECTOR_ITERATE(enum effect_type, vector, ptype)
+#define effect_type_vector_iterate_end  VECTOR_ITERATE_END
+
+/* Effect requirement type. */
+enum req_type {
+  REQ_NONE,
+  REQ_TECH,
+  REQ_GOV,
+  REQ_BUILDING,
+  REQ_SPECIAL,
+  REQ_TERRAIN,
+  REQ_LAST
+};
+
+struct effect_group;
+
+struct effect {
+  enum effect_range range;                     /* effect range */
+
+  int value;                                   /* effect modifier value */
+
+  struct effect_group *group;                  /* effect group */
+  bool survives;                               /* does this effect survive? */
+
+  struct {
+    enum req_type type;                                /* requirement type */
+
+    union {
+      Tech_Type_id tech;                       /* requirement tech */
+      int gov;                                 /* requirement government */
+      Impr_Type_id building;                   /* requirement building */
+      enum tile_special_type special;          /* requirement special */
+      enum tile_terrain_type terrain;          /* requirement terrain type */
+    } value;                                   /* requirement value */
+  } req;
+};
+
+#define SPECLIST_TAG effect
+#define SPECLIST_TYPE struct effect
+#include "speclist.h"
+
+struct conn_list;
+
+struct city;
+struct player;
+struct tile;
+
+/* ruleset cache creation and communication functions */
+void ruleset_cache_init(void);
+void ruleset_cache_free(void);
+void ruleset_cache_add(Impr_Type_id id, enum effect_type eff,
+                      enum effect_range range, bool survives,
+                      int value, enum req_type req, int arg, int equiv);
+void send_ruleset_cache(struct conn_list *dest);
+
+/* equivalent effect group */
+struct effect_group *effect_group_new(const char *name);
+void effect_group_add(struct effect_group *group, Impr_Type_id id,
+                     enum effect_range range, bool survives);
+int find_effect_group(const char *name);
+
+/* name string to value functions */
+enum req_type req_type_from_str(const char *str);
+int parse_effect_requirement(Impr_Type_id id, enum req_type req,
+                            const char *arg);
+
+/* effect presence tests */
+enum target_type {
+  TARGET_PLAYER,
+  TARGET_CITY,
+  TARGET_BUILDING 
+};
+
+bool is_effect_useful(enum target_type target, const struct player *plr,
+                     const struct city *pcity, Impr_Type_id id,
+                     const struct tile *ptile, Impr_Type_id source,
+                     const struct effect *eff);
+
+bool building_replaced(const struct city *pcity, Impr_Type_id id);
+
+/* functions to know the bonuses a certain effect is granting */
+int get_player_bonus(const struct player *plr, enum effect_type eff);
+int get_city_bonus(const struct city *pcity, enum effect_type eff);
+int get_city_tile_bonus(const struct city *city, const struct tile *ptile,
+                       enum effect_type eff);
+int get_building_bonus(const struct city *pcity, Impr_Type_id id,
+                      enum effect_type eff);
+
+/* miscellaneous auxiliary effects functions */
+struct effect_list *get_building_effects(Impr_Type_id id,
+                                        enum effect_type eff);
+struct effect_type_vector *get_building_effect_types(Impr_Type_id id);
+
+struct building_vector get_city_bonus_sources(const struct city *pcity,
+                                             enum effect_type eff);
 
 bool building_has_effect(Impr_Type_id building, enum effect_type effect);
 int get_current_construction_bonus(const struct city *pcity,
                                   enum effect_type effect);
 
+Impr_Type_id ai_find_source_building(struct player *plr,
+                                    enum effect_type effect);
+Impr_Type_id get_building_for_effect(enum effect_type effect);
+
 #endif  /* FC__EFFECTS_H */
+
Index: common/fc_types.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fc_types.h,v
retrieving revision 1.5
diff -u -r1.5 fc_types.h
--- common/fc_types.h   3 Sep 2004 04:22:37 -0000       1.5
+++ common/fc_types.h   6 Sep 2004 01:11:09 -0000
@@ -20,25 +20,7 @@
 
 typedef signed short Continent_id;
 typedef enum tile_terrain_type Terrain_type_id;
-
-/* TODO: Remove this enum and make this an integer when gen-eff is done. */
-typedef enum {
-  B_AIRPORT=0, B_AQUEDUCT, B_BANK, B_BARRACKS, B_BARRACKS2, B_BARRACKS3, 
-  B_CATHEDRAL, B_CITY, B_COASTAL, B_COLOSSEUM, B_COURTHOUSE,  B_FACTORY, 
-  B_GRANARY, B_HARBOUR, B_HYDRO, B_LIBRARY, B_MARKETPLACE, B_MASS, B_MFG, 
-  B_NUCLEAR, B_OFFSHORE, B_PALACE, B_POLICE, B_PORT, B_POWER,
-  B_RECYCLING, B_RESEARCH, B_SAM, B_SDI, B_SEWER, B_SOLAR, B_SCOMP, 
-  B_SMODULE, B_SSTRUCTURAL, B_STOCK, B_SUPERHIGHWAYS, B_SUPERMARKET, B_TEMPLE,
-  B_UNIVERSITY,  
-  
-  B_APOLLO, B_ASMITHS, B_COLLOSSUS, B_COPERNICUS, B_CURE, B_DARWIN, B_EIFFEL,
-  B_GREAT, B_WALL, B_HANGING, B_HOOVER, B_ISAAC, B_BACH, B_RICHARDS, 
-  B_LEONARDO, B_LIGHTHOUSE, B_MAGELLAN, B_MANHATTEN, B_MARCO, B_MICHELANGELO, 
-  B_ORACLE, B_PYRAMIDS, B_SETI, B_SHAKESPEARE, B_LIBERTY, B_SUNTZU, 
-  B_UNITED, B_WOMENS,
-  B_CAPITAL, B_LAST_ENUM
-} Impr_Type_id;
-
+typedef int Impr_Type_id;
 
 struct city;
 struct government;
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.184
diff -u -r1.184 game.c
--- common/game.c       4 Sep 2004 20:19:51 -0000       1.184
+++ common/game.c       6 Sep 2004 01:11:10 -0000
@@ -278,6 +278,10 @@
   game.government_when_anarchy = G_MAGIC;   /* flag */
   game.ai_goal_government = G_MAGIC;        /* flag */
 
+  game.default_building = B_LAST;
+  game.palace_building = B_LAST;
+  game.land_defend_building = B_LAST;
+
   sz_strlcpy(game.demography, GAME_DEFAULT_DEMOGRAPHY);
   sz_strlcpy(game.allow_take, GAME_DEFAULT_ALLOW_TAKE);
 
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.149
diff -u -r1.149 game.h
--- common/game.h       3 Sep 2004 04:22:37 -0000       1.149
+++ common/game.h       6 Sep 2004 01:11:10 -0000
@@ -168,6 +168,10 @@
   char rulesetdir[MAX_LEN_NAME];
   int firepower_factor;                /* See README.rulesets */
 
+  Impr_Type_id default_building;
+  Impr_Type_id palace_building;
+  Impr_Type_id land_defend_building;
+
   struct {
     int cathedral_plus;                /* eg Theology */
     int cathedral_minus;       /* eg Communism */
Index: common/government.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.c,v
retrieving revision 1.45
diff -u -r1.45 government.c
--- common/government.c 18 Aug 2004 18:11:05 -0000      1.45
+++ common/government.c 6 Sep 2004 01:11:10 -0000
@@ -237,7 +237,7 @@
     return FALSE;
   } else {
     return (get_invention(pplayer, req) == TECH_KNOWN
-           || player_owns_active_govchange_wonder(pplayer));
+           || get_player_bonus(pplayer, EFT_ANY_GOVERNMENT) > 0);
   }
 }
 
Index: common/improvement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v
retrieving revision 1.45
diff -u -r1.45 improvement.c
--- common/improvement.c        4 Sep 2004 20:19:51 -0000       1.45
+++ common/improvement.c        6 Sep 2004 01:11:10 -0000
@@ -99,9 +99,6 @@
   free(p->equiv_repl);
   p->equiv_repl = NULL;
 
-  free(p->effect);
-  p->effect = NULL;
-
   free(p->helptext);
   p->helptext = NULL;
 }
@@ -355,15 +352,6 @@
 }
 
 /**************************************************************************
-Barbarians don't get enough knowledges to be counted as normal players.
-**************************************************************************/
-bool is_wonder_useful(Impr_Type_id id)
-{
-  if ((id == B_GREAT) && (get_num_human_and_ai_players () < 3)) return FALSE;
-  return TRUE;
-}
-
-/**************************************************************************
  Clears a list of improvements - sets them all to I_NONE
 **************************************************************************/
 void improvement_status_init(Impr_Status * improvements, size_t elements)
@@ -380,18 +368,22 @@
 }
 
 /**************************************************************************
-  Whether player could build this improvement, assuming they had
-  the tech req, and assuming a city with the right pre-reqs etc.
+  Whether player can build given improvement somewhere,
+  ignoring whether improvement is obsolete.
 **************************************************************************/
-bool could_player_eventually_build_improvement(struct player *p,
-                                             Impr_Type_id id)
+bool can_player_build_improvement_direct(struct player *p, Impr_Type_id id)
 {
   struct impr_type *impr;
   bool space_part = FALSE;
 
   /* This also checks if tech req is Never */
-  if (!improvement_exists(id))
+  if (!improvement_exists(id)) {
     return FALSE;
+  }
+
+  if (!player_knows_improvement_tech(p, id)) {
+    return FALSE;
+  }
 
   impr = get_improvement_type(id);
 
@@ -415,46 +407,50 @@
       return FALSE;
     }
   }
-  if (space_part && (game.global_wonders[B_APOLLO] == 0
-                    || p->spaceship.state >= SSHIP_LAUNCHED)) {
+  if (space_part &&
+      (!get_player_bonus(p, EFT_ENABLE_SPACE) > 0
+       || p->spaceship.state >= SSHIP_LAUNCHED)) {
     return FALSE;
   }
 
   if (is_wonder(id)) {
     /* Can't build wonder if already built */
     if (game.global_wonders[id] != 0) return FALSE;
-  } else {
-    /* Can't build if obsolette */
-    if (improvement_obsolete(p, id)) return FALSE;
   }
+
   return TRUE;
 }
 
 /**************************************************************************
-...
+  Whether player can _eventually_ build given improvement somewhere -- ie,
+  returns 1 if improvement is available with current tech OR will be available
+  with future tech.  returns 0 if improvement is obsolete.
 **************************************************************************/
-static bool could_player_build_improvement(struct player *p, Impr_Type_id id)
+bool can_player_build_improvement(struct player *p, Impr_Type_id id)
 {
-  if (!could_player_eventually_build_improvement(p, id))
+  if (!can_player_build_improvement_direct(p, id)) {
     return FALSE;
-
-  /* Make sure we have the tech /now/.*/
-  if (get_invention(p, improvement_types[id].tech_req) == TECH_KNOWN)
-    return TRUE;
-  return FALSE;
+  }
+  if (improvement_obsolete(p, id)) {
+    return FALSE;
+  }
+  return TRUE;
 }
-  
+
 /**************************************************************************
-  Can a player build this improvement somewhere?  Ignores the fact that 
-  player may not have a city with appropriate prereqs.
+  Whether player can _eventually_ build given improvement somewhere -- ie,
+  returns 1 if improvement is available with current tech OR will be available
+  with future tech.  returns 0 if unit is obsolete.
 **************************************************************************/
-bool can_player_build_improvement(struct player *p, Impr_Type_id id)
+bool can_player_eventually_build_improvement(struct player *p, Impr_Type_id id)
 {
-  if (!improvement_exists(id))
+  if (!improvement_exists(id)) {
     return FALSE;
-  if (!player_knows_improvement_tech(p,id))
+  }
+  if (improvement_obsolete(p, id)) {
     return FALSE;
-  return(could_player_build_improvement(p, id));
+  }
+  return TRUE;
 }
 
 /**************************************************************************
@@ -564,7 +560,7 @@
 
   We only check improvements within the equiv_range range. 
 
-  N.B. Unlike effects, we do not have to do multiple iterations: an 
+  N.B. We do not need to do multiple iterations: an 
   improvement making another improvement redundant does not depend on 
   whether it itself it redundant or not. having been built is all that 
   counts.
Index: common/improvement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.h,v
retrieving revision 1.32
diff -u -r1.32 improvement.h
--- common/improvement.h        3 Sep 2004 04:22:37 -0000       1.32
+++ common/improvement.h        6 Sep 2004 01:11:10 -0000
@@ -23,6 +23,12 @@
 #include "terrain.h"           /* Terrain_type_id etc */
 #include "unittype.h"          /* Unit_Class_id, Unit_Type_id */
 
+/* B_LAST is a value which is guaranteed to be larger than all
+ * actual Impr_Type_id values.  It is used as a flag value;
+ * it can also be used for fixed allocations to ensure ability
+ * to hold full number of improvement types.  */
+#define B_LAST MAX_NUM_ITEMS
+
 /* Improvement status (for cities' lists of improvements)
  * An enum or bitfield would be neater here, but we use a typedef for
  * a) less memory usage and b) compatibility with old behaviour */
@@ -50,25 +56,6 @@
   IR_LAST      /* keep this last */
 };
 
-/* An effect conferred by an improvement. */
-struct impr_effect {
-  enum effect_type type;
-  enum effect_range range;
-  int amount;
-  int survives;                           /* 1 = effect survives wonder 
destruction */
-  Impr_Type_id cond_bldg;         /* B_LAST = unconditional */
-  int cond_gov;                           /* game.government_count = 
unconditional */
-  Tech_Type_id cond_adv;          /* A_NONE = unconditional; A_LAST = never */
-  enum effect_type cond_eff;      /* EFT_LAST = unconditional */
-  Unit_Class_id aff_unit;         /* UCL_LAST = all */
-  Terrain_type_id aff_terr; /* T_UNKNOWN = all; T_NONE = none */
-  enum tile_special_type aff_spec; /* S_* bit mask of specials affected */
-};
-
-/* Maximum number of effects per improvement 
- * (this should not be more than the number of bits in the Eff_Status type) */
-#define MAX_EFFECTS 16
-  
 /* Type of improvement. (Read from buildings.ruleset file.) */
 struct impr_type {
   char name[MAX_LEN_NAME];
@@ -83,11 +70,11 @@
   Impr_Type_id *equiv_dupl;            /* list; B_LAST terminated */
   Impr_Type_id *equiv_repl;            /* list; B_LAST terminated */
   Tech_Type_id obsolete_by;            /* A_LAST = never obsolete */
+  Impr_Type_id replaced_by;            /* B_LAST = never replaced */
   bool is_wonder;
   int build_cost;                      /* Use wrappers to access this. */
   int upkeep;
   int sabotage;                /* Base chance of diplomat sabotage succeeding. 
*/
-  struct impr_effect *effect;          /* list; .type==EFT_LAST terminated */
   int variant;                 /* FIXME: remove when gen-impr obsoletes */
   struct Sprite *sprite;               /* icon of the improvement */
   char *helptext;
@@ -122,15 +109,15 @@
 bool improvement_redundant(struct player *pplayer, const struct city *pcity,
                           Impr_Type_id id, bool want_to_build);
 bool wonder_obsolete(Impr_Type_id id);
-bool is_wonder_useful(Impr_Type_id id);
 Impr_Type_id find_improvement_by_name(const char *s);
 Impr_Type_id find_improvement_by_name_orig(const char *s);
 void improvement_status_init(Impr_Status * improvements, size_t elements);
 
 /* player related improvement and unit functions */
-bool could_player_eventually_build_improvement(struct player *p, 
-                                               Impr_Type_id id);
+bool can_player_build_improvement_direct(struct player *p, Impr_Type_id id);
 bool can_player_build_improvement(struct player *p, Impr_Type_id id);
+bool can_player_eventually_build_improvement(struct player *p,
+                                            Impr_Type_id id);
 
 /* city related improvement functions */
 void mark_improvement(struct city *pcity,Impr_Type_id id,Impr_Status status);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.45
diff -u -r1.45 packets.def
--- common/packets.def  3 Sep 2004 03:56:58 -0000       1.45
+++ common/packets.def  6 Sep 2004 01:11:10 -0000
@@ -157,7 +157,6 @@
 type BIT_STRING                = bit_string(char)
 type WORKLIST          = worklist(struct worklist)
 type TECH_LIST         = tech_list(int)
-type EFFECT            = effect(struct impr_effect)
 
 # typedefs for enums
 type CLAUSE            = uint8(enum clause_type)
@@ -178,6 +177,11 @@
 type ORDERS            = uint8(enum unit_orders)
 type SSET_TYPE         = uint8(enum sset_type)
 
+# typedefs for effects
+type EFF               = uint8(enum effect_type)
+type EFR               = uint8(enum effect_range)
+type REQ               = uint8(enum req_type)
+
 # typedefs for IDs
 type PLAYER            = UINT8
 type CITY              = UINT16
@@ -1140,7 +1144,7 @@
   STRING graphic_str[MAX_LEN_NAME];
   STRING graphic_alt[MAX_LEN_NAME];
   TECH tech_req, obsolete_by;
-  IMPROVEMENT bldg_req;
+  IMPROVEMENT bldg_req, replaced_by;
   BOOL is_wonder;
   IMPR_RANGE equiv_range;
   UINT16 build_cost;
@@ -1157,8 +1161,6 @@
   IMPROVEMENT equiv_dupl[255:equiv_dupl_count];
   UINT8 equiv_repl_count;
   IMPROVEMENT equiv_repl[255:equiv_repl_count];
-  UINT8 effect_count;
-  EFFECT effect[255:effect_count];  
 end
 
 PACKET_RULESET_TERRAIN=105;sc,lsend
@@ -1245,6 +1247,8 @@
   BOOL slow_invasions;
 
   STRING team_name[MAX_NUM_TEAMS][MAX_LEN_NAME];
+
+  IMPROVEMENT default_building;
 end
 
 
@@ -1296,3 +1300,26 @@
 
   UINT8 category;                              /* which category this is in */
 end
+
+/************** Effects hash packets **********************/
+
+PACKET_RULESET_CACHE_GROUP=120;sc,lsend
+  STRING name[MAX_LEN_NAME];
+
+  UINT8 num_elements;
+  IMPROVEMENT improvements[255:num_elements];
+  EFR ranges[255:num_elements];
+  BOOL survives[255:num_elements];
+end
+
+PACKET_RULESET_CACHE_EFFECT=121;sc,lsend
+  IMPROVEMENT id;
+  EFF eff;
+  EFR range;
+  BOOL survives;
+  SINT32 value;
+  REQ req;
+  SINT32 arg;
+  SINT32 group;
+end
+
Index: common/packets.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v
retrieving revision 1.162
diff -u -r1.162 packets.h
--- common/packets.h    14 Jan 2004 11:58:12 -0000      1.162
+++ common/packets.h    6 Sep 2004 01:11:10 -0000
@@ -19,7 +19,7 @@
 #include "connection.h"                /* struct connection, MAX_LEN_* */
 #include "diptreaty.h"
 #include "events.h"
-#include "effects.h"
+#include "improvement.h"
 #include "map.h"
 #include "player.h"
 #include "shared.h"            /* MAX_LEN_NAME, MAX_LEN_ADDR */
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.150
diff -u -r1.150 player.c
--- common/player.c     29 Aug 2004 19:03:31 -0000      1.150
+++ common/player.c     6 Sep 2004 01:11:10 -0000
@@ -65,7 +65,7 @@
 {
   return (TEST_BIT(pplayer->embassy, pplayer2->player_no)
           || (pplayer == pplayer2)
-          || (player_owns_active_wonder(pplayer, B_MARCO)
+          || (get_player_bonus(pplayer, EFT_HAVE_EMBASSIES) > 0
               && !is_barbarian(pplayer2)));
 }
 
@@ -370,31 +370,6 @@
 }
 
 /**************************************************************************
- Return 1 if one of the player's cities has the specified wonder,
- and it is not obsolete.
-**************************************************************************/
-bool player_owns_active_wonder(struct player *pplayer,
-                             Impr_Type_id id)
-{
-  return (improvement_exists(id)
-         && is_wonder(id)
-         && (!wonder_obsolete(id))
-         && player_find_city_by_id(pplayer, game.global_wonders[id]));
-}
-
-/**************************************************************************
- ...
-**************************************************************************/
-bool player_owns_active_govchange_wonder(struct player *pplayer)
-{
-  return ( player_owns_active_wonder(pplayer, B_LIBERTY) ||
-          ( (improvement_variant(B_PYRAMIDS)==1) &&
-            player_owns_active_wonder(pplayer, B_PYRAMIDS) ) ||
-          ( (improvement_variant(B_UNITED)==1) &&
-            player_owns_active_wonder(pplayer, B_UNITED) ) );
-}
-
-/**************************************************************************
  Returns the number of techs the player has researched which has this
  flag. Needs to be optimized later (e.g. int tech_flags[TF_LAST] in
  struct player)
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.122
diff -u -r1.122 player.h
--- common/player.h     3 Sep 2004 04:22:37 -0000       1.122
+++ common/player.h     6 Sep 2004 01:11:10 -0000
@@ -217,7 +217,6 @@
   Impr_Status improvements[B_LAST]; /* improvements with equiv_range==Player */
   Impr_Status *island_improv; /* improvements with equiv_range==Island, 
dimensioned to
                                 [map.num_continents][game.num_impr_types] */
-
   struct {
     int length;
     void *data;
@@ -250,9 +249,6 @@
                                    int unit_id);
 
 bool player_in_city_radius(struct player *pplayer, int x, int y);
-bool player_owns_active_wonder(struct player *pplayer,
-                             Impr_Type_id id);
-bool player_owns_active_govchange_wonder(struct player *pplayer);
 bool player_knows_improvement_tech(struct player *pplayer,
                                   Impr_Type_id id);
 bool player_knows_techs_with_flag(struct player *pplayer,
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.216
diff -u -r1.216 unit.c
--- common/unit.c       31 Aug 2004 04:40:50 -0000      1.216
+++ common/unit.c       6 Sep 2004 01:11:10 -0000
@@ -28,6 +28,7 @@
 #include "support.h"
 #include "tech.h"
 
+#include "city.h"
 #include "unit.h"
 
 /***************************************************************
@@ -53,15 +54,9 @@
   case SEA_MOVING:
     move_rate = (base_move_rate * punit->hp) / unit_type(punit)->hp;
 
-    if (player_owns_active_wonder(unit_owner(punit), B_LIGHTHOUSE)) {
-      move_rate += SINGLE_MOVE;
-    }
- 
-    if (player_owns_active_wonder(unit_owner(punit), B_MAGELLAN)) {
-      move_rate += (improvement_variant(B_MAGELLAN) == 1) 
-                     ? SINGLE_MOVE : 2 * SINGLE_MOVE;
-    }
- 
+    move_rate += (get_player_bonus(unit_owner(punit), EFT_SEA_MOVE)
+                 * SINGLE_MOVE);
+
     if (player_knows_techs_with_flag(unit_owner(punit), TF_BOAT_FAST)) {
       move_rate += SINGLE_MOVE;
     }
@@ -497,14 +492,8 @@
     return AB_TOO_BIG;
   if (pcity->owner != punit->owner)
     return AB_NOT_OWNER;
-  if (improvement_exists(B_AQUEDUCT)
-      && !city_got_building(pcity, B_AQUEDUCT)
-      && new_pop > game.aqueduct_size)
-    return AB_NO_AQUEDUCT;
-  if (improvement_exists(B_SEWER)
-      && !city_got_building(pcity, B_SEWER)
-      && new_pop > game.sewer_size)
-    return AB_NO_SEWER;
+  if (!city_can_grow_to(pcity, new_pop))
+    return AB_NO_SPACE;
   return AB_ADD_OK;
 }
 
@@ -1643,7 +1632,7 @@
 **************************************************************************/
 int base_trireme_loss_pct(struct player *pplayer, struct unit *punit)
 {
-  if (player_owns_active_wonder(pplayer, B_LIGHTHOUSE)) {
+  if (get_player_bonus(pplayer, EFT_NO_SINK_DEEP) > 0) {
     return 0;
   } else if (player_knows_techs_with_flag(pplayer, TF_REDUCE_TRIREME_LOSS2)) {
     return game.trireme_loss_chance[punit->veteran] / 4;
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.123
diff -u -r1.123 unit.h
--- common/unit.h       3 Sep 2004 04:22:37 -0000       1.123
+++ common/unit.h       6 Sep 2004 01:11:10 -0000
@@ -96,11 +96,7 @@
   AB_NOT_OWNER,                        /* Owner of unit is not owner of
                                   city */
   AB_TOO_BIG,                  /* City is too big to be added to */
-  AB_NO_AQUEDUCT,              /* Adding takes city past limit for
-                                  aquaduct but city has no
-                                  aquaduct */
-  AB_NO_SEWER                  /* Adding takes city past limit for
-                                  sewer but city has no sewer */
+  AB_NO_SPACE                  /* Adding takes city past limit */
 };
 
 enum unit_upgrade_result {
Index: common/unittype.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v
retrieving revision 1.39
diff -u -r1.39 unittype.c
--- common/unittype.c   26 Aug 2004 06:26:09 -0000      1.39
+++ common/unittype.c   6 Sep 2004 01:11:11 -0000
@@ -476,7 +476,8 @@
 
   if (!unit_type_exists(id))
     return FALSE;
-  if (unit_type_flag(id, F_NUCLEAR) && game.global_wonders[B_MANHATTEN] == 0)
+  if (unit_type_flag(id, F_NUCLEAR)
+      && !get_player_bonus(p, EFT_ENABLE_NUKE) > 0)
     return FALSE;
   if (unit_type_flag(id, F_NOBUILD)) {
     return FALSE;
Index: common/aicore/cm.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/cm.c,v
retrieving revision 1.39
diff -u -r1.39 cm.c
--- common/aicore/cm.c  24 Jul 2004 03:43:35 -0000      1.39
+++ common/aicore/cm.c  6 Sep 2004 01:11:11 -0000
@@ -401,7 +401,7 @@
   freelog(LOG_NORMAL, "  trade   = %3d", pcity->trade_prod);
 
   freelog(LOG_NORMAL, "  gold    = %3d (%+3d)", pcity->tax_total,
-         city_gold_surplus(pcity));
+         city_gold_surplus(pcity, pcity->tax_total));
   freelog(LOG_NORMAL, "  luxury  = %3d", pcity->luxury_total);
   freelog(LOG_NORMAL, "  science = %3d", pcity->science_total);
 }
@@ -501,7 +501,7 @@
   result->surplus[FOOD] = pcity->food_surplus;
   result->surplus[SHIELD] = pcity->shield_surplus;
   result->surplus[TRADE] = pcity->trade_prod;
-  result->surplus[GOLD] = city_gold_surplus(pcity);
+  result->surplus[GOLD] = city_gold_surplus(pcity, pcity->tax_total);
   result->surplus[LUXURY] = pcity->luxury_total;
   result->surplus[SCIENCE] = pcity->science_total;
 
Index: data/civ1/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ1/buildings.ruleset,v
retrieving revision 1.36
diff -u -r1.36 buildings.ruleset
--- data/civ1/buildings.ruleset 4 Sep 2004 20:19:51 -0000       1.36
+++ data/civ1/buildings.ruleset 6 Sep 2004 01:11:12 -0000
@@ -59,6 +59,51 @@
  some movement points left to be airlifted.\
 ")
 
+[group_factories]
+name           = "Factories"
+elements       =
+    { "building", "range"
+      "Mfg. Plant", "City"
+      "Factory", "City"
+    }
+
+[group_generators]
+name           = "Generators"
+elements       =
+    { "building", "range"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+      "Power Plant", "City"
+    }
+
+[group_janitors]
+name            = "Janitors"
+elements       =
+    { "building", "range"
+      "Recycling Center", "City"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+    }
+
+[group_defenders]
+name           = "Defenders"
+elements       =
+    { "building", "range"
+      "Great Wall", "Player"
+      "City Walls", "City"
+    }
+
+[group_purifiers]
+name           = "Purifiers"
+elements       =
+    { "building", "range"
+      "Palace", "City"
+      "Courthouse", "City"
+    }
+
+
 [building_aqueduct]
 name           = _("Aqueduct")
 tech_req       = "Construction"
@@ -75,9 +120,9 @@
 build_cost     = 120
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount"
-       "Size_Unlimit", "City", 10
+effect          =
+    { "name"
+      "Size_Unlimit"
     }
 sound          = "b_aqueduct"
 sound_alt      = "b_generic"
@@ -102,9 +147,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Marketplace"
-       "Luxury_Bonus", "City", 50, "Marketplace"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Marketplace"
+      "Luxury_Bonus", 50, "Building", "Marketplace"
     }
 sound          = "b_bank"
 sound_alt      = "b_generic"
@@ -124,24 +169,17 @@
 ;spec_gate     =
 equiv_range    = "City"
 ;equiv_dupl    =
-equiv_repl     = "Sun Tzu's War Academy", "Barracks II", "Barracks III"
+equiv_repl     = "Barracks II", "Barracks III"
 obsolete_by    = "Gunpowder"
 is_wonder      = 0
 build_cost     = 40
-upkeep         = 0
+upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Unit_Veteran", "City", "Helicopter"
-       "Unit_Repair", "City", "Helicopter"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
-       "Unit_Veteran", "City", "Missile"
-       "Unit_Repair", "City", "Missile"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Land_Veteran"
+      "Sea_Veteran"
+      "Air_Veteran"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "b_barracks_i"
@@ -164,24 +202,17 @@
 ;spec_gate     =
 equiv_range    = "City"
 ;equiv_dupl    =
-equiv_repl     = "Sun Tzu's War Academy", "Barracks III"
+equiv_repl     = "Barracks III"
 obsolete_by    = "Combustion"
 is_wonder      = 0
 build_cost     = 40
-upkeep         = 1
+upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Unit_Veteran", "City", "Helicopter"
-       "Unit_Repair", "City", "Helicopter"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
-       "Unit_Veteran", "City", "Missile"
-       "Unit_Repair", "City", "Missile"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Land_Veteran"
+      "Sea_Veteran"
+      "Air_Veteran"
     }
 sound          = "b_barracks_ii"
 sound_alt      = "b_generic"
@@ -203,24 +234,17 @@
 ;spec_gate     =
 equiv_range    = "City"
 ;equiv_dupl    =
-equiv_repl     = "Sun Tzu's War Academy"
+;equiv_repl    =
 obsolete_by    = "None"
 is_wonder      = 0
 build_cost     = 40
-upkeep         = 2
+upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Unit_Veteran", "City", "Helicopter"
-       "Unit_Repair", "City", "Helicopter"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
-       "Unit_Veteran", "City", "Missile"
-       "Unit_Repair", "City", "Missile"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Land_Veteran"
+      "Sea_Veteran"
+      "Air_Veteran"
     }
 sound          = "b_barracks_iii"
 sound_alt      = "b_generic"
@@ -249,8 +273,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 4
+    { "name", "value"
+      "Make_Content", 4
     }
 sound          = "b_cathedral"
 sound_alt      = "b_generic"
@@ -276,11 +300,10 @@
 upkeep         = 2
 sabotage       = 50
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 300, "Helicopter"
-       "Unit_Defend", "City", 300, "Land"
-       "Unit_Defend", "City", 300, "Sea"
-       "Unit_No_Lose_Pop", "City", 0, "Land"
+    { "name", "value", "equiv"
+      "Land_Defend", 200, "Defenders"
+      "Sea_Defend", 200, "Defenders"
+      "Unit_No_Lose_Pop"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "b_city_walls"
@@ -293,33 +316,6 @@
  occurs when a defending unit is destroyed by a land unit.\
 ")
 
-[building_coastal_defense]
-name           = _("Coastal Defense")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.coastal_defense"
-graphic_alt    = "-"
-terr_gate      = "Ocean"
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 80
-upkeep         = 1
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Sea"
-    }
-sound          = "b_coastal_defense"
-sound_alt      = "b_generic"
-helptext       = _("\
-Increases the defence strength of units within a city by a factor\
- of 2 when defending against bombardments from enemy ships.\
-")
-
 [building_colosseum]
 name           = _("Colosseum")
 tech_req       = "Construction"
@@ -337,8 +333,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 3
+    { "name", "value"
+      "Make_Content", 3
     }
 sound          = "b_colosseum"
 sound_alt      = "b_generic"
@@ -363,10 +359,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Corrupt_Pct", "City", 50
-       "Make_Content", "City", 1, "Democracy"
-       "Revolt_Dist_Pct", "City", 50
+    { "name", "value", "equiv", "req_type", "req"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
     }
 sound          = "b_courthouse"
 sound_alt      = "b_generic"
@@ -394,8 +389,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Prod_Bonus", "City", 50
+    { "name", "value", "equiv"
+      "Prod_Bonus", 50, "Factories"
     }
 sound          = "b_factory"
 sound_alt      = "b_generic"
@@ -421,8 +416,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "City", 50
+    { "name"
+      "Growth_Food"
     }
 sound          = "b_granary"
 sound_alt      = "b_generic"
@@ -435,33 +430,6 @@
 ; In Civ1, city size reduction does not generate food like this.
 ; Dare I ask where this food comes from?? :-)
 
-[building_harbour]
-name           = _("Harbour")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.harbour"
-graphic_alt    = "-"
-terr_gate      = "Ocean"
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 60
-upkeep         = 1
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Add_Tile", "City", 1, "Ocean", "None"
-    }
-sound          = "b_harbour"
-sound_alt      = "b_generic"
-helptext       = _("\
-Gives one extra food resource on all Ocean squares.  The city needs\
- to be coastal to build this improvement.\
-")
-
 [building_hydro_plant]
 name           = _("Hydro Plant")
 tech_req       = "Electronics"
@@ -479,10 +447,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv"
+      "Prod_Bonus", 50, "Generators"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_hydro_plant"
 sound_alt      = "b_generic"
@@ -516,8 +483,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "b_library"
 sound_alt      = "b_generic"
@@ -543,9 +510,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Tax_Bonus", "City", 50
-       "Luxury_Bonus", "City", 50
+    { "name", "value"
+      "Tax_Bonus", 50
+      "Luxury_Bonus", 50
     }
 sound          = "b_marketplace"
 sound_alt      = "b_generic"
@@ -571,8 +538,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Pop_Pct", "City", 0
+    { "name", "value"
+      "Pollu_Pop_Pct", 100
     }
 sound          = "b_mass_transit"
 sound_alt      = "b_generic"
@@ -599,8 +566,8 @@
 upkeep         = 6
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "equiv"
+      "Prod_Bonus", 100, "Factories"
     }
 sound          = "b_mfg_plant"
 sound_alt      = "b_generic"
@@ -623,14 +590,13 @@
 equiv_repl     = "Hoover Dam", "Power Plant", "Hydro Plant"
 obsolete_by    = "None"
 is_wonder      = 0
-build_cost     = 160
+build_cost     = 240
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv"
+      "Prod_Bonus", 50, "Generators"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_nuclear_plant"
 sound_alt      = "b_generic"
@@ -649,33 +615,6 @@
 ; For Civ1/2 there should be a change of meltdown during
 ; civil disorder, but that has not been implemented yet.
 
-[building_offshore_platform]
-name           = _("Offshore Platform")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.offshore_platform"
-graphic_alt    = "-"
-terr_gate      = "Ocean"
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 160
-upkeep         = 3
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Prod_Add_Tile", "City", 1, "Ocean", "None"
-    }
-sound          = "b_offshore_platform"
-sound_alt      = "b_generic"
-helptext       = _("\
-Adds 1 extra shield resource on all Ocean squares in a city.  The\
- city needs to be coastal to build this improvement.\
-")
-
 [building_palace]
 name           = _("Palace")
 tech_req       = "Masonry"
@@ -693,9 +632,12 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Capital_City", "City"
-       "Capital_Exists", "Player"
+    { "name", "value", "equiv"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Spy_Resistant", 50
+      "No_Incite"
+      "Capital_City"
     }
 sound          = "b_palace"
 sound_alt      = "b_generic"
@@ -712,64 +654,6 @@
  results in losing whatever spaceship you might have.\
 ")
 
-[building_police_station]
-name           = _("Police Station")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.police_station"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-equiv_repl     = "Women's Suffrage"
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 60
-upkeep         = 2
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "City", 1, "Republic"
-       "Make_Content_Mil", "City", 2, "Democracy"
-    }
-sound          = "b_police_station"
-sound_alt      = "b_generic"
-helptext       = _("\
-Reduces the unhappiness caused by military units outside the city\
- by 2 under Democracy and 1 under Republic.  This improvement has no\
- effect under other governments.\
-")
-
-[building_port_facility]
-name           = _("Port Facility")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.port_facility"
-graphic_alt    = "-"
-terr_gate      = "Ocean"
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 80
-upkeep         = 3
-sabotage       = 100
-effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
-    }
-sound          = "b_port_facility"
-sound_alt      = "b_generic"
-helptext       = _("\
-Allows a city to build veteran sea units.  Also, damaged sea units\
- which stay in town for one full turn without moving are completely\
- restored.\
-")
-
 [building_power_plant]
 name           = _("Power Plant")
 tech_req       = "Refining"
@@ -787,8 +671,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "equiv"
+      "Prod_Bonus", 50, "Generators"
     }
 sound          = "b_power_plant"
 sound_alt      = "b_generic"
@@ -821,8 +705,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Prod_Pct", "City", 34
+    { "name", "value", "equiv"
+      "Pollu_Prod_Pct", 3, "Janitors"
     }
 sound          = "b_recycling_center"
 sound_alt      = "b_generic"
@@ -832,63 +716,6 @@
  generated by production in a city by 66%.\
 ")
 
-[building_research_lab]
-name           = _("Research Lab")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "Library"
-graphic                = "b.research_lab"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-equiv_repl     = "SETI Program"
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 160
-upkeep         = 3
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
-    }
-sound          = "b_research_lab"
-sound_alt      = "b_generic"
-helptext       = _("\
-Together with a Library, a Research Lab increases the science\
- production of a city by 100%. \
-Together with a Library and a University, a Research Lab increases\
- the science production of a city by 150%.\
-")
-
-[building_sam_battery]
-name           = _("SAM Battery")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.sam_battery"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 100
-upkeep         = 2
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Air"
-       "Unit_Defend", "City", 200, "Missile"
-    }
-sound          = "b_sam_battery"
-sound_alt      = "b_generic"
-helptext       = _("\
-Doubles the defense of all units inside the city when attacked by\
- non-nuclear air units.\
-")
-
 [building_sdi_defense]
 name           = _("SDI Defense")
 tech_req       = "Superconductors"
@@ -906,9 +733,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Nuke_Proof", "City", 3
-       "Unit_Defend", "City", 200, "Missile"
+    { "name"
+      "Nuke_Proof"
     }
 sound          = "b_sdi_defense"
 sound_alt      = "b_generic"
@@ -960,12 +786,6 @@
 build_cost     = 320
 upkeep         = 4
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 0
-       "Slow_Global_Warm", "World", 10
-    }
 sound          = "b_solar_plant"
 sound_alt      = "b_generic"
 ; /* xgettext:no-c-format */
@@ -999,9 +819,9 @@
 build_cost     = 160
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Component", "Local"
+effect          =
+    { "name"
+      "SS_Component"
     }
 sound          = "b_space_component"
 sound_alt      = "b_generic"
@@ -1030,9 +850,9 @@
 build_cost     = 320
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Module", "Local"
+effect          =
+    { "name"
+      "SS_Module"
     }
 sound          = "b_space_module"
 sound_alt      = "b_generic"
@@ -1070,9 +890,9 @@
 build_cost     = 80
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Structural", "Local"
+effect          =
+    { "name"
+      "SS_Structural"
     }
 sound          = "b_space_structural"
 sound_alt      = "b_generic"
@@ -1085,93 +905,6 @@
  must have been built by any player.\
 ")
 
-[building_stock_exchange]
-name           = _("Stock Exchange")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "Bank"
-graphic                = "b.stock_exchange"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 160
-upkeep         = 4
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Bank"
-       "Luxury_Bonus", "City", 50, "Bank"
-    }
-sound          = "b_stock_exchange"
-sound_alt      = "b_generic"
-; /* xgettext:no-c-format */
-helptext       = _("\
-Together with a Marketplace and a Bank, a Stock Exchange boosts\
- tax and luxury production in a city by 150%.\
-")
-
-[building_super_highways]
-name           = _("Super Highways")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.super_highways"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 160
-upkeep         = 3
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Trade_Per_Tile", "City", 50, "None", "Road"
-       "Trade_Route_Pct", "City", 10
-    }
-sound          = "b_super_highways"
-sound_alt      = "b_generic"
-; /* xgettext:no-c-format */
-helptext       = _("\
-Increases trade resources by 50% on all squares with roads or\
- railroads.\
-")
-
-[building_supermarket]
-name           = _("Supermarket")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.supermarket"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 0
-build_cost     = 120
-upkeep         = 3
-sabotage       = 100
-effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Per_Tile", "City", 50, "None", "Farmland"
-    }
-sound          = "b_supermarket"
-sound_alt      = "b_generic"
-; /* xgettext:no-c-format */
-helptext       = _("\
-Increases the food resources by 50% on each farmland square which\
- is being used around the city.  Farmland squares are those which\
- have been irrigated a second time.\
-")
-
 [building_temple]
 name           = _("Temple")
 tech_req       = "Ceremonial Burial"
@@ -1189,9 +922,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 1
-       "Make_Content", "City", 1, "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 1
+      "Make_Content", 1, "Tech", "Mysticism"
     }
 sound          = "b_temple"
 sound_alt      = "b_generic"
@@ -1218,8 +951,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "req_type", "req"
+      "Science_Bonus", 50, "Building", "Library"
     }
 sound          = "b_university"
 sound_alt      = "b_generic"
@@ -1246,9 +979,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Reveal_Cities", "Player", 0
-       "Enable_Space", "World", 1
+    { "name", "range", "survives"
+      "Reveal_Cities", "Player", 0
+      "Enable_Space", "World", 1
     }
 helptext       = _("\
 All cities on the map become visible for the player who owns it. \
@@ -1256,33 +989,6 @@
  they have researched the necessary technologies).\
 ")
 
-[building_asmiths_trading_co]
-name           = _("A.Smith's Trading Co.")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.asmiths_trading_co"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "Player"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 1
-build_cost     = 400
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Upkeep_Free", "Player", 1
-    }
-sound          = "w_asmiths_trading_co"
-sound_alt      = "w_generic"
-helptext       = _("\
-City improvements which would normally have an upkeep of 1 are free\
- of upkeep, for all cities.\
-")
-
 [building_colossus]
 name           = _("Colossus")
 tech_req       = "Bronze Working"
@@ -1294,14 +1000,14 @@
 equiv_range    = "City"
 ;equiv_dupl    =
 ;equiv_repl    =
-obsolete_by    = "Flight"
+obsolete_by    = "Electricity"
 is_wonder      = 1
 build_cost     = 200
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Trade_Inc_Tile", "City", 1
+    { "name", "value"
+      "Trade_Inc_Tile", 1
     }
 sound          = "w_colossus"
 sound_alt      = "w_generic"
@@ -1327,8 +1033,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value", "req_type", "req"
+      "Science_Bonus", 50, "Building", "Library"
+      "Science_Bonus", 50, "Building", "University"
+      "Science_Bonus", 100
     }
 sound          = "w_copernicus_observatory"
 sound_alt      = "w_generic"
@@ -1354,8 +1062,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
+    { "name", "range", "value"
+      "Force_Content", "Player", 1
     }
 sound          = "w_cure_for_cancer"
 sound_alt      = "w_generic"
@@ -1381,8 +1089,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Give_Imm_Adv", "Player", 2
+    { "name", "range", "value"
+      "Give_Imm_Tech", "Player", 2
     }
 sound          = "w_darwins_voyage"
 sound_alt      = "w_generic"
@@ -1408,10 +1116,6 @@
 build_cost     = 300
 upkeep         = 0
 sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Improve_Rep", "Player", 25
-    }
 sound          = "w_eiffel_tower"
 sound_alt      = "w_generic"
 ; /* xgettext:no-c-format */
@@ -1433,14 +1137,14 @@
 equiv_range    = "None"
 ;equiv_dupl    =
 ;equiv_repl    =
-obsolete_by    = "University"
+obsolete_by    = "Electronics"
 is_wonder      = 1
 build_cost     = 300
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Adv_Parasite", "Player", 2
+    { "name", "range", "value"
+      "Tech_Parasite", "Player", 2
     }
 sound          = "w_great_library"
 sound_alt      = "w_generic"
@@ -1466,10 +1170,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "Player", 300, "Land"
-       "Unit_No_Lose_Pop", "Player", 0, "Land"
-       "Barb_Attack", "Player", 200
+    { "name", "range", "value", "equiv"
+      "Land_Defend", "Player", 200, "Defenders"
+      "Sea_Defend", "Player", 200, "Defenders"
     }
 sound          = "w_great_wall"
 sound_alt      = "w_generic"
@@ -1496,9 +1199,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
-       "Make_Happy", "City", 2
+    { "name", "range", "value"
+      "Make_Happy", "Player", 1
     }
 sound          = "w_hanging_gardens"
 sound_alt      = "w_generic"
@@ -1527,10 +1229,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "Island", 50, "Factory"
-       "Pollu_Prod_Pct", "Island", 50
-       "Pollu_Prod_Pct", "Island", -50, "Recycling Center"
+    { "name", "range", "value", "equiv"
+      "Prod_Bonus", "Continent", 50, "Generators"
+      "Pollu_Prod_Pct", "Continent", 2, "Janitors"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_hoover_dam"
@@ -1559,6 +1260,11 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
+    { "name", "range", "value", "req_type", "req"
+      "Science_Bonus", "Player", 50, "Building", "Library"
+      "Science_Bonus", "Player", 50, "Building", "University"
+    }
+effect         =
     { "type", "range", "amount"
        "Science_Bonus", "City", 100
     }
@@ -1586,8 +1292,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Island", 2
+    { "name", "range", "value"
+      "Force_Content", "Continent", 2
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_js_bachs_cathedral"
@@ -1597,59 +1303,6 @@
  on the same continent where the wonder is built.\
 ")
 
-[building_king_richards_crusade]
-name           = _("King Richard's Crusade")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.king_richards_crusade"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "City"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "Industrialization"
-is_wonder      = 1
-build_cost     = 300
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Prod_Add_Tile", "City", 1
-    }
-sound          = "w_king_richards_crusade"
-sound_alt      = "w_generic"
-helptext       = _("\
-Adds one extra shield resource on every square around the city\
- where it is built.\
-")
-
-[building_leonardos_workshop]
-name           = _("Leonardo's Workshop")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.leonardos_workshop"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "Player"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "Automobile"
-is_wonder      = 1
-build_cost     = 400
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Upgrade_One_Leap", "Player", 100
-    }
-sound          = "w_leonardos_workshop"
-sound_alt      = "w_generic"
-helptext       = _("\
-Upgrades one obsolete unit per game turn.\
-")
-
 [building_lighthouse]
 name           = _("Lighthouse")
 tech_req       = "Map Making"
@@ -1667,10 +1320,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 1, "Sea"
-       "No_Sink_Deep", "Player"
-       "Unit_Veteran", "Player", 0, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 1
     }
 sound          = "w_lighthouse"
 sound_alt      = "w_generic"
@@ -1699,8 +1350,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 1, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 1
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_magellans_expedition"
@@ -1726,40 +1377,14 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Enable_Nuke", "World", 1
+    { "name", "range", "survives"
+      "Enable_Nuke", "World", 1
     }
 sound          = "w_manhattan_project"
 sound_alt      = "w_generic"
 ;helptext is set in client/helpdata.c:helptext_wonder()
 ;helptext      =
 
-[building_marco_polos_embassy]
-name           = _("Marco Polo's Embassy")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.marco_polos_embassy"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "None"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "Communism"
-is_wonder      = 1
-build_cost     = 200
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range"
-       "Have_Embassies", "Player"
-    }
-sound          = "w_marco_polos_embassy"
-sound_alt      = "w_generic"
-helptext       = _("\
-The player who owns it gets an embassy with all players.\
-")
-
 [building_michelangelos_chapel]
 name           = _("Michelangelo's Chapel")
 tech_req       = "Religion"
@@ -1773,12 +1398,12 @@
 ;equiv_repl    =
 obsolete_by    = "Communism"
 is_wonder      = 1
-build_cost     = 400
+build_cost     = 300
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Make_Content", "Player", 4, "Cathedral"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 4, "Building", "Cathedral"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_michelangelos_chapel"
@@ -1804,9 +1429,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg", "cond_adv"
-       "Make_Content", "Player", 1, "Temple"
-       "Make_Content", "Player", 1, "Temple", "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 2, "Building", "Temple"
     }
 sound          = "w_oracle"
 sound_alt      = "w_generic"
@@ -1831,9 +1455,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
+    { "name", "range"
+      "Any_Government", "Player"
+      "No_Anarchy", "Player"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_pyramids"
@@ -1861,8 +1485,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "Player", 50, "Library"
+    { "name", "range", "value"
+      "Science_Bonus", "Player", 50
     }
 sound          = "w_seti_program"
 sound_alt      = "w_generic"
@@ -1888,8 +1512,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 99
+    { "name"
+      "No_Unhappy"
     }
 sound          = "w_shakespeares_theatre"
 sound_alt      = "w_generic"
@@ -1897,64 +1521,6 @@
 Makes all unhappy citizens content, in the city where it is located.\
 ")
 
-[building_statue_of_liberty]
-name           = _("Statue of Liberty")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.statue_of_liberty"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "None"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "None"
-is_wonder      = 1
-build_cost     = 400
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
-    }
-sound          = "w_statue_of_liberty"
-sound_alt      = "w_generic"
-helptext       = _("\
-Allows you to choose any government, including those that have not yet\
- been researched by your civilization, and without the transition\
- period of Anarchy.\
-")
-
-[building_sun_tzus_war_academy]
-name           = _("Sun Tzu's War Academy")
-tech_req       = "Never"       ; remove when may have indefinite count of 
improvements
-bldg_req       = "None"
-graphic                = "b.sun_tzus_war_academy"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-equiv_range    = "Player"
-;equiv_dupl    =
-;equiv_repl    =
-obsolete_by    = "Mobile Warfare"
-is_wonder      = 1
-build_cost     = 300
-upkeep         = 0
-sabotage       = 0
-effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Veteran", "Player", 0, "Land"
-       "Unit_Vet_Combat", "Player", 100, "Land"
-    }
-sound          = "w_sun_tzus_war_academy"
-sound_alt      = "w_generic"
-helptext       = _("\
-All your new ground units become veterans (for all cities). \
- The chance of a unit becoming a veteran after a battle increases\
- from 50% to 100%.\
-")
-
 [building_united_nations]
 name           = _("United Nations")
 tech_req       = "Communism"
@@ -1972,9 +1538,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
+    { "name", "range"
+      "Any_Government", "Player"
+      "No_Anarchy", "Player"
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_united_nations"
@@ -2007,8 +1573,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content_Mil", "Player", 1
+    { "name", "range", "value"
+      "Make_Content_Mil_Per", "Player", 1
     }
 variant                = 1             ; FIXME: remove when gen-impr obsoletes
 sound          = "w_womens_suffrage"
@@ -2036,8 +1602,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_To_Gold", "City", 100
+    { "name"
+      "Prod_To_Gold"
     }
 helptext       = _("\
 This is not a normal improvement.  Instead, setting a city's\
@@ -2046,13 +1612,15 @@
 ")
 
 
-; FIXME: remove all of the following when gen-impr implemented...
-
 [b_special]
 
 ; Special values:
 
 aqueduct_size=10;
+default="Capitalization"
+
+; FIXME: remove all of the following when gen-impr implemented...
+
 sewer_size=99;
 
 ; Techs which modify building effects:
Index: data/civ2/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/civ2/buildings.ruleset,v
retrieving revision 1.39
diff -u -r1.39 buildings.ruleset
--- data/civ2/buildings.ruleset 4 Sep 2004 20:19:51 -0000       1.39
+++ data/civ2/buildings.ruleset 6 Sep 2004 01:11:12 -0000
@@ -24,6 +24,67 @@
 ; /*** For details of this file's format, ***/
 ; /*** see the default buildings.ruleset. ***/
 
+[group_cathedrals]
+name           = "Cathedrals"
+elements       =
+    { "building", "range"
+      "Michelangelo's Chapel", "Player"
+      "Cathedral", "City"
+    }
+
+[group_labs]
+name           = "Labs"
+elements       =
+    { "building", "range"
+      "SETI Program", "Player"
+      "Research Lab", "City"
+    }
+
+[group_generators]
+name           = "Generators"
+elements       =
+    { "building", "range"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+      "Power Plant", "City"
+    }
+
+[group_janitors]
+name            = "Janitors"
+elements       =
+    { "building", "range"
+      "Recycling Center", "City"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+    }
+
+[group_defenders]
+name           = "Defenders"
+elements       =
+    { "building", "range"
+      "Great Wall", "Player"
+      "City Walls", "City"
+    }
+
+[group_peacekeepers]
+name           = "Peacekeepers"
+elements       =
+    { "building", "range"
+      "Women's Suffrage", "Player"
+      "Police Station", "City"
+    }
+
+[group_purifiers]
+name           = "Purifiers"
+elements       =
+    { "building", "range"
+      "Palace", "City"
+      "Courthouse", "City"
+    }
+
+
 [building_airport]
 name           = _("Airport")
 tech_req       = "Radio"
@@ -41,10 +102,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Airlift", "City"
+    { "name"
+      "Air_Veteran"
+      "Air_Regen"
+      "Airlift"
     }
 sound          = "b_airport"
 sound_alt      = "b_generic"
@@ -75,9 +136,9 @@
 build_cost     = 80
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount"
-       "Size_Unlimit", "City", 8
+effect          =
+    { "name", "value"
+      "Size_Adj", 4
     }
 sound          = "b_aqueduct"
 sound_alt      = "b_generic"
@@ -103,9 +164,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Marketplace"
-       "Luxury_Bonus", "City", 50, "Marketplace"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Marketplace"
+      "Luxury_Bonus", 50, "Building", "Marketplace"
     }
 sound          = "b_bank"
 sound_alt      = "b_generic"
@@ -132,9 +193,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_i"
 sound_alt      = "b_generic"
@@ -163,9 +224,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_ii"
 sound_alt      = "b_generic"
@@ -194,9 +255,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_iii"
 sound_alt      = "b_generic"
@@ -225,10 +286,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Theology"
-       "Make_Content", "City", -1, "Communism"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content", 3, "Cathedrals"
+      "Make_Content", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "b_cathedral"
 sound_alt      = "b_generic"
@@ -258,11 +319,9 @@
 upkeep         = 0
 sabotage       = 50
 effect         =
-    { "type", "range", "amount", "cond_bldg", "aff_unit"
-       "Unit_Defend", "City", 300, "", "Land"
-       "Unit_No_Lose_Pop", "City", 0, "", "Land"
-       "Spy_Resistant", "Local", 50
-       "Spy_Resistant", "Local", -50, "Palace"
+    { "name", "value", "equiv"
+      "Land_Defend", 200, "Defenders"
+      "Unit_No_Lose_Pop"
     }
 sound          = "b_city_walls"
 sound_alt      = "b_generic"
@@ -291,8 +350,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Sea"
+    { "name", "value"
+      "Sea_Defend", 100
     }
 sound          = "b_coastal_defense"
 sound_alt      = "b_generic"
@@ -318,9 +377,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Electronics"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 3
+      "Make_Content", 1, "Tech", "Electricity"
     }
 sound          = "b_colosseum"
 sound_alt      = "b_generic"
@@ -346,10 +405,11 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Corrupt_Pct", "City", 50
-       "Make_Content", "City", 1, "Democracy"
-       "Revolt_Dist_Pct", "City", 50
+    { "name", "value", "equiv", "req_type", "req"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Make_Content", 1, "", "Gov", "Democracy"
+      "Incite_Dist_Pct", 75
     }
 sound          = "b_courthouse"
 sound_alt      = "b_generic"
@@ -377,8 +437,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Prod_Bonus", "City", 50
+    { "name", "value"
+      "Prod_Bonus", 50
     }
 sound          = "b_factory"
 sound_alt      = "b_generic"
@@ -404,8 +464,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "City", 50
+    { "name"
+      "Growth_Food"
     }
 sound          = "b_granary"
 sound_alt      = "b_generic"
@@ -435,8 +495,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+       "Food_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_harbour"
 sound_alt      = "b_generic"
@@ -462,10 +522,10 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_hydro_plant"
 sound_alt      = "b_generic"
@@ -501,8 +561,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "b_library"
 sound_alt      = "b_generic"
@@ -528,9 +588,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Tax_Bonus", "City", 50
-       "Luxury_Bonus", "City", 50
+    { "name", "value"
+      "Tax_Bonus", 50
+      "Luxury_Bonus", 50
     }
 sound          = "b_marketplace"
 sound_alt      = "b_generic"
@@ -556,8 +616,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Pop_Pct", "City", 0
+    { "name", "value"
+      "Pollu_Pop_Pct", 100
     }
 sound          = "b_mass_transit"
 sound_alt      = "b_generic"
@@ -584,8 +644,8 @@
 upkeep         = 6
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "req_type", "req"
+      "Prod_Bonus", 50, "Building", "Factory"
     }
 sound          = "b_mfg_plant"
 sound_alt      = "b_generic"
@@ -612,10 +672,10 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_nuclear_plant"
 sound_alt      = "b_generic"
@@ -653,8 +713,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Prod_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+      "Prod_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_offshore_platform"
 sound_alt      = "b_generic"
@@ -680,10 +740,12 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Capital_City", "City"
-       "Capital_Exists", "Player"
-       "Spy_Resistant", "City", 50
+    { "name", "value", "equiv"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Spy_Resistant", 50
+      "No_Incite"
+      "Capital_City"
     }
 sound          = "b_palace"
 sound_alt      = "b_generic"
@@ -717,9 +779,9 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "City", 1, "Republic"
-       "Make_Content_Mil", "City", 2, "Democracy"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "b_police_station"
 sound_alt      = "b_generic"
@@ -746,9 +808,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Sea_Veteran"
+      "Sea_Regen"
     }
 sound          = "b_port_facility"
 sound_alt      = "b_generic"
@@ -775,8 +837,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
     }
 sound          = "b_power_plant"
 sound_alt      = "b_generic"
@@ -809,8 +872,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Prod_Pct", "City", 34
+    { "name", "value", "equiv"
+      "Pollu_Prod_Pct", 3, "Janitors"
     }
 sound          = "b_recycling_center"
 sound_alt      = "b_generic"
@@ -837,8 +900,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "equiv", "req_type", "req"
+       "Science_Bonus", 50, "Labs", "Building", "Library"
     }
 sound          = "b_research_lab"
 sound_alt      = "b_generic"
@@ -866,9 +929,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Air"
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Air_Defend", 100
     }
 sound          = "b_sam_battery"
 sound_alt      = "b_generic"
@@ -894,9 +956,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Nuke_Proof", "City", 3
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Nuke_Proof"
+      "Missile_Defend", 100
     }
 sound          = "b_sdi_defense"
 sound_alt      = "b_generic"
@@ -924,9 +986,9 @@
 build_cost     = 120
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Size_Unlimit", "City", 12, "Aqueduct"
+effect          =
+    { "name", "req_type", "req"
+      "Size_Unlimit", "Building", "Aqueduct"
     }
 sound          = "b_sewer_system"
 sound_alt      = "b_generic"
@@ -951,12 +1013,6 @@
 build_cost     = 320
 upkeep         = 4
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
-       "Pollu_Prod_Pct", "City", 0
-       "Slow_Global_Warm", "World", 10
-    }
 sound          = "b_solar_plant"
 sound_alt      = "b_generic"
 ; /* xgettext:no-c-format */
@@ -990,9 +1046,9 @@
 build_cost     = 160
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Component", "Local"
+effect          =
+    { "name"
+      "SS_Component"
     }
 sound          = "b_space_component"
 sound_alt      = "b_generic"
@@ -1021,9 +1077,9 @@
 build_cost     = 320
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Module", "Local"
+effect          =
+    { "name"
+      "SS_Module"
     }
 sound          = "b_space_module"
 sound_alt      = "b_generic"
@@ -1061,9 +1117,9 @@
 build_cost     = 80
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Structural", "Local"
+effect          =
+    { "name"
+      "SS_Structural"
     }
 sound          = "b_space_structural"
 sound_alt      = "b_generic"
@@ -1093,9 +1149,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Bank"
-       "Luxury_Bonus", "City", 50, "Bank"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Bank"
+      "Luxury_Bonus", 50, "Building", "Bank"
     }
 sound          = "b_stock_exchange"
 sound_alt      = "b_generic"
@@ -1122,9 +1178,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Trade_Per_Tile", "City", 50, "None", "Road"
-       "Trade_Route_Pct", "City", 10
+    { "name", "value", "req_type", "req"
+      "Trade_Per_Tile", 50, "Special", "Road"
     }
 sound          = "b_super_highways"
 sound_alt      = "b_generic"
@@ -1151,8 +1206,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Per_Tile", "City", 50, "None", "Farmland"
+    { "name", "value", "req_type", "req"
+      "Food_Per_Tile", 50, "Special", "Farmland"
     }
 sound          = "b_supermarket"
 sound_alt      = "b_generic"
@@ -1180,9 +1235,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 1
-       "Make_Content", "City", 1, "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 1
+      "Make_Content", 1, "Tech", "Mysticism"
     }
 sound          = "b_temple"
 sound_alt      = "b_generic"
@@ -1209,8 +1264,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "req_type", "req"
+      "Science_Bonus", 50, "Building", "Library"
     }
 sound          = "b_university"
 sound_alt      = "b_generic"
@@ -1237,9 +1292,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Reveal_Map", "Player", 0
-       "Enable_Space", "World", 1
+    { "name", "range", "survives"
+      "Reveal_Map", "Player", 0
+      "Enable_Space", "World", 1
     }
 sound          = "w_apollo_program"
 sound_alt      = "w_generic"
@@ -1266,8 +1321,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upkeep_Free", "Player", 1
+    { "name", "range", "value"
+      "Upkeep_Free", "Player", 1
     }
 sound          = "w_asmiths_trading_co"
 sound_alt      = "w_generic"
@@ -1293,8 +1348,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Trade_Inc_Tile", "City", 1
+    { "name", "value"
+      "Trade_Inc_Tile", 1
     }
 sound          = "w_colossus"
 sound_alt      = "w_generic"
@@ -1320,8 +1375,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "w_copernicus_observatory"
 sound_alt      = "w_generic"
@@ -1347,8 +1402,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
+    { "name", "range", "value"
+      "Force_Content", "Player", 1
     }
 sound          = "w_cure_for_cancer"
 sound_alt      = "w_generic"
@@ -1374,8 +1429,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Give_Imm_Adv", "Player", 2
+    { "name", "range", "value"
+      "Give_Imm_Tech", "Player", 2
     }
 sound          = "w_darwins_voyage"
 sound_alt      = "w_generic"
@@ -1401,10 +1456,6 @@
 build_cost     = 300
 upkeep         = 0
 sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Improve_Rep", "Player", 25
-    }
 sound          = "w_eiffel_tower"
 sound_alt      = "w_generic"
 ; /* xgettext:no-c-format */
@@ -1432,8 +1483,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Adv_Parasite", "Player", 2
+    { "name", "range", "value"
+      "Tech_Parasite", "Player", 2
     }
 sound          = "w_great_library"
 sound_alt      = "w_generic"
@@ -1459,10 +1510,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "Player", 300, "Land"
-       "Unit_No_Lose_Pop", "Player", 0, "Land"
-       "Barb_Attack", "Player", 200
+    { "name", "range", "value", "equiv"
+      "Land_Defend", "Player", 200, "Defenders"
+      "Unit_No_Lose_Pop", "Player"
     }
 sound          = "w_great_wall"
 sound_alt      = "w_generic"
@@ -1489,9 +1539,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
-       "Make_Happy", "City", 2
+    { "name", "range", "value"
+      "Make_Happy", "Player", 1
+      "Make_Happy", "City", 2
     }
 sound          = "w_hanging_gardens"
 sound_alt      = "w_generic"
@@ -1520,10 +1570,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "Player", 50, "Factory"
-       "Pollu_Prod_Pct", "Player", 50
-       "Pollu_Prod_Pct", "Player", -50, "Recycling Center"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", "Player", 2, "Janitors"
     }
 sound          = "w_hoover_dam"
 sound_alt      = "w_generic"
@@ -1549,8 +1599,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 100
+    { "name", "value"
+      "Science_Bonus", 100
     }
 sound          = "w_isaac_newtons_college"
 sound_alt      = "w_generic"
@@ -1576,8 +1626,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Player", 2
+    { "name", "range", "value"
+      "Force_Content", "Player", 2
     }
 sound          = "w_js_bachs_cathedral"
 sound_alt      = "w_generic"
@@ -1602,8 +1652,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_Add_Tile", "City", 1
+    { "name", "value"
+      "Prod_Add_Tile", 1
     }
 sound          = "w_king_richards_crusade"
 sound_alt      = "w_generic"
@@ -1629,8 +1679,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upgrade_One_Leap", "Player", 100
+    { "name", "range", "value"
+      "Upgrade_Unit", "Player", 1
     }
 sound          = "w_leonardos_workshop"
 sound_alt      = "w_generic"
@@ -1655,10 +1705,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 1, "Sea"
-       "No_Sink_Deep", "Player"
-       "Unit_Veteran", "Player", 0, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 1
+      "No_Sink_Deep", "Player"
+      "Sea_Veteran", "Player"
     }
 sound          = "w_lighthouse"
 sound_alt      = "w_generic"
@@ -1685,8 +1735,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 2
     }
 sound          = "w_magellans_expedition"
 sound_alt      = "w_generic"
@@ -1711,8 +1761,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Enable_Nuke", "World", 1
+    { "name", "range", "survives"
+      "Enable_Nuke", "World", 1
     }
 sound          = "w_manhattan_project"
 sound_alt      = "w_generic"
@@ -1736,8 +1786,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Have_Embassies", "Player"
+    { "name", "range"
+      "Have_Embassies", "Player"
     }
 sound          = "w_marco_polos_embassy"
 sound_alt      = "w_generic"
@@ -1762,10 +1812,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "Player", 3
-       "Make_Content", "Player", 1, "Theology"
-       "Make_Content", "Player", -1, "Communism"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content", "Player", 3, "Cathedrals"
+      "Make_Content", "Player", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", "Player", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "w_michelangelos_chapel"
 sound_alt      = "w_generic"
@@ -1795,9 +1845,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg", "cond_adv"
-       "Make_Content", "Player", 1, "Temple"
-       "Make_Content", "Player", 1, "Temple", "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 2, "Building", "Temple"
     }
 sound          = "w_oracle"
 sound_alt      = "w_generic"
@@ -1822,8 +1871,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "Player", 50
+    { "name", "range"
+      "Growth_Food", "Player"
     }
 sound          = "w_pyramids"
 sound_alt      = "w_generic"
@@ -1848,8 +1897,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "Player", 50, "Library"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Science_Bonus", "Player", 50, "Labs", "Building", "Library"
     }
 sound          = "w_seti_program"
 sound_alt      = "w_generic"
@@ -1875,8 +1924,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 99
+    { "name"
+      "No_Unhappy"
     }
 sound          = "w_shakespeares_theatre"
 sound_alt      = "w_generic"
@@ -1901,9 +1950,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
+    { "name", "range"
+      "Any_Government", "Player"
+      "No_Anarchy", "Player"
     }
 sound          = "w_statue_of_liberty"
 sound_alt      = "w_generic"
@@ -1930,9 +1979,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Veteran", "Player", 0, "Land"
-       "Unit_Vet_Combat", "Player", 100, "Land"
+    { "name", "range", "value"
+      "Land_Veteran", "Player"
+      "Land_Vet_Combat", "Player", 100
     }
 sound          = "w_sun_tzus_war_academy"
 sound_alt      = "w_generic"
@@ -1959,12 +2008,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Recover", "Player", 2, "Air"
-       "Unit_Recover", "Player", 2, "Helicopter"
-       "Unit_Recover", "Player", 2, "Land"
-       "Unit_Recover", "Player", 2, "Missile"
-       "Unit_Recover", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Unit_Recover", "Player", 2
     }
 sound          = "w_united_nations"
 sound_alt      = "w_generic"
@@ -1997,9 +2042,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "Player", 1, "Republic"
-       "Make_Content_Mil", "Player", 2, "Democracy"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", "Player", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", "Player", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "w_womens_suffrage"
 sound_alt      = "w_generic"
@@ -2027,8 +2072,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_To_Gold", "City", 100
+    { "name"
+      "Prod_To_Gold"
     }
 helptext       = _("\
 This is not a normal improvement.  Instead, setting a city's\
@@ -2037,14 +2082,16 @@
 ")
 
 
-; FIXME: remove all of the following when gen-impr implemented...
-
 [b_special]
 
 ; Special values:
 
 aqueduct_size=8;
-sewer_size=12;
+default="Capitalization"
+
+; FIXME: remove all of the following when gen-impr implemented...
+
+sewer_size=12
 
 ; Techs which modify building effects:
 
Index: data/default/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/buildings.ruleset,v
retrieving revision 1.51
diff -u -r1.51 buildings.ruleset
--- data/default/buildings.ruleset      4 Sep 2004 20:19:51 -0000       1.51
+++ data/default/buildings.ruleset      6 Sep 2004 01:11:12 -0000
@@ -58,19 +58,92 @@
 ; build_cost   = production shields required to build
 ; upkeep       = monetary upkeep value
 ; sabotage     = percent chance of diplomat sabotage being successful
-; effect {     = list of named effects (and parameters thereto):
+; effect {     = list of effects; parameters are:
 ;
 ;   ( See doc/README.effects for information and a listing of effects. )
 ;
-; }              (All effects in list(s) are cumulative.)
-; sound                = optional sound effect associated
-; sound_alt    = optional alternative sound effect if above not
-;                supported in client
-; helptext     = optional help text string; should escape all raw
-;                newlines so that xgettext parsing works
+;   eff                = effect name; e.g. "Tax_Bonus"
+;   range      = effect range; one of:
+;                "Local", "City", "Continent", "Player", "World".
+;                by ommission the range is "City".
+;   value       = modifier value of effect; by ommission +1.
+;   type        = requirement type; one of:
+;                "None", "Tech", "Gov", "Building", "Special", "Terrain".
+;                by ommission the type is "None".
+;   req                = requirement data; varies with requirement type.
+;
+; }              the effects in the list are cumulative.
 ;
 ; */ <-- avoid gettext warnings
 
+;
+; Effect groups are a convenience mechanism to handle
+; equivalent effects which may be done by one of several buildings.
+; The first building in the 'buildings' list of the group which
+; exists wins.
+;
+
+[group_cathedrals]
+name           = "Cathedrals"
+elements       =
+    { "building", "range"
+      "Michelangelo's Chapel", "Player"
+      "Cathedral", "City"
+    }
+
+[group_labs]
+name           = "Labs"
+elements       =
+    { "building", "range"
+      "SETI Program", "Player"
+      "Research Lab", "City"
+    }
+
+[group_generators]
+name           = "Generators"
+elements       =
+    { "building", "range"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+      "Power Plant", "City"
+    }
+
+[group_janitors]
+name            = "Janitors"
+elements       =
+    { "building", "range"
+      "Recycling Center", "City"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+    }
+
+[group_defenders]
+name           = "Defenders"
+elements       =
+    { "building", "range"
+      "Great Wall", "Player"
+      "City Walls", "City"
+    }
+
+[group_peacekeepers]
+name           = "Peacekeepers"
+elements       =
+    { "building", "range"
+      "Women's Suffrage", "Player"
+      "Police Station", "City"
+    }
+
+[group_purifiers]
+name           = "Purifiers"
+elements       =
+    { "building", "range"
+      "Palace", "City"
+      "Courthouse", "City"
+    }
+
+
 [building_airport]
 name           = _("Airport")
 tech_req       = "Radio"
@@ -88,10 +161,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Airlift", "City"
+    { "name"
+      "Air_Veteran"
+      "Air_Regen"
+      "Airlift"
     }
 sound          = "b_airport"
 sound_alt      = "b_generic"
@@ -122,9 +195,9 @@
 build_cost     = 60
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount"
-       "Size_Unlimit", "City", 8
+effect          =
+    { "name", "value"
+      "Size_Adj", 4
     }
 sound          = "b_aqueduct"
 sound_alt      = "b_generic"
@@ -150,9 +223,9 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Marketplace"
-       "Luxury_Bonus", "City", 50, "Marketplace"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Marketplace"
+      "Luxury_Bonus", 50, "Building", "Marketplace"
     }
 sound          = "b_bank"
 sound_alt      = "b_generic"
@@ -174,14 +247,15 @@
 ;equiv_dupl    = 
 equiv_repl     = "Sun Tzu's War Academy","Barracks II", "Barracks III"
 obsolete_by    = "Gunpowder"
+replaced_by    = "Barracks II"
 is_wonder      = 0
 build_cost     = 30
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_i"
 sound_alt      = "b_generic"
@@ -205,14 +279,15 @@
 ;equiv_dupl    =
 equiv_repl     = "Sun Tzu's War Academy", "Barracks III"
 obsolete_by    = "Mobile Warfare"
+replaced_by    = "Barracks III"
 is_wonder      = 0
 build_cost     = 30
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_ii"
 sound_alt      = "b_generic"
@@ -241,9 +316,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_iii"
 sound_alt      = "b_generic"
@@ -272,10 +347,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Theology"
-       "Make_Content", "City", -1, "Communism"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content", 3, "Cathedrals"
+      "Make_Content", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "b_cathedral"
 sound_alt      = "b_generic"
@@ -305,11 +380,9 @@
 upkeep         = 0
 sabotage       = 50
 effect         =
-    { "type", "range", "amount", "cond_bldg", "aff_unit"
-       "Unit_Defend", "City", 300, "", "Land"
-       "Unit_No_Lose_Pop", "City", 0, "", "Land"
-       "Spy_Resistant", "Local", 50
-       "Spy_Resistant", "Local", -50, "Palace"
+    { "name", "value", "equiv"
+      "Land_Defend", 200, "Defenders"
+      "Unit_No_Lose_Pop"
     }
 sound          = "b_city_walls"
 sound_alt      = "b_generic"
@@ -338,8 +411,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Sea"
+    { "name", "value"
+      "Sea_Defend", 100
     }
 sound          = "b_coastal_defense"
 sound_alt      = "b_generic"
@@ -365,9 +438,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Electricity"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 3
+      "Make_Content", 1, "Tech", "Electricity"
     }
 sound          = "b_colosseum"
 sound_alt      = "b_generic"
@@ -395,10 +468,11 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Corrupt_Pct", "City", 50
-       "Make_Content", "City", 1, "Democracy"
-       "Revolt_Dist_Pct", "City", 50
+    { "name", "value", "equiv", "req_type", "req"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Make_Content", 1, "", "Gov", "Democracy"
+      "Incite_Dist_Pct", 75
     }
 sound          = "b_courthouse"
 sound_alt      = "b_generic"
@@ -426,8 +500,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Prod_Bonus", "City", 50
+    { "name", "value"
+      "Prod_Bonus", 50
     }
 sound          = "b_factory"
 sound_alt      = "b_generic"
@@ -453,8 +527,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "City", 50
+    { "name", "value"
+      "Growth_Food", 50
     }
 sound          = "b_granary"
 sound_alt      = "b_generic"
@@ -484,8 +558,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+       "Food_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_harbour"
 sound_alt      = "b_generic"
@@ -511,11 +585,10 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_hydro_plant"
 sound_alt      = "b_generic"
@@ -554,8 +627,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "b_library"
 sound_alt      = "b_generic"
@@ -581,9 +654,9 @@
 upkeep         = 0
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Tax_Bonus", "City", 50
-       "Luxury_Bonus", "City", 50
+    { "name", "value"
+      "Tax_Bonus", 50
+      "Luxury_Bonus", 50
     }
 sound          = "b_marketplace"
 sound_alt      = "b_generic"
@@ -609,8 +682,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Pop_Pct", "City", 0
+    { "name", "value"
+      "Pollu_Pop_Pct", 100
     }
 sound          = "b_mass_transit"
 sound_alt      = "b_generic"
@@ -637,8 +710,8 @@
 upkeep         = 6
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "req_type", "req"
+      "Prod_Bonus", 50, "Building", "Factory"
     }
 sound          = "b_mfg_plant"
 sound_alt      = "b_generic"
@@ -665,11 +738,10 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_nuclear_plant"
 sound_alt      = "b_generic"
@@ -709,8 +781,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Prod_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+       "Prod_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_offshore_platform"
 sound_alt      = "b_generic"
@@ -736,10 +808,12 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Capital_City", "City"
-       "Capital_Exists", "Player"
-       "Spy_Resistant", "City", 50
+    { "name", "value", "equiv"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Spy_Resistant", 50
+      "No_Incite"
+      "Capital_City"
     }
 sound          = "b_palace"
 sound_alt      = "b_generic"
@@ -773,9 +847,9 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "City", 1, "Republic"
-       "Make_Content_Mil", "City", 2, "Democracy"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "b_police_station"
 sound_alt      = "b_generic"
@@ -805,9 +879,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Sea_Veteran"
+      "Sea_Regen"
     }
 sound          = "b_port_facility"
 sound_alt      = "b_generic"
@@ -834,9 +908,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
     }
 sound          = "b_power_plant"
 sound_alt      = "b_generic"
@@ -872,8 +946,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Prod_Pct", "City", 34
+    { "name", "value", "equiv"
+      "Pollu_Prod_Pct", 3, "Janitors"
     }
 sound          = "b_recycling_center"
 sound_alt      = "b_generic"
@@ -900,8 +974,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "equiv", "req_type", "req"
+       "Science_Bonus", 50, "Labs", "Building", "Library"
     }
 sound          = "b_research_lab"
 sound_alt      = "b_generic"
@@ -929,9 +1003,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Air"
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Air_Defend", 100
     }
 sound          = "b_sam_battery"
 sound_alt      = "b_generic"
@@ -957,9 +1030,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Nuke_Proof", "City", 3
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Nuke_Proof"
+      "Missile_Defend", 100
     }
 sound          = "b_sdi_defense"
 sound_alt      = "b_generic"
@@ -987,9 +1060,9 @@
 build_cost     = 80
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Size_Unlimit", "City", 12, "Aqueduct"
+effect          =
+    { "name", "req_type", "req"
+      "Size_Unlimit", "Building", "Aqueduct"
     }
 sound          = "b_sewer_system"
 sound_alt      = "b_generic"
@@ -1014,13 +1087,6 @@
 build_cost     = 220
 upkeep         = 4
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 0
-       "Slow_Global_Warm", "World", 10
-    }
 sound          = "b_solar_plant"
 sound_alt      = "b_generic"
 ; /* xgettext:no-c-format */
@@ -1057,9 +1123,9 @@
 build_cost     = 160
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Component", "Local"
+effect          =
+    { "name"
+      "SS_Component"
     }
 sound          = "b_space_component"
 sound_alt      = "b_generic"
@@ -1088,9 +1154,9 @@
 build_cost     = 320
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Module", "Local"
+effect          =
+    { "name"
+      "SS_Module"
     }
 sound          = "b_space_module"
 sound_alt      = "b_generic"
@@ -1128,9 +1194,9 @@
 build_cost     = 80
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Structural", "Local"
+effect          =
+    { "name"
+      "SS_Structural"
     }
 sound          = "b_space_structural"
 sound_alt      = "b_generic"
@@ -1160,9 +1226,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Bank"
-       "Luxury_Bonus", "City", 50, "Bank"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Bank"
+      "Luxury_Bonus", 50, "Building", "Bank"
     }
 sound          = "b_stock_exchange"
 sound_alt      = "b_generic"
@@ -1189,8 +1255,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Trade_Per_Tile", "City", 50, "None", "Road"
+    { "name", "value", "req_type", "req"
+       "Trade_Per_Tile", 50, "Special", "Road"
     }
 sound          = "b_super_highways"
 sound_alt      = "b_generic"
@@ -1219,8 +1285,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Per_Tile", "City", 50, "None", "Farmland"
+    { "name", "value", "req_type", "req"
+       "Food_Per_Tile", 50, "Special", "Farmland"
     }
 sound          = "b_supermarket"
 sound_alt      = "b_generic"
@@ -1248,9 +1314,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 1
-       "Make_Content", "City", 1, "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 1
+      "Make_Content", 1, "Tech", "Mysticism"
     }
 sound          = "b_temple"
 sound_alt      = "b_generic"
@@ -1277,8 +1343,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "req_type", "req"
+      "Science_Bonus", 50, "Building", "Library"
     }
 sound          = "b_university"
 sound_alt      = "b_generic"
@@ -1305,9 +1371,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Reveal_Map", "Player", 0
-       "Enable_Space", "World", 1
+    { "name", "range", "survives"
+      "Reveal_Map", "Player", 0
+      "Enable_Space", "World", 1
     }
 sound          = "w_apollo_program"
 sound_alt      = "w_generic"
@@ -1334,8 +1400,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upkeep_Free", "Player", 1
+    { "name", "range", "value"
+      "Upkeep_Free", "Player", 1
     }
 sound          = "w_asmiths_trading_co"
 sound_alt      = "w_generic"
@@ -1361,8 +1427,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Trade_Inc_Tile", "City", 1
+    { "name", "value"
+      "Trade_Inc_Tile", 1
     }
 sound          = "w_colossus"
 sound_alt      = "w_generic"
@@ -1388,8 +1454,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "w_copernicus_observatory"
 sound_alt      = "w_generic"
@@ -1415,8 +1481,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Player", 1
+    { "name", "range", "value"
+      "Force_Content", "Player", 1
     }
 sound          = "w_cure_for_cancer"
 sound_alt      = "w_generic"
@@ -1444,8 +1510,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Give_Imm_Adv", "Player", 2
+    { "name", "range", "value"
+      "Give_Imm_Tech", "Player", 2
     }
 sound          = "w_darwins_voyage"
 sound_alt      = "w_generic"
@@ -1471,10 +1537,6 @@
 build_cost     = 300
 upkeep         = 0
 sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Improve_Rep", "Player", 25
-    }
 sound          = "w_eiffel_tower"
 sound_alt      = "w_generic"
 ; /* xgettext:no-c-format */
@@ -1502,8 +1564,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Adv_Parasite", "Player", 2
+    { "name", "range", "value"
+      "Tech_Parasite", "Player", 2
     }
 sound          = "w_great_library"
 sound_alt      = "w_generic"
@@ -1529,9 +1591,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "Player", 300, "Land"
-       "Unit_No_Lose_Pop", "Player", 0, "Land"
+    { "name", "range", "value", "equiv"
+      "Land_Defend", "Player", 200, "Defenders"
+      "Unit_No_Lose_Pop", "Player"
     }
 sound          = "w_great_wall"
 sound_alt      = "w_generic"
@@ -1559,9 +1621,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
-       "Make_Happy", "City", 2
+    { "name", "range", "value"
+      "Make_Happy", "Player", 1
+      "Make_Happy", "City", 2
     }
 sound          = "w_hanging_gardens"
 sound_alt      = "w_generic"
@@ -1590,11 +1652,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "Player", 25, "Factory"
-       "Prod_Bonus", "Player", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "Player", 50
-       "Pollu_Prod_Pct", "Player", -50, "Recycling Center"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", "Player", 2, "Janitors"
     }
 sound          = "w_hoover_dam"
 sound_alt      = "w_generic"
@@ -1620,8 +1681,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 100
+    { "name", "value"
+      "Science_Bonus", 100
     }
 sound          = "w_isaac_newtons_college"
 sound_alt      = "w_generic"
@@ -1647,8 +1708,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Player", 2
+    { "name", "range", "value"
+      "Force_Content", "Player", 2
     }
 sound          = "w_js_bachs_cathedral"
 sound_alt      = "w_generic"
@@ -1673,8 +1734,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_Add_Tile", "City", 1
+    { "name", "value"
+      "Prod_Add_Tile", 1
     }
 sound          = "w_king_richards_crusade"
 sound_alt      = "w_generic"
@@ -1691,7 +1752,7 @@
 graphic_alt    = "-"
 ;terr_gate     =
 ;spec_gate     =
-equiv_range    = "Player"
+equiv_range    = "None"
 ;equiv_dupl    =
 ;equiv_repl    =
 obsolete_by    = "Automobile"
@@ -1700,8 +1761,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upgrade_One_Leap", "Player", 100
+    { "name", "range", "value"
+      "Upgrade_Unit", "Player", 1
     }
 sound          = "w_leonardos_workshop"
 sound_alt      = "w_generic"
@@ -1726,10 +1787,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 1, "Sea"
-       "No_Sink_Deep", "Player"
-       "Unit_Veteran", "Player", 0, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 1
+      "No_Sink_Deep", "Player"
+      "Sea_Veteran", "Player"
     }
 sound          = "w_lighthouse"
 sound_alt      = "w_generic"
@@ -1747,7 +1808,7 @@
 graphic_alt    = "-"
 ;terr_gate     =
 ;spec_gate     =
-equiv_range    = "Player"
+equiv_range    = "None"
 ;equiv_dupl    =
 ;equiv_repl    =
 obsolete_by    = "None"
@@ -1756,8 +1817,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 2
     }
 sound          = "w_magellans_expedition"
 sound_alt      = "w_generic"
@@ -1782,8 +1843,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Enable_Nuke", "World", 1
+    { "name", "range", "survives"
+      "Enable_Nuke", "World", 1
     }
 sound          = "w_manhattan_project"
 sound_alt      = "w_generic"
@@ -1807,8 +1868,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Have_Embassies", "Player"
+    { "name", "range"
+      "Have_Embassies", "Player"
     }
 sound          = "w_marco_polos_embassy"
 sound_alt      = "w_generic"
@@ -1833,10 +1894,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "Player", 3
-       "Make_Content", "Player", 1, "Theology"
-       "Make_Content", "Player", -1, "Communism"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content", "Player", 3, "Cathedrals"
+      "Make_Content", "Player", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", "Player", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "w_michelangelos_chapel"
 sound_alt      = "w_generic"
@@ -1866,9 +1927,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg", "cond_adv"
-       "Make_Content", "Player", 1, "Temple"
-       "Make_Content", "Player", 1, "Temple", "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 2, "Building", "Temple"
     }
 sound          = "w_oracle"
 sound_alt      = "w_generic"
@@ -1893,8 +1953,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "Player", 50
+    { "name", "value", "range"
+      "Growth_Food", 50, "Player"
     }
 sound          = "w_pyramids"
 sound_alt      = "w_generic"
@@ -1919,8 +1979,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "Player", 50, "Library"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Science_Bonus", "Player", 50, "Labs", "Building", "Library"
     }
 sound          = "w_seti_program"
 sound_alt      = "w_generic"
@@ -1946,8 +2006,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 99
+    { "name"
+      "No_Unhappy"
     }
 sound          = "w_shakespeares_theatre"
 sound_alt      = "w_generic"
@@ -1972,9 +2032,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
+    { "name", "range"
+      "Any_Government", "Player"
+      "No_Anarchy", "Player"
     }
 sound          = "w_statue_of_liberty"
 sound_alt      = "w_generic"
@@ -2001,9 +2061,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Veteran", "Player", 0, "Land"
-       "Unit_Vet_Combat", "Player", 100, "Land"
+    { "name", "range", "value"
+      "Land_Veteran", "Player"
+      "Land_Vet_Combat", "Player", 50
     }
 sound          = "w_sun_tzus_war_academy"
 sound_alt      = "w_generic"
@@ -2030,12 +2090,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Recover", "Player", 2, "Air"
-       "Unit_Recover", "Player", 2, "Helicopter"
-       "Unit_Recover", "Player", 2, "Land"
-       "Unit_Recover", "Player", 2, "Missile"
-       "Unit_Recover", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Unit_Recover", "Player", 2
     }
 sound          = "w_united_nations"
 sound_alt      = "w_generic"
@@ -2068,9 +2124,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "Player", 1, "Republic"
-       "Make_Content_Mil", "Player", 2, "Democracy"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", "Player", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", "Player", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "w_womens_suffrage"
 sound_alt      = "w_generic"
@@ -2106,8 +2162,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_To_Gold", "City", 100
+    { "name"
+      "Prod_To_Gold"
     }
 ; FIXME: this is the real helptext; restore when have a subordnate analogue
 ; /* (ignore for gettext until fixed)
@@ -2124,14 +2180,16 @@
 ")
 
 
-; FIXME: remove all of the following when gen-impr implemented...
-
 [b_special]
 
 ; Special values:
 
-aqueduct_size=8;
-sewer_size=12;
+aqueduct_size=8
+default="Coinage"
+
+; FIXME: remove all of the following when gen-impr implemented...
+
+sewer_size=12
 
 ; Techs which modify building effects:
 
@@ -2139,3 +2197,4 @@
 cathedral_minus="Communism"
 colosseum_plus="Electricity"
 temple_plus="Mysticism"
+
Index: data/history/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/history/buildings.ruleset,v
retrieving revision 1.11
diff -u -r1.11 buildings.ruleset
--- data/history/buildings.ruleset      4 Sep 2004 20:19:51 -0000       1.11
+++ data/history/buildings.ruleset      6 Sep 2004 01:11:14 -0000
@@ -24,6 +24,67 @@
 ; /*** For details of this file's format, ***/
 ; /*** see the default buildings.ruleset. ***/
 
+[group_cathedrals]
+name           = "Cathedrals"
+elements       =
+    { "building", "range"
+      "Michelangelo's Chapel", "Player"
+      "Cathedral", "City"
+    }
+
+[group_labs]
+name           = "Labs"
+elements       =
+    { "building", "range"
+      "SETI Program", "Player"
+      "Research Lab", "City"
+    }
+
+[group_generators]
+name           = "Generators"
+elements       =
+    { "building", "range"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+      "Power Plant", "City"
+    }
+
+[group_janitors]
+name            = "Janitors"
+elements       =
+    { "building", "range"
+      "Recycling Center", "City"
+      "Hoover Dam", "Player"
+      "Nuclear Plant", "City"
+      "Hydro Plant", "City"
+    }
+
+[group_defenders]
+name           = "Defenders"
+elements       =
+    { "building", "range"
+      "Great Wall", "Player"
+      "City Walls", "City"
+    }
+
+[group_peacekeepers]
+name           = "Peacekeepers"
+elements       =
+    { "building", "range"
+      "Women's Suffrage", "Player"
+      "Police Station", "City"
+    }
+
+[group_purifiers]
+name           = "Purifiers"
+elements       =
+    { "building", "range"
+      "Palace", "City"
+      "Courthouse", "City"
+    }
+
+
 [building_airport]
 name           = _("Airport")
 tech_req       = "Radio"
@@ -41,10 +102,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Air"
-       "Unit_Repair", "City", "Air"
-       "Airlift", "City"
+    { "name"
+      "Air_Veteran"
+      "Air_Regen"
+      "Airlift"
     }
 sound          = "b_airport"
 sound_alt      = "b_generic"
@@ -75,9 +136,9 @@
 build_cost     = 80
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount"
-       "Size_Unlimit", "City", 8
+effect          =
+    { "name", "value"
+      "Size_Adj", 4
     }
 sound          = "b_aqueduct"
 sound_alt      = "b_generic"
@@ -103,9 +164,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Marketplace"
-       "Luxury_Bonus", "City", 50, "Marketplace"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Marketplace"
+      "Luxury_Bonus", 50, "Building", "Marketplace"
     }
 sound          = "b_bank"
 sound_alt      = "b_generic"
@@ -127,14 +188,15 @@
 ;equiv_dupl    = 
 equiv_repl     = "Sun Tzu's War Academy","Barracks II", "Barracks III"
 obsolete_by    = "Gunpowder"
+replaced_by    = "Barracks II"
 is_wonder      = 0
 build_cost     = 40
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_i"
 sound_alt      = "b_generic"
@@ -158,14 +220,15 @@
 ;equiv_dupl    =
 equiv_repl     = "Sun Tzu's War Academy", "Barracks III"
 obsolete_by    = "Mobile Warfare"
+replaced_by    = "Barracks III"
 is_wonder      = 0
 build_cost     = 40
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_ii"
 sound_alt      = "b_generic"
@@ -194,9 +257,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Land"
-       "Unit_Repair", "City", "Land"
+    { "name"
+      "Land_Veteran"
+      "Land_Regen"
     }
 sound          = "b_barracks_iii"
 sound_alt      = "b_generic"
@@ -225,10 +288,10 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Theology"
-       "Make_Content", "City", -1, "Communism"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content", 3, "Cathedrals"
+      "Make_Content", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "b_cathedral"
 sound_alt      = "b_generic"
@@ -258,11 +321,9 @@
 upkeep         = 0
 sabotage       = 50
 effect         =
-    { "type", "range", "amount", "cond_bldg", "aff_unit"
-       "Unit_Defend", "City", 300, "", "Land"
-       "Unit_No_Lose_Pop", "City", 0, "", "Land"
-       "Spy_Resistant", "Local", 50
-       "Spy_Resistant", "Local", -50, "Palace"
+    { "name", "value", "equiv"
+      "Land_Defend", 200, "Defenders"
+      "Unit_No_Lose_Pop"
     }
 sound          = "b_city_walls"
 sound_alt      = "b_generic"
@@ -291,8 +352,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Sea"
+    { "name", "value"
+      "Sea_Defend", 100
     }
 sound          = "b_coastal_defense"
 sound_alt      = "b_generic"
@@ -318,9 +379,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 3
-       "Make_Content", "City", 1, "Electricity"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 3
+      "Make_Content", 1, "Tech", "Electricity"
     }
 sound          = "b_colosseum"
 sound_alt      = "b_generic"
@@ -348,10 +409,11 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Corrupt_Pct", "City", 50
-       "Make_Content", "City", 1, "Democracy"
-       "Revolt_Dist_Pct", "City", 50
+    { "name", "value", "equiv", "req_type", "req"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Make_Content", 1, "", "Gov", "Democracy"
+      "Incite_Dist_Pct", 75
     }
 sound          = "b_courthouse"
 sound_alt      = "b_generic"
@@ -379,8 +441,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Prod_Bonus", "City", 50
+    { "name", "value"
+      "Prod_Bonus", 50
     }
 sound          = "b_factory"
 sound_alt      = "b_generic"
@@ -406,8 +468,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "City", 50
+    { "name"
+      "Growth_Food"
     }
 sound          = "b_granary"
 sound_alt      = "b_generic"
@@ -437,8 +499,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+       "Food_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_harbour"
 sound_alt      = "b_generic"
@@ -464,11 +526,10 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_hydro_plant"
 sound_alt      = "b_generic"
@@ -507,8 +568,8 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "b_library"
 sound_alt      = "b_generic"
@@ -534,9 +595,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Tax_Bonus", "City", 50
-       "Luxury_Bonus", "City", 50
+    { "name", "value"
+      "Tax_Bonus", 50
+      "Luxury_Bonus", 50
     }
 sound          = "b_marketplace"
 sound_alt      = "b_generic"
@@ -562,8 +623,8 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Pop_Pct", "City", 0
+    { "name", "value"
+      "Pollu_Pop_Pct", 100
     }
 sound          = "b_mass_transit"
 sound_alt      = "b_generic"
@@ -590,8 +651,8 @@
 upkeep         = 6
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 50, "Factory"
+    { "name", "value", "req_type", "req"
+      "Prod_Bonus", 50, "Building", "Factory"
     }
 sound          = "b_mfg_plant"
 sound_alt      = "b_generic"
@@ -618,11 +679,10 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 50
-       "Pollu_Prod_Pct", "City", -50, "Recycling Center"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", 2, "Janitors"
     }
 sound          = "b_nuclear_plant"
 sound_alt      = "b_generic"
@@ -662,8 +722,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Prod_Add_Tile", "City", 1, "Ocean", "None"
+    { "name", "value", "req_type", "req"
+       "Prod_Add_Tile", 1, "Terrain", "Ocean"
     }
 sound          = "b_offshore_platform"
 sound_alt      = "b_generic"
@@ -689,10 +749,12 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Capital_City", "City"
-       "Capital_Exists", "Player"
-       "Spy_Resistant", "City", 50
+    { "name", "value", "equiv"
+      "Corrupt_Pct", 50, "Purifiers"
+      "Waste_Pct", 50, "Purifiers"
+      "Spy_Resistant", 50
+      "No_Incite"
+      "Capital_City"
     }
 sound          = "b_palace"
 sound_alt      = "b_generic"
@@ -726,9 +788,9 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "City", 1, "Republic"
-       "Make_Content_Mil", "City", 2, "Democracy"
+    { "name", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "b_police_station"
 sound_alt      = "b_generic"
@@ -758,9 +820,9 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "aff_unit"
-       "Unit_Veteran", "City", "Sea"
-       "Unit_Repair", "City", "Sea"
+    { "name"
+      "Sea_Veteran"
+      "Sea_Regen"
     }
 sound          = "b_port_facility"
 sound_alt      = "b_generic"
@@ -787,9 +849,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
+    { "name", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", 25, "Generators", "Building", "Mfg. Plant"
     }
 sound          = "b_power_plant"
 sound_alt      = "b_generic"
@@ -825,8 +887,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount"
-       "Pollu_Prod_Pct", "City", 34
+    { "name", "value", "equiv"
+      "Pollu_Prod_Pct", 3, "Janitors"
     }
 sound          = "b_recycling_center"
 sound_alt      = "b_generic"
@@ -853,8 +915,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "equiv", "req_type", "req"
+       "Science_Bonus", 50, "Labs", "Building", "Library"
     }
 sound          = "b_research_lab"
 sound_alt      = "b_generic"
@@ -882,9 +944,8 @@
 upkeep         = 2
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "City", 200, "Air"
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Air_Defend", 100
     }
 sound          = "b_sam_battery"
 sound_alt      = "b_generic"
@@ -910,9 +971,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Nuke_Proof", "City", 3
-       "Unit_Defend", "City", 200, "Missile"
+    { "name", "value"
+      "Nuke_Proof"
+      "Missile_Defend", 100
     }
 sound          = "b_sdi_defense"
 sound_alt      = "b_generic"
@@ -940,9 +1001,9 @@
 build_cost     = 120
 upkeep         = 2
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Size_Unlimit", "City", 12, "Aqueduct"
+effect          =
+    { "name", "req_type", "req"
+      "Size_Unlimit", "Building", "Aqueduct"
     }
 sound          = "b_sewer_system"
 sound_alt      = "b_generic"
@@ -967,13 +1028,6 @@
 build_cost     = 320
 upkeep         = 4
 sabotage       = 100
-effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "City", 25, "Factory"
-       "Prod_Bonus", "City", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "City", 0
-       "Slow_Global_Warm", "World", 10
-    }
 sound          = "b_solar_plant"
 sound_alt      = "b_generic"
 ; /* xgettext:no-c-format */
@@ -1010,9 +1064,9 @@
 build_cost     = 160
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Component", "Local"
+effect          =
+    { "name"
+      "SS_Component"
     }
 sound          = "b_space_component"
 sound_alt      = "b_generic"
@@ -1041,9 +1095,9 @@
 build_cost     = 320
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Module", "Local"
+effect          =
+    { "name"
+      "SS_Module"
     }
 sound          = "b_space_module"
 sound_alt      = "b_generic"
@@ -1081,9 +1135,9 @@
 build_cost     = 80
 upkeep         = 0
 sabotage       = 100
-effect         =
-    { "type", "range"
-       "SS_Structural", "Local"
+effect          =
+    { "name"
+      "SS_Structural"
     }
 sound          = "b_space_structural"
 sound_alt      = "b_generic"
@@ -1113,9 +1167,9 @@
 upkeep         = 4
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Tax_Bonus", "City", 50, "Bank"
-       "Luxury_Bonus", "City", 50, "Bank"
+    { "name", "value", "req_type", "req"
+      "Tax_Bonus", 50, "Building", "Bank"
+      "Luxury_Bonus", 50, "Building", "Bank"
     }
 sound          = "b_stock_exchange"
 sound_alt      = "b_generic"
@@ -1142,8 +1196,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Trade_Per_Tile", "City", 50, "None", "Road"
+    { "name", "value", "req_type", "req"
+       "Trade_Per_Tile", 50, "Special", "Road"
     }
 sound          = "b_super_highways"
 sound_alt      = "b_generic"
@@ -1172,8 +1226,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "aff_terr", "aff_spec"
-       "Food_Per_Tile", "City", 50, "None", "Farmland"
+    { "name", "value", "req_type", "req"
+       "Food_Per_Tile", 50, "Special", "Farmland"
     }
 sound          = "b_supermarket"
 sound_alt      = "b_generic"
@@ -1201,9 +1255,9 @@
 upkeep         = 1
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "City", 1
-       "Make_Content", "City", 1, "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 1
+      "Make_Content", 1, "Tech", "Mysticism"
     }
 sound          = "b_temple"
 sound_alt      = "b_generic"
@@ -1230,8 +1284,8 @@
 upkeep         = 3
 sabotage       = 100
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "City", 50, "Library"
+    { "name", "value", "req_type", "req"
+      "Science_Bonus", 50, "Building", "Library"
     }
 sound          = "b_university"
 sound_alt      = "b_generic"
@@ -1258,9 +1312,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Reveal_Map", "Player", 0
-       "Enable_Space", "World", 1
+    { "name", "range", "survives"
+      "Reveal_Map", "Player", 0
+      "Enable_Space", "World", 1
     }
 sound          = "w_apollo_program"
 sound_alt      = "w_generic"
@@ -1287,8 +1341,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upkeep_Free", "Player", 1
+    { "name", "range", "value"
+      "Upkeep_Free", "Player", 1
     }
 sound          = "w_asmiths_trading_co"
 sound_alt      = "w_generic"
@@ -1314,8 +1368,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Trade_Inc_Tile", "City", 1
+    { "name", "value"
+      "Trade_Inc_Tile", 1
     }
 sound          = "w_colossus"
 sound_alt      = "w_generic"
@@ -1341,8 +1395,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 50
+    { "name", "value"
+      "Science_Bonus", 50
     }
 sound          = "w_copernicus_observatory"
 sound_alt      = "w_generic"
@@ -1368,8 +1422,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Player", 1
+    { "name", "range", "value"
+      "Force_Content", "Player", 1
     }
 sound          = "w_cure_for_cancer"
 sound_alt      = "w_generic"
@@ -1397,8 +1451,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Give_Imm_Adv", "Player", 2
+    { "name", "range", "value"
+      "Give_Imm_Tech", "Player", 2
     }
 sound          = "w_darwins_voyage"
 sound_alt      = "w_generic"
@@ -1424,10 +1478,6 @@
 build_cost     = 300
 upkeep         = 0
 sabotage       = 0
-effect         =
-    { "type", "range", "amount"
-       "Improve_Rep", "Player", 25
-    }
 sound          = "w_eiffel_tower"
 sound_alt      = "w_generic"
 ; /* xgettext:no-c-format */
@@ -1455,8 +1505,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Adv_Parasite", "Player", 2
+    { "name", "range", "value"
+      "Tech_Parasite", "Player", 2
     }
 sound          = "w_great_library"
 sound_alt      = "w_generic"
@@ -1482,9 +1532,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Defend", "Player", 300, "Land"
-       "Unit_No_Lose_Pop", "Player", 0, "Land"
+    { "name", "range", "value", "equiv"
+      "Land_Defend", "Player", 200, "Defenders"
+      "Unit_No_Lose_Pop", "Player"
     }
 sound          = "w_great_wall"
 sound_alt      = "w_generic"
@@ -1512,9 +1562,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Happy", "Player", 1
-       "Make_Happy", "City", 2
+    { "name", "range", "value"
+      "Make_Happy", "Player", 1
+      "Make_Happy", "City", 2
     }
 sound          = "w_hanging_gardens"
 sound_alt      = "w_generic"
@@ -1543,11 +1593,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Prod_Bonus", "Player", 25, "Factory"
-       "Prod_Bonus", "Player", 25, "Mfg. Plant"
-       "Pollu_Prod_Pct", "Player", 50
-       "Pollu_Prod_Pct", "Player", -50, "Recycling Center"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Factory"
+      "Prod_Bonus", "Player", 25, "Generators", "Building", "Mfg. Plant"
+      "Pollu_Prod_Pct", "Player", 2, "Janitors"
     }
 sound          = "w_hoover_dam"
 sound_alt      = "w_generic"
@@ -1573,8 +1622,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Science_Bonus", "City", 100
+    { "name", "value"
+      "Science_Bonus", 100
     }
 sound          = "w_isaac_newtons_college"
 sound_alt      = "w_generic"
@@ -1600,8 +1649,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "Player", 2
+    { "name", "range", "value"
+      "Force_Content", "Player", 2
     }
 sound          = "w_js_bachs_cathedral"
 sound_alt      = "w_generic"
@@ -1626,8 +1675,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_Add_Tile", "City", 1
+    { "name", "value"
+      "Prod_Add_Tile", 1
     }
 sound          = "w_king_richards_crusade"
 sound_alt      = "w_generic"
@@ -1644,7 +1693,7 @@
 graphic_alt    = "-"
 ;terr_gate     =
 ;spec_gate     =
-equiv_range    = "Player"
+equiv_range    = "None"
 ;equiv_dupl    =
 ;equiv_repl    =
 obsolete_by    = "Automobile"
@@ -1653,8 +1702,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Upgrade_One_Leap", "Player", 100
+    { "name", "range", "value"
+      "Upgrade_Unit", "Player", 1
     }
 sound          = "w_leonardos_workshop"
 sound_alt      = "w_generic"
@@ -1679,10 +1728,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 1, "Sea"
-       "No_Sink_Deep", "Player"
-       "Unit_Veteran", "Player", 0, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 1
+      "No_Sink_Deep", "Player"
+      "Sea_Veteran", "Player"
     }
 sound          = "w_lighthouse"
 sound_alt      = "w_generic"
@@ -1700,7 +1749,7 @@
 graphic_alt    = "-"
 ;terr_gate     =
 ;spec_gate     =
-equiv_range    = "Player"
+equiv_range    = "None"
 ;equiv_dupl    =
 ;equiv_repl    =
 obsolete_by    = "None"
@@ -1709,8 +1758,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Move", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Sea_Move", "Player", 2
     }
 sound          = "w_magellans_expedition"
 sound_alt      = "w_generic"
@@ -1735,8 +1784,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "survives"
-       "Enable_Nuke", "World", 1
+    { "name", "range", "survives"
+      "Enable_Nuke", "World", 1
     }
 sound          = "w_manhattan_project"
 sound_alt      = "w_generic"
@@ -1760,8 +1809,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Have_Embassies", "Player"
+    { "name", "range"
+      "Have_Embassies", "Player"
     }
 sound          = "w_marco_polos_embassy"
 sound_alt      = "w_generic"
@@ -1786,10 +1835,10 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_adv"
-       "Make_Content", "Player", 3
-       "Make_Content", "Player", 1, "Theology"
-       "Make_Content", "Player", -1, "Communism"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content", "Player", 3, "Cathedrals"
+      "Make_Content", "Player", 1, "Cathedrals", "Tech", "Theology"
+      "Make_Content", "Player", -1, "Cathedrals", "Tech", "Communism"
     }
 sound          = "w_michelangelos_chapel"
 sound_alt      = "w_generic"
@@ -1819,9 +1868,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg", "cond_adv"
-       "Make_Content", "Player", 1, "Temple"
-       "Make_Content", "Player", 1, "Temple", "Mysticism"
+    { "name", "value", "req_type", "req"
+      "Make_Content", 2, "Building", "Temple"
     }
 sound          = "w_oracle"
 sound_alt      = "w_generic"
@@ -1846,8 +1894,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Growth_Food", "Player", 50
+    { "name", "range"
+      "Growth_Food", "Player"
     }
 sound          = "w_pyramids"
 sound_alt      = "w_generic"
@@ -1872,8 +1920,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_bldg"
-       "Science_Bonus", "Player", 50, "Library"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Science_Bonus", "Player", 50, "Labs", "Building", "Library"
     }
 sound          = "w_seti_program"
 sound_alt      = "w_generic"
@@ -1899,8 +1947,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Make_Content", "City", 99
+    { "name"
+      "No_Unhappy"
     }
 sound          = "w_shakespeares_theatre"
 sound_alt      = "w_generic"
@@ -1925,9 +1973,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range"
-       "Any_Government", "Player"
-       "No_Anarchy", "Player"
+    { "name", "range"
+      "Any_Government", "Player"
+      "No_Anarchy", "Player"
     }
 sound          = "w_statue_of_liberty"
 sound_alt      = "w_generic"
@@ -1954,9 +2002,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Veteran", "Player", 0, "Land"
-       "Unit_Vet_Combat", "Player", 100, "Land"
+    { "name", "range", "value"
+      "Land_Veteran", "Player"
+      "Land_Vet_Combat", "Player", 50
     }
 sound          = "w_sun_tzus_war_academy"
 sound_alt      = "w_generic"
@@ -1983,12 +2031,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "aff_unit"
-       "Unit_Recover", "Player", 2, "Air"
-       "Unit_Recover", "Player", 2, "Helicopter"
-       "Unit_Recover", "Player", 2, "Land"
-       "Unit_Recover", "Player", 2, "Missile"
-       "Unit_Recover", "Player", 2, "Sea"
+    { "name", "range", "value"
+      "Unit_Recover", "Player", 2
     }
 sound          = "w_united_nations"
 sound_alt      = "w_generic"
@@ -2021,9 +2065,9 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount", "cond_gov"
-       "Make_Content_Mil", "Player", 1, "Republic"
-       "Make_Content_Mil", "Player", 2, "Democracy"
+    { "name", "range", "value", "equiv", "req_type", "req"
+      "Make_Content_Mil", "Player", 1, "Peacekeepers", "Gov", "Republic"
+      "Make_Content_Mil", "Player", 2, "Peacekeepers", "Gov", "Democracy"
     }
 sound          = "w_womens_suffrage"
 sound_alt      = "w_generic"
@@ -2059,8 +2103,8 @@
 upkeep         = 0
 sabotage       = 0
 effect         =
-    { "type", "range", "amount"
-       "Prod_To_Gold", "City", 100
+    { "name"
+      "Prod_To_Gold"
     }
 ; FIXME: this is the real helptext; restore when have a subordnate analogue
 ; /* (ignore for gettext until fixed)
@@ -2077,14 +2121,16 @@
 ")
 
 
-; FIXME: remove all of the following when gen-impr implemented...
-
 [b_special]
 
 ; Special values:
 
-aqueduct_size=8;
-sewer_size=12;
+aqueduct_size=8
+default="Coinage"
+
+; FIXME: remove all of the following when gen-impr implemented...
+
+sewer_size=12
 
 ; Techs which modify building effects:
 
@@ -2092,3 +2138,4 @@
 cathedral_minus="Communism"
 colosseum_plus="Electricity"
 temple_plus="Mysticism"
+
Index: doc/README.effects
===================================================================
RCS file: /home/freeciv/CVS/freeciv/doc/README.effects,v
retrieving revision 1.2
diff -u -r1.2 README.effects
--- doc/README.effects  30 Sep 2003 23:20:10 -0000      1.2
+++ doc/README.effects  6 Sep 2004 01:11:14 -0000
@@ -5,7 +5,7 @@
 Some effects are not suitable for certain assignments. This will be 
 especially true for unit effects. Unit effects are restricted to Local range.
 
-.type may be one of:
+.name may be one of:
 
 "Adv_Parasite" - gains advances known by AMOUNT other players
 
@@ -152,7 +152,7 @@
 "Prod_Per_Tile"        - increases shield production generated on each worked
                  tile by AMOUNT percent
 
-"Prod_To_Gold" - convert production to gold at AMOUNT percent rate
+"Prod_To_Gold" - convert production to gold at 1:1 ratio
 
 "Reveal_Cities"        - make all city tiles known
 
@@ -182,14 +182,18 @@
 "Slow_Global_Warm" - reduces the effect of polluted terrain within
                  range on global warming by AMOUNT percent
 
-"Space_Part"   - a part of a spaceship; per AMOUNT:
-                 1 = structural, 2 = component, 3 = module
+"SS_Structural"
+"SS_Component"
+"SS_Module"    - a part of a spaceship;
                   this is a "Local" ranged effect. It (for now) applies
                   to improvements which cannot be built unless "Enable_Space"
-                  is felt.
+                  is felt.  Buildings which have this effect should probably
+                  not be given any other effects.
 
 "Spy_Resistant"        - if a spy specifies a target for sabotage,
-                 then she  has an AMOUNT percent chance to fail
+                 then she  has an AMOUNT percent chance to fail.  Also in
+                  diplomatic combat defending diplomatic units in cities will
+                  get an AMOUNT percent bonus.
                  (all Spy_Resistant's are summed before being applied)
 
 "Tax_Bonus"    - tax revenues are increased by AMOUNT percent
@@ -256,21 +260,9 @@
 
 "Unit_Veteran" - all units of class .aff_unit produced are veteran
                  units
-"Upgrade_One_Step" - upgrade one obsolete unit per turn, stepping to each
-                 intermediate type; chance to upgrade each unit is
-                 AMOUNT percent
-
-"Upgrade_One_Leap" - upgrade one obsolete unit per turn, leaping to most
-                 advanced type; chance to upgrade each unit is AMOUNT
-                 percent
-
-"Upgrade_All_Step" - upgrade all obsolete units each turn, stepping to
-                 each intermediate type; chance to upgrade each unit
-                 is AMOUNT percent
-
-"Upgrade_All_Leap" - upgrade all obsolete units each turn, leaping to
-                 most advanced type; chance to upgrade each unit is
-                 AMOUNT percent
+
+"Upgrade_Unit" - upgrade AMOUNT obsolete units per turn to the most
+                advanced type available.
 
 "Upkeep_Free"  - improvements with AMOUNT or less upkeep cost become
                  free to upkeep (others are unaffected)
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.271
diff -u -r1.271 citytools.c
--- server/citytools.c  31 Aug 2004 04:40:50 -0000      1.271
+++ server/citytools.c  6 Sep 2004 01:11:14 -0000
@@ -384,17 +384,6 @@
   return tempname;
 }
 
-/****************************************************************
-...
-*****************************************************************/
-bool city_got_barracks(struct city *pcity)
-{
-  return (city_affected_by_wonder(pcity, B_SUNTZU) ||
-         city_got_building(pcity, B_BARRACKS) || 
-         city_got_building(pcity, B_BARRACKS2) ||
-         city_got_building(pcity, B_BARRACKS3));
-}
-
 /****************************************************************************
   Return TRUE iff the city can sell the given improvement.
 ****************************************************************************/
@@ -437,14 +426,13 @@
                                 G_BUILD_VETERAN_DIPLOMAT) ? 1 : 0);
   }
     
-  if (is_ground_unittype(id) || improvement_variant(B_BARRACKS) == 1) {
-    return (city_got_barracks(pcity) ? 1 : 0);
+  if (is_ground_unittype(id)) {
+    return (get_city_bonus(pcity, EFT_LAND_VETERAN) > 0) ? 1 : 0;
   } else {
     if (is_water_unit(id)) {
-      return ((city_affected_by_wonder(pcity, B_LIGHTHOUSE)
-               || city_got_building(pcity, B_PORT)) ? 1 : 0);
+      return (get_city_bonus(pcity, EFT_SEA_VETERAN) > 0) ? 1 : 0;
     } else {
-      return (city_got_building(pcity, B_AIRPORT) ? 1 : 0);
+      return (get_city_bonus(pcity, EFT_AIR_VETERAN) > 0) ? 1 : 0;
     }
   }
   
@@ -651,7 +639,7 @@
 
   /* We don't use city_remove_improvement here as the global effects
      stuff has already been handled by transfer_city */
-  pcity->improvements[B_PALACE]=I_NONE;
+  pcity->improvements[game.palace_building]=I_NONE;
 
   /* land barbarians are more likely to destroy city improvements */
   if (is_land_barbarian(city_owner(pcity)))
@@ -659,7 +647,7 @@
 
   built_impr_iterate(pcity, i) {
     if (!is_wonder(i) && (myrand(100) < razechance)) {
-      pcity->improvements[i]=I_NONE;
+      pcity->improvements[i] = I_NONE;
     }
   } built_impr_iterate_end;
 
@@ -710,7 +698,7 @@
 
   pnew_capital = city_list_get(&pplayer->cities, myrand(size));
 
-  city_add_improvement(pnew_capital, B_PALACE);
+  city_add_improvement(pnew_capital, game.palace_building);
 
   /*
    * send_player_cities will recalculate all cities and send them to
@@ -743,7 +731,7 @@
   struct unit_list old_city_units;
   struct player *pgiver = city_owner(pcity);
   int old_trade_routes[NUM_TRADEROUTES];
-  bool had_palace = pcity->improvements[B_PALACE] != I_NONE;
+  bool had_palace = pcity->improvements[game.palace_building] != I_NONE;
   char old_city_name[MAX_LEN_NAME];
 
   assert(pgiver != ptaker);
@@ -1014,7 +1002,8 @@
   int o, x, y;
   struct player *pplayer = city_owner(pcity);
   struct tile *ptile = map_get_tile(pcity->x, pcity->y);
-  bool effect_update, had_palace = pcity->improvements[B_PALACE] != I_NONE;
+  bool effect_update,
+  had_palace = pcity->improvements[game.palace_building] != I_NONE;
   char *city_name = mystrdup(pcity->name);
 
   gamelog(GAMELOG_LOSEC, _("%s lose %s (%i,%i)"),
Index: server/citytools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.h,v
retrieving revision 1.55
diff -u -r1.55 citytools.h
--- server/citytools.h  6 Aug 2004 16:46:24 -0000       1.55
+++ server/citytools.h  6 Sep 2004 01:11:14 -0000
@@ -30,7 +30,6 @@
 #define POLLUTION_WEIGHTING 14 /* tentative */
 #define WARMING_FACTOR 50
 
-bool city_got_barracks(struct city *pcity);
 bool can_sell_building(struct city *pcity, Impr_Type_id id);
 struct city *find_city_wonder(Impr_Type_id id);
 int build_points_left(struct city *pcity);
@@ -39,6 +38,7 @@
 int city_luxury_bonus(struct city *pcity);
 int city_science_bonus(struct city *pcity);
 int city_tax_bonus(struct city *pcity);
+int city_luxury_bonus(struct city *pcity);
 
 void transfer_city_units(struct player *pplayer, struct player *pvictim, 
                         struct unit_list *units, struct city *pcity,
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.259
diff -u -r1.259 cityturn.c
--- server/cityturn.c   4 Sep 2004 20:19:51 -0000       1.259
+++ server/cityturn.c   6 Sep 2004 01:11:15 -0000
@@ -67,11 +67,10 @@
 static bool city_build_building(struct player *pplayer, struct city *pcity);
 static bool city_build_unit(struct player *pplayer, struct city *pcity);
 static bool city_build_stuff(struct player *pplayer, struct city *pcity);
-static int improvement_upgrades_to(struct city *pcity, int imp);
+static Impr_Type_id building_upgrades_to(struct city *pcity, Impr_Type_id id);
 static void upgrade_building_prod(struct city *pcity);
 static Unit_Type_id unit_upgrades_to(struct city *pcity, Unit_Type_id id);
 static void upgrade_unit_prod(struct city *pcity);
-static void obsolete_building_test(struct city *pcity, int b1, int b2);
 static void pay_for_buildings(struct player *pplayer, struct city *pcity);
 
 static bool disband_city(struct city *pcity);
@@ -307,10 +306,10 @@
     turns_growth = (city_granary_size(pcity->size) - pcity->food_stock - 1)
                   / pcity->food_surplus;
 
-    if (!city_got_effect(pcity,B_GRANARY) && !pcity->is_building_unit
-       && pcity->currently_building == B_GRANARY
+    if (get_city_bonus(pcity, EFT_GROWTH_FOOD) == 0
+       && get_current_construction_bonus(pcity, EFT_GROWTH_FOOD) > 0
        && pcity->shield_surplus > 0) {
-      turns_granary = (impr_build_shield_cost(B_GRANARY)
+      turns_granary = (impr_build_shield_cost(pcity->currently_building)
                       - pcity->shield_stock) / pcity->shield_surplus;
       /* if growth and granary completion occur simultaneously, granary
         preserves food.  -AJS */
@@ -320,7 +319,7 @@
                         E_CITY_GRAN_THROTTLE,
                         _("Game: Suggest throttling growth in %s to use %s "
                           "(being built) more effectively."), pcity->name,
-                        improvement_types[B_GRANARY].name);
+                        improvement_types[pcity->currently_building].name);
       }
     }
 
@@ -425,50 +424,42 @@
 }
 
 /**************************************************************************
+  Return the percentage of food that is lost in this city.
+
+  Normally this value is 100% but this can be reduced by EFT_GROWTH_FOOD
+  effects.
+**************************************************************************/
+static int granary_savings(const struct city *pcity)
+{
+  int savings = get_city_bonus(pcity, EFT_GROWTH_FOOD);
+
+  return CLIP(0, savings, 100);
+}
+
+/**************************************************************************
 Note: We do not send info about the city to the clients as part of this 
function
 **************************************************************************/
 static void city_increase_size(struct city *pcity)
 {
   struct player *powner = city_owner(pcity);
   bool have_square;
-  bool has_granary = city_got_effect(pcity, B_GRANARY);
+  int savings_pct = granary_savings(pcity), new_food;
   bool rapture_grow = city_rapture_grow(pcity); /* check before size increase! 
*/
-  int new_food;
 
-  if (!city_got_building(pcity, B_AQUEDUCT)
-      && pcity->size>=game.aqueduct_size) {/* need aqueduct */
-    if (!pcity->is_building_unit && pcity->currently_building == B_AQUEDUCT) {
+  if (!city_can_grow_to(pcity, pcity->size + 1)) { /* need improvement */
+    if (get_current_construction_bonus(pcity, EFT_SIZE_ADJ) > 0) {
       notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQ_BUILDING,
                       _("Game: %s needs %s (being built) "
                         "to grow any further."), pcity->name,
-                      improvement_types[B_AQUEDUCT].name);
+                      improvement_types[pcity->currently_building].name);
     } else {
       notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQUEDUCT,
-                      _("Game: %s needs %s to grow any further."),
-                      pcity->name, improvement_types[B_AQUEDUCT].name);
-    }
-    /* Granary can only hold so much */
-    new_food = (city_granary_size(pcity->size) *
-               (100 - game.aqueductloss / (1 + (has_granary ? 1 : 0)))) / 100;
-    pcity->food_stock = MIN(pcity->food_stock, new_food);
-    return;
-  }
-
-  if (!city_got_building(pcity, B_SEWER)
-      && pcity->size>=game.sewer_size) {/* need sewer */
-    if (!pcity->is_building_unit && pcity->currently_building == B_SEWER) {
-      notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQ_BUILDING,
-                      _("Game: %s needs %s (being built) "
-                        "to grow any further."), pcity->name,
-                      improvement_types[B_SEWER].name);
-    } else {
-      notify_player_ex(powner, pcity->x, pcity->y, E_CITY_AQUEDUCT,
-                      _("Game: %s needs %s to grow any further."),
-                      pcity->name, improvement_types[B_SEWER].name);
+                      _("Game: %s needs an improvement to grow any further."),
+                      pcity->name);
     }
     /* Granary can only hold so much */
-    new_food = (city_granary_size(pcity->size) *
-               (100 - game.aqueductloss / (1 + (has_granary ? 1 : 0)))) / 100;
+    new_food = (city_granary_size(pcity->size) * (100 - game.aqueductloss)
+               * savings_pct) / (100 * 100);
     pcity->food_stock = MIN(pcity->food_stock, new_food);
     return;
   }
@@ -478,10 +469,7 @@
   if (rapture_grow) {
     new_food = city_granary_size(pcity->size);
   } else {
-    if (has_granary)
-      new_food = city_granary_size(pcity->size) / 2;
-    else
-      new_food = 0;
+    new_food = city_granary_size(pcity->size) * savings_pct;
   }
   pcity->food_stock = MIN(pcity->food_stock, new_food);
 
@@ -547,20 +535,16 @@
                         pcity->name, utname);
        gamelog(GAMELOG_UNITFS, _("%s lose %s (famine)"),
                get_nation_name_plural(city_owner(pcity)->nation), utname);
-       if (city_got_effect(pcity, B_GRANARY))
-         pcity->food_stock=city_granary_size(pcity->size)/2;
-       else
-         pcity->food_stock=0;
+       pcity->food_stock = (city_granary_size(pcity->size)
+                            * granary_savings(pcity)) / 100;
        return;
       }
     } unit_list_iterate_safe_end;
     notify_player_ex(city_owner(pcity), pcity->x, pcity->y, E_CITY_FAMINE,
                     _("Game: Famine causes population loss in %s."),
                     pcity->name);
-    if (city_got_effect(pcity, B_GRANARY))
-      pcity->food_stock = city_granary_size(pcity->size - 1) / 2;
-    else
-      pcity->food_stock = 0;
+    pcity->food_stock = (city_granary_size(pcity->size - 1)
+                        * granary_savings(pcity)) / 100;
     city_reduce_size(pcity, 1);
   }
 }
@@ -570,31 +554,12 @@
 **************************************************************************/
 void advisor_choose_build(struct player *pplayer, struct city *pcity)
 {
-  struct ai_choice choice;
   Impr_Type_id id = -1;
-  int want=0;
-
-  init_choice(&choice);
-  if (!city_owner(pcity)->ai.control) {
-    /* so that ai_advisor is smart even for humans */
-    ai_eval_buildings(pcity);
-  }
-  ai_advisor_choose_building(pcity, &choice); /* much smarter version -- Syela 
*/
-  freelog(LOG_DEBUG, "Advisor_choose_build got %d/%d"
-         " from ai_advisor_choose_building.",
-         choice.choice, choice.want);
-  id = choice.choice;
-  want = choice.want;
-
-  if (id >= 0 && id < B_LAST && want > 0) {
-    change_build_target(pplayer, pcity, id, FALSE, E_IMP_AUTO);
-    /* making something. */
-    return;
-  }
 
   /* Build something random, undecided. */
   impr_type_iterate(i) {
-    if (can_build_improvement(pcity, i) && i != B_PALACE) {
+    if (can_build_improvement(pcity, i)
+       && !building_has_effect(i, EFT_CAPITAL_CITY)) {
       id = i;
       break;
     }
@@ -675,7 +640,7 @@
        target = new_target;
       }
     } else if (!is_unit && !can_build_improvement(pcity, target)) {
-      Impr_Type_id new_target = improvement_upgrades_to(pcity, target);
+      Impr_Type_id new_target = building_upgrades_to(pcity, target);
 
       /* If the city can never build this improvement, drop it. */
       if (!can_eventually_build_improvement(pcity, new_target)) {
@@ -758,45 +723,47 @@
 }
 
 /**************************************************************************
-...
+  Follow the list of replaced_by buildings until we hit something that
+  we can build.  Return id if we can't upgrade at all.  NB:  returning
+  id doesn't guarantee that pcity really _can_ build id; just that
+  pcity can't build whatever _obsoletes_ id.
 **************************************************************************/
-static void obsolete_building_test(struct city *pcity, int b1, int b2)
+static Impr_Type_id building_upgrades_to(struct city *pcity, Impr_Type_id id)
 {
-  if (pcity->currently_building == b1
-      && !pcity->is_building_unit
-      && can_build_improvement(pcity, b2)) {
-    pcity->currently_building = b2;
+  Impr_Type_id check = id, latest_ok = id;
+
+  if (!can_build_improvement_direct(pcity, check)) {
+    return -1;
+  }
+  while(improvement_exists(check = improvement_types[check].replaced_by)) {
+    if (can_build_improvement_direct(pcity, check)) {
+      latest_ok = check;
+    }
+  }
+  if (latest_ok == id) {
+    return -1; /* Can't upgrade */
   }
-}
 
-/**************************************************************************
-  If imp is obsolete, return the improvement that _can_ be built that
-  lead to imp's obsolesence.
-  !!! Note:  I hear that the building ruleset code is going to be
-  overhauled soon.  If this happens, then this function should be updated
-  to follow the new model.  This function will probably look a lot like
-  unit_upgrades_to().
-**************************************************************************/
-static int improvement_upgrades_to(struct city *pcity, int imp)
-{
-  if (imp == B_BARRACKS && can_build_improvement(pcity, B_BARRACKS3))
-    return B_BARRACKS3;
-  else if (imp == B_BARRACKS && can_build_improvement(pcity, B_BARRACKS2))
-    return B_BARRACKS2;
-  else if (imp == B_BARRACKS2 && can_build_improvement(pcity, B_BARRACKS3))
-    return B_BARRACKS3;
-  else
-    return imp;
+  return latest_ok;
 }
 
 /**************************************************************************
-...
+  Try to upgrade production in pcity.
 **************************************************************************/
 static void upgrade_building_prod(struct city *pcity)
 {
-  obsolete_building_test(pcity, B_BARRACKS,B_BARRACKS3);
-  obsolete_building_test(pcity, B_BARRACKS,B_BARRACKS2);
-  obsolete_building_test(pcity, B_BARRACKS2,B_BARRACKS3);
+  struct player *pplayer = city_owner(pcity);
+  Impr_Type_id upgrades_to = building_upgrades_to(pcity,
+                                                 pcity->currently_building);
+
+  if (can_build_improvement(pcity, upgrades_to)) {
+    pcity->currently_building = upgrades_to;
+    notify_player_ex(pplayer, pcity->x, pcity->y, E_UNIT_UPGRADED, 
+                 _("Game: Production of %s is upgraded to %s in %s."),
+                 get_improvement_type(pcity->currently_building)->name, 
+                 get_improvement_type(upgrades_to)->name , 
+                 pcity->name);
+  }
 }
 
 /**************************************************************************
@@ -903,6 +870,7 @@
 static bool city_build_building(struct player *pplayer, struct city *pcity)
 {
   bool space_part;
+  int mod;
 
   if (get_current_construction_bonus(pcity, EFT_PROD_TO_GOLD) > 0) {
     assert(pcity->shield_surplus >= 0);
@@ -924,10 +892,10 @@
   }
   if (pcity->shield_stock
       >= impr_build_shield_cost(pcity->currently_building)) {
-    if (pcity->currently_building == B_PALACE) {
+    if (pcity->currently_building == game.palace_building) {
       city_list_iterate(pplayer->cities, palace) {
-       if (city_got_building(palace, B_PALACE)) {
-         city_remove_improvement(palace, B_PALACE);
+       if (city_got_building(palace, game.palace_building)) {
+         city_remove_improvement(palace, game.palace_building);
          break;
        }
       } city_list_iterate_end;
@@ -971,38 +939,31 @@
                     _("Game: %s has finished building %s."), pcity->name,
                     improvement_types[pcity->currently_building].name);
 
-    if (pcity->currently_building == B_DARWIN) {
-      Tech_Type_id first, second;
-      char buffer[200];
+
+    if ((mod = get_current_construction_bonus(pcity, EFT_GIVE_IMM_TECH))) {
+      int i;
 
       notify_player(pplayer, _("Game: %s boosts research, "
-                              "you gain 2 immediate advances."),
-                   improvement_types[B_DARWIN].name);
+                              "you gain %d immediate advances."),
+                   improvement_types[pcity->currently_building].name, mod);
 
-      if (pplayer->research.researching == A_UNSET) {
-        choose_random_tech(pplayer);
-      }
-      do_free_cost(pplayer);
-      first = pplayer->research.researching;
-      found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE, 
-                     A_NONE);
+      for (i = 0; i < mod; i++) {
+       Tech_Type_id tech = pplayer->research.researching;
+
+       if (tech == A_UNSET) {
+         choose_random_tech(pplayer);
+         tech = pplayer->research.researching;
+       }
+       do_free_cost(pplayer);
+       found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE, 
+                      A_NONE);
 
-      if (pplayer->research.researching == A_UNSET) {
-        choose_random_tech(pplayer);
+       notify_embassies(pplayer, NULL,
+           _("Game: The %s have acquired %s from %s."),
+           get_nation_name_plural(pplayer->nation),
+           get_tech_name(pplayer, tech),
+           improvement_types[pcity->currently_building].name);
       }
-      do_free_cost(pplayer);
-      second = pplayer->research.researching;
-      found_new_tech(pplayer, pplayer->research.researching, TRUE, TRUE,
-                     A_NONE);
-
-      (void) mystrlcpy(buffer, get_tech_name(pplayer, first),
-                      sizeof(buffer));
-
-      notify_embassies(pplayer, NULL,
-                      _("Game: The %s have acquired %s and %s from %s."),
-                      get_nation_name_plural(pplayer->nation), buffer,
-                      get_tech_name(pplayer, second),
-                      improvement_types[B_DARWIN].name);
     }
     if (space_part && pplayer->spaceship.state == SSHIP_NONE) {
       notify_player_ex(NULL, pcity->x, pcity->y, E_SPACESHIP,
@@ -1200,7 +1161,10 @@
   struct city *capital;
   int dist, size, cost;
 
-  if (city_got_building(pcity, B_PALACE)) {
+  if (government_has_flag(get_gov_pcity(pcity), G_UNBRIBABLE)) {
+    return INCITE_IMPOSSIBLE_COST;
+  }
+  if (get_city_bonus(pcity, EFT_NO_INCITE) > 0) {
     return INCITE_IMPOSSIBLE_COST;
   }
 
@@ -1250,9 +1214,7 @@
     /* No capital? Take max penalty! */
     dist = 32;
   }
-  if (city_got_building(pcity, B_COURTHOUSE)) {
-    dist /= 4;
-  }
+  dist -= (dist * get_city_bonus(pcity, EFT_INCITE_DIST_PCT)) / 100;
   if (g->fixed_corruption_distance != 0) {
     dist = MIN(g->fixed_corruption_distance, dist);
   }
@@ -1358,10 +1320,7 @@
 
     pcity->did_sell=FALSE;
     pcity->did_buy = FALSE;
-    if (city_got_building(pcity, B_AIRPORT))
-      pcity->airlift=TRUE;
-    else
-      pcity->airlift=FALSE;
+    pcity->airlift = (get_city_bonus(pcity, EFT_AIRLIFT) > 0);
     update_tech(pplayer, pcity->science_total);
     pplayer->economic.gold+=pcity->tax_total;
     pay_for_units(pplayer, pcity);
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.59
diff -u -r1.59 diplomats.c
--- server/diplomats.c  1 Sep 2004 03:16:47 -0000       1.59
+++ server/diplomats.c  6 Sep 2004 01:11:15 -0000
@@ -737,7 +737,6 @@
                     struct city *pcity)
 {
   struct player *cplayer;
-  struct city *capital;
   int revolt_cost;
 
   /* Fetch target civilization's player.  Sanity checks. */
@@ -757,12 +756,11 @@
     return;
   }
 
-  /* Check for city being the capital. */
-  capital = find_palace (city_owner (pcity));
-  if (pcity == capital) {
+  /* See if the city is subvertable. */
+  if (get_city_bonus(pcity, EFT_NO_INCITE) > 0) {
     notify_player_ex(pplayer, pcity->x, pcity->y, E_MY_DIPLOMAT_FAILED,
-                    _("Game: You can't subvert the capital of a nation."));
-    freelog (LOG_DEBUG, "incite: city is the capital");
+                    _("Game: You can't subvert this city."));
+    freelog (LOG_DEBUG, "incite: city is protected");
     return;
   }
 
@@ -1031,9 +1029,9 @@
      * City Walls, then there is a 50% chance of getting caught.
      */
     vulnerability = get_improvement_type(improvement)->sabotage;
-    if (city_got_building(pcity, B_PALACE)) {
-      vulnerability /= 2;
-    }
+
+    vulnerability -= (vulnerability
+                     * get_city_bonus(pcity, EFT_SPY_RESISTANT) / 100);
     if (myrand(100) >= vulnerability) {
       /* Caught! */
       notify_player_ex(pplayer, pcity->x, pcity->y, E_MY_DIPLOMAT_FAILED,
@@ -1120,9 +1118,8 @@
   def += (def/5.0) * pdefender->veteran;
 
   if (pdefender_tile->city) {
-    if (city_got_building(pdefender_tile->city, B_PALACE)) {
-      def = (def * 3) / 2;/* +50% */
-    }
+    def = def * (100 + get_city_bonus(pdefender_tile->city,
+                                     EFT_SPY_RESISTANT)) / 100;
   } else {
     if (tile_has_special(pdefender_tile, S_FORTRESS)
        || tile_has_special(pdefender_tile, S_AIRBASE)) {
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.183
diff -u -r1.183 gotohand.c
--- server/gotohand.c   1 Sep 2004 19:54:18 -0000       1.183
+++ server/gotohand.c   6 Sep 2004 01:11:16 -0000
@@ -922,7 +922,8 @@
   struct unit *passenger;
   struct player *pplayer = unit_owner(punit);
   bool afraid_of_sinking = (unit_flag(punit, F_TRIREME) && 
-                           !player_owns_active_wonder(pplayer, B_LIGHTHOUSE));
+                           get_player_bonus(pplayer, EFT_NO_SINK_DEEP) == 0);
+
   /* 
    * If the destination is one step away, look around first or just go
    * there?
@@ -1004,18 +1005,11 @@
      */
     defence_multiplier = 2;
     if (pcity) {
-      if (city_got_citywalls(pcity)) {
-       defence_multiplier += 2;
-      }
-      if (city_got_building(pcity, B_SDI)) {
-       defence_multiplier++;
-      }
-      if (city_got_building(pcity, B_SAM)) {
-       defence_multiplier++;
-      }
-      if (city_got_building(pcity, B_COASTAL)) {
-       defence_multiplier++;
-      }
+      /* This isn't very accurate. */
+      defence_multiplier += (get_city_bonus(pcity, EFT_LAND_DEFEND)
+                            + get_city_bonus(pcity, EFT_MISSILE_DEFEND)
+                            + get_city_bonus(pcity, EFT_AIR_DEFEND)
+                            + get_city_bonus(pcity, EFT_SEA_DEFEND)) / 100;
     }
 
     /* 
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.319
diff -u -r1.319 plrhand.c
--- server/plrhand.c    27 Aug 2004 17:36:53 -0000      1.319
+++ server/plrhand.c    6 Sep 2004 01:11:16 -0000
@@ -126,33 +126,31 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void great_library(struct player *pplayer)
+void do_tech_parasite_effect(struct player *pplayer)
 {
-  if (wonder_obsolete(B_GREAT)) 
-    return;
-  if (find_city_wonder(B_GREAT)) {
-    if (pplayer->player_no==find_city_wonder(B_GREAT)->owner) {
-      tech_type_iterate(i) {
-       if (get_invention(pplayer, i) != TECH_KNOWN
-           && tech_is_available(pplayer, i)
-           && game.global_advances[i]>=2) {
-         notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
-                          _("Game: %s acquired from The Great Library!"),
-                          advances[i].name);
-         gamelog(GAMELOG_TECH, _("%s discover %s (Library)"),
-                 get_nation_name_plural(pplayer->nation), advances[i].name);
-         notify_embassies(pplayer, NULL,
-                          _("Game: The %s have acquired %s"
-                            " from the Great Library."),
-                          get_nation_name_plural(pplayer->nation),
-                          advances[i].name);
-
-         do_free_cost(pplayer);
-         found_new_tech(pplayer, i, FALSE, FALSE, A_NONE);
-         break;
-       }
-      } tech_type_iterate_end;
-    }
+  int mod;
+
+  if ((mod = get_player_bonus(pplayer, EFT_TECH_PARASITE)) > 0) {
+    tech_type_iterate(i) {
+      if (get_invention(pplayer, i) != TECH_KNOWN
+         && tech_is_available(pplayer, i)
+         && game.global_advances[i] >= mod) {
+       notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
+           _("Game: %s acquired from a building!"),
+           advances[i].name);
+       gamelog(GAMELOG_TECH, _("%s discover %s (building)"),
+           get_nation_name_plural(pplayer->nation), advances[i].name);
+       notify_embassies(pplayer, NULL,
+           _("Game: The %s have acquired %s"
+             " from a building."),
+           get_nation_name_plural(pplayer->nation),
+           advances[i].name);
+
+       do_free_cost(pplayer);
+       found_new_tech(pplayer, i, FALSE, FALSE, A_NONE);
+       break;
+      }
+    } tech_type_iterate_end;
   }
 }
 
@@ -289,9 +287,14 @@
 {
   bool bonus_tech_hack = FALSE;
   bool was_first = FALSE;
-  bool macro_polo_was_obsolete = wonder_obsolete(B_MARCO);
+  bool had_embassy[MAX_NUM_PLAYERS];
   struct city *pcity;
 
+  players_iterate(aplr) {
+    had_embassy[aplr->player_no]
+      = (get_player_bonus(aplr, EFT_HAVE_EMBASSIES) > 0);
+  } players_iterate_end;
+
   /* HACK: A_FUTURE doesn't "exist" and is thus not "available".  This may
    * or may not be the correct thing to do.  For these sanity checks we
    * just special-case it. */
@@ -453,17 +456,14 @@
    * Send all player an updated info of the owner of the Marco Polo
    * Wonder if this wonder has become obsolete.
    */
-  if (!macro_polo_was_obsolete && wonder_obsolete(B_MARCO)) {
-    struct city *pcity = find_city_wonder(B_MARCO);
-
-    if (pcity) {
-      struct player *owner = city_owner(pcity);
-
+  players_iterate(owner) {
+    if (had_embassy[owner->player_no]
+       && get_player_bonus(owner, EFT_HAVE_EMBASSIES) == 0) {
       players_iterate(other_player) {
        send_player_info(owner, other_player);
       } players_iterate_end;
     }
-  }
+  } players_iterate_end;
 
   /* Update Team */
   if (next_tech > A_NONE) {
@@ -933,7 +933,7 @@
 
   check_player_government_rates(pplayer);
   global_city_refresh(pplayer);
-  if (player_owns_active_govchange_wonder(pplayer)) {
+  if (get_player_bonus(pplayer, EFT_NO_ANARCHY) > 0) {
     pplayer->revolution_finishes = game.turn;
   }
   send_player_info(pplayer, pplayer);
Index: server/plrhand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.h,v
retrieving revision 1.66
diff -u -r1.66 plrhand.h
--- server/plrhand.h    3 Sep 2004 04:22:37 -0000       1.66
+++ server/plrhand.h    6 Sep 2004 01:11:16 -0000
@@ -34,7 +34,7 @@
 void kill_player(struct player *pplayer);
 void kill_dying_players(void);
 void update_revolution(struct player *pplayer);
-void great_library(struct player *pplayer);
+void do_tech_parasite_effect(struct player *pplayer);
 void check_player_government_rates(struct player *pplayer);
 void make_contact(struct player *pplayer1, struct player *pplayer2, int x,
                  int y);
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.192
diff -u -r1.192 ruleset.c
--- server/ruleset.c    31 Aug 2004 04:40:50 -0000      1.192
+++ server/ruleset.c    6 Sep 2004 01:11:18 -0000
@@ -1138,12 +1138,7 @@
            nval, B_LAST, filename);
     exit(EXIT_FAILURE);
   }
-  /* FIXME: Remove this restriction when gen-impr implemented. */
-  if (nval != B_LAST_ENUM) {
-    freelog(LOG_FATAL, "Bad number of buildings %d (%s)", nval, filename);
-    exit(EXIT_FAILURE);
-  }
-  /* REMOVE TO HERE when gen-impr implemented. */
+
   game.num_impr_types = nval;
 
   impr_type_iterate(i) {
@@ -1152,6 +1147,8 @@
     improvement_types[i].name_orig[0] = 0;
   } impr_type_iterate_end;
 
+  ruleset_cache_init();
+
   free(sec);
 }
 
@@ -1162,13 +1159,58 @@
 {
   char **sec, *item, **list;
   int i, j, k, nval, count;
-  bool problem;
   struct impr_type *b;
-  struct impr_effect *e;
   const char *filename = secfile_filename(file);
 
   (void) check_ruleset_capabilities(file, "+1.10.1", filename);
 
+  /* Parse effect equivalence effect building groups. */
+  sec = secfile_get_secnames_prefix(file, "group_", &nval);
+  for (i = 0; i < nval; i++) {
+    struct effect_group *group;
+    char name[MAX_LEN_NAME];
+
+    item = secfile_lookup_str(file, "%s.name", sec[i]);
+    sz_strlcpy(name, item);
+
+    group = effect_group_new(name);
+
+    for (j = 0;
+        (item = secfile_lookup_str_default(file, NULL,
+                                           "%s.elements%d.building",
+                                           sec[i], j));
+        j++) {
+      Impr_Type_id id;
+      enum effect_range range;
+      bool survives;
+
+      if ((id = find_improvement_by_name(item)) == B_LAST) {
+       freelog(LOG_ERROR, "for %s unknown improvement: \"%s\" (%s)",
+               name, item, filename);
+       continue;
+      }
+
+      item = secfile_lookup_str_default(file, NULL, "%s.elements%d.range",
+                                       sec[i], j);
+      if (item) {
+       if ((range = effect_range_from_str(item)) == EFR_LAST) {
+         freelog(LOG_ERROR, "for %s bad range: \"%s\" (%s)",
+                 name, item, filename);
+         continue;
+       }
+      } else {
+       range = EFR_CITY;
+      }
+
+      survives
+       = secfile_lookup_bool_default(file, FALSE, "%s.elements%d.survives",
+                                     sec[i], j);
+
+      effect_group_add(group, id, range, survives);
+    }
+  }
+  free(sec);
+
   sec = secfile_get_secnames_prefix(file, "building_", &nval);
 
   for (i = 0; i < nval; i++) {
@@ -1263,6 +1305,9 @@
       b->obsolete_by = A_LAST;
     }
 
+    b->replaced_by = lookup_impr_type(file, sec[i], "replaced_by",
+                                     FALSE, filename, b->name);
+
     b->is_wonder = secfile_lookup_bool(file, "%s.is_wonder", sec[i]);
 
     b->build_cost = secfile_lookup_int(file, "%s.build_cost", sec[i]);
@@ -1271,164 +1316,82 @@
 
     b->sabotage = secfile_lookup_int(file, "%s.sabotage", sec[i]);
 
-    for (count = 0;
-        secfile_lookup_str_default(file, NULL, "%s.effect%d.type", sec[i],
-                                   count); count++) {
-      /* nothing */
-    }
-
-    if (count>MAX_EFFECTS) {
-      freelog(LOG_FATAL, "For %s maximum number of effects (%d) exceeded",
-              b->name, MAX_EFFECTS);
-      exit(EXIT_FAILURE);
-    }
-
-    b->effect = fc_malloc((count + 1) * sizeof(b->effect[0]));
-    k = 0;
-    for (j = 0; j < count; j++) {
-      e = &b->effect[k];
-      problem = FALSE;
-
-      item = secfile_lookup_str(file, "%s.effect%d.type", sec[i], j);
-      e->type = effect_type_from_str(item);
-      if (e->type == EFT_LAST) {
-       freelog(LOG_ERROR,
-               "for %s effect[%d].type couldn't match type \"%s\" (%s)",
-               b->name, j, item, filename);
-       problem = TRUE;
-      }
-
-      item =
-       secfile_lookup_str_default(file, "None", "%s.effect%d.range", sec[i], 
j);
-      e->range = effect_range_from_str(item);
-      if (e->range == EFR_LAST) {
-       freelog(LOG_ERROR,
-               "for %s effect[%d].range couldn't match range \"%s\" (%s)",
-               b->name, j, item, filename);
-       problem = TRUE;
-      }
-
-      e->amount =
-       secfile_lookup_int_default(file, 0, "%s.effect%d.amount", sec[i], j);
-
-      e->survives =
-       secfile_lookup_int_default(file, 0, "%s.effect%d.survives", sec[i], j);
-
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.cond_bldg", sec[i], 
j);
-      if (*item != '\0') {
-       e->cond_bldg = find_improvement_by_name(item);
-       if (e->cond_bldg == B_LAST) {
-         freelog(LOG_ERROR,
-                 "for %s effect[%d].cond_bldg couldn't match improvement 
\"%s\" (%s)",
-                 b->name, j, item, filename);
-         problem = TRUE;
+    /* Parse building effects and add them to the effects hash. */
+    {
+      for (j = 0;
+          (item = secfile_lookup_str_default(file, NULL, "%s.effect%d.name",
+                                             sec[i], j));
+         j++) {
+       int value;
+       enum effect_type eff;
+       enum effect_range range;
+       bool survives;
+       enum req_type type;
+       int req, equiv;
+
+       if ((eff = effect_type_from_str(item)) == EFT_LAST) {
+         freelog(LOG_ERROR, "for %s unknown effect type: \"%s\" (%s)",
+                 b->name, item, filename);
+         continue;
        }
-      } else {
-       e->cond_bldg = B_LAST;
-      }
 
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.cond_gov", sec[i], j);
-      if (*item != '\0') {
-       struct government *g = find_government_by_name(item);
-       if (!g) {
-         freelog(LOG_ERROR,
-                 "for %s effect[%d].cond_gov couldn't match government \"%s\" 
(%s)",
-                 b->name, j, item, filename);
-         e->cond_gov = game.government_count;
-         problem = TRUE;
+       item = secfile_lookup_str_default(file, "", "%s.effect%d.range",
+                                         sec[i], j);
+       if (*item != '\0') {
+         if ((range = effect_range_from_str(item)) == EFR_LAST) {
+           freelog(LOG_ERROR, "for %s bad range: \"%s\" (%s)",
+                   b->name, item, filename);
+           continue;
+         }
        } else {
-         e->cond_gov = g->index;
-       }
-      } else {
-       e->cond_gov = game.government_count;
-      }
-
-      item =
-       secfile_lookup_str_default(file, "None", "%s.effect%d.cond_adv", 
sec[i], j);
-      if (*item != '\0') {
-       e->cond_adv = find_tech_by_name(item);
-       if (e->cond_adv == A_LAST) {
-         freelog(LOG_ERROR,
-                 "for %s effect[%d].cond_adv couldn't match tech \"%s\" (%s)",
-                 b->name, j, item, filename);
-         problem = TRUE;
+         range = EFR_CITY;
        }
-      } else {
-       e->cond_adv = A_NONE;
-      }
 
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.cond_eff", sec[i], j);
-      if (*item != '\0') {
-       e->cond_eff = effect_type_from_str(item);
-       if (e->cond_eff == EFT_LAST) {
-         freelog(LOG_ERROR,
-                 "for %s effect[%d].cond_eff couldn't match effect \"%s\" 
(%s)",
-                 b->name, j, item, filename);
-         problem = TRUE;
-       }
-      } else {
-       e->cond_eff = EFT_LAST;
-      }
+       survives = secfile_lookup_bool_default(file, FALSE, 
"%s.effect%d.survives",
+                                              sec[i], j);
 
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.aff_unit", sec[i], j);
-      if (*item != '\0') {
-       e->aff_unit = unit_class_from_str(item);
-       if (e->aff_unit == UCL_LAST) {
-         freelog(LOG_ERROR,
-                 "for %s effect[%d].aff_unit couldn't match class \"%s\" (%s)",
-                 b->name, j, item, filename);
-         problem = TRUE;
-       }
-      } else {
-       e->aff_unit = UCL_LAST;
-      }
+       value = secfile_lookup_int_default(file, 1, "%s.effect%d.value",
+                                          sec[i], j);
 
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.aff_terr", sec[i], j);
-      if (*item != '\0') {
-       if (0 == strcmp("None", item)) {
-         e->aff_terr = T_NONE;
-       } else {
-         e->aff_terr = get_terrain_by_name(item);
-         if (e->aff_terr == T_UNKNOWN) {
-           freelog(LOG_ERROR,
-                   "for %s effect[%d].aff_terr couldn't match terrain \"%s\" 
(%s)",
-                   b->name, j, item, filename);
-           e->aff_terr = T_NONE;
-           problem = TRUE;
+       item = secfile_lookup_str_default(file, "", "%s.effect%d.equiv",
+                                         sec[i], j);
+       if (*item != '\0') {
+         if ((equiv = find_effect_group(item)) == -1) {
+           freelog(LOG_ERROR, "for %s bad effect group: \"%s\" (%s)",
+                   b->name, item, filename);
+           continue;
          }
+       } else {
+         equiv = -1;
        }
-      } else {
-       e->aff_terr = T_UNKNOWN;
-      }
 
-      item =
-       secfile_lookup_str_default(file, "", "%s.effect%d.aff_spec", sec[i], j);
-      if (*item != '\0') {
-       if (0 == strcmp("None", item)) {
-         e->aff_spec = S_NO_SPECIAL;
-       } else {
-         e->aff_spec = get_special_by_name(item);
-         if (e->aff_spec == S_NO_SPECIAL) {
-           freelog(LOG_ERROR,
-                   "for %s effect[%d].aff_spec couldn't match special \"%s\" 
(%s)",
-                   b->name, j, item, filename);
-           problem = TRUE;
+       item = secfile_lookup_str_default(file, "", "%s.effect%d.req_type",
+                                         sec[i], j);
+       if (*item != '\0') {
+         if ((type = req_type_from_str(item)) == REQ_LAST) {
+           freelog(LOG_ERROR, "for %s unknown requirement type: \"%s\" (%s)",
+                   b->name, item, filename);
+           continue;
+          }
+
+         item = secfile_lookup_str_default(file, NULL, "%s.effect%d.req",
+                                           sec[i], j);
+
+         if (!item) {
+           freelog(LOG_ERROR, "for %s missing requirement data (%s)",
+               b->name, filename);
+           continue;
+         } else {
+           req = parse_effect_requirement(i, type, item);
          }
-       }
-      } else {
-       e->aff_spec = S_ALL;
-      }
+        } else {
+          type = REQ_NONE;
+          req = 0;
+        }
 
-      if (!problem) {
-       k++;
+       ruleset_cache_add(i, eff, range, survives, value, type, req, equiv);
       }
     }
-    b->effect[k].type = EFT_LAST;
 
     /* FIXME: remove when gen-impr obsoletes */
     b->variant = secfile_lookup_int_default(file, 0, "%s.variant", sec[i]);
@@ -1446,6 +1409,20 @@
     b->helptext = lookup_helptext(file, sec[i]);
   }
 
+  /*
+   * Hack to allow code that explicitly checks for Palace or City Walls
+   * to work.
+   */
+  game.palace_building = get_building_for_effect(EFT_CAPITAL_CITY);
+  if (game.palace_building == B_LAST) {
+    freelog(LOG_FATAL, "Cannot find any palace building");
+  }
+
+  game.land_defend_building = get_building_for_effect(EFT_LAND_DEFEND);
+  if (game.land_defend_building == B_LAST) {
+    freelog(LOG_FATAL, "Cannot find any land defend building");
+  }
+
   /* Some more consistency checking: */
   impr_type_iterate(i) {
     b = &improvement_types[i];
@@ -1463,21 +1440,24 @@
                b->name, advances[b->obsolete_by].name, filename);
        b->obsolete_by = A_LAST;
       }
-      for (j = 0; b->effect[j].type != EFT_LAST; j++) {
-       if (!tech_exists(b->effect[j].cond_adv)) {
-         freelog(LOG_ERROR,
-                 "improvement \"%s\": effect conditional on"
-                 " removed tech \"%s\" (%s)",
-                 b->name, advances[b->effect[j].cond_adv].name, filename);
-         b->effect[j].cond_adv = A_LAST;
-       }
-      }
     }
   } impr_type_iterate_end;
 
+  game.aqueduct_size = secfile_lookup_int(file, "b_special.aqueduct_size");
+
+  item = secfile_lookup_str(file, "b_special.default");
+  if (*item != '\0') {
+    game.default_building = find_improvement_by_name(item);
+    if (game.default_building == B_LAST) {
+      freelog(LOG_ERROR, "Bad value \"%s\" for b_special.default (%s)",
+             item, filename);
+    }
+  } else {
+    game.default_building = B_LAST;
+  }
+
   /* FIXME: remove all of the following when gen-impr implemented... */
 
-  game.aqueduct_size = secfile_lookup_int(file, "b_special.aqueduct_size");
   game.sewer_size = secfile_lookup_int(file, "b_special.sewer_size");
   
   game.rtech.cathedral_plus =
@@ -2004,6 +1984,8 @@
     sz_strlcpy(packet.team_name[i], team_get_by_id(i)->name);
   }
 
+  packet.default_building = game.default_building;
+
   lsend_packet_ruleset_control(dest, &packet);
 }
 
@@ -2390,6 +2372,11 @@
     lookup_building_list(file, sec[i], "init_buildings", pl->init_buildings,
                         filename);
 
+    /* Load nation specific initial buildings */
+
+    lookup_building_list(file, sec[i], "init_buildings", pl->init_buildings,
+                        filename);
+
     /* AI techs */
 
     techs = secfile_lookup_str_vec(file, &dim, "%s.tech_goals", sec[i]);
@@ -2763,6 +2750,12 @@
   lookup_building_list(&file, "options", "global_init_buildings",
                       game.rgame.global_init_buildings, filename);
 
+  /*
+   * Load global initial buildings
+   */
+  lookup_building_list(&file, "options", "global_init_buildings",
+                      game.rgame.global_init_buildings, filename);
+
   /* Enable/Disable killstack */
   game.rgame.killstack = secfile_lookup_bool(&file, "combat_rules.killstack");
        
@@ -2869,7 +2862,6 @@
   impr_type_iterate(i) {
     struct impr_type *b = &improvement_types[i];
     struct packet_ruleset_building packet;
-    struct impr_effect *eff;
 
     packet.id = i;
     sz_strlcpy(packet.name, b->name_orig);
@@ -2879,6 +2871,7 @@
     packet.bldg_req = b->bldg_req;
     packet.equiv_range = b->equiv_range;
     packet.obsolete_by = b->obsolete_by;
+    packet.replaced_by = b->replaced_by;
     packet.is_wonder = b->is_wonder;
     packet.build_cost = b->build_cost;
     packet.upkeep = b->upkeep;
@@ -2904,12 +2897,6 @@
     T(equiv_repl, equiv_repl_count, B_LAST);
 #undef T
 
-    packet.effect_count = 0;
-    for (eff = b->effect; eff->type != EFT_LAST; eff++) {
-      packet.effect[packet.effect_count] = *eff;
-      packet.effect_count++;
-    }
-
     lsend_packet_ruleset_building(dest, &packet);
   } impr_type_iterate_end;
 }
@@ -3105,7 +3092,8 @@
       packet.leader_sex[i] = n->leaders[i].is_male;
     }
     packet.city_style = n->city_style;
-    memcpy(packet.init_techs, n->init_techs, sizeof(packet.init_techs));
+    memcpy(packet.init_techs, n->init_techs,
+          sizeof(packet.init_techs));
     sz_strlcpy(packet.class, n->class);
     sz_strlcpy(packet.legend, n->legend);
 
@@ -3250,7 +3238,9 @@
   send_ruleset_buildings(dest);
   send_ruleset_nations(dest);
   send_ruleset_cities(dest);
+  send_ruleset_cache(dest);
 
   lsend_packet_thaw_hint(dest);
   conn_list_do_unbuffer(dest);
 }
+
Index: server/score.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/score.c,v
retrieving revision 1.6
diff -u -r1.6 score.c
--- server/score.c      3 Sep 2004 01:21:03 -0000       1.6
+++ server/score.c      6 Sep 2004 01:11:18 -0000
@@ -408,6 +408,8 @@
   }
 
   city_list_iterate(pplayer->cities, pcity) {
+    int bonus;
+
     pplayer->score.happy += pcity->ppl_happy[4];
     pplayer->score.content += pcity->ppl_content[4];
     pplayer->score.unhappy += pcity->ppl_unhappy[4];
@@ -421,11 +423,9 @@
     pplayer->score.techout += pcity->science_total;
     pplayer->score.bnp += pcity->trade_prod;
     pplayer->score.mfg += pcity->shield_surplus;
-    if (city_got_building(pcity, B_UNIVERSITY)) {
-      pplayer->score.literacy += city_population(pcity);
-    } else if (city_got_building(pcity,B_LIBRARY)) {
-      pplayer->score.literacy += city_population(pcity) / 2;
-    }
+
+    bonus = CLIP(0, get_city_bonus(pcity, EFT_SCIENCE_BONUS), 100);
+    pplayer->score.literacy += (city_population(pcity) * bonus) / 100;
   } city_list_iterate_end;
 
   if (pplayer->player_no == 0) {
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.199
diff -u -r1.199 settlers.c
--- server/settlers.c   31 Aug 2004 04:40:51 -0000      1.199
+++ server/settlers.c   6 Sep 2004 01:11:18 -0000
@@ -883,9 +883,13 @@
     /* It is a virtual unit, so must start in a city... */
     struct city *pcity = map_get_city(punit->x, punit->y);
 
+    /* The default is to lose 100%.  The growth bonus reduces this. */
+    int foodloss_pct = 100 - get_city_bonus(pcity, EFT_GROWTH_FOOD);
+
+    foodloss_pct = CLIP(0, foodloss_pct, 100);
     assert(pcity != NULL);
     cost = city_granary_size(pcity->size);
-    if (city_got_effect(pcity, B_GRANARY)) { cost /= 2; }
+    cost = cost * foodloss_pct / 100;
   }
 
   return cost;
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.185
diff -u -r1.185 srv_main.c
--- server/srv_main.c   4 Sep 2004 21:25:58 -0000       1.185
+++ server/srv_main.c   6 Sep 2004 01:11:19 -0000
@@ -323,40 +323,37 @@
 /**************************************************************************
 ...
 **************************************************************************/
-static void do_apollo_program(void)
+static void do_reveal_effects(void)
 {
-  struct city *pcity = find_city_wonder(B_APOLLO);
-
-  if (pcity) {
-    struct player *pplayer = city_owner(pcity);
-
-    if (game.civstyle == 1) {
-      players_iterate(other_player) {
-       city_list_iterate(other_player->cities, pcity) {
+  players_iterate(pplayer) {
+    if (get_player_bonus(pplayer, EFT_REVEAL_CITIES) > 0) {
+      players_iterate(pother) {
+       city_list_iterate(pother->cities, pcity) {
          show_area(pplayer, pcity->x, pcity->y, 0);
        } city_list_iterate_end;
       } players_iterate_end;
-    } else {
+    }
+    if (get_player_bonus(pplayer, EFT_REVEAL_MAP) > 0) {
       /* map_know_all will mark all unknown tiles as known and send
        * tile, unit, and city updates as necessary.  No other actions are
        * needed. */
       map_know_all(pplayer);
     }
-  }
+  } players_iterate_end;
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-static void marco_polo_make_contact(void)
+static void do_have_embassies_effect(void)
 {
-  struct city *pcity = find_city_wonder(B_MARCO);
-
-  if (pcity) {
-    players_iterate(pplayer) {
-      make_contact(city_owner(pcity), pplayer, pcity->x, pcity->y);
-    } players_iterate_end;
-  }
+  players_iterate(pplayer) {
+    if (get_player_bonus(pplayer, EFT_HAVE_EMBASSIES) > 0) {
+      players_iterate(pother) {
+       make_contact(pplayer, pother, -1, -1);
+      } players_iterate_end;
+    }
+  } players_iterate_end;
 }
 
 /**************************************************************************
@@ -572,7 +569,7 @@
 
   /* Refresh cities */
   shuffled_players_iterate(pplayer) {
-    great_library(pplayer);
+    do_tech_parasite_effect(pplayer);
     player_restore_units(pplayer);
     update_city_activities(pplayer);
     pplayer->research.changed_from=-1;
@@ -589,8 +586,8 @@
   } players_iterate_end;
   flush_packets();  /* to curb major city spam */
 
-  do_apollo_program();
-  marco_polo_make_contact();
+  do_reveal_effects();
+  do_have_embassies_effect();
 
   freelog(LOG_DEBUG, "Auto-Attack phase");
   auto_attack();
@@ -1662,6 +1659,7 @@
    */
   server_state = RUN_GAME_STATE;
   players_iterate(pplayer) {
+    ai_data_analyze_rulesets(pplayer);
     if (pplayer->is_observer) {
       pplayer->nation = OBSERVER_NATION;
     } else if (pplayer->nation == NO_NATION_SELECTED && !pplayer->ai.control) {
@@ -1819,5 +1817,6 @@
   diplhand_free();
   game_free();
   stdinhand_free();
+  ruleset_cache_free();
   BV_CLR_ALL(srvarg.draw);
 }
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.303
diff -u -r1.303 unithand.c
--- server/unithand.c   26 Aug 2004 18:37:52 -0000      1.303
+++ server/unithand.c   6 Sep 2004 01:11:19 -0000
@@ -443,17 +443,11 @@
                     _("Game: %s is too big to add %s."),
                     pcity->name, unit_name);
     break;
-  case AB_NO_AQUEDUCT:
+  case AB_NO_SPACE:
     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
-                    _("Game: %s needs %s to grow, so you cannot add %s."),
-                    pcity->name, get_improvement_name(B_AQUEDUCT),
-                    unit_name);
-    break;
-  case AB_NO_SEWER:
-    notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
-                    _("Game: %s needs %s to grow, so you cannot add %s."),
-                    pcity->name, get_improvement_name(B_SEWER),
-                    unit_name);
+                    _("Game: %s needs an improvement to grow, so "
+                      "you cannot add %s."),
+                    pcity->name, unit_name);
     break;
   default:
     /* Shouldn't happen */
@@ -715,7 +709,7 @@
   
   if (pcity
       && pcity->size > 1
-      && !city_got_citywalls(pcity)
+      && get_city_bonus(pcity, EFT_UNIT_NO_LOSE_POP) == 0
       && kills_citizen_after_attack(punit)) {
     city_reduce_size(pcity,1);
     city_refresh(pcity);
@@ -814,8 +808,8 @@
   if (punit->hp &&
       (pcity=map_get_city(def_x, def_y)) &&
       pcity->size>1 &&
-      !city_got_citywalls(pcity) &&
-      kills_citizen_after_attack(punit)) {
+      get_city_bonus(pcity, EFT_UNIT_NO_LOSE_POP) == 0
+      && kills_citizen_after_attack(punit)) {
     city_reduce_size(pcity,1);
     city_refresh(pcity);
     send_city_info(NULL, pcity);
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.301
diff -u -r1.301 unittools.c
--- server/unittools.c  3 Sep 2004 03:56:59 -0000       1.301
+++ server/unittools.c  6 Sep 2004 01:11:21 -0000
@@ -60,7 +60,7 @@
 static void unit_restore_movepoints(struct player *pplayer, struct unit 
*punit);
 static void update_unit_activity(struct unit *punit);
 static void wakeup_neighbor_sentries(struct unit *punit);
-static void handle_leonardo(struct player *pplayer);
+static void do_upgrade_effects(struct player *pplayer);
 
 static void sentry_transported_idle_units(struct unit *ptrans);
 
@@ -116,21 +116,22 @@
       || unit_type(punit)->veteran[punit->veteran].name[0] == '\0'
       || unit_flag(punit, F_NO_VETERAN)) {
     return FALSE;
-  }
-  if (is_ground_unittype(punit->type)
-      && player_owns_active_wonder(get_player(punit->owner), B_SUNTZU)) {
-    if (myrand(100) < 1.5 * game.veteran_chance[punit->veteran]) {
-      punit->veteran++;
-      return TRUE;
-    }
   } else {
-    if (myrand(100) < game.veteran_chance[punit->veteran]) {
+    struct player *plr;
+    double mod = 1.0;
+
+    plr = get_player(punit->owner);
+
+    if (is_ground_unittype(punit->type)) {
+      mod += (0.01 * get_player_bonus(plr, EFT_LAND_VET_COMBAT));
+    }
+
+    if (myrand(100) < (mod * game.veteran_chance[punit->veteran])) {
       punit->veteran++;
       return TRUE;
     }
+    return FALSE;
   }
-
-  return FALSE;  
 }
 
 /**************************************************************************
@@ -197,49 +198,42 @@
 Do Leonardo's Workshop upgrade(s). Select unit to upgrade by random. --Zamar
 Now be careful not to strand units at sea with the Workshop. --dwp
 ****************************************************************************/
-static void handle_leonardo(struct player *pplayer)
+static void do_upgrade_effects(struct player *pplayer)
 {
-  int leonardo_variant;
-       
+  int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
   struct unit_list candidates;
-  int candidate_to_upgrade=-1;
 
-  int i;
+  if (upgrades <= 0) {
+    return;
+  }
 
-  leonardo_variant = improvement_variant(B_LEONARDO);
-       
   unit_list_init(&candidates);
-       
+
   unit_list_iterate(pplayer->units, punit) {
     if (test_unit_upgrade(punit, TRUE) == UR_OK) {
       unit_list_insert(&candidates, punit);    /* Potential candidate :) */
     }
   } unit_list_iterate_end;
-       
-  if (unit_list_size(&candidates) == 0)
-    return; /* We have Leonardo, but nothing to upgrade! */
-       
-  if (leonardo_variant == 0)
-    candidate_to_upgrade=myrand(unit_list_size(&candidates));
-
-  i=0; 
-  unit_list_iterate(candidates, punit) {
-    if (leonardo_variant != 0 || i == candidate_to_upgrade) {
-      Unit_Type_id upgrade_type = can_upgrade_unittype(pplayer, punit->type);
-
-      notify_player(pplayer,
-            _("Game: %s has upgraded %s to %s%s."),
-            improvement_types[B_LEONARDO].name,
-            unit_type(punit)->name,
-            get_unit_type(upgrade_type)->name,
-            get_location_str_in(pplayer, punit->x, punit->y));
-      punit->veteran = 0;
-      assert(test_unit_upgrade(punit, TRUE) == UR_OK);
-      upgrade_unit(punit, upgrade_type, TRUE);
-    }
-    i++;
-  } unit_list_iterate_end;
-       
+
+  while (upgrades > 0 && unit_list_size(&candidates) > 0) {
+    /* Upgrade one unit. */
+    int candidate_to_upgrade = myrand(unit_list_size(&candidates));
+    struct unit *punit = unit_list_get(&candidates, candidate_to_upgrade);
+    Unit_Type_id upgrade_type = can_upgrade_unittype(pplayer, punit->type);
+
+    notify_player(pplayer,
+                 _("Game: %s was upgraded for free to %s%s."),
+                 unit_type(punit)->name,
+                 get_unit_type(upgrade_type)->name,
+                 get_location_str_in(pplayer, punit->x, punit->y));
+
+    punit->veteran = 0;
+    assert(test_unit_upgrade(punit, TRUE) == UR_OK);
+    upgrade_unit(punit, upgrade_type, TRUE);
+    unit_list_unlink(&candidates, punit);
+    upgrades--;
+  }
+
   unit_list_unlink_all(&candidates);
 }
 
@@ -294,8 +288,7 @@
 void player_restore_units(struct player *pplayer)
 {
   /* 1) get Leonardo out of the way first: */
-  if (player_owns_active_wonder(pplayer, B_LEONARDO))
-    handle_leonardo(pplayer);
+  do_upgrade_effects(pplayer);
 
   unit_list_iterate_safe(pplayer->units, punit) {
 
@@ -430,9 +423,8 @@
     punit->hp+=hp_gain_coord(punit);
   }
   
-  if (player_owns_active_wonder(pplayer, B_UNITED)) 
-    punit->hp+=2;
-    
+  punit->hp += get_player_bonus(pplayer, EFT_UNIT_RECOVER);
+
   if(is_heli_unit(punit)) {
     struct city *pcity = map_get_city(punit->x,punit->y);
     if(!pcity) {
@@ -492,11 +484,12 @@
   else
     hp=0;
   if((pcity=map_get_city(punit->x,punit->y))) {
-    if ((city_got_barracks(pcity) &&
-        (is_ground_unit(punit) || improvement_variant(B_BARRACKS)==1)) ||
-       (city_got_building(pcity, B_AIRPORT) && is_air_unit(punit)) || 
-       (city_got_building(pcity, B_AIRPORT) && is_heli_unit(punit)) || 
-       (city_got_building(pcity, B_PORT) && is_sailing_unit(punit))) {
+    if ((get_city_bonus(pcity, EFT_LAND_REGEN) > 0
+        && is_ground_unit(punit))
+       || (get_city_bonus(pcity, EFT_AIR_REGEN) > 0
+           && (is_air_unit(punit) || is_heli_unit(punit)))
+       || (get_city_bonus(pcity, EFT_SEA_REGEN) > 0
+           && is_sailing_unit(punit))) {
       hp=unit_type(punit)->hp;
     }
     else

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#9961) Re: effects, Jason Short <=