[Freeciv-Dev] Re: (PR#2521) 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=2521 >
I updated the effects patch. It's a bit smaller now. I didn't really
edit it at all although I was tempted. Nor have I tested the new patch.
I had some problems with the AI part. I fixed it enough to get it to
compile. Per, will you search the patch for "#if 0" and for "ocean[1]"
and see what needs to be changed there?
jason
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 1 Sep 2004 01:53:02 -0000
@@ -39,6 +39,7 @@
#include "advdomestic.h"
+#if 0 /* FIXME */
/**************************************************************************
Calculate desire for land defense. First look for potentially hostile
cities on our continent, indicating danger of being attacked by land.
@@ -915,6 +916,7 @@
return;
}
+#endif
/***************************************************************************
* Evaluate the need for units (like caravans) that aid wonder construction.
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 1 Sep 2004 01:53: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.171
diff -u -r1.171 advmilitary.c
--- ai/advmilitary.c 29 Aug 2004 20:14:41 -0000 1.171
+++ ai/advmilitary.c 1 Sep 2004 01:53:02 -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_DEFEND)) {
+ danger /= 2;
+ }
+ if (is_air_unit(punit) && get_city_bonus(pcity, EFT_AIR_DEFEND)) {
+ danger /= 2;
+ }
return danger;
}
@@ -413,7 +417,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;
@@ -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_building(pplayer, EFT_LAND_DEFEND);
+ defender[1] = find_source_building(pplayer, EFT_SEA_DEFEND);
+ defender[2] = find_source_building(pplayer, EFT_AIR_DEFEND);
+ defender[3] = 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;
@@ -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_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. */
@@ -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_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 = 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 = 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;
@@ -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_building(pplayer, EFT_LAND_DEFEND);
+ sea_id = find_source_building(pplayer, EFT_SEA_DEFEND);
+ air_id = 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;
}
@@ -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.160
diff -u -r1.160 aicity.c
--- ai/aicity.c 13 Aug 2004 15:59:11 -0000 1.160
+++ ai/aicity.c 1 Sep 2004 01:53:02 -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,363 @@
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 = 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);
+
+ if (building_has_effect(id, EFT_CAPITAL_CITY)) {
+ pcity->ai.building_want[id] = 0;
+ return;
}
- return i;
+ /* 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. */
+ eft_vector_iterate(get_building_effect_types(id), ptype) {
+ eff_list_iterate(*get_building_effects(id, *ptype), peff) {
+
+ if (eff_eventually_active(TARGET_BUILDING, pplayer, pcity, id,
+ NULL, id, peff)) {
+ int amount = peff->value, c = cities[peff->range];
+
+ switch (*ptype) {
+ /* 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_INCITE_DIST_ADJ:
+ case EFT_INCITE_DIST_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:
+ case EFT_LUXURY_BONUS:
+ case EFT_UNIT_RECOVER:
+ case EFT_CAPITAL_CITY:
+ case EFT_FOOD_BONUS:
+ case EFT_FOOD_PCT:
+ case EFT_FOOD_INC_TILE:
+ case EFT_FORCE_CONTENT_PCT:
+ case EFT_LUXURY_PCT:
+ case EFT_MAKE_CONTENT_PCT:
+ case EFT_POLLU_ADJ:
+ case EFT_POLLU_PCT:
+ case EFT_POLLU_POP_ADJ:
+ case EFT_POLLU_PROD_ADJ:
+ case EFT_PROD_PCT:
+ case EFT_PROD_INC_TILE:
+ case EFT_PROD_PER_TILE:
+ case EFT_SCIENCE_PCT:
+ case EFT_SPACE_PART:
+ case EFT_TAX_PCT:
+ case EFT_TRADE_ADD_TILE:
+ case EFT_TRADE_BONUS:
+ case EFT_TRADE_PCT:
+ case EFT_UPGRADE_ONE_STEP:
+ case EFT_UPGRADE_ALL_STEP:
+ case EFT_SEA_VET_COMBAT:
+ case EFT_AIR_VET_COMBAT:
+ case EFT_NO_UPKEEP:
+ /* 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_CORRUPT_PCT:
+ v += (pcity->corruption / 2)
+ * MAX(ai->science_priority, ai->gold_priority);
+ v += c * MAX(ai->science_priority, ai->gold_priority) / 10;
+ break;
+ case EFT_WASTE_PCT:
+ v += (pcity->shield_waste / 2) * ai->shield_priority;
+ v += c * ai->shield_priority / 10;
+ break;
+
+ /* Special cased effects */
+ 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_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 */
+ }
+ /* FIXME: use of ocean[1] here is wrong. We need to calculate
+ * the right ocean(s) for this city, and figure out how to
+ * handle the multiple-city case. */
+ v += ai->threats.ocean[1] ? 8 * amount : amount; /* for single
city */
+ v += (amount + ai->threats.ocean[1] - 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_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;
+ }
+ }
+
+ } eff_list_iterate_end;
+ } eft_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 +547,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 +606,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 +740,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) {
@@ -633,7 +885,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));
}
/**************************************************************************
@@ -645,8 +897,10 @@
built_impr_iterate(pcity, i) {
if(!is_wonder(i)
- && 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))) {
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.22
diff -u -r1.22 aicity.h
--- ai/aicity.h 24 May 2004 02:09:27 -0000 1.22
+++ ai/aicity.h 1 Sep 2004 01:53:03 -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.36
diff -u -r1.36 aidata.c
--- ai/aidata.c 30 Aug 2004 21:20:33 -0000 1.36
+++ ai/aidata.c 1 Sep 2004 01:53:03 -0000
@@ -17,6 +17,7 @@
#include "aisupport.h"
#include "city.h"
+#include "effects.h"
#include "game.h"
#include "government.h"
#include "log.h"
@@ -59,6 +60,16 @@
struct ai_data *ai = &aidata[pplayer->player_no];
int i, nuke_units = num_role_units(F_NUCLEAR);
bool danger_of_nukes = FALSE;
+#if 0 /* FIXME */
+ bool can_build_antisea =
+ (find_source_building(pplayer, EFT_SEA_DEFEND) != B_LAST);
+ bool can_build_antiair =
+ (find_source_building(pplayer, EFT_AIR_DEFEND) != B_LAST);
+ bool can_build_antimissile =
+ (find_source_building(pplayer, EFT_MISSILE_DEFEND) != B_LAST);
+ bool can_build_antinuke =
+ (find_source_building(pplayer, EFT_NUKE_PROOF) != B_LAST);
+#endif
int ally_strength = -1;
struct player *ally_strongest = NULL;
@@ -71,6 +82,7 @@
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)) {
@@ -87,6 +99,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.15
diff -u -r1.15 aidata.h
--- ai/aidata.h 29 Aug 2004 19:43:37 -0000 1.15
+++ ai/aidata.h 1 Sep 2004 01:53:03 -0000
@@ -76,6 +76,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.38
diff -u -r1.38 aidiplomat.c
--- ai/aidiplomat.c 29 Aug 2004 17:54:13 -0000 1.38
+++ ai/aidiplomat.c 1 Sep 2004 01:53: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 1 Sep 2004 01:53:03 -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))) {
return FALSE;
} else {
return TRUE;
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.121
diff -u -r1.121 aitools.c
--- ai/aitools.c 31 Aug 2004 15:35:31 -0000 1.121
+++ ai/aitools.c 1 Sep 2004 01:53:03 -0000
@@ -792,8 +792,6 @@
struct government *g)
{
int free_happy;
- bool have_police;
- int variant;
int unhap = 0;
/* bail out now if happy_cost is 0 */
@@ -802,14 +800,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);
@@ -829,7 +823,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.332
diff -u -r1.332 aiunit.c
--- ai/aiunit.c 31 Aug 2004 18:21:09 -0000 1.332
+++ ai/aiunit.c 1 Sep 2004 01:53:04 -0000
@@ -1720,14 +1720,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;
}
}
Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.43
diff -u -r1.43 citydlg_common.c
--- client/citydlg_common.c 28 Aug 2004 19:15:39 -0000 1.43
+++ client/citydlg_common.c 1 Sep 2004 01:53:04 -0000
@@ -281,7 +281,7 @@
int id, bool is_unit,
struct city *pcity)
{
- if (!is_unit && id == B_CAPITAL) {
+ if (!is_unit && building_has_effect(id, EFT_PROD_TO_GOLD)) {
my_snprintf(buffer, buffer_len, _("%s (XX) %d/turn"),
get_impr_name_ex(pcity, id), MAX(0, pcity->shield_surplus));
} else {
@@ -333,7 +333,7 @@
my_snprintf(buf[2], column_size, "%d", unit_build_shield_cost(id));
} else {
/* Total & turns left meaningless on capitalization */
- if (id == B_CAPITAL) {
+ if (building_has_effect(id, EFT_PROD_TO_GOLD)) {
my_snprintf(buf[0], column_size, get_improvement_type(id)->name);
buf[1][0] = '\0';
my_snprintf(buf[2], column_size, "---");
@@ -341,7 +341,7 @@
my_snprintf(buf[0], column_size, get_improvement_type(id)->name);
/* from city.c get_impr_name_ex() */
- if (pcity && wonder_replacement(pcity, id)) {
+ if (pcity && building_replaced(pcity, id)) {
my_snprintf(buf[1], column_size, "*");
} else {
const char *state = "";
@@ -365,7 +365,7 @@
/* Add the turns-to-build entry in the 4th position */
if (pcity) {
- if (!is_unit && id == B_CAPITAL) {
+ if (!is_unit && building_has_effect(id, EFT_PROD_TO_GOLD)) {
my_snprintf(buf[3], column_size, _("%d/turn"),
MAX(0, pcity->shield_surplus));
} else {
Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.136
diff -u -r1.136 climisc.c
--- client/climisc.c 28 Aug 2004 19:15:39 -0000 1.136
+++ client/climisc.c 1 Sep 2004 01:53:04 -0000
@@ -559,7 +559,7 @@
struct items and also sort it.
section 0: normal buildings
- section 1: B_CAPITAL
+ section 1: Capitalization
section 2: F_NONMIL units
section 3: other units
section 4: wonders
@@ -583,7 +583,7 @@
pitem->section = unit_type_flag(id, F_NONMIL) ? 2 : 3;
} else {
name = get_impr_name_ex(pcity, id);
- if (id == B_CAPITAL) {
+ if (building_has_effect(id, EFT_PROD_TO_GOLD)) {
cost = -1;
pitem->section = 1;
} else {
@@ -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.73
diff -u -r1.73 helpdata.c
--- client/helpdata.c 31 Aug 2004 04:40:48 -0000 1.73
+++ client/helpdata.c 1 Sep 2004 01:53:04 -0000
@@ -533,7 +533,8 @@
assert(buf&&user_text);
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) {
int u, t;
u = get_role_unit(F_NUCLEAR, 0);
assert(u<game.num_unit_types);
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 1 Sep 2004 01:53: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 eff_group *pgroup;
+ int i;
+
+ pgroup = eff_group_new(packet->name);
+
+ for (i = 0; i < packet->num_elements; i++) {
+ eff_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/repodlgs_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/repodlgs_common.c,v
retrieving revision 1.12
diff -u -r1.12 repodlgs_common.c
--- client/repodlgs_common.c 29 Aug 2004 12:36:12 -0000 1.12
+++ client/repodlgs_common.c 1 Sep 2004 01:53:05 -0000
@@ -321,7 +321,7 @@
if (!pcity->did_sell && city_got_building(pcity, impr)
&& (!obsolete_only
|| improvement_obsolete(game.player_ptr, impr)
- || wonder_replacement(pcity, impr))) {
+ || building_replaced(pcity, impr))) {
count++;
gold += impr_sell_gold(impr);
city_sell_improvement(pcity, impr);
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 1 Sep 2004 01:53:05 -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: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.239
diff -u -r1.239 city.c
--- common/city.c 31 Aug 2004 04:40:50 -0000 1.239
+++ common/city.c 1 Sep 2004 01:53:06 -0000
@@ -263,54 +263,6 @@
}
/**************************************************************************
- FIXME: This should be replaced in the near future with
- improvment_redundant()
-**************************************************************************/
-bool wonder_replacement(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,14 @@
}
/**************************************************************************
- 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)) {
+ struct impr_type *impr;
+
+ if (!can_player_build_improvement_direct(city_owner(pcity), id)) {
return FALSE;
}
@@ -413,24 +366,7 @@
return FALSE;
}
- if (!city_has_terr_spec_gate(pcity,id)) {
- return FALSE;
- }
-
- return !improvement_redundant(city_owner(pcity),pcity, id, TRUE);
-}
-
-/**************************************************************************
- Could this improvment be built in the city, without checking if the
- owner has the required tech, but if all other pre reqs are fulfiled?
- modularized so the AI can choose the tech it wants -- Syela
-**************************************************************************/
-static bool could_build_improvement(const struct city *pcity,
- Impr_Type_id id)
-{
- struct impr_type *impr;
-
- if (!can_eventually_build_improvement(pcity, id)) {
+ if (!city_has_terr_spec_gate(pcity, id)) {
return FALSE;
}
@@ -438,7 +374,7 @@
/* The building pre req */
if (impr->bldg_req != B_LAST) {
- if (!city_got_building(pcity,impr->bldg_req)) {
+ if (!city_got_building(pcity, impr->bldg_req)) {
return FALSE;
}
}
@@ -447,19 +383,37 @@
}
/**************************************************************************
- Can this improvement get built in this city by the player who owns it?
+ Return whether given city can build given unit; returns 0 if unit is
+ obsolete.
**************************************************************************/
bool can_build_improvement(const struct city *pcity, Impr_Type_id id)
-{
- struct player *p = city_owner(pcity);
+{
+ if (!can_build_improvement_direct(pcity, id)) {
+ return FALSE;
+ }
+ if (improvement_obsolete(city_owner(pcity), id)) {
+ return FALSE;
+ }
+ return TRUE;
+}
- if (!improvement_exists(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;
}
- if (!player_knows_improvement_tech(p, id)) {
+
+ if (!city_has_terr_spec_gate(pcity, id)) {
return FALSE;
}
- return could_build_improvement(pcity, id);
+
+ return TRUE;
}
/**************************************************************************
@@ -565,11 +519,10 @@
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)) {
return 0;
}
@@ -587,6 +540,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)) {
@@ -610,17 +564,14 @@
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 */
if (s > 0) {
s += (is_celebrating ? g->celeb_shield_bonus : g->shield_bonus);
+ s += get_city_tile_bonus(pcity, ptile, EFT_PROD_INC_TILE);
}
+
if (before_penalty > 0 && s > before_penalty) {
s--;
}
@@ -692,6 +643,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)) {
@@ -705,50 +657,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);
}
@@ -806,36 +754,43 @@
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;
+ /* create dummy tile which has the city center bonuses. */
+ tile.terrain = tile_t;
+ tile.special = spec_t;
+
+ if (auto_water) {
+ /* The center tile is auto-irrigated. */
+ tile.special |= S_IRRIGATION;
+
+ if (player_knows_techs_with_flag(city_owner(pcity), TF_FARMLAND)) {
+ tile.special |= S_FARMLAND;
+ }
+ }
+
+ 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 = get_tile_type(tile_t)->food;
+ f = type->food;
}
- if (contains_special(spec_t, S_IRRIGATION) || auto_water) {
- /* The center tile is auto-irrigated. */
+ if (contains_special(tile.special, S_IRRIGATION)) {
f += type->irrigation_food_incr;
+ }
- /* 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;
- }
+ /* Farmland only affects cities with supermarkets. */
+ if (pcity) {
+ f += (f * get_city_tile_bonus(pcity, &tile, EFT_FOOD_PER_TILE)) / 100;
}
- if (contains_special(spec_t, S_RAILROAD)) {
+ if (contains_special(tile.special, S_RAILROAD)) {
f += (f * terrain_control.rail_food_bonus) / 100;
}
@@ -844,23 +799,23 @@
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);
}
+
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;
}
@@ -1123,22 +1078,12 @@
}
/**************************************************************************
- 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) || wonder_replacement(pcity, id);
-}
-
-/**************************************************************************
Return TRUE iff this city is its nation's capital. The capital city is
special-cased in a number of ways.
**************************************************************************/
bool is_capital(const struct city *pcity)
{
- return city_got_building(pcity, B_PALACE);
+ return (get_city_bonus(pcity, EFT_CAPITAL_CITY) != 0);
}
/**************************************************************************
@@ -1146,80 +1091,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);
}
/**************************************************************************
@@ -1560,10 +1432,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)) {
+ return TRUE;
+ } else {
+ int max_size;
+
+ max_size = game.aqueduct_size + get_city_bonus(pcity, EFT_SIZE_ADJ);
+ return (pop_size <= max_size);
+ }
}
/**************************************************************************
@@ -1706,23 +1582,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));
}
/**************************************************************************
@@ -1730,19 +1590,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));
}
/**************************************************************************
@@ -1750,8 +1598,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));
}
/**************************************************************************
@@ -1767,16 +1614,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;
}
@@ -1786,23 +1625,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;
}
@@ -1880,6 +1706,7 @@
/* 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);
@@ -2012,21 +1839,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) {
@@ -2046,14 +1863,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]++;
@@ -2062,10 +1878,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]--;
@@ -2078,7 +1893,7 @@
bonus--;
}
- if (city_affected_by_wonder(pcity, B_SHAKESPEARE)) {
+ if (get_city_bonus(pcity, EFT_NO_UNHAPPY)) {
pcity->ppl_content[4] += pcity->ppl_unhappy[4] + pcity->ppl_angry[4];
pcity->ppl_unhappy[4] = 0;
pcity->ppl_angry[4] = 0;
@@ -2110,22 +1925,22 @@
static inline void set_pollution(struct city *pcity)
{
struct player *pplayer = city_owner(pcity);
+ int mod;
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) {
+ pcity->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;
+
+ pcity->pollution += mod;
+
pcity->pollution = MAX(0, pcity->pollution - 20);
}
@@ -2187,18 +2002,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);
@@ -2270,7 +2080,7 @@
happy_cost = 0;
}
}
- if (happy_cost > 0 && variant == 1 && have_police) {
+ if (happy_cost > 0 && get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL_PER)) {
happy_cost--;
}
@@ -2415,10 +2225,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;
@@ -2454,10 +2261,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;
}
@@ -2477,49 +2282,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.
@@ -2657,7 +2419,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;
@@ -2692,6 +2454,7 @@
pcity->shield_bonus = 100;
pcity->luxury_bonus = 100;
pcity->tax_bonus = 100;
+ pcity->luxury_bonus = 100;
pcity->science_bonus = 100;
pcity->client.occupied = FALSE;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.157
diff -u -r1.157 city.h
--- common/city.h 14 Aug 2004 21:29:43 -0000 1.157
+++ common/city.h 1 Sep 2004 01:53:06 -0000
@@ -209,6 +209,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 {
@@ -257,7 +260,7 @@
int currently_building;
Impr_Status improvements[B_LAST];
-
+
struct worklist worklist;
enum city_tile_type city_map[CITY_MAP_SIZE][CITY_MAP_SIZE];
@@ -361,18 +364,17 @@
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 wonder_replacement(const struct city *pcity, Impr_Type_id id);
int city_change_production_penalty(const struct city *pcity,
int target, bool is_unit);
int city_turns_to_build(const struct city *pcity, int id, bool id_is_unit,
@@ -486,9 +488,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);
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 1 Sep 2004 01:53:06 -0000
@@ -301,9 +301,9 @@
**************************************************************************/
bool unit_really_ignores_citywalls(struct unit *punit)
{
- return unit_ignores_citywalls(punit)
+ return (unit_ignores_citywalls(punit)
|| is_air_unit(punit)
- || (is_sailing_unit(punit) && !(improvement_variant(B_CITY)==1));
+ || is_sailing_unit(punit));
}
/**************************************************************************
@@ -322,7 +322,7 @@
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)) return pcity;
} square_iterate_end;
return NULL;
@@ -406,6 +406,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 +420,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))) {
+ defensepower *= mod;
}
- if (city_got_building(pcity, B_SDI)
+ if ((mod = get_city_bonus(pcity, EFT_MISSILE_DEFEND))
&& unit_type_flag(att_type, F_MISSILE)) {
- defensepower *= 2;
+ defensepower *= mod;
}
} 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))) {
+ defensepower *= mod;
}
}
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))) {
+ defensepower *= mod;
}
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.11
diff -u -r1.11 dataio.c
--- common/dataio.c 2 Jun 2004 19:47:41 -0000 1.11
+++ common/dataio.c 1 Sep 2004 01:53:06 -0000
@@ -712,32 +712,3 @@
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_uint8(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_uint8(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 1 Sep 2004 01:53:06 -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.6
diff -u -r1.6 effects.c
--- common/effects.c 28 Aug 2004 19:15:39 -0000 1.6
+++ common/effects.c 1 Sep 2004 01:53:06 -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",
"Space_Part",
"Spy_Resistant",
"Tax_Bonus",
@@ -107,24 +102,34 @@
"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"
+ "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",
+ "SS_Structural",
+ "SS_Component",
+ "SS_Module",
+ "No_Incite"
};
/**************************************************************************
@@ -194,44 +199,877 @@
}
/**************************************************************************
- Return TRUE iff the two effects are equal.
+ 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.
**************************************************************************/
-bool are_effects_equal(const struct impr_effect *const peff1,
- const struct impr_effect *const peff2)
+
+static const char *req_type_names[] = {
+ "None",
+ "Tech",
+ "Gov",
+ "Building",
+ "Special",
+ "Terrain"
+};
+
+struct eff_group_element {
+ Impr_Type_id improvement;
+ enum effect_range range;
+ bool survives;
+};
+
+#define SPECLIST_TAG eff_group_element
+#define SPECLIST_TYPE struct eff_group_element
+#include "speclist.h"
+
+#define eff_group_element_list_iterate(list, elt) \
+TYPED_LIST_ITERATE(struct eff_group_element, list, elt)
+#define eff_group_element_list_iterate_end LIST_ITERATE_END
+
+struct eff_group {
+ char *name;
+ int id;
+ struct eff_group_element_list elements;
+};
+
+#define SPECLIST_TAG eff_group
+#define SPECLIST_TYPE struct eff_group
+#include "speclist.h"
+
+#define eff_group_list_iterate(list, pgroup) \
+TYPED_LIST_ITERATE(struct eff_group, list, pgroup)
+#define eff_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 {
+ struct building_vector buildings;
+ struct eff_list buckets[B_LAST];
+ } effs[EFT_LAST];
+
+ struct {
+ struct eft_vector types;
+ } buildings[B_LAST];
+
+} ruleset_cache;
+
+static struct eff_group_list groups;
+static int groups_id;
+
+
+/**************************************************************************
+ Wrappers for access to ruleset cache data.
+**************************************************************************/
+
+/**************************************************************************
+ Get a vector of buildings which grant the effect type.
+**************************************************************************/
+static inline struct building_vector *get_buildings_with_effect(
+ enum effect_type eff)
{
-#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;
+ return &ruleset_cache.effs[eff].buildings;
}
/**************************************************************************
- 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.
+ Get a list of effects of a type granted by a building.
**************************************************************************/
-int get_current_construction_bonus(const struct city *pcity,
- enum effect_type effect)
+inline struct eff_list *get_building_effects(Impr_Type_id id,
+ enum effect_type eff)
{
- if (effect == EFT_PROD_TO_GOLD) {
- return (!pcity->is_building_unit
- && pcity->currently_building == B_CAPITAL) ? 1 : 0;
+ return &ruleset_cache.effs[eff].buckets[id];
+}
+
+/**************************************************************************
+ Get a vector of effects types granted by a building.
+**************************************************************************/
+struct eft_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 eff_group *eff_group_new(const char *name)
+{
+ struct eff_group *group;
+
+ group = fc_malloc(sizeof(*group));
+ group->name = mystrdup(name);
+ group->id = groups_id++;
+ eff_group_element_list_init(&group->elements);
+
+ eff_group_list_insert_back(&groups, group);
+ return group;
+}
+
+/**************************************************************************
+ Add a new building to an existing effects group.
+**************************************************************************/
+void eff_group_add(struct eff_group *group, Impr_Type_id id,
+ enum effect_range range, bool survives)
+{
+ struct eff_group_element *elt;
+
+ elt = fc_malloc(sizeof(*elt));
+ elt->improvement = id;
+ elt->range = range;
+ elt->survives = survives;
+
+ eff_group_element_list_insert_back(&group->elements, elt);
+}
+
+/**************************************************************************
+ Find the id of an effects group by name.
+**************************************************************************/
+int find_eff_group(const char *name)
+{
+ int i = 0;
+
+ eff_group_list_iterate(groups, pgroup) {
+ if (0 == strcasecmp(pgroup->name, name)) {
+ return i;
+ }
+ i++;
+ } eff_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);
+
+ eff_group_list_init(&groups);
+ groups_id = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ruleset_cache.buildings); i++) {
+ eft_vector_init(get_building_effect_types(i));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ruleset_cache.effs); i++) {
+ building_vector_init(get_buildings_with_effect(i));
+
+ for (j = 0; j < ARRAY_SIZE(ruleset_cache.effs[i].buckets); j++) {
+ eff_list_init(get_building_effects(j, i));
+ }
+ }
+}
+
+/**************************************************************************
+ Parse effect requirement.
+**************************************************************************/
+int parse_req(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 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;
+ }
+
+ eff_list_insert_back(get_building_effects(id, eff), peff);
+
+ if (group >= 0) {
+ peff->group = eff_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 eft_vector *vec;
+ bool exists = FALSE;
+
+ vec = get_building_effect_types(id);
+
+ eft_vector_iterate(vec, ptype) {
+ if (*ptype == eff) {
+ exists = TRUE;
+ break;
+ }
+ } eft_vector_iterate_end;
+
+ if (!exists) {
+ eft_vector_append(vec, &eff);
+ }
+ }
+}
+
+/**************************************************************************
+ Send the ruleset cache groups data.
+**************************************************************************/
+static void send_ruleset_cache_groups(struct conn_list *dest)
+{
+ struct packet_ruleset_cache_group packet;
+ int i;
+
+ eff_group_list_iterate(groups, pgroup) {
+ sz_strlcpy(packet.name, pgroup->name);
+
+ packet.num_elements = eff_group_element_list_size(&pgroup->elements);
+ for (i = 0; i < packet.num_elements; i++) {
+ struct eff_group_element *elt;
+
+ elt = eff_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);
+ } eff_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;
+
+ eff_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);
+ } eff_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.
+**************************************************************************/
+Impr_Type_id find_source_building(struct player *plr, enum effect_type eff)
+{
+ /* FIXME: this just returns the first building. it should return the best
+ * building instead. */
+ building_vector_iterate(get_buildings_with_effect(eff), 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;
+}
+
+/**************************************************************************
+ Can the building grant this effect?
+**************************************************************************/
+bool building_has_effect(Impr_Type_id id, enum effect_type eff)
+{
+ return (eff_list_size(get_building_effects(id, eff)) > 0);
+}
+
+/**************************************************************************
+ Returns the number of surviving world buildings.
+**************************************************************************/
+static int num_surviving_buildings(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 buildings of a certain type in a continent.
+**************************************************************************/
+static int num_continent_buildings(const struct player *plr, int continent,
+ Impr_Type_id id)
+{
+ if (is_wonder(id)) {
+ struct city *tmp;
+
+ 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 inline 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 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_surviving_buildings(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
+ (i.e. are its effects replaced by other sources in the group)?
+**************************************************************************/
+static bool eff_redundant(enum target_type target,
+ const struct player *plr,
+ const struct city *pcity,
+ Impr_Type_id id,
+ Impr_Type_id source,
+ const struct effect *eff)
+{
+ if (eff->group) {
+ /* got more than one building in the same equiv group?
+ * first in the group that exists wins. */
+ eff_group_element_list_iterate(eff->group->elements, elt) {
+ if (elt->improvement == source) {
+ return FALSE;
+ } else {
+ if (targets_in_range(target, plr, pcity, id, elt->range, elt->survives,
+ elt->improvement) > 0) {
+ return TRUE;
+ }
+ }
+ } eff_group_element_list_iterate_end;
+ }
+ return FALSE;
+}
+
+/**************************************************************************
+ Are the effect requirements active?
+**************************************************************************/
+static bool eff_reqs_active(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 active = FALSE;
+
+ switch (eff->req.type) {
+ case REQ_NONE:
+ active = TRUE;
+ break;
+ case REQ_TECH:
+ active = plr && player_knows_tech(plr, eff->req.value.tech);
+ break;
+ case REQ_GOV:
+ active = plr && (plr->government == eff->req.value.gov);
+ break;
+ case REQ_BUILDING:
+ active = (targets_in_range(target, plr, pcity, id, EFR_CITY,
+ FALSE, eff->req.value.building) > 0);
+ break;
+ case REQ_SPECIAL:
+ active = ptile && tile_has_special(ptile, eff->req.value.special);
+ break;
+ case REQ_TERRAIN:
+ active = ptile && (ptile->terrain == eff->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 deps.
+**************************************************************************/
+bool eff_eventually_active(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)
+{
+ if (eff_redundant(target, plr, pcity, id, source, eff)) {
+ return FALSE;
+ }
+ return (eff_reqs_active(target, plr, pcity, id, ptile, source, eff));
+}
+
+/**************************************************************************
+ Is the effect from the source building active at a certain target (player,
+ city or building)?
+**************************************************************************/
+static inline bool eff_active(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)
+{
+ if (targets_in_range(target, plr, pcity, id, eff->range, eff->survives,
+ source) == 0) {
+ return FALSE;
+ }
+ return eff_eventually_active(target, plr, pcity, id, ptile, source, eff);
+}
+
+/**************************************************************************
+ Returns TRUE if a building is replaced. To be replaced, all building
+ equivs must be disabled.
+**************************************************************************/
+bool building_replaced(const struct city *pcity, Impr_Type_id id)
+{
+ bool equivs_present = FALSE;
+
+ eft_vector_iterate(get_building_effect_types(id), ptype) {
+ eff_list_iterate(*get_building_effects(id, *ptype), peff) {
+ if (!eff_redundant(TARGET_BUILDING, city_owner(pcity), pcity, id,
+ id, peff)) {
+ return FALSE;
+ }
+ if (peff->group) {
+ equivs_present = TRUE;
+ }
+ } eff_list_iterate_end;
+ } eft_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 inline 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 eff)
+{
+ int value = 0;
+
+ eff_list_iterate(*get_building_effects(source, eff), peff) {
+ if (eff_active(target, plr, pcity, id, ptile, source, peff)) {
+ value += peff->value;
+ }
+ } eff_list_iterate_end;
+
+ return value;
+}
+
+/**************************************************************************
+ Returns the effect bonus for a player.
+**************************************************************************/
+int get_player_bonus(const struct player *plr, enum effect_type eff)
+{
+ int bonus = 0;
+
+ building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+ bonus += get_effect_value(TARGET_PLAYER, plr, NULL, B_LAST, NULL,
+ *pbldg, eff);
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+ Returns the effect bonus at a city.
+**************************************************************************/
+int get_city_bonus(const struct city *pcity, enum effect_type eff)
+{
+ int bonus = 0;
+ struct player *plr = city_owner(pcity);
+
+ building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+ bonus += get_effect_value(TARGET_CITY, plr, pcity, B_LAST, NULL,
+ *pbldg, eff);
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+ Returns the effect bonus at a city tile.
+**************************************************************************/
+int get_city_tile_bonus(const struct city *pcity, const struct tile *ptile,
+ enum effect_type eff)
+{
+ int bonus = 0;
+ struct player *plr = city_owner(pcity);
+
+ building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+ bonus += get_effect_value(TARGET_CITY, plr, pcity, B_LAST, ptile,
+ *pbldg, eff);
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+ Returns the effect bonus at a building.
+**************************************************************************/
+int get_building_bonus(const struct city *pcity, Impr_Type_id id,
+ enum effect_type eff)
+{
+ int bonus = 0;
+ struct player *plr = city_owner(pcity);
+
+ building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+ bonus += get_effect_value(TARGET_BUILDING, plr, pcity, id, NULL,
+ *pbldg, eff);
+ } building_vector_iterate_end;
+
+ return bonus;
+}
+
+/**************************************************************************
+ 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 eff)
+{
+ struct player *plr = city_owner(pcity);
+ struct building_vector res;
+
+ building_vector_init(&res);
+
+ building_vector_iterate(get_buildings_with_effect(eff), pbldg) {
+ if (get_effect_value(TARGET_CITY, plr, pcity, B_LAST, NULL, *pbldg, eff)) {
+ building_vector_append(&res, pbldg);
+ }
+ } building_vector_iterate_end;
+
+ return res;
+}
+
+/**************************************************************************
+ Returns the effect bonus the currently in construction item will provide.
+**************************************************************************/
+int get_current_construction_bonus(const struct city *pcity,
+ enum effect_type eff)
+{
+ if (!pcity->is_building_unit) {
+ Impr_Type_id id;
+ int power = 0;
+
+ id = pcity->currently_building;
+
+ eff_list_iterate(*get_building_effects(id, eff), peff) {
+ if (eff_eventually_active(TARGET_BUILDING, city_owner(pcity), pcity, id,
+ NULL, id, peff)) {
+ power += peff->value;
+ }
+ } eff_list_iterate_end;
+
+ return power;
+ }
+
return 0;
}
Index: common/effects.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.h,v
retrieving revision 1.4
diff -u -r1.4 effects.h
--- common/effects.h 28 Aug 2004 19:15:39 -0000 1.4
+++ common/effects.h 1 Sep 2004 01:53:06 -0000
@@ -13,8 +13,6 @@
#ifndef FC__EFFECTS_H
#define FC__EFFECTS_H
-struct impr_effect;
-
#include "shared.h" /* bool */
#include "fc_types.h"
@@ -25,7 +23,7 @@
enum effect_range {
EFR_LOCAL,
EFR_CITY,
- EFR_ISLAND,
+ EFR_CONTINENT,
EFR_PLAYER,
EFR_WORLD,
EFR_LAST /* keep this last */
@@ -34,20 +32,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 +47,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 +57,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 +74,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_SPACE_PART,
EFT_SPY_RESISTANT,
EFT_TAX_BONUS,
@@ -100,39 +88,168 @@
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_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_SS_STRUCTURAL,
+ EFT_SS_COMPONENT,
+ EFT_SS_MODULE,
+ 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 eff_list_iterate(list, peff) \
+TYPED_LIST_ITERATE(struct effect, list, peff)
+#define eff_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 eft
+#define SPECVEC_TYPE enum effect_type
+#include "specvec.h"
+
+#define eft_vector_iterate(vector, ptype) \
+TYPED_VECTOR_ITERATE(enum effect_type, vector, ptype)
+#define eft_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 eff_group;
+
+struct effect {
+ enum effect_range range; /* effect range */
+
+ int value; /* effect modifier value */
+
+ struct eff_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 eff
+#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_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 eff_group *eff_group_new(const char *name);
+void eff_group_add(struct eff_group *group, Impr_Type_id id,
+ enum effect_range range, bool survives);
+int find_eff_group(const char *name);
+
+/* name string to value functions */
+enum req_type req_type_from_str(const char *str);
+int parse_req(Impr_Type_id id, enum req_type req, const char *arg);
+
+/* effect presence tests */
+enum target_type {
+ TARGET_PLAYER,
+ TARGET_CITY,
+ TARGET_BUILDING
+};
+
+bool eff_eventually_active(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 eff_list *get_building_effects(Impr_Type_id id, enum effect_type eff);
+struct eft_vector *get_building_effect_types(Impr_Type_id id);
+
+bool building_has_effect(Impr_Type_id id, enum effect_type eff);
+
+struct building_vector get_city_bonus_sources(const struct city *pcity,
+ enum effect_type eff);
int get_current_construction_bonus(const struct city *pcity,
enum effect_type effect);
+Impr_Type_id find_source_building(struct player *plr, enum effect_type eff);
+Impr_Type_id get_building_for_effect(enum effect_type eff);
+
#endif /* FC__EFFECTS_H */
+
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.183
diff -u -r1.183 game.c
--- common/game.c 21 Jul 2004 16:34:33 -0000 1.183
+++ common/game.c 1 Sep 2004 01:53:07 -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);
@@ -365,8 +369,7 @@
***************************************************************/
int game_next_year(int year)
{
- int spaceshipparts, i;
- Impr_Type_id parts[] = { B_SCOMP, B_SMODULE, B_SSTRUCTURAL, B_LAST };
+ int spaceshipparts;
if (year == 1) /* hacked it to get rid of year 0 */
year = 0;
@@ -384,13 +387,14 @@
* about 1900 AD
*/
- spaceshipparts= 0;
+ spaceshipparts = 0;
if (game.spacerace) {
- for(i=0; parts[i] < B_LAST; i++) {
- int t = improvement_types[parts[i]].tech_req;
- if (tech_exists(t) && game.global_advances[t] != 0)
+ tech_type_iterate(t) {
+ if (tech_exists(t) && game.global_advances[t] != 0
+ && tech_flag(t, TF_SPACE_PARTS_INC)) {
spaceshipparts++;
- }
+ }
+ } tech_type_iterate_end;
}
if( year >= 1900 || ( spaceshipparts>=3 && year>0 ) )
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.148
diff -u -r1.148 game.h
--- common/game.h 16 Aug 2004 15:42:59 -0000 1.148
+++ common/game.h 1 Sep 2004 01:53:07 -0000
@@ -169,6 +169,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 1 Sep 2004 01:53:07 -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));
}
}
Index: common/improvement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v
retrieving revision 1.43
diff -u -r1.43 improvement.c
--- common/improvement.c 13 Aug 2004 15:59:12 -0000 1.43
+++ common/improvement.c 1 Sep 2004 01:53:07 -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;
}
@@ -130,8 +127,7 @@
if (id<0 || id>=B_LAST || id>=game.num_impr_types)
return FALSE;
- if ((id==B_SCOMP || id==B_SMODULE || id==B_SSTRUCTURAL)
- && !game.spacerace)
+ if (!game.spacerace && building_has_effect(id, EFT_SPACE_PART))
return FALSE;
return (improvement_types[id].tech_req!=A_LAST);
@@ -177,7 +173,7 @@
int cost = 0, missing =
improvement_types[id].build_cost - shields_in_stock;
- if (id == B_CAPITAL) {
+ if (building_has_effect(id, EFT_PROD_TO_GOLD)) {
/* Can't buy capitalization. */
return 0;
}
@@ -351,15 +347,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)
@@ -376,77 +363,88 @@
}
/**************************************************************************
- 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);
- if (impr->effect) {
- struct impr_effect *peffect = impr->effect;
- enum effect_type type;
-
- /* This if for a spaceship component is asked */
- while ((type = peffect->type) != EFT_LAST) {
- if (type == EFT_SPACE_PART) {
- /* TODO: remove this */
- if (game.global_wonders[B_APOLLO] == 0)
- return FALSE;
- if (p->spaceship.state >= SSHIP_LAUNCHED)
- return FALSE;
- if (peffect->amount == 1 && p->spaceship.structurals >=
NUM_SS_STRUCTURALS)
- return FALSE;
- if (peffect->amount == 2 && p->spaceship.components >=
NUM_SS_COMPONENTS)
- return FALSE;
- if (peffect->amount == 3 && p->spaceship.modules >= NUM_SS_MODULES)
- return FALSE;
- }
- peffect++;
+ /* This if for a spaceship component is asked */
+ if (building_has_effect(id, EFT_SS_STRUCTURAL)) {
+ space_part = TRUE;
+ if (p->spaceship.structurals >= NUM_SS_STRUCTURALS) {
+ return FALSE;
+ }
+ }
+ if (building_has_effect(id, EFT_SS_COMPONENT)) {
+ space_part = TRUE;
+ if (p->spaceship.components >= NUM_SS_COMPONENTS) {
+ return FALSE;
+ }
+ }
+ if (building_has_effect(id, EFT_SS_MODULE)) {
+ space_part = TRUE;
+ if (p->spaceship.modules >= NUM_SS_MODULES) {
+ return FALSE;
}
}
+ if (space_part &&
+ (!get_player_bonus(p, EFT_ENABLE_SPACE)
+ || 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;
}
/**************************************************************************
Index: common/improvement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.h,v
retrieving revision 1.30
diff -u -r1.30 improvement.h
--- common/improvement.h 31 Aug 2004 04:40:50 -0000 1.30
+++ common/improvement.h 1 Sep 2004 01:53:07 -0000
@@ -14,6 +14,19 @@
#define FC__IMPROVEMENT_H
/* City Improvements, including Wonders. (Alternatively "Buildings".) */
+typedef int Impr_Type_id;
+
+/*
+ * Hack to allow code that explicitly checks for Palace or City Walls
+ * to work.
+ */
+extern int B_CAPITAL_CITY, B_LAND_DEFEND;
+
+/* 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
#include "fc_types.h"
@@ -35,38 +48,6 @@
#define I_REDUNDANT 3 /* Built, but replaced by wonder/other building */
-/* FIXME: Remove this define when there is per-file need for this enum. */
-#define OLD_IMPR_TYPE_ENUM
-
-/* FIXME: Remove this enum and the ifdef/endif when gen-impr implemented. */
-#ifdef OLD_IMPR_TYPE_ENUM
-enum improvement_type_id {
- 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
-};
-typedef enum improvement_type_id Impr_Type_id;
-#else
-typedef int Impr_Type_id;
-#endif
-
-/* 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
-
/* Range of equivalence (used in equiv_range fields)
* These must correspond to impr_range_names[] in improvement.c. */
enum impr_range {
@@ -78,25 +59,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];
@@ -111,11 +73,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;
@@ -150,15 +112,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.43
diff -u -r1.43 packets.def
--- common/packets.def 27 Aug 2004 17:36:53 -0000 1.43
+++ common/packets.def 1 Sep 2004 01:53:07 -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
@@ -1142,8 +1146,9 @@
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 affected_cities;
IMPR_RANGE equiv_range;
UINT16 build_cost;
UINT8 upkeep, sabotage;
@@ -1159,8 +1164,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
@@ -1247,6 +1250,8 @@
BOOL slow_invasions; add-cap(slow_invasions)
STRING team_name[MAX_NUM_TEAMS][MAX_LEN_NAME];
+
+ IMPROVEMENT default_building;
end
@@ -1298,3 +1303,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 1 Sep 2004 01:53:07 -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 1 Sep 2004 01:53:07 -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)
&& !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.121
diff -u -r1.121 player.h
--- common/player.h 29 Aug 2004 19:03:31 -0000 1.121
+++ common/player.h 1 Sep 2004 01:53:07 -0000
@@ -218,7 +218,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;
@@ -251,9 +250,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/tech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tech.c,v
retrieving revision 1.75
diff -u -r1.75 tech.c
--- common/tech.c 2 Aug 2004 23:19:36 -0000 1.75
+++ common/tech.c 1 Sep 2004 01:53:07 -0000
@@ -41,7 +41,7 @@
"Bonus_Tech", "Boat_Fast", "Bridge", "Railroad", "Fortress",
"Watchtower", "Population_Pollution_Inc", "Trade_Revenue_Reduce",
"Airbase", "Farmland", "Reduce_Trireme_Loss1", "Reduce_Trireme_Loss2",
- "Build_Airborne"
+ "Build_Airborne", "Space_Parts_Inc"
};
/* Note that these strings must correspond with the enums in tech_flag_id,
in common/tech.h */
Index: common/tech.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tech.h,v
retrieving revision 1.46
diff -u -r1.46 tech.h
--- common/tech.h 12 Aug 2004 20:58:59 -0000 1.46
+++ common/tech.h 1 Sep 2004 01:53:07 -0000
@@ -67,6 +67,7 @@
TF_REDUCE_TRIREME_LOSS1, /* Reduces chance of Trireme being lost at sea */
TF_REDUCE_TRIREME_LOSS2, /* Reduces chance of Trireme being lost at sea */
TF_BUILD_AIRBORNE, /* Player can build air units */
+ TF_SPACE_PARTS_INC, /* Increases the number of spaceship parts */
TF_LAST
};
@@ -152,4 +153,8 @@
} \
}
+/* Does the player know this tech? */
+#define player_knows_tech(plr, tech) \
+ (get_invention((plr), (tech)) == TECH_KNOWN)
+
#endif /* FC__TECH_H */
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 1 Sep 2004 01:53:08 -0000
@@ -28,6 +28,7 @@
#include "support.h"
#include "tech.h"
+#include "city.h"
#include "unit.h"
/***************************************************************
@@ -53,15 +54,8 @@
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 +491,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 +1631,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)) {
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.122
diff -u -r1.122 unit.h
--- common/unit.h 26 Aug 2004 18:37:52 -0000 1.122
+++ common/unit.h 1 Sep 2004 01:53:08 -0000
@@ -97,11 +97,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 1 Sep 2004 01:53:08 -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))
return FALSE;
if (unit_type_flag(id, F_NOBUILD)) {
return FALSE;
Index: data/default/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/buildings.ruleset,v
retrieving revision 1.50
diff -u -r1.50 buildings.ruleset
--- data/default/buildings.ruleset 27 Aug 2004 17:14:42 -0000 1.50
+++ data/default/buildings.ruleset 1 Sep 2004 01:53:08 -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"
+ { "eff"
+ "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 =
+ { "eff", "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"
+ { "eff", "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"
+ { "eff"
+ "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"
+ { "eff"
+ "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"
+ { "eff"
+ "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"
+ { "eff", "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"
+ { "eff", "value", "equiv"
+ "Land_Defend", 3, "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"
+ { "eff", "value"
+ "Sea_Defend", 2
}
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"
+ { "eff", "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
+ { "eff", "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
+ { "eff", "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
+ { "eff"
+ "Growth_Food"
}
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"
+ { "eff", "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"
+ { "eff", "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
+ { "eff", "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
+ { "eff", "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
+ { "eff", "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"
+ { "eff", "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"
+ { "eff", "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"
+ { "eff", "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
+ { "eff", "value", "equiv"
+ "Corrupt_Pct", 50, "Purifiers"
+ "Waste_Pct", 50, "Purifiers"
+ "Spy_Resistant"
+ "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"
+ { "eff", "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"
+ { "eff"
+ "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"
+ { "eff", "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
+ { "eff", "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"
+ { "eff", "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"
+ { "eff", "value"
+ "Air_Defend", 2
}
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"
+ { "eff", "value"
+ "Nuke_Proof"
+ "Missile_Defend", 2
}
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 =
+ { "eff", "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,10 @@
build_cost = 160
upkeep = 0
sabotage = 100
-effect =
- { "type", "range", "amount"
- "Space_Part", "Local", 2
+effect =
+ { "eff"
+ "Space_Part"
+ "SS_Component"
}
sound = "b_space_component"
sound_alt = "b_generic"
@@ -1088,9 +1155,10 @@
build_cost = 320
upkeep = 0
sabotage = 100
-effect =
- { "type", "range", "amount"
- "Space_Part", "Local", 3
+effect =
+ { "eff"
+ "Space_Part"
+ "SS_Module"
}
sound = "b_space_module"
sound_alt = "b_generic"
@@ -1128,9 +1196,10 @@
build_cost = 80
upkeep = 0
sabotage = 100
-effect =
- { "type", "range", "amount"
- "Space_Part", "Local", 1
+effect =
+ { "eff"
+ "Space_Part"
+ "SS_Structural"
}
sound = "b_space_structural"
sound_alt = "b_generic"
@@ -1160,9 +1229,9 @@
upkeep = 3
sabotage = 100
effect =
- { "type", "range", "amount", "cond_bldg"
- "Tax_Bonus", "City", 50, "Bank"
- "Luxury_Bonus", "City", 50, "Bank"
+ { "eff", "value", "req_type", "req"
+ "Tax_Bonus", 50, "Building", "Bank"
+ "Luxury_Bonus", 50, "Building", "Bank"
}
sound = "b_stock_exchange"
sound_alt = "b_generic"
@@ -1189,8 +1258,8 @@
upkeep = 3
sabotage = 100
effect =
- { "type", "range", "amount", "aff_terr", "aff_spec"
- "Trade_Per_Tile", "City", 50, "None", "Road"
+ { "eff", "value", "req_type", "req"
+ "Trade_Per_Tile", 50, "Special", "Road"
}
sound = "b_super_highways"
sound_alt = "b_generic"
@@ -1219,8 +1288,8 @@
upkeep = 3
sabotage = 100
effect =
- { "type", "range", "amount", "aff_terr", "aff_spec"
- "Food_Per_Tile", "City", 50, "None", "Farmland"
+ { "eff", "value", "req_type", "req"
+ "Food_Per_Tile", 50, "Special", "Farmland"
}
sound = "b_supermarket"
sound_alt = "b_generic"
@@ -1248,9 +1317,9 @@
upkeep = 1
sabotage = 100
effect =
- { "type", "range", "amount", "cond_adv"
- "Make_Content", "City", 1
- "Make_Content", "City", 1, "Mysticism"
+ { "eff", "value", "req_type", "req"
+ "Make_Content", 1
+ "Make_Content", 1, "Tech", "Mysticism"
}
sound = "b_temple"
sound_alt = "b_generic"
@@ -1277,8 +1346,8 @@
upkeep = 3
sabotage = 100
effect =
- { "type", "range", "amount", "cond_bldg"
- "Science_Bonus", "City", 50, "Library"
+ { "eff", "value", "req_type", "req"
+ "Science_Bonus", 50, "Building", "Library"
}
sound = "b_university"
sound_alt = "b_generic"
@@ -1305,9 +1374,9 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "survives"
- "Reveal_Map", "Player", 0
- "Enable_Space", "World", 1
+ { "eff", "range", "survives"
+ "Reveal_Map", "Player", 0
+ "Enable_Space", "World", 1
}
sound = "w_apollo_program"
sound_alt = "w_generic"
@@ -1334,8 +1403,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Upkeep_Free", "Player", 1
+ { "eff", "range", "value"
+ "Upkeep_Free", "Player", 1
}
sound = "w_asmiths_trading_co"
sound_alt = "w_generic"
@@ -1361,8 +1430,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Trade_Inc_Tile", "City", 1
+ { "eff", "value"
+ "Trade_Inc_Tile", 1
}
sound = "w_colossus"
sound_alt = "w_generic"
@@ -1388,8 +1457,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Science_Bonus", "City", 50
+ { "eff", "value"
+ "Science_Bonus", 50
}
sound = "w_copernicus_observatory"
sound_alt = "w_generic"
@@ -1415,8 +1484,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Make_Content", "Player", 1
+ { "eff", "range", "value"
+ "Force_Content", "Player", 1
}
sound = "w_cure_for_cancer"
sound_alt = "w_generic"
@@ -1444,8 +1513,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Give_Imm_Adv", "Player", 2
+ { "eff", "range", "value"
+ "Give_Imm_Tech", "Player", 2
}
sound = "w_darwins_voyage"
sound_alt = "w_generic"
@@ -1471,10 +1540,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 +1567,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Adv_Parasite", "Player", 2
+ { "eff", "range", "value"
+ "Tech_Parasite", "Player", 2
}
sound = "w_great_library"
sound_alt = "w_generic"
@@ -1529,9 +1594,9 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "aff_unit"
- "Unit_Defend", "Player", 300, "Land"
- "Unit_No_Lose_Pop", "Player", 0, "Land"
+ { "eff", "range", "value", "equiv"
+ "Land_Defend", "Player", 3, "Defenders"
+ "Unit_No_Lose_Pop", "Player"
}
sound = "w_great_wall"
sound_alt = "w_generic"
@@ -1559,9 +1624,9 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Make_Happy", "Player", 1
- "Make_Happy", "City", 2
+ { "eff", "range", "value"
+ "Make_Happy", "Player", 1
+ "Make_Happy", "City", 2
}
sound = "w_hanging_gardens"
sound_alt = "w_generic"
@@ -1590,11 +1655,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"
+ { "eff", "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 +1684,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Science_Bonus", "City", 100
+ { "eff", "value"
+ "Science_Bonus", 100
}
sound = "w_isaac_newtons_college"
sound_alt = "w_generic"
@@ -1647,8 +1711,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Make_Content", "Player", 2
+ { "eff", "range", "value"
+ "Force_Content", "Player", 2
}
sound = "w_js_bachs_cathedral"
sound_alt = "w_generic"
@@ -1673,8 +1737,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Prod_Add_Tile", "City", 1
+ { "eff", "value"
+ "Prod_Add_Tile", 1
}
sound = "w_king_richards_crusade"
sound_alt = "w_generic"
@@ -1691,7 +1755,7 @@
graphic_alt = "-"
;terr_gate =
;spec_gate =
-equiv_range = "Player"
+equiv_range = "None"
;equiv_dupl =
;equiv_repl =
obsolete_by = "Automobile"
@@ -1700,8 +1764,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Upgrade_One_Leap", "Player", 100
+ { "eff", "range"
+ "Upgrade_One_Leap", "Player"
}
sound = "w_leonardos_workshop"
sound_alt = "w_generic"
@@ -1726,10 +1790,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"
+ { "eff", "range", "value"
+ "Sea_Move", "Player", 1
+ "No_Sink_Deep", "Player"
+ "Sea_Veteran", "Player"
}
sound = "w_lighthouse"
sound_alt = "w_generic"
@@ -1747,7 +1811,7 @@
graphic_alt = "-"
;terr_gate =
;spec_gate =
-equiv_range = "Player"
+equiv_range = "None"
;equiv_dupl =
;equiv_repl =
obsolete_by = "None"
@@ -1756,8 +1820,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "aff_unit"
- "Unit_Move", "Player", 2, "Sea"
+ { "eff", "range", "value"
+ "Sea_Move", "Player", 2
}
sound = "w_magellans_expedition"
sound_alt = "w_generic"
@@ -1782,8 +1846,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "survives"
- "Enable_Nuke", "World", 1
+ { "eff", "range", "survives"
+ "Enable_Nuke", "World", 1
}
sound = "w_manhattan_project"
sound_alt = "w_generic"
@@ -1807,8 +1871,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range"
- "Have_Embassies", "Player"
+ { "eff", "range"
+ "Have_Embassies", "Player"
}
sound = "w_marco_polos_embassy"
sound_alt = "w_generic"
@@ -1833,10 +1897,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"
+ { "eff", "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 +1930,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "cond_bldg", "cond_adv"
- "Make_Content", "Player", 1, "Temple"
- "Make_Content", "Player", 1, "Temple", "Mysticism"
+ { "eff", "value", "req_type", "req"
+ "Make_Content", 2, "Building", "Temple"
}
sound = "w_oracle"
sound_alt = "w_generic"
@@ -1893,8 +1956,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Growth_Food", "Player", 50
+ { "eff", "range"
+ "Growth_Food", "Player"
}
sound = "w_pyramids"
sound_alt = "w_generic"
@@ -1919,8 +1982,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "cond_bldg"
- "Science_Bonus", "Player", 50, "Library"
+ { "eff", "range", "value", "equiv", "req_type", "req"
+ "Science_Bonus", "Player", 50, "Labs", "Building", "Library"
}
sound = "w_seti_program"
sound_alt = "w_generic"
@@ -1946,8 +2009,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Make_Content", "City", 99
+ { "eff"
+ "No_Unhappy"
}
sound = "w_shakespeares_theatre"
sound_alt = "w_generic"
@@ -1972,9 +2035,9 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range"
- "Any_Government", "Player"
- "No_Anarchy", "Player"
+ { "eff", "range"
+ "Any_Government", "Player"
+ "No_Anarchy", "Player"
}
sound = "w_statue_of_liberty"
sound_alt = "w_generic"
@@ -2001,9 +2064,10 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "aff_unit"
- "Unit_Veteran", "Player", 0, "Land"
- "Unit_Vet_Combat", "Player", 100, "Land"
+ { "eff", "range", "value"
+ "Land_Veteran", "Player"
+ "Land_Regen", "Player"
+ "Land_Vet_Combat", "Player", 50
}
sound = "w_sun_tzus_war_academy"
sound_alt = "w_generic"
@@ -2030,12 +2094,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"
+ { "eff", "range", "value"
+ "Unit_Recover", "Player", 2
}
sound = "w_united_nations"
sound_alt = "w_generic"
@@ -2068,9 +2128,9 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount", "cond_gov"
- "Make_Content_Mil", "Player", 1, "Republic"
- "Make_Content_Mil", "Player", 2, "Democracy"
+ { "eff", "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 +2166,8 @@
upkeep = 0
sabotage = 0
effect =
- { "type", "range", "amount"
- "Prod_To_Gold", "City", 100
+ { "eff"
+ "Prod_To_Gold"
}
; FIXME: this is the real helptext; restore when have a subordnate analogue
; /* (ignore for gettext until fixed)
@@ -2124,14 +2184,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 +2201,4 @@
cathedral_minus="Communism"
colosseum_plus="Electricity"
temple_plus="Mysticism"
+
Index: data/default/techs.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/techs.ruleset,v
retrieving revision 1.23
diff -u -r1.23 techs.ruleset
--- data/default/techs.ruleset 12 Aug 2004 20:59:00 -0000 1.23
+++ data/default/techs.ruleset 1 Sep 2004 01:53:08 -0000
@@ -552,7 +552,7 @@
name = _("Plastics")
req1 = "Refining"
req2 = "Space Flight"
-flags = "Population_Pollution_Inc"
+flags = "Population_Pollution_Inc","Space_Parts_Inc"
graphic = "a.plastics"
graphic_alt = "-"
@@ -648,7 +648,7 @@
name = _("Space Flight")
req1 = "Computers"
req2 = "Rocketry"
-flags = ""
+flags = "Space_Parts_Inc"
graphic = "a.space_flight"
graphic_alt = "-"
@@ -680,7 +680,7 @@
name = _("Superconductors")
req1 = "Nuclear Power"
req2 = "Laser"
-flags = ""
+flags = "Space_Parts_Inc"
graphic = "a.superconductors"
graphic_alt = "-"
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 1 Sep 2004 01:53:09 -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) ? 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) ? 1 : 0);
} else {
- return (city_got_building(pcity, B_AIRPORT) ? 1 : 0);
+ return (get_city_bonus(pcity, EFT_AIR_VETERAN) ? 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)))
@@ -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 1 Sep 2004 01:53:09 -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.258
diff -u -r1.258 cityturn.c
--- server/cityturn.c 28 Aug 2004 19:15:39 -0000 1.258
+++ server/cityturn.c 1 Sep 2004 01:53:09 -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)
+ && get_current_construction_bonus(pcity, EFT_GROWTH_FOOD)
&& 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);
}
}
@@ -431,40 +430,20 @@
{
struct player *powner = city_owner(pcity);
bool have_square;
- bool has_granary = city_got_effect(pcity, B_GRANARY);
+ bool has_granary = get_city_bonus(pcity, EFT_GROWTH_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) *
@@ -547,7 +526,7 @@
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))
+ if (get_city_bonus(pcity, EFT_GROWTH_FOOD))
pcity->food_stock=city_granary_size(pcity->size)/2;
else
pcity->food_stock=0;
@@ -557,7 +536,7 @@
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))
+ if (get_city_bonus(pcity, EFT_GROWTH_FOOD))
pcity->food_stock = city_granary_size(pcity->size - 1) / 2;
else
pcity->food_stock = 0;
@@ -570,31 +549,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 +635,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 +718,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);
+ int id = pcity->currently_building;
+ int id2 = building_upgrades_to(pcity, pcity->currently_building);
+
+ if (can_build_improvement(pcity, id2)) {
+ pcity->currently_building = id2;
+ notify_player_ex(pplayer, pcity->x, pcity->y, E_UNIT_UPGRADED,
+ _("Game: Production of %s is upgraded to %s in %s."),
+ get_improvement_type(id)->name,
+ get_improvement_type(id2)->name ,
+ pcity->name);
+ }
}
/**************************************************************************
@@ -903,6 +865,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,21 +887,21 @@
}
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;
}
space_part = TRUE;
- if (pcity->currently_building == B_SSTRUCTURAL) {
+ if (get_current_construction_bonus(pcity, EFT_SS_STRUCTURAL)) {
pplayer->spaceship.structurals++;
- } else if (pcity->currently_building == B_SCOMP) {
+ } else if (get_current_construction_bonus(pcity, EFT_SS_COMPONENT)) {
pplayer->spaceship.components++;
- } else if (pcity->currently_building == B_SMODULE) {
+ } else if (get_current_construction_bonus(pcity, EFT_SS_MODULE)) {
pplayer->spaceship.modules++;
} else {
space_part = FALSE;
@@ -971,38 +934,32 @@
_("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];
- notify_player(pplayer, _("Game: %s boosts research, "
- "you gain 2 immediate advances."),
- improvement_types[B_DARWIN].name);
+ if ((mod = get_current_construction_bonus(pcity, EFT_GIVE_IMM_TECH))) {
+ int i;
- 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);
+ notify_player(pplayer, _("Game: %s boosts research, "
+ "you gain %d immediate advances."),
+ improvement_types[pcity->currently_building].name,
+ mod);
+
+ 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 +1157,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)) {
return INCITE_IMPOSSIBLE_COST;
}
@@ -1250,9 +1210,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,7 +1316,7 @@
pcity->did_sell=FALSE;
pcity->did_buy = FALSE;
- if (city_got_building(pcity, B_AIRPORT))
+ if (get_city_bonus(pcity, EFT_AIRLIFT))
pcity->airlift=TRUE;
else
pcity->airlift=FALSE;
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.58
diff -u -r1.58 diplomats.c
--- server/diplomats.c 26 Jul 2004 19:52:02 -0000 1.58
+++ server/diplomats.c 1 Sep 2004 01:53:10 -0000
@@ -737,7 +737,6 @@
struct city *pcity)
{
struct player *cplayer;
- struct city *capital;
int revolt_cost;
/* Fetch target civilization's player. Sanity checks. */
@@ -758,11 +757,10 @@
}
/* Check for city being the capital. */
- capital = find_palace (city_owner (pcity));
- if (pcity == capital) {
+ if (get_city_bonus(pcity, EFT_NO_INCITE)) {
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,7 +1029,8 @@
* City Walls, then there is a 50% chance of getting caught.
*/
vulnerability = get_improvement_type(improvement)->sabotage;
- if (city_got_building(pcity, B_CAPITAL)) {
+
+ if (get_city_bonus(pcity, EFT_SPY_RESISTANT)) {
vulnerability /= 2;
}
if (myrand(100) >= vulnerability) {
@@ -1120,7 +1119,7 @@
def += (def/5.0) * pdefender->veteran;
if (pdefender_tile->city) {
- if (city_got_building(pdefender_tile->city, B_PALACE)) {
+ if (get_city_bonus(pdefender_tile->city, EFT_SPY_RESISTANT)) {
def = (def * 3) / 2;/* +50% */
}
} else {
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.181
diff -u -r1.181 gotohand.c
--- server/gotohand.c 9 Aug 2004 05:24:35 -0000 1.181
+++ server/gotohand.c 1 Sep 2004 01:53:10 -0000
@@ -923,7 +923,7 @@
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));
/*
* If the destination is one step away, look around first or just go
* there?
@@ -1005,17 +1005,20 @@
*/
defence_multiplier = 2;
if (pcity) {
- if (city_got_citywalls(pcity)) {
- defence_multiplier += 2;
+ int mod;
+
+ if ((mod = get_city_bonus(pcity, EFT_LAND_DEFEND)) > 0) {
+ defence_multiplier += (mod - 1);
}
- if (city_got_building(pcity, B_SDI)) {
- defence_multiplier++;
+
+ if ((mod = get_city_bonus(pcity, EFT_MISSILE_DEFEND)) > 0) {
+ defence_multiplier += (mod - 1);
}
- if (city_got_building(pcity, B_SAM)) {
- defence_multiplier++;
+ if ((mod = get_city_bonus(pcity, EFT_AIR_DEFEND)) > 0) {
+ defence_multiplier += (mod - 1);
}
- if (city_got_building(pcity, B_COASTAL)) {
- defence_multiplier++;
+ if ((mod = get_city_bonus(pcity, EFT_SEA_DEFEND)) > 0) {
+ defence_multiplier += (mod - 1);
}
}
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 1 Sep 2004 01:53:10 -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,13 @@
{
bool bonus_tech_hack = FALSE;
bool was_first = FALSE;
- bool macro_polo_was_obsolete = wonder_obsolete(B_MARCO);
+ int had_embassy[MAX_NUM_PLAYERS];
struct city *pcity;
+ players_iterate(aplr) {
+ had_embassy[aplr->player_no] = get_player_bonus(aplr, EFT_HAVE_EMBASSIES);
+ } 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 +455,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)) {
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 +932,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)) {
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.65
diff -u -r1.65 plrhand.h
--- server/plrhand.h 17 Jun 2004 19:50:41 -0000 1.65
+++ server/plrhand.h 1 Sep 2004 01:53:11 -0000
@@ -33,7 +33,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 1 Sep 2004 01:53:11 -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,56 @@
{
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 eff_group *group;
+ char name[MAX_LEN_NAME];
+
+ item = secfile_lookup_str(file, "%s.name", sec[i]);
+ sz_strlcpy(name, item);
+
+ group = eff_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);
+
+ eff_group_add(group, id, range, survives);
+ }
+ }
+ free(sec);
+
sec = secfile_get_secnames_prefix(file, "building_", &nval);
for (i = 0; i < nval; i++) {
@@ -1263,6 +1303,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 +1314,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.eff",
+ 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;
+ range = EFR_CITY;
}
- } 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;
- }
- } else {
- e->cond_adv = A_NONE;
- }
+ survives = secfile_lookup_bool_default(file, FALSE,
"%s.effect%d.survives",
+ sec[i], j);
- 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;
- }
+ value = secfile_lookup_int_default(file, 1, "%s.effect%d.value",
+ 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;
- }
-
- 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_eff_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_req(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 +1407,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 +1438,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 +1982,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 +2370,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 +2748,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 +2860,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 +2869,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 +2895,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 +3090,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);
@@ -3251,6 +3237,9 @@
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.5
diff -u -r1.5 score.c
--- server/score.c 27 May 2004 22:14:19 -0000 1.5
+++ server/score.c 1 Sep 2004 01:53:11 -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 1 Sep 2004 01:53:11 -0000
@@ -885,7 +885,7 @@
assert(pcity != NULL);
cost = city_granary_size(pcity->size);
- if (city_got_effect(pcity, B_GRANARY)) { cost /= 2; }
+ if (get_city_bonus(pcity, EFT_GROWTH_FOOD)) { cost /= 2; }
}
return cost;
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.184
diff -u -r1.184 srv_main.c
--- server/srv_main.c 29 Aug 2004 19:03:32 -0000 1.184
+++ server/srv_main.c 1 Sep 2004 01:53:12 -0000
@@ -307,40 +307,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)) {
+ 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)) {
/* 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)) {
+ players_iterate(pother) {
+ make_contact(pplayer, pother, -1, -1);
+ } players_iterate_end;
+ }
+ } players_iterate_end;
}
/**************************************************************************
@@ -556,7 +553,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;
@@ -573,8 +570,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();
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 1 Sep 2004 01:53:12 -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)
&& kills_citizen_after_attack(punit)) {
city_reduce_size(pcity,1);
city_refresh(pcity);
@@ -814,7 +808,7 @@
if (punit->hp &&
(pcity=map_get_city(def_x, def_y)) &&
pcity->size>1 &&
- !city_got_citywalls(pcity) &&
+ !get_city_bonus(pcity, EFT_UNIT_NO_LOSE_POP) &&
kills_citizen_after_attack(punit)) {
city_reduce_size(pcity,1);
city_refresh(pcity);
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.300
diff -u -r1.300 unittools.c
--- server/unittools.c 26 Aug 2004 18:37:53 -0000 1.300
+++ server/unittools.c 1 Sep 2004 01:53:13 -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,50 +198,54 @@
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;
-
- struct unit_list candidates;
- int candidate_to_upgrade=-1;
-
- int i;
-
- 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;
-
- unit_list_unlink_all(&candidates);
+ bool one_leap = FALSE, all_leap = FALSE;
+
+ all_leap = get_player_bonus(pplayer, EFT_UPGRADE_ALL_LEAP);
+ if (!all_leap) {
+ one_leap = get_player_bonus(pplayer, EFT_UPGRADE_ONE_LEAP);
+ }
+
+ if (one_leap || all_leap) {
+ struct unit_list candidates;
+ int candidate_to_upgrade=-1;
+
+ int i;
+
+ 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 (one_leap)
+ candidate_to_upgrade=myrand(unit_list_size(&candidates));
+
+ i=0;
+ unit_list_iterate(candidates, punit) {
+ if (all_leap || i == 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);
+ }
+ i++;
+ } unit_list_iterate_end;
+
+ unit_list_unlink_all(&candidates);
+ }
}
/***************************************************************************
@@ -294,8 +299,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 +434,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 +495,9 @@
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) && is_ground_unit(punit)) ||
+ (get_city_bonus(pcity, EFT_AIR_REGEN) && (is_air_unit(punit) ||
is_heli_unit(punit))) ||
+ (get_city_bonus(pcity, EFT_SEA_REGEN) && is_sailing_unit(punit))) {
hp=unit_type(punit)->hp;
}
else
- [Freeciv-Dev] Re: (PR#2521) effects patch,
Jason Short <=
|
|