[Freeciv-Dev] Re: (PR#8754) effects patch
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=8754 >
On Wed, 7 Jul 2004, Per Inge Mathisen wrote:
> I will post an update of the AI code very soon.
Here goes. Replace the AI code in eff12 with this. It is cleaned up and
almost all effects are covered in some way now. The WAGs are probably way
off (some playtesting suggested the AI did somewhat ok), but it will do
for now, I think. Nothing is easier than adjusting WAGs based on player
feedback...
Eventually more smart and accurate code will replace the first batch of
effects in the big adjust function.
- Per
Index: ai/advdiplomacy.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdiplomacy.c,v
retrieving revision 1.21
diff -u -r1.21 advdiplomacy.c
--- ai/advdiplomacy.c 25 Jun 2004 23:43:00 -0000 1.21
+++ ai/advdiplomacy.c 7 Jul 2004 09:56:40 -0000
@@ -378,7 +378,7 @@
} else if (give) {
/* AI must be crazy to trade away its cities */
worth -= city_gold_worth(offer);
- if (city_got_building(offer, B_PALACE)) {
+ if (is_capital(offer)) {
worth = -BIG_NUMBER; /* Never! Ever! */
} else {
worth *= 15;
Index: ai/advdomestic.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
retrieving revision 1.111
diff -u -r1.111 advdomestic.c
--- ai/advdomestic.c 25 Jun 2004 23:43:00 -0000 1.111
+++ ai/advdomestic.c 7 Jul 2004 09:56:40 -0000
@@ -40,811 +40,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);
- int 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 */
- return ai->threats.sea ? TRADE_WEIGHTING + 3 : 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);
- int 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);
- int 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);
- int 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;
-}
-
-/**************************************************************************
-Get value of best usable tile on city map.
-**************************************************************************/
-static int ai_best_tile_value(struct city *pcity)
-{
- int best = 0;
- int food;
-
- /* food = (pcity->size * 2 - get_food_tile(2,2, pcity)) +
settler_eats(pcity); */
- /* Following simply works better, as far as I can tell. */
- food = 0;
-
- city_map_iterate(x, y) {
- if (can_place_worker_here(pcity, x, y)) {
- int value = city_tile_value(pcity, x, y, food, 0);
-
- if (value > best) {
- best = value;
- }
- }
- } city_map_iterate_end;
-
- return best;
-}
-
-/**************************************************************************
-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;
-}
-
-/**************************************************************************
- 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 = ai_best_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)
- freelog(LOG_DEBUG, "ai_eval_buildings: %s wants %s with desire %d.",
- pcity->name, 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.6
diff -u -r1.6 advdomestic.h
--- ai/advdomestic.h 21 Jul 2002 00:48:38 -0000 1.6
+++ ai/advdomestic.h 7 Jul 2004 09:56:40 -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.169
diff -u -r1.169 advmilitary.c
--- ai/advmilitary.c 25 Jun 2004 23:43:00 -0000 1.169
+++ ai/advmilitary.c 7 Jul 2004 09:56:40 -0000
@@ -299,8 +299,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_REGEN)) {
+ danger /= 2;
+ }
+ if (is_air_unit(punit) && get_city_bonus(pcity, EFT_AIR_REGEN)) {
+ danger /= 2;
+ }
return danger;
}
@@ -413,7 +417,7 @@
static int assess_danger(struct city *pcity)
{
int i;
- int danger[5];
+ int danger[5], defender[4];
struct player *pplayer = city_owner(pcity);
bool pikemen = FALSE;
int urgency = 0;
@@ -523,17 +527,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] = find_source_improvement(pplayer, EFT_LAND_DEFEND);
+ defender[1] = find_source_improvement(pplayer, EFT_SEA_DEFEND);
+ defender[2] = find_source_improvement(pplayer, EFT_AIR_DEFEND);
+ defender[3] = find_source_improvement(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;
@@ -775,9 +794,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));
+ || find_source_improvement(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. */
@@ -1124,6 +1143,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;
@@ -1131,36 +1151,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 = find_source_improvement(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 = find_source_improvement(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 = find_source_improvement(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;
@@ -1199,6 +1208,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 */
@@ -1224,40 +1234,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 = find_source_improvement(pplayer, EFT_LAND_DEFEND);
+ sea_id = find_source_improvement(pplayer, EFT_SEA_DEFEND);
+ air_id = find_source_improvement(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;
}
@@ -1267,7 +1287,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)) {
/* unlikely */
choice->want = MIN(49, danger);
} else {
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.157
diff -u -r1.157 aicity.c
--- ai/aicity.c 7 Jul 2004 07:32:02 -0000 1.157
+++ ai/aicity.c 7 Jul 2004 09:56:40 -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"
@@ -59,114 +61,344 @@
static void resolve_city_emergency(struct player *pplayer, struct city *pcity);
static void ai_sell_obsolete_buildings(struct city *pcity);
-/**************************************************************************
- This calculates the usefulness of pcity to us. Note that you can pass
- another player's ai_data structure here for evaluation by different
- priorities.
-**************************************************************************/
-int ai_eval_calc_city(struct city *pcity, struct ai_data *ai)
-{
- int i = (pcity->food_surplus * ai->food_priority
- + pcity->shield_surplus * ai->shield_priority
- + pcity->luxury_total * ai->luxury_priority
- + pcity->tax_total * ai->gold_priority
- + pcity->science_total * ai->science_priority
- + pcity->ppl_happy[4] * ai->happy_priority
- - 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);
+/**************************************************************************
+ 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.
+
+ TODO: 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, int id)
+{
+ struct player *pplayer = city_owner(pcity);
+ struct impr_type *pimpr = get_improvement_type(id);
+ int *v = &pcity->ai.building_want[id];
+ int cities;
+ 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);
+
+ memset(&cities, 0, sizeof(cities));
+
+ /* FIXME: after effect ranges are generalized. */
+ if (is_wonder(id)) {
+ switch (pimpr->affected_cities) {
+ case IR_WORLD:
+ case IR_PLAYER:
+ city_list_iterate(pplayer->cities, acity) {
+ cities++;
+ } city_list_iterate_end;
+ break;
+
+ case IR_ISLAND:
+ city_list_iterate(pplayer->cities, acity) {
+ if (map_get_tile(acity->x, acity->y)->continent == ptile->continent)
+ cities++;
+ } city_list_iterate_end;
+ break;
+
+ case IR_CITY:
+ cities = 1;
+ break;
+
+ default:
+ cities = 0;
+ break;
+ }
+ } else {
+ cities = 1;
+ }
+
+ eff_vector_iterate(get_building_effects(id), peff_type) {
+ int amount, c = cities;
+
+ if (id == game.palace_improvement) {
+ /* TODO: Special case palace movement here. */
+ continue;
+ }
+
+ amount = get_construction_bonus(pplayer, pcity, id, *peff_type);
+
+ switch (*peff_type) {
+ /* Modify general city parameter effects. We do them fast and furious
+ * for now, since we will do this more accurately later on with a
+ * different kind of code. */
+ case EFT_REVOLT_DIST_ADJ:
+ case EFT_REVOLT_DIST_PCT:
+ case EFT_TRADE_ROUTE_PCT:
+ case EFT_UPKEEP_FREE:
+ case EFT_MAKE_CONTENT_MIL_PER:
+ case EFT_FOOD_PER_TILE:
+ case EFT_FOOD_ADD_TILE:
+ case EFT_MAKE_HAPPY:
+ case EFT_POLLU_POP_PCT:
+ case EFT_POLLU_PROD_PCT:
+ case EFT_TRADE_PER_TILE:
+ case EFT_PROD_ADD_TILE:
+ case EFT_PROD_TO_GOLD:
+ case EFT_TRADE_INC_TILE:
+ case EFT_NO_UNHAPPY:
+ /* FIXME */
+ break;
+ case EFT_FORCE_CONTENT:
+ if (!government_has_flag(gov, G_NO_UNHAPPY_CITIZENS)) {
+ v += pcity->ppl_unhappy[0] * 5;
+ 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_PROD_BONUS:
+ v += (100 + amount) * pcity->shield_prod * ai->shield_priority / 200;
+ v += (100 + amount) * c * ai->shield_priority / 400;
+ break;
+ case EFT_SCIENCE_BONUS:
+ if (!ai_wants_no_science(pplayer)) {
+ v += (100 + amount) * pcity->science_total * ai->science_priority /
200;
+ v += (100 + amount) * c * ai->science_priority / 400;
+ }
+ break;
+ case EFT_TAX_BONUS:
+ if (!ai_wants_no_science(pplayer)) {
+ /* Increase gold income so that we can lower taxes and research more */
+ v += (pplayer->economic.tax * 2 + amount) * pcity->tax_total
+ * ai->gold_priority / 200;
+ v += (pplayer->economic.tax * 2 + amount) * c * ai->gold_priority /
400;
+ } else {
+ v += (100 + amount) * pcity->tax_total * ai->gold_priority / 400;
+ v += (100 + amount) * c * ai->gold_priority / 800;
+ }
+ break;
+ case EFT_HALVE_CORRUPTION:
+ v += (pcity->corruption / 2)
+ * MAX(ai->science_priority, ai->gold_priority);
+ v += c * MAX(ai->science_priority, ai->gold_priority) / 10;
+ break;
+ case EFT_HALVE_WASTE:
+ v += (pcity->shield_waste / 2) * ai->shield_priority;
+ v += c * ai->shield_priority / 10;
+ break;
+
+ /* Special cased effects */
+ case EFT_ADV_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_ADV:
+ *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_UNIT_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_ONE_LEAP:
+ *v += 5 * c + ai->stats.units[UCL_LAST] * 2;
+ break;
+ case EFT_UPGRADE_ALL_LEAP:
+ *v += 5 * c + ai->stats.units[UCL_LAST] * 4;
+ break;
+ case EFT_SEA_DEFEND:
+ if (ai_handicap(pplayer, H_DEFENSIVE)) {
+ v += amount * 10; /* make AI slow */
+ }
+ v += ai->threats.sea ? 8 * amount : amount; /* for single city */
+ v += (amount + ai->threats.sea - 1) * c; /* for wonder */
+ if (capital) {
+ 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_SPY_UNBRIBABLE:
+ 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;
+ default:
+ freelog(LOG_ERROR, "AI does not recognize effect type %d", *peff_type);
+ assert(FALSE); /* add me! */
+ break;
+ }
+ } eff_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));
}
- return i;
+ /* Adjust by building cost */
+ *v -= pimpr->build_cost / (pcity->shield_surplus * 10 + 1);
}
/**************************************************************************
-...
+ 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;
+#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
+ || (is_wonder(id) && pcity->shield_surplus <= 2)
+ || !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;
}
/***************************************************************************
@@ -295,8 +527,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_improvement)) {
+ pcity->ai.choice.choice = game.default_improvement;
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);
@@ -354,7 +586,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)
+ && (get_city_building_bonus(pcity, id, EFT_LAND_DEFEND) <= 0)) {
/* selling walls to buy defenders is counterproductive -- Syela */
really_handle_city_sell(pplayer, pcity, id);
break;
@@ -487,7 +720,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)
&& pcity->size == 1
&& city_granary_size(pcity->size)
> pcity->food_stock + pcity->food_surplus) {
@@ -630,7 +863,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));
}
/**************************************************************************
@@ -642,7 +875,8 @@
built_impr_iterate(pcity, i) {
if(!is_wonder(i)
- && i != B_CITY /* selling city walls is really, really dumb -- Syela */
+ && (get_city_building_bonus(pcity, i, EFT_LAND_DEFEND) <= 0)
+ /* selling city walls is really, really dumb -- Syela */
&& (wonder_replacement(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,
Index: ai/aicity.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.h,v
retrieving revision 1.22
diff -u -r1.22 aicity.h
--- ai/aicity.h 24 May 2004 02:09:27 -0000 1.22
+++ ai/aicity.h 7 Jul 2004 09:56:40 -0000
@@ -14,19 +14,39 @@
#define FC__AICITY_H
#include "unit.h" /* enum unit_move_type */
+#include "city.h"
+#include "aidata.h"
struct player;
-struct city;
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);
Unit_Type_id ai_choose_defender_versus(struct city *pcity, Unit_Type_id v);
-enum ai_city_task { AICITY_NONE, AICITY_TECH, AICITY_TAX, AICITY_PROD};
-/* These are not used (well, except AICITY_NONE) --dwp */
+/**************************************************************************
+ This calculates the usefulness of pcity to us. Note that you can pass
+ another player's ai_data structure here for evaluation by different
+ priorities.
+**************************************************************************/
+static inline int ai_eval_calc_city(struct city *pcity, struct ai_data *ai)
+{
+ int i = (pcity->food_surplus * ai->food_priority
+ + pcity->shield_surplus * ai->shield_priority
+ + pcity->luxury_total * ai->luxury_priority
+ + pcity->tax_total * ai->gold_priority
+ + pcity->science_total * ai->science_priority
+ + pcity->ppl_happy[4] * ai->happy_priority
+ - 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);
+ }
+
+ return i;
+}
#endif /* FC__AICITY_H */
Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.29
diff -u -r1.29 aidata.c
--- ai/aidata.c 25 Jun 2004 23:43:00 -0000 1.29
+++ ai/aidata.c 7 Jul 2004 09:56:40 -0000
@@ -17,6 +17,7 @@
#include "aisupport.h"
#include "city.h"
+#include "effects.h"
#include "game.h"
#include "government.h"
#include "log.h"
@@ -60,10 +61,14 @@
struct ai_data *ai = &aidata[pplayer->player_no];
int i, nuke_units = num_role_units(F_NUCLEAR);
bool danger_of_nukes = FALSE;
- bool can_build_antisea = can_player_build_improvement(pplayer, B_COASTAL);
- bool can_build_antiair = can_player_build_improvement(pplayer, B_SAM);
- bool can_build_antinuke = can_player_build_improvement(pplayer, B_SDI);
- bool can_build_antimissile = can_player_build_improvement(pplayer, B_SDI);
+ bool can_build_antisea =
+ (find_source_improvement(pplayer, EFT_SEA_DEFEND) != B_LAST);
+ bool can_build_antiair =
+ (find_source_improvement(pplayer, EFT_AIR_DEFEND) != B_LAST);
+ bool can_build_antimissile =
+ (find_source_improvement(pplayer, EFT_MISSILE_DEFEND) != B_LAST);
+ bool can_build_antinuke =
+ (find_source_improvement(pplayer, EFT_NUKE_PROOF) != B_LAST);
int ally_strength = -1;
struct player *ally_strongest = NULL;
@@ -75,6 +80,7 @@
ai->threats.air = FALSE;
ai->threats.nuclear = 0; /* none */
ai->threats.sea = FALSE;
+ ai->threats.igwall = FALSE;
players_iterate(aplayer) {
if (!is_player_dangerous(pplayer, aplayer)) {
@@ -91,6 +97,10 @@
} 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. */
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.13
diff -u -r1.13 aidata.h
--- ai/aidata.h 20 Jun 2004 07:41:14 -0000 1.13
+++ ai/aidata.h 7 Jul 2004 09:56:40 -0000
@@ -77,6 +77,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 */
@@ -89,6 +90,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 */
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.36
diff -u -r1.36 aidiplomat.c
--- ai/aidiplomat.c 25 Jun 2004 23:43:00 -0000 1.36
+++ ai/aidiplomat.c 7 Jul 2004 09:56:40 -0000
@@ -67,7 +67,7 @@
int count = 0;
built_impr_iterate(pcity, index) {
- if (!is_wonder(index) && index != B_PALACE) {
+ if (get_improvement_type(index)->sabotage > 0) {
count++;
}
} built_impr_iterate_end;
@@ -174,7 +174,7 @@
}
incite_cost = city_incite_cost(pplayer, acity);
if (HOSTILE_PLAYER(pplayer, ai, city_owner(acity))
- && !city_got_building(acity, B_PALACE)
+ && !get_city_bonus(acity, EFT_SPY_UNBRIBABLE)
&& !government_has_flag(get_gov_pplayer(city_owner(acity)),
G_UNBRIBABLE)
&& (incite_cost <
@@ -346,7 +346,7 @@
continue;
}
- can_incite = !(city_got_building(acity, B_PALACE)
+ can_incite = !(get_city_bonus(acity, EFT_SPY_UNBRIBABLE)
|| government_has_flag(get_gov_pplayer(aplayer),
G_UNBRIBABLE));
Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.89
diff -u -r1.89 aihand.c
--- ai/aihand.c 7 Jul 2004 07:32:03 -0000 1.89
+++ ai/aihand.c 7 Jul 2004 09:56:40 -0000
@@ -170,10 +170,7 @@
if (cmr.found_a_valid
&& pcity->food_surplus > 0
&& pcity->size >= g->rapture_size
- && (pcity->size < game.aqueduct_size
- || city_got_building(pcity, B_AQUEDUCT))
- && (pcity->size < game.sewer_size
- || city_got_building(pcity, B_SEWER))) {
+ && city_can_grow_to(pcity, pcity->size + 1)) {
pcity->ai.celebrate = TRUE;
can_celebrate++;
} else {
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.114
diff -u -r1.114 aitools.c
--- ai/aitools.c 7 Jul 2004 07:32:03 -0000 1.114
+++ ai/aitools.c 7 Jul 2004 09:56:40 -0000
@@ -760,8 +760,6 @@
struct government *g)
{
int free_happy;
- bool have_police;
- int variant;
int unhap = 0;
/* bail out now if happy_cost is 0 */
@@ -770,14 +768,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);
@@ -797,7 +791,7 @@
continue;
}
- if (variant == 1 && have_police) {
+ if (get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL_PER)) {
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.321
diff -u -r1.321 aiunit.c
--- ai/aiunit.c 25 Jun 2004 23:43:01 -0000 1.321
+++ ai/aiunit.c 7 Jul 2004 09:56:41 -0000
@@ -371,7 +371,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))) {
return FALSE;
} else {
return TRUE;
@@ -2031,14 +2031,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)) {
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)) {
cur /= 3;
}
}
- [Freeciv-Dev] Re: (PR#8754) effects patch, Jason Short, 2004/07/06
- [Freeciv-Dev] Re: (PR#8754) effects patch, Mike Kaufman, 2004/07/06
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/07/06
- [Freeciv-Dev] (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/07/06
- [Freeciv-Dev] Re: (PR#8754) effects patch, Jason Short, 2004/07/06
- [Freeciv-Dev] Re: (PR#8754) effects patch, Per Inge Mathisen, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Per Inge Mathisen, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch,
Per Inge Mathisen <=
- [Freeciv-Dev] Re: (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Jason Short, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Per Inge Mathisen, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Mike Kaufman, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Jason Short, 2004/07/07
- [Freeciv-Dev] Re: (PR#8754) effects patch, Vasco Alexandre da Silva Costa, 2004/07/07
|
|