diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/city.c freeciv-patched/common/city.c --- freeciv-cvs/common/city.c 2003-07-24 16:59:50.000000000 +0100 +++ freeciv-patched/common/city.c 2003-07-24 17:00:08.000000000 +0100 @@ -579,11 +579,14 @@ } if (contains_special(spec_t, S_RAILROAD)) s+=(s*terrain_control.rail_shield_bonus)/100; - if (city_affected_by_wonder(pcity, B_RICHARDS)) - s++; - if (is_ocean(tile_t) && city_got_building(pcity, B_OFFSHORE)) { - s++; + + /* Add effects from generalised improvements */ + s += pcity->tile_bonuses[x][y].shields; + if (s > 0) { + s += pcity->tile_add[x][y].shields; } + s = s * pcity->tile_pct[x][y].shields / 100; + /* government shield bonus & penalty */ if (s > 0) s += (is_celebrating ? g->celeb_shield_bonus : g->shield_bonus); @@ -673,6 +676,15 @@ if (contains_special(spec_t, S_ROAD)) { t += (get_tile_type(tile_t))->road_trade_incr; } + + /* Add effects from generalised improvements */ + t += pcity->tile_bonuses[x][y].trade; + if (t > 0) { + t += pcity->tile_add[x][y].trade; + } + if (t < 0) t = 0; /* Don't want tiles producing negative trade */ + t = t * pcity->tile_pct[x][y].trade / 100; + if (t > 0) { int before_penalty = (is_celebrating ? g->celeb_trade_before_penalty : g->trade_before_penalty); @@ -685,11 +697,6 @@ if (t > 0) t += (is_celebrating ? g->celeb_trade_bonus : g->trade_bonus); - if(city_affected_by_wonder(pcity, B_COLLOSSUS)) - t++; - if(contains_special(spec_t, S_ROAD) && city_got_building(pcity, B_SUPERHIGHWAYS)) - t+=(t*terrain_control.road_superhighway_trade_bonus)/100; - /* government trade penalty -- SKi */ if (before_penalty > 0 && t > before_penalty) t--; @@ -784,17 +791,14 @@ if (contains_special(spec_t, S_IRRIGATION) || city_auto_water) { f += type->irrigation_food_incr; - if ((contains_special(spec_t, S_FARMLAND) || - (city_auto_water && - player_knows_techs_with_flag(city_owner(pcity), TF_FARMLAND))) && - city_got_building(pcity, B_SUPERMARKET)) { - f += (f * terrain_control.farmland_supermarket_food_bonus) / 100; - } } - if (is_ocean(tile_t) && city_got_building(pcity, B_HARBOUR)) { - f++; + /* Add effects from generalised improvements */ + f += pcity->tile_bonuses[x][y].food; + if (f > 0) { + f += pcity->tile_add[x][y].food; } + f = f * pcity->tile_pct[x][y].food / 100; if (contains_special(spec_t, S_RAILROAD)) f+=(f*terrain_control.rail_food_bonus)/100; @@ -1680,6 +1684,80 @@ } /************************************************************************** + Sets the given city's shield/food/trade per-tile bonuses to defaults +**************************************************************************/ +void city_init_tile_mods(struct city *pcity) +{ + struct tile_mod *tilept; + + city_map_iterate(x, y) { + tilept = &pcity->tile_bonuses[x][y]; + tilept->trade = tilept->shields = tilept->food = 0; + + tilept = &pcity->tile_add[x][y]; + tilept->trade = tilept->shields = tilept->food = 0; + + tilept = &pcity->tile_pct[x][y]; + tilept->trade = tilept->shields = tilept->food = 100; + } city_map_iterate_end; +} + +static int handle_tile_bonuses( + struct impr_effect *imeff, + struct tile_mod add[CITY_MAP_SIZE][CITY_MAP_SIZE], + struct tile_mod bonus[CITY_MAP_SIZE][CITY_MAP_SIZE], + struct tile_mod pct[CITY_MAP_SIZE][CITY_MAP_SIZE], + enum tile_special_type tile_spec[CITY_MAP_SIZE][CITY_MAP_SIZE], + enum tile_terrain_type tile_terr[CITY_MAP_SIZE][CITY_MAP_SIZE]) +{ + int amount; + + amount = imeff->amount; + + switch(imeff->type) { + case EFT_TRADE_ADD_TILE: + case EFT_TRADE_INC_TILE: + case EFT_TRADE_PER_TILE: + case EFT_PROD_ADD_TILE: + case EFT_PROD_INC_TILE: + case EFT_PROD_PER_TILE: + case EFT_FOOD_ADD_TILE: + case EFT_FOOD_INC_TILE: + case EFT_FOOD_PER_TILE: + city_map_iterate(x, y) { + if (is_unit_terrain_affected(imeff, UCL_LAST, tile_terr[x][y], + tile_spec[x][y])) { + switch(imeff->type) { + case EFT_TRADE_ADD_TILE: + add[x][y].trade += amount; break; + case EFT_TRADE_INC_TILE: + bonus[x][y].trade += amount; break; + case EFT_TRADE_PER_TILE: + pct[x][y].trade = pct[x][y].trade * amount / 100; break; + case EFT_PROD_ADD_TILE: + add[x][y].shields += amount; break; + case EFT_PROD_INC_TILE: + bonus[x][y].shields += amount; break; + case EFT_PROD_PER_TILE: + pct[x][y].shields = pct[x][y].shields * amount / 100; break; + case EFT_FOOD_ADD_TILE: + add[x][y].food += amount; break; + case EFT_FOOD_INC_TILE: + bonus[x][y].food += amount; break; + case EFT_FOOD_PER_TILE: + pct[x][y].food = pct[x][y].food * amount / 100; break; + default: + break; + } + } + } city_map_iterate_end; + return TRUE; + default: + return FALSE; + } +} + +/************************************************************************** Updates the various modifiers and bonuses due to city improvements (should be called whenever city effects change - i.e. by update_all_effects and friends) @@ -1699,6 +1777,11 @@ int makecontentpct = 100, forcecontentpct = 100; int makecontentmil = 0, makecontentmilper = 0; + enum tile_special_type spec = map_get_special(pcity->x, pcity->y); + enum tile_terrain_type terr = map_get_terrain(pcity->x, pcity->y); + enum tile_special_type tile_spec[CITY_MAP_SIZE][CITY_MAP_SIZE]; + enum tile_terrain_type tile_terr[CITY_MAP_SIZE][CITY_MAP_SIZE]; + int amount; struct player *pplayer; struct government *gov; @@ -1706,9 +1789,41 @@ pplayer = city_owner(pcity); gov = get_gov_pcity(pcity); - city_effects_iterate(iter, pcity) { - amount = iter.imeff->amount; - switch(iter.imeff->type) { + city_init_tile_mods(pcity); + + city_map_iterate(x, y) { + struct tile_type *type; + int map_x, map_y, is_real, city_auto_water; + + is_real = city_map_to_map(&map_x, &map_y, pcity, x, y); + if (is_real) { + tile_spec[x][y] = map_get_special(map_x, map_y); + tile_terr[x][y] = map_get_terrain(map_x, map_y); + } else { + tile_spec[x][y] = S_ALL; + tile_terr[x][y] = T_UNKNOWN; + } + + type = get_tile_type(tile_terr[x][y]); + city_auto_water = (is_city_center(x, y) + && tile_terr[x][y] == type->irrigation_result + && terrain_control.may_irrigate); + /* City centre counts as farmland if we have the necessary tech */ + if (city_auto_water + && player_knows_techs_with_flag(city_owner(pcity), TF_FARMLAND)) { + tile_spec[x][y] |= S_FARMLAND; + } + } city_map_iterate_end; + + /* Ignore terrain in the iteration, as it's the terrain of the city + center - we need to consider all city tiles too */ + city_effects_iterate_full(iter, pcity, UCL_LAST, T_UNKNOWN, S_ALL) { + if (!handle_tile_bonuses(iter.imeff, pcity->tile_add, + pcity->tile_bonuses, pcity->tile_pct, + tile_spec, tile_terr) + && is_unit_terrain_affected(iter.imeff, UCL_LAST, terr, spec)) { + amount = iter.imeff->amount; + switch(iter.imeff->type) { case EFT_TAX_BONUS: tax_bonus += amount; break; case EFT_TAX_PCT: @@ -1755,6 +1870,7 @@ forcehappy += amount; break; default: break; + } } } city_effects_iterate_end; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/city.h freeciv-patched/common/city.h --- freeciv-cvs/common/city.h 2003-07-24 16:59:50.000000000 +0100 +++ freeciv-patched/common/city.h 2003-07-24 17:00:08.000000000 +0100 @@ -204,6 +204,10 @@ * all units coming to kill us. */ }; +struct tile_mod { + int trade, shields, food; +}; + struct city { int id; int owner; @@ -235,6 +239,11 @@ int shield_bonus, tax_bonus, science_bonus; /* more CPU savings! */ int tithes_bonus; + /* per tile production bonuses from city improvements */ + struct tile_mod tile_bonuses[CITY_MAP_SIZE][CITY_MAP_SIZE]; + struct tile_mod tile_add[CITY_MAP_SIZE][CITY_MAP_SIZE]; + struct tile_mod tile_pct[CITY_MAP_SIZE][CITY_MAP_SIZE]; + /* happiness modifiers from city improvements */ int makecontent, makehappy, forcecontent, forcehappy; int makecontentmil, makecontentmilper; @@ -460,6 +469,7 @@ /* city update functions */ void update_city_bonuses(struct city *pcity); +void city_init_tile_mods(struct city *pcity); void generic_city_refresh(struct city *pcity, bool refresh_trade_route_cities, void (*send_unit_info) (struct player * pplayer,