diff -urd -X clean/diff_ignore Part_app/ai/advmilitary.c work/ai/advmilitary.c --- Part_app/ai/advmilitary.c Wed Feb 27 14:11:50 2002 +++ work/ai/advmilitary.c Wed Feb 27 16:20:11 2002 @@ -591,11 +591,7 @@ } else if (real_map_distance(pcity->x, pcity->y, x, y) * SINGLE_MOVE <= m) c = 1; else c = real_map_distance(pcity->x, pcity->y, x, y) * SINGLE_MOVE * q / m; - m = get_virtual_defense_power(i, n, x, y); - m *= unit_types[n].hp * unit_types[n].firepower; - if (vet) m *= 1.5; - m /= 30; - m *= m; + m = unit_vulnerability_virtual2(i, n, x, y, FALSE, vet, FALSE, 0); d = m; if (unit_types[i].move_type == LAND_MOVING && acity && @@ -724,12 +720,11 @@ else c = real_map_distance(myunit->x, myunit->y, acity->x, acity->y) * SINGLE_MOVE / m; n = ai_choose_defender_versus(acity, v); - m = get_virtual_defense_power(v, n, x, y); - m *= unit_types[n].hp * unit_types[n].firepower; - if (do_make_unit_veteran(acity, n)) m *= 1.5; - m /= 30; + m = unit_vulnerability_virtual2(v, n, x, y, FALSE, + do_make_unit_veteran(acity, n), FALSE, + 0); if (c > 1) { - d = m * m; + d = m; b = unit_types[n].build_cost + 40; vet = do_make_unit_veteran(acity, n); } else { @@ -742,14 +737,11 @@ Yet, somehow, this line existed, and remained here for months, bugging the AI tech progression beyond all description. Only when adding the override code did I realize the magnitude of my transgression. How despicable. -- Syela */ - m = get_virtual_defense_power(v, pdef->type, x, y); - if (pdef->veteran) m *= 1.5; /* with real defenders, this must be before * hp -- Syela */ - m *= (myunit->id ? pdef->hp : unit_type(pdef)->hp) * - unit_type(pdef)->firepower; + m = unit_vulnerability_virtual2(v, pdef->type, x, y, FALSE, + pdef->veteran, myunit->id, pdef->hp); /* m /= (pdef->veteran ? 20 : 30); -- led to rounding errors. Duh! -- Syela */ - m /= 30; - if (d < m * m) { - d = m * m; + if (d < m) { + d = m; b = unit_type(pdef)->build_cost + 40; vet = pdef->veteran; n = pdef->type; /* and not before, or heinous things occur!! */ @@ -784,16 +776,9 @@ c = ((dist + m - 1) / m); n = pdef->type; - m = get_virtual_defense_power(v, n, x, y); - if (pdef->veteran) m += m / 2; - if (pdef->activity == ACTIVITY_FORTIFIED) m += m / 2; -/* attempting to recreate the rounding errors in get_total_defense_power -- Syela */ - - m *= (myunit->id ? pdef->hp : unit_types[n].hp) * unit_types[n].firepower; -/* let this be the LAST discrepancy! How horribly many there have been! -- Syela */ -/* m /= (pdef->veteran ? 20 : 30);*/ - m /= 30; - m *= m; + m = unit_vulnerability_virtual2(v, n, x, y, + pdef->activity == ACTIVITY_FORTIFIED, + pdef->veteran, myunit->id, pdef->hp); d = m; vet = pdef->veteran; } /* end dealing with units */ diff -urd -X clean/diff_ignore Part_app/ai/aicity.c work/ai/aicity.c --- Part_app/ai/aicity.c Wed Feb 27 14:06:01 2002 +++ work/ai/aicity.c Wed Feb 27 16:20:10 2002 @@ -303,12 +303,11 @@ static int ai_city_defender_value(struct city *pcity, Unit_Type_id a_type, Unit_Type_id d_type) { - int m; - m = get_virtual_defense_power(a_type, d_type, pcity->x, pcity->y); - if (do_make_unit_veteran(pcity, d_type)) m *= 1.5; - m *= unit_types[d_type].hp * unit_types[d_type].firepower; - m /= 30; - return (m * m); + int m = unit_vulnerability_virtual2(a_type, d_type, pcity->x, + pcity->y, FALSE, + do_make_unit_veteran(pcity, d_type), + FALSE, 0); + return m; } #endif @@ -689,7 +688,7 @@ if (!is_ai_simple_military(i)) continue; m = unit_types[i].move_type; if (can_build_unit(pcity, i) && (m == LAND_MOVING || m == SEA_MOVING)) { - j = get_virtual_defense_power(v, i, pcity->x, pcity->y); + j = get_virtual_defense_power(v, i, pcity->x, pcity->y, FALSE, FALSE); if (j > best || (j == best && get_unit_type(i)->build_cost <= get_unit_type(bestid)->build_cost)) { best = j; diff -urd -X clean/diff_ignore Part_app/ai/aiunit.c work/ai/aiunit.c --- Part_app/ai/aiunit.c Wed Feb 27 14:11:50 2002 +++ work/ai/aiunit.c Wed Feb 27 16:20:15 2002 @@ -588,23 +588,29 @@ int unit_vulnerability_basic(struct unit *punit, struct unit *pdef) { - int v; - - v = get_total_defense_power(punit, pdef) * - (punit->id ? pdef->hp : unit_type(pdef)->hp) * - unit_type(pdef)->firepower / 30; - - return(v); + return (get_total_defense_power(punit, pdef) * + (punit->id != 0 ? pdef->hp : unit_type(pdef)->hp) * + unit_type(pdef)->firepower / POWER_DIVIDER); } int unit_vulnerability_virtual(struct unit *punit) { - int v; - v = unit_type(punit)->defense_strength * - (punit->veteran ? 15 : 10) * punit->hp / 30; + int v = base_get_defense_power(punit) * punit->hp / POWER_DIVIDER; + return(v * v); } +int unit_vulnerability_virtual2(Unit_Type_id att_type, Unit_Type_id def_type, + int x, int y, bool fortified, bool veteran, + bool use_extra_hp, int extra_hp) +{ + int v = (get_virtual_defense_power(att_type, def_type, x, y, fortified, + veteran) * + (use_extra_hp ? extra_hp : unit_types[def_type].hp) * + unit_types[def_type].firepower / POWER_DIVIDER); + return v * v; +} + int unit_vulnerability(struct unit *punit, struct unit *pdef) { int v = unit_vulnerability_basic(punit, pdef); @@ -755,14 +761,13 @@ continue; if (!can_unit_attack_unit_at_tile(aunit, pdef, pdef->x, pdef->y)) continue; - d = - get_virtual_defense_power(aunit->type, pdef->type, pdef->x, - pdef->y); + d = get_virtual_defense_power(aunit->type, pdef->type, pdef->x, + pdef->y, FALSE, FALSE); if (!d) return TRUE; /* Thanks, Markus -- Syela */ cur = unit_belligerence_primitive(aunit) * get_virtual_defense_power(punit->type, pdef->type, pdef->x, - pdef->y) / d; + pdef->y, FALSE, FALSE) / d; if (cur > val && ai_fuzzy(unit_owner(punit), TRUE)) return FALSE; } @@ -1089,11 +1094,9 @@ freelog(LOG_DEBUG, "%s@(%d,%d) looking for bodyguard, d_val=%d, my_val=%d", unit_type(punit)->name, punit->x, punit->y, d_val, - (punit->hp * (punit->veteran ? 15 : 10) - * unit_type(punit)->defense_strength)); + (punit->hp * base_get_defense_power(punit))); ptile = map_get_tile(punit->x, punit->y); - if (d_val >= punit->hp * (punit->veteran ? 15 : 10) * - unit_type(punit)->defense_strength) { + if (d_val >= punit->hp * base_get_defense_power(punit)) { /* if (!unit_list_find(&pplayer->units, punit->ai.bodyguard)) Ugggggh */ if (!unit_list_find(&ptile->units, punit->ai.bodyguard)) punit->ai.bodyguard = -1; @@ -1532,10 +1535,11 @@ * SINGLE_MOVE) / m; if (c > 1) { n = ai_choose_defender_versus(acity, punit->type); - v = get_virtual_defense_power(punit->type, n, acity->x, acity->y) * - unit_types[n].hp * unit_types[n].firepower * - (do_make_unit_veteran(acity, n) ? 1.5 : 1.0) / 30; - if (v * v >= d) { d = v * v; b = unit_types[n].build_cost + 40; } + v = unit_vulnerability_virtual2(punit->type, n, acity->x, + acity->y, FALSE, + do_make_unit_veteran(acity, n), + FALSE, 0); + if (v >= d) { d = v; b = unit_types[n].build_cost + 40; } } /* let's hope this works! */ if (!is_ground_unit(punit) && !is_heli_unit(punit) && (!(acity->ai.invasion&1))) b -= 40; /* boats can't conquer cities */ diff -urd -X clean/diff_ignore Part_app/ai/aiunit.h work/ai/aiunit.h --- Part_app/ai/aiunit.h Wed Feb 27 14:11:50 2002 +++ work/ai/aiunit.h Wed Feb 27 16:07:19 2002 @@ -48,6 +48,9 @@ int unit_belligerence(struct unit *punit); int unit_vulnerability_basic(struct unit *punit, struct unit *pdef); int unit_vulnerability_virtual(struct unit *punit); +int unit_vulnerability_virtual2(Unit_Type_id att_type, Unit_Type_id def_type, + int x, int y, bool fortified, bool veteran, + bool use_extra_hp, int extra_hp); int unit_vulnerability(struct unit *punit, struct unit *pdef); int military_amortize(int value, int delay, int build_cost); diff -urd -X clean/diff_ignore Part_app/common/combat.c work/common/combat.c --- Part_app/common/combat.c Wed Feb 27 14:11:50 2002 +++ work/common/combat.c Wed Feb 27 16:43:15 2002 @@ -266,27 +266,29 @@ } /************************************************************************** + returns the defense power, modified by veteran status +**************************************************************************/ +int base_get_defense_power(struct unit *punit) +{ + int power = unit_type(punit)->defense_strength * POWER_FACTOR; + if (punit->veteran) { + power = (power * 3) / 2; + } + return power; +} + +/************************************************************************** returns the defense power, modified by terrain and veteran status **************************************************************************/ int get_defense_power(struct unit *punit) { - int power; - enum tile_terrain_type terra; - int db; + int db, power = base_get_defense_power(punit); - if (!punit || punit->type<0 || punit->type>=U_LAST - || punit->type>=game.num_unit_types) - abort(); - power = unit_type(punit)->defense_strength * POWER_FACTOR; - if (punit->veteran) { - power *= 3; - power /= 2; - } - terra=map_get_terrain(punit->x, punit->y); - db = get_tile_type(terra)->defense_bonus; - if (map_has_special(punit->x, punit->y, S_RIVER)) + db = get_tile_type(map_get_terrain(punit->x, punit->y))->defense_bonus; + if (map_has_special(punit->x, punit->y, S_RIVER)) { db += (db * terrain_control.river_defense_bonus) / 100; - power=(power*db)/10; + } + power = (power * db) / 10; return power; } @@ -302,81 +304,97 @@ return attackpower; } -/*************************************************************************** - Like get_virtual_defense_power, but don't include most of the modifications. - (For calls which used to be g_v_d_p(U_HOWITZER,...)) - Specifically, include: - unit def, terrain effect, fortress effect, ground unit in city effect -***************************************************************************/ -int get_simple_defense_power(Unit_Type_id d_type, int x, int y) +/************************************************************************** + Return an increased defensepower. Effects which increase the + defensepower are: + - unit type effects (horse vs pikemen for example) + - defender in a fortress + - fortified defender + +May be called with a non-existing att_type to avoid any unit type +effects. +**************************************************************************/ +static int defence_multiplication(Unit_Type_id att_type, + Unit_Type_id def_type, int x, int y, + int defensepower, bool fortified) { - int defensepower=unit_types[d_type].defense_strength; struct city *pcity = map_get_city(x, y); - enum tile_terrain_type t = map_get_terrain(x, y); - int db; - if (unit_types[d_type].move_type == LAND_MOVING && t == T_OCEAN) return 0; -/* I had this dorky bug where transports with mech inf aboard would go next -to enemy ships thinking the mech inf would defend them adequately. -- Syela */ + if (unit_type_exists(att_type)) { + enum unit_move_type att_m_type = unit_types[att_type].move_type; - db = get_tile_type(t)->defense_bonus; - if (map_has_special(x, y, S_RIVER)) - db += (db * terrain_control.river_defense_bonus) / 100; - defensepower *= db; + if (unit_type_flag(def_type, F_PIKEMEN) + && unit_type_flag(att_type, F_HORSE)) { + defensepower *= 2; + } - if (map_has_special(x, y, S_FORTRESS) && !pcity) - defensepower+=(defensepower*terrain_control.fortress_defense_bonus)/100; - if (pcity && unit_types[d_type].move_type == LAND_MOVING) - defensepower*=1.5; + if (unit_type_flag(def_type, F_AEGIS) && + (att_m_type == AIR_MOVING || att_m_type == HELI_MOVING)) { + defensepower *= 5; + } + + if (att_m_type == AIR_MOVING && pcity) { + if (city_got_building(pcity, B_SAM)) { + defensepower *= 2; + } + if (city_got_building(pcity, B_SDI) + && unit_type_flag(att_type, F_MISSILE)) { + defensepower *= 2; + } + } else if (att_m_type == SEA_MOVING && pcity) { + if (city_got_building(pcity, B_COASTAL)) { + defensepower *= 2; + } + } + if (!unit_type_flag(att_type, F_IGWALL) + && (att_m_type == LAND_MOVING || att_m_type == HELI_MOVING + || (improvement_variant(B_CITY) == 1 + && att_m_type == SEA_MOVING)) && pcity + && city_got_citywalls(pcity)) { + defensepower *= 3; + } + } + + if (map_has_special(x, y, S_FORTRESS) && !pcity) { + defensepower += + (defensepower * terrain_control.fortress_defense_bonus) / 100; + } + + if ((pcity || fortified) && unit_types[def_type].move_type == LAND_MOVING) { + defensepower = (defensepower * 3) / 2; + } return defensepower; } /************************************************************************** -... + May be called with a non-existing att_type to avoid any effects which + depend on the attacker. **************************************************************************/ -int get_virtual_defense_power(Unit_Type_id a_type, Unit_Type_id d_type, int x, int y) +int get_virtual_defense_power(Unit_Type_id att_type, Unit_Type_id def_type, + int x, int y, bool fortified, bool veteran) { - int defensepower=unit_types[d_type].defense_strength; - enum unit_move_type m_type = unit_types[a_type].move_type; - struct city *pcity = map_get_city(x, y); + int defensepower = unit_types[def_type].defense_strength; enum tile_terrain_type t = map_get_terrain(x, y); int db; - if (unit_types[d_type].move_type == LAND_MOVING && t == T_OCEAN) return 0; -/* I had this dorky bug where transports with mech inf aboard would go next -to enemy ships thinking the mech inf would defend them adequately. -- Syela */ + if (unit_types[def_type].move_type == LAND_MOVING && t == T_OCEAN) { + /* Ground units on ship doesn't defend. */ + return 0; + } db = get_tile_type(t)->defense_bonus; - if (map_has_special(x, y, S_RIVER)) + if (map_has_special(x, y, S_RIVER)) { db += (db * terrain_control.river_defense_bonus) / 100; + } defensepower *= db; - if (unit_type_flag(d_type, F_PIKEMEN) && unit_type_flag(a_type, F_HORSE)) - defensepower*=2; - if (unit_type_flag(d_type, F_AEGIS) && - (m_type == AIR_MOVING || m_type == HELI_MOVING)) defensepower*=5; - if (m_type == AIR_MOVING && pcity) { - if (city_got_building(pcity, B_SAM)) - defensepower*=2; - if (city_got_building(pcity, B_SDI) && unit_type_flag(a_type, F_MISSILE)) - defensepower*=2; - } else if (m_type == SEA_MOVING && pcity) { - if (city_got_building(pcity, B_COASTAL)) - defensepower*=2; - } - if (!unit_type_flag(a_type, F_IGWALL) - && (m_type == LAND_MOVING || m_type == HELI_MOVING - || (improvement_variant(B_CITY)==1 && m_type == SEA_MOVING)) - && pcity && city_got_citywalls(pcity)) { - defensepower*=3; + if (veteran) { + defensepower = (defensepower * 3) / 2; } - if (map_has_special(x, y, S_FORTRESS) && !pcity) - defensepower+=(defensepower*terrain_control.fortress_defense_bonus)/100; - if (pcity && unit_types[d_type].move_type == LAND_MOVING) - defensepower*=1.5; - return defensepower; + return defence_multiplication(att_type, def_type, x, y, defensepower, + fortified); } /*************************************************************************** @@ -386,33 +404,10 @@ ***************************************************************************/ int get_total_defense_power(struct unit *attacker, struct unit *defender) { - int defensepower=get_defense_power(defender); - if (unit_flag(defender, F_PIKEMEN) && unit_flag(attacker, F_HORSE)) - defensepower*=2; - if (unit_flag(defender, F_AEGIS) - && (is_air_unit(attacker) || is_heli_unit(attacker))) - defensepower *= 5; - if (is_air_unit(attacker)) { - if (unit_behind_sam(defender)) - defensepower*=2; - if (unit_behind_sdi(defender) && unit_flag(attacker, F_MISSILE)) - defensepower*=2; - } else if (is_sailing_unit(attacker)) { - if (unit_behind_coastal(defender)) - defensepower*=2; - } - if (!unit_really_ignores_citywalls(attacker) - && unit_behind_walls(defender)) - defensepower*=3; - if (unit_on_fortress(defender) && - !map_get_city(defender->x, defender->y)) - defensepower*=2; - if ((defender->activity == ACTIVITY_FORTIFIED || - map_get_city(defender->x, defender->y)) && - is_ground_unit(defender)) - defensepower*=1.5; - - return defensepower; + return defence_multiplication(attacker->type, defender->type, + defender->x, defender->y, + get_defense_power(defender), + defender->activity == ACTIVITY_FORTIFIED); } /************************************************************************** diff -urd -X clean/diff_ignore Part_app/common/combat.h work/common/combat.h --- Part_app/common/combat.h Wed Feb 27 14:11:50 2002 +++ work/common/combat.h Wed Feb 27 15:37:18 2002 @@ -43,10 +43,11 @@ int get_attack_power(struct unit *punit); int base_get_attack_power(Unit_Type_id type, bool veteran, int moves_left); +int base_get_defense_power(struct unit *punit); int get_defense_power(struct unit *punit); int get_total_defense_power(struct unit *attacker, struct unit *defender); -int get_simple_defense_power(Unit_Type_id d_type, int x, int y); -int get_virtual_defense_power(Unit_Type_id a_type, Unit_Type_id d_type, int x, int y); +int get_virtual_defense_power(Unit_Type_id att_type, Unit_Type_id def_type, + int x, int y, bool fortified, bool veteran); int get_total_attack_power(struct unit *attacker, struct unit *defender); struct unit *get_defender(struct unit *attacker, int x, int y); Only in work/: diff diff -urd -X clean/diff_ignore Part_app/server/gotohand.c work/server/gotohand.c --- Part_app/server/gotohand.c Wed Feb 27 10:02:41 2002 +++ work/server/gotohand.c Wed Feb 27 15:39:05 2002 @@ -888,7 +888,7 @@ const int dest_x, const int dest_y) { #define UNIT_DEFENSE(punit, x, y, defence_multiplier) \ - ((get_simple_defense_power((punit)->type, (x), (y)) * \ + ((get_virtual_defense_power(U_LAST, (punit)->type, (x), (y), FALSE, FALSE) * \ (defence_multiplier)) / 2) #define UNIT_RATING(punit, x, y, defence_multiplier) \ diff -urd -X clean/diff_ignore Part_app/server/unittools.c work/server/unittools.c --- Part_app/server/unittools.c Wed Feb 27 11:34:01 2002 +++ work/server/unittools.c Wed Feb 27 15:39:57 2002 @@ -1276,7 +1276,7 @@ continue; if (unit_list_size(&ptile->units) > 0) continue; - value = get_simple_defense_power(u_type, x1, y1); + value = get_virtual_defense_power(U_LAST, u_type, x1, y1, FALSE, FALSE); value *= 10; if (ptile->continent != map_get_continent(pcity->x, pcity->y))