Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2005:
[Freeciv-Dev] Re: (PR#14314) effects and unitclass cleanup
Home

[Freeciv-Dev] Re: (PR#14314) effects and unitclass cleanup

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#14314) effects and unitclass cleanup
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 22 Oct 2005 15:11:41 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=14314 >

And this one adds support for all rulesets.  The only thing remaining 
(maybe to be done after committing it) is to improve AI support.

-jason


Index: doc/README.effects
===================================================================
--- doc/README.effects  (revision 11170)
+++ doc/README.effects  (working copy)
@@ -88,6 +88,9 @@
 
 "Incite_Cost_Pct" - increases revolt cost by AMOUNT percent
 
+"Defend_Bonus"  - Increases defensive bonuses of units.  Any unit requirements
+                  on this effect will be applied to the _attacking_ unit.
+
 "Size_Adj"      - Increases maximum city size by AMOUNT
 
 "Size_Unlimit" - Removes maximum city size limitation
Index: server/gotohand.c
===================================================================
--- server/gotohand.c   (revision 11175)
+++ server/gotohand.c   (working copy)
@@ -912,7 +912,8 @@
                            struct tile *dest_tile)
 {
 #define UNIT_DEFENSE(punit, ptile, defence_multiplier) \
-  ((get_virtual_defense_power(NULL, (punit)->type, (ptile), FALSE, 0) * \
+  ((get_virtual_defense_power(NULL, (punit)->type, (punit)->owner, \
+                             (ptile), FALSE, 0) *                 \
     (defence_multiplier)) / 2)
 
 #define UNIT_RATING(punit, ptile, defence_multiplier) \
@@ -1017,12 +1018,9 @@
      */
     defence_multiplier = 2;
     if (pcity) {
-      /* This isn't very accurate. */
-      defence_multiplier += (get_city_bonus(pcity, EFT_LAND_DEFEND)
-                            + get_city_bonus(pcity, EFT_MISSILE_DEFEND)
-                            + get_city_bonus(pcity, EFT_AIR_DEFEND)
-                            + get_city_bonus(pcity, EFT_SEA_DEFEND)) / 100;
+      defence_multiplier += get_city_bonus(pcity, EFT_DEFEND_BONUS) / 100;
     }
+    defence_multiplier = MAX(1, defence_multiplier); /* no division by 0 */
 
     /* 
      * Find the best ally unit at the target tile.
Index: server/citytools.c
===================================================================
--- server/citytools.c  (revision 11175)
+++ server/citytools.c  (working copy)
@@ -478,17 +478,10 @@
       || unit_type_flag(punittype, F_CITIES)) {
     return 0;
   }
-  
-  if (unit_type_flag(punittype, F_DIPLOMAT)) {
-    return (get_city_bonus(pcity, EFT_VETERAN_DIPLOMATS) ? 1 : 0);
-  } else if (is_ground_unittype(punittype)) {
-    return (get_city_bonus(pcity, EFT_LAND_VETERAN) > 0) ? 1 : 0;
-  } else {
-    if (is_sailing_unittype(punittype)) {
-      return (get_city_bonus(pcity, EFT_SEA_VETERAN) > 0) ? 1 : 0;
-    } else {
-      return (get_city_bonus(pcity, EFT_AIR_VETERAN) > 0) ? 1 : 0;
-    }
+
+  if (get_unittype_bonus(pcity->owner, pcity->tile, punittype,
+                        EFT_VETERAN_BUILD) > 0) {
+    return 1;
   }
   
   return 0;
Index: server/unittools.c
===================================================================
--- server/unittools.c  (revision 11175)
+++ server/unittools.c  (working copy)
@@ -148,12 +148,9 @@
       || unit_flag(punit, F_NO_VETERAN)) {
     return FALSE;
   } else {
-    int mod = 100;
+    int mod = 100 + get_unittype_bonus(punit->owner, punit->tile,
+                                      punit->type, EFT_VETERAN_COMBAT);
 
-    if (is_ground_unittype(punit->type)) {
-      mod += get_unit_bonus(punit, EFT_LAND_VET_COMBAT);
-    }
-
     /* The modification is tacked on as a multiplier to the base chance.
      * For example with a base chance of 50% for green units and a modifier
      * of +50% the end chance is 75%. */
@@ -515,34 +512,25 @@
 ***************************************************************************/
 static int hp_gain_coord(struct unit *punit)
 {
-  int hp;
-  struct city *pcity;
-  struct unit_class *class = get_unit_class(punit->type);
+  int hp = 0;
+  const int base = unit_type(punit)->hp;
 
-  if (unit_on_fortress(punit))
-    hp=unit_type(punit)->hp/4;
-  else
-    hp=0;
-  if((pcity=tile_get_city(punit->tile))) {
-    if ((get_city_bonus(pcity, EFT_LAND_REGEN) > 0
-        && is_ground_unit(punit))
-       || (get_city_bonus(pcity, EFT_AIR_REGEN) > 0
-           && (is_air_unit(punit) || is_heli_unit(punit)))
-       || (get_city_bonus(pcity, EFT_SEA_REGEN) > 0
-           && is_sailing_unit(punit))) {
-      hp=unit_type(punit)->hp;
-    }
-    else
-      hp=unit_type(punit)->hp/3;
+  /* Includes barracks (100%), fortress (25%), etc. */
+  hp += base * get_unit_bonus(punit, EFT_HP_REGEN) / 100;
+
+  if (punit->tile->city) {
+    hp = MAX(hp, base / 3);
   }
-  else if (!class->hp_loss_pct) {
-    hp++;
+
+  if (!punit->type->class->hp_loss_pct) {
+    hp += (base + 9) / 10;
   }
 
-  if(punit->activity==ACTIVITY_FORTIFIED)
-    hp++;
-  
-  return hp;
+  if (punit->activity == ACTIVITY_FORTIFIED) {
+    hp += (base + 9) / 10;
+  }
+
+  return MAX(hp, 0);
 }
 
 /**************************************************************************
@@ -937,7 +925,10 @@
       continue;
     if (unit_list_size(ptile->units) > 0)
       continue;
-    value = get_virtual_defense_power(NULL, u_type, ptile, FALSE, 0);
+
+    /* City has not changed hands yet; see place_partisans(). */
+    value = get_virtual_defense_power(NULL, u_type, pcity->owner,
+                                     ptile, FALSE, 0);
     value *= 10;
 
     if (ptile->continent != tile_get_continent(pcity->tile)) {
Index: data/civ1/effects.ruleset
===================================================================
--- data/civ1/effects.ruleset   (revision 11170)
+++ data/civ1/effects.ruleset   (working copy)
@@ -47,6 +47,16 @@
     }
 
 
+; Fortress HP regen
+[effect_fortress_hp_regen]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Special", "Fortress", "Tile"
+      "UnitClass", "Land", "Local"
+    }
+
 ; Base vision range - radius of vision is sqrt(5) = 2.24
 [effect_city_vision]
 name    = "City_Vision_Radius_Sq"
@@ -288,11 +298,12 @@
     }
 
 [effect_communism_0]
-name    = "Veteran_Diplomats"
+name    = "Veteran_Build"
 value   = 1
 reqs    =
     { "type",       "name",      "range"
       "Gov", "Communism", "Player"
+      "UnitFlag", "Diplomat", "Local"
     }
 
 [effect_revolution_0]
@@ -353,77 +364,29 @@
     }
 
 [effect_barracks]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
     }
 
-[effect_barracks_1]
-name   = "Sea_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks", "City"
-    }
-
-[effect_barracks_2]
-name   = "Air_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks", "City"
-    }
-
 [effect_barracks_ii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
     }
 
-[effect_barracks_ii_1]
-name   = "Sea_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks II", "City"
-    }
-
-[effect_barracks_ii_2]
-name   = "Air_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks II", "City"
-    }
-
 [effect_barracks_iii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
     }
 
-[effect_barracks_iii_1]
-name   = "Sea_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks III", "City"
-    }
-
-[effect_barracks_iii_2]
-name   = "Air_Veteran"
-value  = 1
-reqs   =
-    { "type", "name", "range"
-      "Building", "Barracks III", "City"
-    }
-
 [effect_cathedral]
 name   = "Make_Content"
 value  = 4
@@ -433,11 +396,12 @@
     }
 
 [effect_city_walls]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "City Walls", "City"
+      "UnitClass", "Land", "Local"
     }
 nreqs  =
     { "type", "name", "range"
@@ -445,11 +409,12 @@
     }
 
 [effect_city_walls_1]
-name   = "Sea_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "City Walls", "City"
+      "UnitClass", "Sea", "Local"
     }
 nreqs  =
     { "type", "name", "range"
@@ -820,19 +785,21 @@
     }
 
 [effect_great_wall]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_great_wall_1]
-name   = "Sea_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_hanging_gardens]
@@ -893,19 +860,21 @@
     }
 
 [effect_lighthouse]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_magellans_expedition]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Magellan's Expedition", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_manhattan_project]
Index: data/civ2/effects.ruleset
===================================================================
--- data/civ2/effects.ruleset   (revision 11170)
+++ data/civ2/effects.ruleset   (working copy)
@@ -48,6 +48,16 @@
     }
 
 
+; Fortress HP regen
+[effect_fortress_hp_regen]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Special", "Fortress", "Tile"
+      "UnitClass", "Land", "Local"
+    }
+
 ; Base vision range - radius of vision is sqrt(5) = 2.24
 [effect_city_vision]
 name    = "City_Vision_Radius_Sq"
@@ -328,11 +338,12 @@
     }
 
 [effect_communism_0]
-name    = "Veteran_Diplomats"
+name    = "Veteran_Build"
 value   = 1
 reqs    =
     { "type",       "name",      "range"
       "Gov", "Communism", "Player"
+      "UnitFlag", "Diplomat", "Local"
     }
 
 [effect_revolution_0]
@@ -390,29 +401,59 @@
 
 ; Nuclear power gives +1 moves to sea units
 [effect_nuclear_powered_boats]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Tech", "Nuclear Power", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_airport]
-name   = "Air_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
     }
 
-[effect_airport_1]
-name   = "Air_Regen"
+[effect_airport_0a]
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Helicoptor", "Local"
     }
 
+[effect_airport_0a]
+name   = "Veteran_Build"
+value  = 1
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Missile", "Local"
+    }
+
+[effect_airport_1]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
+    }
+
+[effect_airport_1a]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_airport_2]
 name   = "Airlift"
 value  = 1
@@ -455,51 +496,69 @@
     }
 
 [effect_barracks]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_ii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_ii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_iii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_iii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_cathedral]
@@ -541,17 +600,31 @@
     }
 
 [effect_city_walls]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "City Walls", "City"
+      "UnitClass", "Land", "Local"
     }
 nreqs  =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
     }
 
+[effect_city_walls]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "City Walls", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+nreqs  =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+    }
+
 [effect_city_walls_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -561,11 +634,12 @@
     }
 
 [effect_coastal_defense]
-name   = "Sea_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Coastal Defense", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_colosseum]
@@ -868,19 +942,21 @@
     }
 
 [effect_port_facility]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_port_facility_1]
-name   = "Sea_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_power_plant]
@@ -938,11 +1014,12 @@
     }
 
 [effect_sam_battery]
-name   = "Air_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SAM Battery", "City"
+      "UnitClass", "Air", "Local"
     }
 
 [effect_sdi_defense]
@@ -954,11 +1031,12 @@
     }
 
 [effect_sdi_defense_1]
-name   = "Missile_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SDI Defense", "City"
+      "UnitClass", "Missile", "Local"
     }
 
 [effect_sewer_system]
@@ -1128,13 +1206,23 @@
     }
 
 [effect_great_wall]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
+      "UnitClass", "Land", "Local"
     }
 
+[effect_great_wall]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_great_wall_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -1226,11 +1314,12 @@
     }
 
 [effect_lighthouse]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_lighthouse_1]
@@ -1242,19 +1331,21 @@
     }
 
 [effect_lighthouse_2]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_magellans_expedition]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 2
 reqs   =
     { "type", "name", "range"
       "Building", "Magellan's Expedition", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_manhattan_project]
@@ -1351,20 +1442,30 @@
     }
 
 [effect_sun_tzus_war_academy]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_sun_tzus_war_academy_1]
-name   = "Land_Vet_Combat"
+name   = "Veteran_Combat"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_united_nations]
 name   = "Unit_Recover"
Index: data/default/effects.ruleset
===================================================================
--- data/default/effects.ruleset        (revision 11170)
+++ data/default/effects.ruleset        (working copy)
@@ -67,6 +67,16 @@
     }
 
 
+; Fortress HP regen
+[effect_fortress_hp_regen]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Special", "Fortress", "Tile"
+      "UnitClass", "Land", "Local"
+    }
+
 ; Base vision range - radius of vision is sqrt(5) = 2.24
 [effect_city_vision]
 name    = "City_Vision_Radius_Sq"
@@ -75,11 +85,12 @@
 
 ; Nuclear power gives +1 moves to sea units
 [effect_nuclear_powered_boats]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Tech", "Nuclear Power", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_civil_war_0]
@@ -356,11 +367,12 @@
     }
 
 [effect_communism_0]
-name    = "Veteran_Diplomats"
+name    = "Veteran_Build"
 value   = 1
 reqs   =
     { "type",       "name",      "range"
       "Gov", "Communism", "Player"
+      "UnitFlag", "Diplomat", "Local"
     }
 
 [effect_revolution_0]
@@ -408,21 +420,50 @@
     }
 
 [effect_airport]
-name   = "Air_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
     }
 
-[effect_airport_1]
-name   = "Air_Regen"
+[effect_airport_0a]
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Helicoptor", "Local"
     }
 
+[effect_airport_0a]
+name   = "Veteran_Build"
+value  = 1
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Missile", "Local"
+    }
+
+[effect_airport_1]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
+    }
+
+[effect_airport_1a]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_airport_2]
 name   = "Airlift"
 value  = 1
@@ -465,51 +506,69 @@
     }
 
 [effect_barracks]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_ii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_ii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_iii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_iii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_cathedral]
@@ -551,17 +610,31 @@
     }
 
 [effect_city_walls]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "City Walls", "City"
+      "UnitClass", "Land", "Local"
     }
 nreqs  =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
     }
 
+[effect_city_walls]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "City Walls", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+nreqs  =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+    }
+
 [effect_city_walls_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -571,11 +644,12 @@
     }
 
 [effect_coastal_defense]
-name   = "Sea_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Coastal Defense", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_colosseum]
@@ -903,19 +977,21 @@
     }
 
 [effect_port_facility]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_port_facility_1]
-name   = "Sea_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_power_plant]
@@ -979,11 +1055,12 @@
     }
 
 [effect_sam_battery]
-name   = "Air_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SAM Battery", "City"
+      "UnitClass", "Air", "Local"
     }
 
 [effect_sdi_defense]
@@ -995,11 +1072,12 @@
     }
 
 [effect_sdi_defense_1]
-name   = "Missile_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SDI Defense", "City"
+      "UnitClass", "Missile", "Local"
     }
 
 [effect_sewer_system]
@@ -1201,13 +1279,23 @@
     }
 
 [effect_great_wall]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
+      "UnitClass", "Land", "Local"
     }
 
+[effect_great_wall]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_great_wall_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -1314,11 +1402,12 @@
     }
 
 [effect_lighthouse]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_lighthouse_1]
@@ -1330,19 +1419,21 @@
     }
 
 [effect_lighthouse_2]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_magellans_expedition]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 2
 reqs   =
     { "type", "name", "range"
       "Building", "Magellan's Expedition", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_manhattan_project]
@@ -1439,20 +1530,30 @@
     }
 
 [effect_sun_tzus_war_academy]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_sun_tzus_war_academy_1]
-name   = "Land_Vet_Combat"
+name   = "Veteran_Combat"
 value  = 50
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_united_nations]
 name   = "Unit_Recover"
Index: data/history/effects.ruleset
===================================================================
--- data/history/effects.ruleset        (revision 11170)
+++ data/history/effects.ruleset        (working copy)
@@ -58,6 +58,16 @@
     }
 
 
+; Fortress HP regen
+[effect_fortress_hp_regen]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Special", "Fortress", "Tile"
+      "UnitClass", "Land", "Local"
+    }
+
 ; Base vision range - radius of vision is sqrt(5) = 2.24
 [effect_city_vision]
 name    = "City_Vision_Radius_Sq"
@@ -66,29 +76,59 @@
 
 ; Nuclear power gives +1 moves to sea units
 [effect_nuclear_powered_boats]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Tech", "Nuclear Power", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_airport]
-name   = "Air_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
     }
 
-[effect_airport_1]
-name   = "Air_Regen"
+[effect_airport_0a]
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Airport", "City"
+      "UnitClass", "Helicoptor", "Local"
     }
 
+[effect_airport_0a]
+name   = "Veteran_Build"
+value  = 1
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Missile", "Local"
+    }
+
+[effect_airport_1]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Air", "Local"
+    }
+
+[effect_airport_1a]
+name   = "HP_Regen"
+value  = 100
+reqs   =
+    { "type", "name", "range"
+      "Building", "Airport", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_airport_2]
 name   = "Airlift"
 value  = 1
@@ -131,51 +171,69 @@
     }
 
 [effect_barracks]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_ii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_ii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks II", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_barracks_iii]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_barracks_iii_1]
-name   = "Land_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Barracks III", "City"
+      "UnitClass", "Land", "Local"
     }
 
 [effect_cathedral]
@@ -217,17 +275,31 @@
     }
 
 [effect_city_walls]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "City Walls", "City"
+      "UnitClass", "Land", "Local"
     }
 nreqs  =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
     }
 
+[effect_city_walls]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "City Walls", "City"
+      "UnitClass", "Helicopter", "Local"
+    }
+nreqs  =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+    }
+
 [effect_city_walls_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -237,11 +309,12 @@
     }
 
 [effect_coastal_defense]
-name   = "Sea_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Coastal Defense", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_colosseum]
@@ -538,19 +611,21 @@
     }
 
 [effect_port_facility]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_port_facility_1]
-name   = "Sea_Regen"
-value  = 1
+name   = "HP_Regen"
+value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "Port Facility", "City"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_power_plant]
@@ -608,11 +683,12 @@
     }
 
 [effect_sam_battery]
-name   = "Air_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SAM Battery", "City"
+      "UnitClass", "Air", "Local"
     }
 
 [effect_sdi_defense]
@@ -624,11 +700,12 @@
     }
 
 [effect_sdi_defense_1]
-name   = "Missile_Defend"
+name   = "Defend_Bonus"
 value  = 100
 reqs   =
     { "type", "name", "range"
       "Building", "SDI Defense", "City"
+      "UnitClass", "Missile", "Local"
     }
 
 [effect_sewer_system]
@@ -798,13 +875,23 @@
     }
 
 [effect_great_wall]
-name   = "Land_Defend"
+name   = "Defend_Bonus"
 value  = 200
 reqs   =
     { "type", "name", "range"
       "Building", "Great Wall", "Player"
+      "UnitClass", "Land", "Local"
     }
 
+[effect_great_wall]
+name   = "Defend_Bonus"
+value  = 200
+reqs   =
+    { "type", "name", "range"
+      "Building", "Great Wall", "Player"
+      "UnitClass", "Helicopter", "Local"
+    }
+
 [effect_great_wall_1]
 name   = "Unit_No_Lose_Pop"
 value  = 1
@@ -896,11 +983,12 @@
     }
 
 [effect_lighthouse]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_lighthouse_1]
@@ -912,19 +1000,21 @@
     }
 
 [effect_lighthouse_2]
-name   = "Sea_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Lighthouse", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_magellans_expedition]
-name   = "Sea_Move"
+name   = "Move_Bonus"
 value  = 2
 reqs   =
     { "type", "name", "range"
       "Building", "Magellan's Expedition", "Player"
+      "UnitClass", "Sea", "Local"
     }
 
 [effect_manhattan_project]
@@ -1021,20 +1111,30 @@
     }
 
 [effect_sun_tzus_war_academy]
-name   = "Land_Veteran"
+name   = "Veteran_Build"
 value  = 1
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_sun_tzus_war_academy_1]
-name   = "Land_Vet_Combat"
+name   = "Veteran_Combat"
 value  = 50
 reqs   =
     { "type", "name", "range"
       "Building", "Sun Tzu's War Academy", "Player"
+      "UnitClass", "Land", "Local"
     }
+nreqs   =
+    { "type", "name", "range"
+      "UnitFlag", "Diplomat", "Local"
+    }
 
 [effect_united_nations]
 name   = "Unit_Recover"
Index: common/combat.c
===================================================================
--- common/combat.c     (revision 11170)
+++ common/combat.c     (working copy)
@@ -258,8 +258,8 @@
   }
 
   if (unit_flag(attacker, F_BADWALLATTACKER)
-      && pcity 
-      && get_city_bonus(pcity, EFT_LAND_DEFEND) > 0) {
+      && get_unittype_bonus(defender->owner, defender->tile, attacker->type,
+                           EFT_DEFEND_BONUS) > 0) {
     *att_fp = 1;
   }
 
@@ -431,6 +431,7 @@
 **************************************************************************/
 static int defense_multiplication(const struct unit_type *att_type,
                                  const struct unit_type *def_type,
+                                 const struct player *def_player,
                                  const struct tile *ptile,
                                  int defensepower, bool fortified)
 {
@@ -451,26 +452,13 @@
        (is_air_unittype(att_type) || is_heli_unittype(att_type))) {
       defensepower *= 5;
     }
-         
-    if (is_air_unittype(att_type) && pcity) {
-      if ((mod = get_city_bonus(pcity, EFT_AIR_DEFEND)) > 0) {
-       defensepower = defensepower * (100 + mod) / 100;
-      }
-      if ((mod = get_city_bonus(pcity, EFT_MISSILE_DEFEND)) > 0
-         && unit_type_flag(att_type, F_MISSILE)) {
-       defensepower = defensepower * (100 + mod) / 100;
-      }
-    } else if (is_sailing_unittype(att_type) && pcity) {
-      if ((mod = get_city_bonus(pcity, EFT_SEA_DEFEND)) > 0) {
-       defensepower = defensepower * (100 + mod) / 100;
-      }
+
+    if (!unit_type_flag(att_type, F_IGWALL)) {
+      /* This applies even if pcity is NULL. */
+      mod = 100 + get_unittype_bonus(def_player, ptile,
+                                    att_type, EFT_DEFEND_BONUS);
+      defensepower = MAX(0, defensepower * mod / 100);
     }
-    if (!unit_type_flag(att_type, F_IGWALL)
-       && (is_ground_unittype(att_type) || is_heli_unittype(att_type))
-        && pcity
-        && (mod = get_city_bonus(pcity, EFT_LAND_DEFEND)) > 0) {
-      defensepower = defensepower * (100 + mod) / 100;
-    }
 
     if (unit_type_flag(att_type, F_FIGHTER) && is_heli_unittype(def_type)) {
       defensepower /= 2;
@@ -495,6 +483,7 @@
 **************************************************************************/
 int get_virtual_defense_power(const struct unit_type *att_type,
                              const struct unit_type *def_type,
+                             const struct player *def_player,
                              const struct tile *ptile,
                              bool fortified, int veteran)
 {
@@ -514,7 +503,8 @@
   defensepower *= db;
   defensepower *= def_type->veteran[veteran].power_fact;
 
-  return defense_multiplication(att_type, def_type, ptile, defensepower,
+  return defense_multiplication(att_type, def_type, def_player,
+                               ptile, defensepower,
                                fortified);
 }
 
@@ -527,6 +517,7 @@
                            const struct unit *defender)
 {
   return defense_multiplication(attacker->type, defender->type,
+                               defender->owner,
                                defender->tile,
                                get_defense_power(defender),
                                defender->activity == ACTIVITY_FORTIFIED);
Index: common/city.c
===================================================================
--- common/city.c       (revision 11174)
+++ common/city.c       (working copy)
@@ -971,7 +971,7 @@
 **************************************************************************/
 bool city_got_citywalls(const struct city *pcity)
 {
-  return (get_city_bonus(pcity, EFT_LAND_DEFEND) > 0);
+  return (get_city_bonus(pcity, EFT_DEFEND_BONUS) > 0);
 }
 
 /**************************************************************************
Index: common/combat.h
===================================================================
--- common/combat.h     (revision 11170)
+++ common/combat.h     (working copy)
@@ -56,6 +56,7 @@
                            const struct unit *defender);
 int get_virtual_defense_power(const struct unit_type *attacker,
                              const struct unit_type *defender,
+                             const struct player *defending_player,
                              const struct tile *ptile,
                              bool fortified, int veteran);
 int get_total_attack_power(const struct unit *attacker,
Index: common/movement.c
===================================================================
--- common/movement.c   (revision 11170)
+++ common/movement.c   (working copy)
@@ -53,13 +53,12 @@
     move_rate = (move_rate * punit->hp) / unit_type(punit)->hp;
   }
 
+  /* Add on effects bonus (Magellan's Expedition, Lighthouse,
+   * Nuclear Power). */
+  move_rate += (get_unit_bonus(punit, EFT_MOVE_BONUS) * SINGLE_MOVE);
+
   /* TODO: These effects should not be hardcoded to unit class enumeration */
   if (pclass->id == UCL_SEA) {
-    /* Add on effects bonus (Magellan's Expedition, Lighthouse,
-     * Nuclear Power). */
-    move_rate += (get_unit_bonus(punit, EFT_SEA_MOVE)
-                 * SINGLE_MOVE);
-
     /* Don't let the move_rate be less than 2 unless the base_move_rate is
      * also less than 2. */
     if (move_rate < 2 * SINGLE_MOVE) {
Index: common/effects.c
===================================================================
--- common/effects.c    (revision 11170)
+++ common/effects.c    (working copy)
@@ -80,27 +80,18 @@
   "SS_Component",
   "SS_Module",
   "Spy_Resistant",
-  "Sea_Move",
+  "Move_Bonus",
   "Unit_No_Lose_Pop",
   "Unit_Recover",
   "Upgrade_Unit",
   "Upkeep_Free",
   "No_Unhappy",
-  "Land_Veteran",
-  "Sea_Veteran",
-  "Air_Veteran",
-  "Land_Vet_Combat",
-  /* TODO: "Sea_Vet_Combat", */
-  /* TODO: "Air_Vet_Combat", */
-  "Land_Regen",
-  "Sea_Regen",
-  "Air_Regen",
+  "Veteran_Build",
+  "Veteran_Combat",
+  "HP_Regen",
   "City_Vision_Radius_Sq",
   "Unit_Vision_Radius_Sq",
-  "Land_Defend",
-  "Sea_Defend",
-  "Air_Defend",
-  "Missile_Defend",
+  "Defend_Bonus",
   "No_Incite",
   "Gain_AI_Love",
   "Slow_Down_Timeline",
@@ -112,7 +103,6 @@
   "Martial_Law_Max",
   "Rapture_Grow",
   "Unbribable_Units",
-  "Veteran_Diplomats",
   "Revolution_When_Unhappy",
   "Has_Senate",
   "Inspire_Partisans",
@@ -856,8 +846,10 @@
 {
   assert(punit != NULL);
   return get_target_bonus_effects(NULL,
-                                 unit_owner(punit), NULL, NULL,
-                                 NULL, punit->type, NULL, NULL,
+                                 unit_owner(punit),
+                                 punit->tile ? punit->tile->city : NULL,
+                                 NULL, punit->tile,
+                                 punit->type, NULL, NULL,
                                  effect_type);
 }
 
Index: common/effects.h
===================================================================
--- common/effects.h    (revision 11170)
+++ common/effects.h    (working copy)
@@ -68,27 +68,18 @@
   EFT_SS_COMPONENT,
   EFT_SS_MODULE,
   EFT_SPY_RESISTANT,
-  EFT_SEA_MOVE,
+  EFT_MOVE_BONUS,
   EFT_UNIT_NO_LOSE_POP,
   EFT_UNIT_RECOVER,
   EFT_UPGRADE_UNIT,
   EFT_UPKEEP_FREE,
   EFT_NO_UNHAPPY,
-  EFT_LAND_VETERAN,
-  EFT_SEA_VETERAN,
-  EFT_AIR_VETERAN,
-  EFT_LAND_VET_COMBAT,
-  /* TODO: EFT_SEA_VET_COMBAT, */
-  /* TODO: EFT_AIR_VET_COMBAT, */
-  EFT_LAND_REGEN,
-  EFT_SEA_REGEN,
-  EFT_AIR_REGEN,
+  EFT_VETERAN_BUILD,
+  EFT_VETERAN_COMBAT,
+  EFT_HP_REGEN,
   EFT_CITY_VISION_RADIUS_SQ,
   EFT_UNIT_VISION_RADIUS_SQ,
-  EFT_LAND_DEFEND,
-  EFT_SEA_DEFEND,
-  EFT_AIR_DEFEND,
-  EFT_MISSILE_DEFEND,
+  EFT_DEFEND_BONUS,
   EFT_NO_INCITE,
   EFT_GAIN_AI_LOVE,
   EFT_SLOW_DOWN_TIMELINE,
@@ -100,7 +91,6 @@
   EFT_MARTIAL_LAW_MAX,
   EFT_RAPTURE_GROW,
   EFT_UNBRIBABLE_UNITS,
-  EFT_VETERAN_DIPLOMATS,
   EFT_REVOLUTION_WHEN_UNHAPPY,
   EFT_HAS_SENATE,
   EFT_INSPIRE_PARTISANS,
@@ -188,6 +178,10 @@
                       const struct tile *ptile, /* pcity is implied */
                       const struct unit_type *punittype,
                       enum effect_type effect_type);
+int get_unittype_bonus(const struct player *pplayer,
+                      const struct tile *ptile, /* pcity is implied */
+                      const struct unit_type *punittype,
+                      enum effect_type effect_type);
 int get_unit_bonus(const struct unit *punit, enum effect_type effect_type);
 
 /* miscellaneous auxiliary effects functions */
Index: ai/aiunit.h
===================================================================
--- ai/aiunit.h (revision 11170)
+++ ai/aiunit.h (working copy)
@@ -85,6 +85,7 @@
 int unit_def_rating_basic_sq(struct unit *punit);
 int unittype_def_rating_sq(const struct unit_type *att_type,
                           const struct unit_type *def_type,
+                          const struct player *def_player,
                            struct tile *ptile, bool fortified, int veteran);
 int kill_desire(int benefit, int attack, int loss, int vuln, int attack_count);
 
Index: ai/advdiplomacy.c
===================================================================
--- ai/advdiplomacy.c   (revision 11170)
+++ ai/advdiplomacy.c   (working copy)
@@ -652,8 +652,7 @@
     want += pcity->size * 20;
     want += pcity->surplus[O_SHIELD] * 8;
     want += pcity->surplus[O_TRADE] * 6;
-    fear += get_city_bonus(pcity, EFT_LAND_DEFEND);
-    fear += get_city_bonus(pcity, EFT_SEA_DEFEND);
+    fear += get_city_bonus(pcity, EFT_DEFEND_BONUS);
     built_impr_iterate(pcity, id) {
       want += impr_build_shield_cost(id);
       if (is_great_wonder(id)) {
Index: ai/aicity.c
===================================================================
--- ai/aicity.c (revision 11170)
+++ ai/aicity.c (working copy)
@@ -543,33 +543,29 @@
        case EFT_SPY_RESISTANT:
          /* Uhm, problem: City Wall has -50% here!! */
          break;
-       case EFT_SEA_MOVE:
-         v += ai->stats.units.sea * 8 * amount;
+       case EFT_MOVE_BONUS:
+         /* FIXME: check other reqs (e.g., unitclass) */
+         v += (8 * v * amount + ai->stats.units.land
+               + ai->stats.units.sea + ai->stats.units.air);
          break;
        case EFT_UNIT_NO_LOSE_POP:
          v += unit_list_size(ptile->units) * 2;
          break;
-       case EFT_LAND_REGEN:
-         v += 5 * c + ai->stats.units.land * 3;
+       case EFT_HP_REGEN:
+         /* FIXME: check other reqs (e.g., unitclass) */
+         v += (5 * c + ai->stats.units.land
+               + ai->stats.units.sea + ai->stats.units.air);
          break;
-       case EFT_SEA_REGEN:
-         v += 5 * c + ai->stats.units.sea * 3;
+       case EFT_VETERAN_COMBAT:
+         /* FIXME: check other reqs (e.g., unitclass) */
+         v += (2 * c + ai->stats.units.land + ai->stats.units.sea
+               + ai->stats.units.air);
          break;
-       case EFT_AIR_REGEN:
-         v += 5 * c + ai->stats.units.air * 3;
+       case EFT_VETERAN_BUILD:
+         /* FIXME: check other reqs (e.g., unitclass, unitflag) */
+         v += (3 * c + ai->stats.units.land + ai->stats.units.sea
+               + ai->stats.units.air);
          break;
-       case EFT_LAND_VET_COMBAT:
-         v += 2 * c + ai->stats.units.land * 2;
-         break;
-       case EFT_LAND_VETERAN:
-         v += 3 * c + ai->stats.units.land;
-         break;
-       case EFT_SEA_VETERAN:
-         v += 5 * c + ai->stats.units.sea;
-         break;
-       case EFT_AIR_VETERAN:
-         v += 5 * c + ai->stats.units.air;
-         break;
        case EFT_UPGRADE_UNIT:
          v += ai->stats.units.upgradeable;
          if (amount == 1) {
@@ -580,7 +576,7 @@
            v *= 4;
          }
          break;
-       case EFT_SEA_DEFEND:
+       case EFT_DEFEND_BONUS:
          if (ai_handicap(pplayer, H_DEFENSIVE)) {
            v += amount / 10; /* make AI slow */
          }
@@ -598,34 +594,16 @@
            } adjc_iterate_end;
          }
          v += (amount/20 + ai->threats.invasions - 1) * c; /* for wonder */
-         if (capital && ai->threats.invasions) {
-           v += amount; /* 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/10 * 5 + amount/10 * c : c;
-         break;
-       case EFT_MISSILE_DEFEND:
-         if (ai->threats.missile
-             && (ai->threats.continent[ptile->continent] || capital)) {
-           v += amount/10 * 5 + (amount/10 - 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->tile))) {
-           v += amount / (!ai->threats.igwall ? (15 - capital * 5) : 15);
+                 && is_water_adjacent_to_tile(pcity->tile))) {
+           if (ai->threats.continent[ptile->continent]) {
+             v += amount;
+           } else {
+             v += amount / (!ai->threats.igwall ? (15 - capital * 5) : 15);
+           }
          }
-         v += (1 + ai->threats.invasions + !ai->threats.igwall) * c;
          break;
        case EFT_NO_INCITE:
          if (get_city_bonus(pcity, EFT_NO_INCITE) <= 0) {
@@ -655,7 +633,6 @@
         case EFT_MARTIAL_LAW_MAX:
         case EFT_RAPTURE_GROW:
         case EFT_UNBRIBABLE_UNITS:
-        case EFT_VETERAN_DIPLOMATS:
         case EFT_REVOLUTION_WHEN_UNHAPPY:
         case EFT_HAS_SENATE:
         case EFT_INSPIRE_PARTISANS:
@@ -1069,7 +1046,7 @@
 {
   impr_type_iterate(id) {
     if (can_city_sell_building(pcity, id)
-       && !building_has_effect(id, EFT_LAND_DEFEND)) {
+       && !building_has_effect(id, EFT_DEFEND_BONUS)) {
 /* selling walls to buy defenders is counterproductive -- Syela */
       really_handle_city_sell(pplayer, pcity, id);
       break;
@@ -1363,7 +1340,7 @@
 
   built_impr_iterate(pcity, i) {
     if(can_city_sell_building(pcity, i) 
-       && !building_has_effect(i, EFT_LAND_DEFEND)
+       && !building_has_effect(i, EFT_DEFEND_BONUS)
              /* selling city walls is really, really dumb -- Syela */
        && (is_building_replaced(pcity, i)
           || building_unwanted(city_owner(pcity), i))) {
Index: ai/aihand.c
===================================================================
--- ai/aihand.c (revision 11170)
+++ ai/aihand.c (working copy)
@@ -313,7 +313,7 @@
       /* Bonuses for non-economic abilities. We increase val by
        * a very small amount here to choose govt in cases where
        * we have no cities yet. */
-      bonus += get_player_bonus(pplayer, EFT_VETERAN_DIPLOMATS) ? 3 : 0;
+      bonus += get_player_bonus(pplayer, EFT_VETERAN_BUILD) ? 3 : 0;
       bonus -= get_player_bonus(pplayer, EFT_REVOLUTION_WHEN_UNHAPPY) ? 3 : 0;
       bonus += get_player_bonus(pplayer, EFT_NO_INCITE) ? 4 : 0;
       bonus += get_player_bonus(pplayer, EFT_UNBRIBABLE_UNITS) ? 2 : 0;
Index: ai/advmilitary.c
===================================================================
--- ai/advmilitary.c    (revision 11170)
+++ ai/advmilitary.c    (working copy)
@@ -62,6 +62,7 @@
     if (can_build_unit(pcity, punittype)
        && (move_type == LAND_MOVING || move_type == SEA_MOVING)) {
       const int defense = get_virtual_defense_power(v, punittype,
+                                                   pcity->owner,
                                                    pcity->tile,
                                                    FALSE, FALSE);
 
@@ -327,6 +328,7 @@
 {
   unsigned int danger;
   bool sailing;
+  int mod;
 
   if (unit_flag(punit, F_NO_LAND_ATTACK)) return 0;
 
@@ -336,12 +338,9 @@
   }
 
   danger = unit_att_rating(punit);
-  if (sailing && get_city_bonus(pcity, EFT_SEA_DEFEND) > 0) {
-    danger /= 2;
-  }
-  if (is_air_unit(punit) && get_city_bonus(pcity, EFT_AIR_DEFEND) > 0) {
-    danger /= 2;
-  }
+  mod = 100 + get_unittype_bonus(pcity->owner, pcity->tile,
+                                punit->type, EFT_DEFEND_BONUS);
+  danger = danger * 100 / MAX(mod, 1);
 
   return danger;
 }
@@ -454,7 +453,7 @@
 static unsigned int assess_danger(struct city *pcity)
 {
   int i;
-  int danger[5], defender[4];
+  int danger[5], defender;
   struct player *pplayer = city_owner(pcity);
   bool pikemen = FALSE;
   unsigned int urgency = 0;
@@ -573,30 +572,12 @@
 
   /* HACK: This needs changing if multiple improvements provide
    * this effect. */
-  defender[0] = ai_find_source_building(pplayer, EFT_LAND_DEFEND);
-  defender[1] = ai_find_source_building(pplayer, EFT_SEA_DEFEND);
-  defender[2] = ai_find_source_building(pplayer, EFT_AIR_DEFEND);
-  defender[3] = ai_find_source_building(pplayer, EFT_MISSILE_DEFEND);
+  defender = ai_find_source_building(pplayer, EFT_DEFEND_BONUS);
 
-  if (defender[0] != B_LAST) {
-    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender[0]],
-       urgency, danger[1], assess_defense(pcity));
+  if (defender != B_LAST) {
+    ai_reevaluate_building(pcity, &pcity->ai.building_want[defender],
+       urgency, danger[1], assess_defense_igwall(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;
@@ -806,6 +787,7 @@
 static void process_attacker_want(struct city *pcity,
                                   int value,
                                  struct unit_type *victim_unit_type,
+                                 struct player *victim_player,
                                   int veteran, struct tile *ptile,
                                   struct ai_choice *best_choice,
                                   struct unit *boat,
@@ -853,9 +835,9 @@
                                       punittype->obsoleted_by))
         && punittype->attack_strength > 0 /* or we'll get SIGFPE */
         && move_type == orig_move_type) {
-      /* TODO: Case for Airport. -- Raahul */
-      int will_be_veteran = (move_type == LAND_MOVING
-         || ai_find_source_building(pplayer, EFT_SEA_VETERAN) != B_LAST);
+      /* TODO: check for the right _type_ of building. */
+      int will_be_veteran
+       = (ai_find_source_building(pplayer, EFT_VETERAN_BUILD) != B_LAST);
       /* Cost (shield equivalent) of gaining these techs. */
       /* FIXME? Katvrr advises that this should be weighted more heavily in big
        * danger. */
@@ -903,6 +885,7 @@
       /* Estimate strength of the enemy. */
       
       vuln = unittype_def_rating_sq(punittype, victim_unit_type,
+                                   victim_player,
                                     ptile, FALSE, veteran);
 
       /* Not bothering to s/!vuln/!pdef/ here for the time being. -- Syela
@@ -1005,21 +988,20 @@
   int attack;
   /* Benefit from fighting the target */
   int benefit;
-  /* Enemy defender type */
+  /* Defender of the target city/tile */
+  struct unit *pdef; 
   struct unit_type *def_type;
+  struct player *def_owner;
+  int def_vet; /* Is the defender veteran? */
   /* Target coordinates */
   struct tile *ptile;
   /* Our transport */
   struct unit *ferryboat = NULL;
   /* Our target */
   struct city *acity;
-  /* Defender of the target city/tile */
-  struct unit *pdef; 
   /* Type of the boat (real or a future one) */
   struct unit_type *boattype = NULL;
   bool go_by_boat;
-  /* Is the defender veteran? */
-  int def_vet;
   struct ai_choice best_choice;
 
   init_choice(&best_choice);
@@ -1100,9 +1082,10 @@
                                     go_by_boat, ferryboat, boattype);
 
     def_type = ai_choose_defender_versus(acity, myunit->type);
+    def_owner = acity->owner;
     if (move_time > 1) {
       def_vet = do_make_unit_veteran(acity, def_type);
-      vuln = unittype_def_rating_sq(myunit->type, def_type,
+      vuln = unittype_def_rating_sq(myunit->type, def_type, acity->owner,
                                     ptile, FALSE, def_vet);
       benefit = unit_build_shield_cost(def_type);
     } else {
@@ -1113,13 +1096,14 @@
 
     pdef = get_defender(myunit, ptile);
     if (pdef) {
-      int m = unittype_def_rating_sq(myunit->type, pdef->type,
+      int m = unittype_def_rating_sq(myunit->type, pdef->type, acity->owner,
                                      ptile, FALSE, pdef->veteran);
       if (vuln < m) {
         vuln = m;
         benefit = unit_build_shield_cost(pdef->type);
         def_vet = pdef->veteran;
         def_type = pdef->type; 
+       def_owner = pdef->owner;
       }
     }
     if (COULD_OCCUPY(myunit) || TEST_BIT(acity->ai.invasion, 0)) {
@@ -1141,17 +1125,20 @@
 
     def_type = pdef->type;
     def_vet = pdef->veteran;
+    def_owner = pdef->owner;
     /* end dealing with units */
   }
   
   if (!go_by_boat) {
-    process_attacker_want(pcity, benefit, def_type, def_vet, ptile, 
+    process_attacker_want(pcity, benefit, def_type, def_owner,
+                         def_vet, ptile, 
                           &best_choice, NULL, NULL);
   } else { 
     /* Attract a boat to our city or retain the one that's already here */
     assert(is_ground_unit(myunit));
     best_choice.need_boat = TRUE;
-    process_attacker_want(pcity, benefit, def_type, def_vet, ptile, 
+    process_attacker_want(pcity, benefit, def_type, def_owner,
+                         def_vet, ptile, 
                           &best_choice, ferryboat, boattype);
   }
 
@@ -1231,31 +1218,11 @@
   }
 
   move_type = get_unit_type(choice->choice)->move_type;
-  switch(move_type) {
-  case LAND_MOVING:
-    if ((id = ai_find_source_building(pplayer, EFT_LAND_VETERAN)) != B_LAST) {
-      choice->choice = id;
-      choice->type = CT_BUILDING;
-    }
-    break;
-  case SEA_MOVING:
-    if ((id = ai_find_source_building(pplayer, EFT_SEA_VETERAN)) != B_LAST) {
-      choice->choice = id;
-      choice->type = CT_BUILDING;
-    }
-    break;
-  case HELI_MOVING:
-  case AIR_MOVING:
-    if ((id = ai_find_source_building(pplayer, EFT_AIR_VETERAN)) != B_LAST
-        && pcity->surplus[O_SHIELD] > impr_build_shield_cost(id) / 10) {
-      /* Only build this if we have really high production */
-      choice->choice = id;
-      choice->type = CT_BUILDING;
-    }
-    break;
-  default:
-    freelog(LOG_ERROR, "Unknown move_type in adjust_ai_unit_choice");
-    assert(FALSE);
+
+  /* TODO: separate checks based on other requirements (e.g., unit class) */
+  if ((id = ai_find_source_building(pplayer, EFT_VETERAN_BUILD)) != B_LAST) {
+    choice->choice = id;
+    choice->type = CT_BUILDING;
   }
 }
 
@@ -1291,7 +1258,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, danger;
+    int wall_id, danger;
 
     /* First determine the danger.  It is measured in percents of our 
      * defensive strength, capped at 200 + urgency */
@@ -1323,61 +1290,32 @@
 
     /* HACK: This needs changing if multiple improvements provide
      * this effect. */
-    land_id = ai_find_source_building(pplayer, EFT_LAND_DEFEND);
-    sea_id = ai_find_source_building(pplayer, EFT_SEA_DEFEND);
-    air_id = ai_find_source_building(pplayer, EFT_AIR_DEFEND);
+    wall_id = ai_find_source_building(pplayer, EFT_DEFEND_BONUS);
 
-    if (land_id != B_LAST
-       && pcity->ai.building_want[land_id] != 0 && our_def != 0 
-        && can_build_improvement(pcity, land_id)
+    if (wall_id != B_LAST
+       && pcity->ai.building_want[wall_id] != 0 && our_def != 0 
+        && can_build_improvement(pcity, wall_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 = land_id;
+      choice->choice = wall_id;
       /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[land_id];
+      choice->want = pcity->ai.building_want[wall_id];
       if (urgency == 0 && choice->want > 100) {
         choice->want = 100;
       }
       choice->type = CT_BUILDING;
-      CITY_LOG(LOG_DEBUG, pcity, "m_a_c_d wants land defense building with %d",
+      CITY_LOG(LOG_DEBUG, pcity, "m_a_c_d wants defense building with %d",
                choice->want);
-    } 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 = sea_id;
-      /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[sea_id];
-      if (urgency == 0 && choice->want > 100) {
-        choice->want = 100;
-      }
-      choice->type = CT_BUILDING;
-      CITY_LOG(LOG_DEBUG, pcity, "m_a_c_d wants sea defense building with %d",
-               choice->want);
-    } 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 = air_id;
-      /* building_want is hacked by assess_danger */
-      choice->want = pcity->ai.building_want[air_id];
-      if (urgency == 0 && choice->want > 100) {
-        choice->want = 100;
-      }
-      choice->type = CT_BUILDING;
-      CITY_LOG(LOG_DEBUG, pcity, "m_a_c_d wants air defense building with %d",
-               choice->want);
     } else if (danger > 0 && num_defenders <= urgency) {
       /* Consider building defensive units units */
       process_defender_want(pplayer, pcity, danger, choice);
       if (urgency == 0
          && get_unit_type(choice->choice)->defense_strength == 1) {
-        if (get_city_bonus(pcity, EFT_LAND_REGEN) > 0) {
+       /* FIXME: check other reqs (unit class?) */
+        if (get_city_bonus(pcity, EFT_HP_REGEN) > 0) {
           /* unlikely */
           choice->want = MIN(49, danger);
         } else {
Index: ai/aiunit.c
===================================================================
--- ai/aiunit.c (revision 11175)
+++ ai/aiunit.c (working copy)
@@ -390,9 +390,10 @@
 **************************************************************************/
 int unittype_def_rating_sq(const struct unit_type *att_type,
                           const struct unit_type *def_type,
+                          const struct player *def_player,
                            struct tile *ptile, bool fortified, int veteran)
 {
-  int v = get_virtual_defense_power(att_type, def_type, ptile,
+  int v = get_virtual_defense_power(att_type, def_type, def_player, ptile,
                                     fortified, veteran)
     * def_type->hp * def_type->firepower / POWER_DIVIDER;
 
@@ -492,12 +493,14 @@
        continue;
       if (!can_unit_attack_all_at_tile(aunit, pdef->tile))
        continue;
-      d = get_virtual_defense_power(aunit->type, pdef->type, pdef->tile,
+      d = get_virtual_defense_power(aunit->type, pdef->type, pdef->owner,
+                                   pdef->tile,
                                    FALSE, 0);
       if (d == 0)
        return TRUE;            /* Thanks, Markus -- Syela */
       cur = unit_att_rating_now(aunit) *
-         get_virtual_defense_power(punit->type, pdef->type, pdef->tile,
+         get_virtual_defense_power(punit->type, pdef->type,
+                                   pdef->owner, pdef->tile,
                                    FALSE, 0) / d;
       if (cur > val && ai_fuzzy(unit_owner(punit), TRUE))
        return FALSE;
@@ -1387,7 +1390,7 @@
         struct unit_type *def_type
          = ai_choose_defender_versus(acity, punit->type);
         int v = unittype_def_rating_sq(punit->type, def_type,
-                                       acity->tile, FALSE,
+                                       acity->owner, acity->tile, FALSE,
                                        do_make_unit_veteran(acity, def_type));
         if (v > vuln) {
           /* They can build a better defender! */ 
@@ -1595,15 +1598,14 @@
       city_list_iterate(aplayer->cities, pcity) {
         if (ground) {
           cur = WARMAP_COST(pcity->tile);
-          if (get_city_bonus(pcity, EFT_LAND_REGEN) > 0) {
-            cur /= 3;
-          }
         } else {
           cur = WARMAP_SEACOST(pcity->tile);
-          if (get_city_bonus(pcity, EFT_SEA_REGEN) > 0) {
-            cur /= 3;
-          }
         }
+       /* Note the "player" here is the unit owner NOT the city owner. */
+       if (get_unittype_bonus(punit->owner, pcity->tile, punit->type,
+                              EFT_HP_REGEN) > 0) {
+         cur /= 3;
+       }
         if (cur < best) {
           best = cur;
           acity = pcity;

[Prev in Thread] Current Thread [Next in Thread]