[Freeciv-Dev] (PR#9961) Re: effects
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<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 <=
|
|