refactor terminate (calculate_armor/resistance)

This commit is contained in:
Steffen Mecke 2018-09-11 17:17:47 +02:00
parent aed7432bb2
commit c15b4c8fbf
5 changed files with 130 additions and 96 deletions

View File

@ -519,6 +519,7 @@ function test_buy_sell()
end end
function test_seaserpent_attack() function test_seaserpent_attack()
-- FIXME what does this test do?
local r = region.create(0, 0, 'ocean') local r = region.create(0, 0, 'ocean')
local sh = ship.create(r, 'boat') local sh = ship.create(r, 'boat')
local us = unit.create(get_monsters(), r, 1, 'seaserpent') local us = unit.create(get_monsters(), r, 1, 'seaserpent')

View File

@ -139,7 +139,7 @@ end
function test_bug_2480() function test_bug_2480()
local r = region.create(0, 0, "plain") local r = region.create(0, 0, "plain")
local f = faction.create("human", "hodor@eressea.de", "de") local f = faction.create("human", "2480@eressea.de", "de")
local u1 = unit.create(f, r, 1) local u1 = unit.create(f, r, 1)
local monster = unit.create(get_monsters(), r, 1, "wyrm") local monster = unit.create(get_monsters(), r, 1, "wyrm")
u1.number = 30 u1.number = 30
@ -147,5 +147,4 @@ function test_bug_2480()
monster:add_order("ATTACK " .. itoa36(u1.id)) monster:add_order("ATTACK " .. itoa36(u1.id))
process_orders() process_orders()
assert_equal(0, u1.number); assert_equal(0, u1.number);
write_reports()
end end

View File

@ -555,8 +555,7 @@ static weapon *preferred_weapon(const troop t, bool attacking)
return melee; return melee;
} }
static weapon *select_weapon(const troop t, bool attacking, weapon *select_weapon(const troop t, bool attacking, bool ismissile)
bool ismissile)
/* select the primary weapon for this trooper */ /* select the primary weapon for this trooper */
{ {
if (attacking) { if (attacking) {
@ -770,7 +769,7 @@ bool missile)
return skill; return skill;
} }
static const armor_type *select_armor(troop t, bool shield) const armor_type *select_armor(troop t, bool shield)
{ {
unsigned int type = shield ? ATF_SHIELD : 0; unsigned int type = shield ? ATF_SHIELD : 0;
unit *u = t.fighter->unit; unit *u = t.fighter->unit;
@ -1012,85 +1011,87 @@ static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_
return modifier; return modifier;
} }
int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awtype, variant *magres) { int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awtype,
const armor_type *armor, const armor_type *shield, bool magic) {
fighter *df = dt.fighter; fighter *df = dt.fighter;
unit *du = df->unit; unit *du = df->unit;
int ar = 0, an, am; int total_armor = 0, nat_armor, magic_armor;
const armor_type *armor = select_armor(dt, false);
const armor_type *shield = select_armor(dt, true);
bool missile = awtype && (awtype->flags&WTF_MISSILE); bool missile = awtype && (awtype->flags&WTF_MISSILE);
if (armor) { if (armor) {
ar += armor->prot; total_armor += armor->prot;
if (missile && armor->projectile > 0 && chance(armor->projectile)) { if (missile && armor->projectile > 0 && chance(armor->projectile)) {
return -1; return -1;
} }
} }
if (shield) { if (shield) {
ar += shield->prot; total_armor += shield->prot;
if (missile && shield->projectile > 0 && chance(shield->projectile)) { if (missile && shield->projectile > 0 && chance(shield->projectile)) {
return -1; return -1;
} }
} }
if (magic) {
/* gegen Magie wirkt nur natuerliche und magische Ruestung */
total_armor = 0;
}
/* nat<61>rliche R<>stung */ /* nat<61>rliche R<>stung */
an = natural_armor(du); nat_armor = natural_armor(du);
/* magische R<>stung durch Artefakte oder Spr<70>che */ /* magische R<>stung durch Artefakte oder Spr<70>che */
/* Momentan nur Trollg<6C>rtel und Werwolf-Eigenschaft */ /* Momentan nur Trollg<6C>rtel und Werwolf-Eigenschaft */
am = select_magicarmor(dt); magic_armor = select_magicarmor(dt);
if (rule_nat_armor == 0) { if (rule_nat_armor == 0) {
/* nat<61>rliche R<>stung ist halbkumulativ */ /* nat<61>rliche R<>stung ist halbkumulativ */
if (ar > 0) { if (total_armor > 0) {
ar += an / 2; total_armor += nat_armor / 2;
} }
else { else {
ar = an; total_armor = nat_armor;
} }
} }
else { else {
/* use the higher value, add half the other value */ /* use the higher value, add half the other value */
ar = (ar > an) ? (ar + an / 2) : (an + ar / 2); total_armor = (total_armor > nat_armor) ? (total_armor + nat_armor / 2) : (nat_armor + total_armor / 2);
} }
if (awtype && fval(awtype, WTF_ARMORPIERCING)) { if (awtype && fval(awtype, WTF_ARMORPIERCING)) {
/* crossbows */ /* crossbows */
ar /= 2; total_armor /= 2;
} }
ar += am; total_armor += magic_armor;
if (magres) { return total_armor;
/* calculate damage multiplier for magical damage */ }
variant res;
variant calculate_resistance(troop dt, const weapon_type *dwtype, const armor_type *armor, const armor_type *shield) {
fighter *df = dt.fighter;
unit *du = df->unit;
/* calculate damage multiplier for magical damage */
variant res;
res = frac_sub(frac_one, magic_resistance(du)); res = frac_sub(frac_one, magic_resistance(du));
if (u_race(du)->battle_flags & BF_EQUIPMENT) { if (u_race(du)->battle_flags & BF_EQUIPMENT) {
/* der Effekt von Laen steigt nicht linear */ /* der Effekt von Laen steigt nicht linear */
if (armor && fval(armor, ATF_LAEN)) { if (armor && fval(armor, ATF_LAEN)) {
res = frac_mul(res, frac_sub(frac_one, armor->magres)); res = frac_mul(res, frac_sub(frac_one, armor->magres));
}
if (shield && fval(shield, ATF_LAEN)) {
res = frac_mul(res, frac_sub(frac_one, shield->magres));
}
if (dwtype) {
res = frac_mul(res, frac_sub(frac_one, dwtype->magres));
}
}
/* gegen Magie wirkt nur natuerliche und magische Ruestung */
ar = an + am;
if (res.sa[0] >= 0) {
*magres = res;
}
else {
*magres = frac_make(0, 1);
}
} }
if (shield && fval(shield, ATF_LAEN)) {
return ar; res = frac_mul(res, frac_sub(frac_one, shield->magres));
}
if (dwtype) {
res = frac_mul(res, frac_sub(frac_one, dwtype->magres));
}
}
if (res.sa[0] >= 0) {
return res;
} else {
return frac_zero;
}
} }
static bool resurrect_troop(troop dt) static bool resurrect_troop(troop dt)
@ -1109,7 +1110,7 @@ static bool resurrect_troop(troop dt)
} }
bool bool
terminate(troop dt, troop at, int type, const char *damage, bool missile) terminate(troop dt, troop at, int type, const char *damage_formula, bool missile)
{ {
item **pitm; item **pitm;
fighter *df = dt.fighter; fighter *df = dt.fighter;
@ -1120,16 +1121,19 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
/* Schild */ /* Schild */
side *ds = df->side; side *ds = df->side;
int ar; int armor_value;
const weapon_type *dwtype = NULL; const weapon_type *dwtype = NULL;
const weapon_type *awtype = NULL; const weapon_type *awtype = NULL;
const weapon *weapon; const weapon *weapon;
variant res = frac_one; const armor_type *armor = NULL;
const armor_type *shield = NULL;
int rda, sk = 0, sd; variant resistance_factor = frac_one;
int reduced_damage, attskill = 0, defskill;
bool magic = false; bool magic = false;
int da = dice_rand(damage); int damage = dice_rand(damage_formula);
assert(du->number > 0); assert(du->number > 0);
++at.fighter->hits; ++at.fighter->hits;
@ -1137,14 +1141,14 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
switch (type) { switch (type) {
case AT_STANDARD: case AT_STANDARD:
weapon = select_weapon(at, true, missile); weapon = select_weapon(at, true, missile);
sk = weapon_effskill(at, dt, weapon, true, missile); attskill = weapon_effskill(at, dt, weapon, true, missile);
if (weapon) if (weapon)
awtype = weapon->type; awtype = weapon->type;
if (awtype && fval(awtype, WTF_MAGICAL)) if (awtype && fval(awtype, WTF_MAGICAL))
magic = true; magic = true;
break; break;
case AT_NATURAL: case AT_NATURAL:
sk = weapon_effskill(at, dt, NULL, true, missile); attskill = weapon_effskill(at, dt, NULL, true, missile);
break; break;
case AT_SPELL: case AT_SPELL:
case AT_COMBATSPELL: case AT_COMBATSPELL:
@ -1154,63 +1158,69 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
break; break;
} }
weapon = select_weapon(dt, false, true); /* missile=true to get the unmodified best weapon she has */ weapon = select_weapon(dt, false, true); /* missile=true to get the unmodified best weapon she has */
sd = weapon_effskill(dt, at, weapon, false, false); defskill = weapon_effskill(dt, at, weapon, false, false);
if (weapon != NULL) if (weapon != NULL)
dwtype = weapon->type; dwtype = weapon->type;
if (is_riding(at) && (awtype == NULL || (fval(awtype, WTF_HORSEBONUS) if (is_riding(at) && (awtype == NULL || (fval(awtype, WTF_HORSEBONUS)
&& !fval(awtype, WTF_MISSILE)))) { && !fval(awtype, WTF_MISSILE)))) {
da += CavalryBonus(au, dt, BONUS_DAMAGE); damage += CavalryBonus(au, dt, BONUS_DAMAGE);
} }
ar = calculate_armor(dt, dwtype, awtype, magic ? &res : 0); armor = select_armor(dt, false);
if (ar < 0) { shield = select_armor(dt, true);
armor_value = calculate_armor(dt, dwtype, awtype, armor, shield, magic);
if (magic) {
resistance_factor = calculate_resistance(dt, dwtype, armor, shield);
}
if (armor_value < 0) {
return false; return false;
} }
if (magic) { if (magic) {
res = frac_mul(frac_make(da, 1), res); variant reduced_damage = frac_mul(frac_make(damage, 1), resistance_factor);
da = res.sa[0] / res.sa[1]; damage = reduced_damage.sa[0] / reduced_damage.sa[1];
} }
if (type != AT_COMBATSPELL && type != AT_SPELL) { if (type != AT_COMBATSPELL && type != AT_SPELL) {
if (rule_damage & DAMAGE_CRITICAL) { if (rule_damage & DAMAGE_CRITICAL) {
double kritchance = (sk * 3 - sd) / 200.0; double kritchance = (attskill * 3 - defskill) / 200.0;
int maxk = 4; int maxk = 4;
kritchance = fmax(kritchance, 0.005); kritchance = fmax(kritchance, 0.005);
kritchance = fmin(0.9, kritchance); kritchance = fmin(0.9, kritchance);
while (maxk-- && chance(kritchance)) { while (maxk-- && chance(kritchance)) {
da += dice_rand(damage); damage += dice_rand(damage_formula);
} }
} }
da += rc_specialdamage(au, du, awtype); damage += rc_specialdamage(au, du, awtype);
if (awtype != NULL && fval(awtype, WTF_MISSILE)) { if (awtype != NULL && fval(awtype, WTF_MISSILE)) {
/* missile weapon bonus */ /* missile weapon bonus */
if (rule_damage & DAMAGE_MISSILE_BONUS) { if (rule_damage & DAMAGE_MISSILE_BONUS) {
da += af->person[at.index].damage_rear; damage += af->person[at.index].damage_rear;
} }
} }
else { else {
/* melee bonus */ /* melee bonus */
if (rule_damage & DAMAGE_MELEE_BONUS) { if (rule_damage & DAMAGE_MELEE_BONUS) {
da += af->person[at.index].damage; damage += af->person[at.index].damage;
} }
} }
/* Skilldifferenzbonus */ /* Skilldifferenzbonus */
if (rule_damage & DAMAGE_SKILL_BONUS) { if (rule_damage & DAMAGE_SKILL_BONUS) {
da += MAX(0, (sk - sd) / DAMAGE_QUOTIENT); damage += MAX(0, (attskill - defskill) / DAMAGE_QUOTIENT);
} }
} }
rda = MAX(da - ar, 0); reduced_damage = MAX(damage - armor_value, 0);
if ((u_race(du)->battle_flags & BF_INV_NONMAGIC) && !magic) if ((u_race(du)->battle_flags & BF_INV_NONMAGIC) && !magic)
rda = 0; reduced_damage = 0;
else { else {
int qi; int qi;
selist *ql; selist *ql;
@ -1224,23 +1234,23 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
i |= WTF_BLUNT; i |= WTF_BLUNT;
if (i && awtype && fval(awtype, i)) if (i && awtype && fval(awtype, i))
rda /= 2; reduced_damage /= 2;
/* Schilde */ /* Schilde */
for (qi = 0, ql = b->meffects; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = b->meffects; ql; selist_advance(&ql, &qi, 1)) {
meffect *me = (meffect *)selist_get(ql, qi); meffect *me = (meffect *)selist_get(ql, qi);
if (meffect_protection(b, me, ds) != 0) { if (meffect_protection(b, me, ds) != 0) {
assert(0 <= rda); /* rda sollte hier immer mindestens 0 sein */ assert(0 <= reduced_damage); /* rda sollte hier immer mindestens 0 sein */
/* jeder Schaden wird um effect% reduziert bis der Schild duration /* jeder Schaden wird um effect% reduziert bis der Schild duration
* Trefferpunkte aufgefangen hat */ * Trefferpunkte aufgefangen hat */
if (me->typ == SHIELD_REDUCE) { if (me->typ == SHIELD_REDUCE) {
int hp = rda * (me->effect / 100); int hp = reduced_damage * (me->effect / 100);
rda -= hp; reduced_damage -= hp;
me->duration -= hp; me->duration -= hp;
} }
/* gibt R<>stung +effect f<>r duration Treffer */ /* gibt R<>stung +effect f<>r duration Treffer */
if (me->typ == SHIELD_ARMOR) { if (me->typ == SHIELD_ARMOR) {
rda = MAX(rda - me->effect, 0); reduced_damage = MAX(reduced_damage - me->effect, 0);
me->duration--; me->duration--;
} }
} }
@ -1248,10 +1258,10 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
} }
assert(dt.index >= 0 && dt.index < du->number); assert(dt.index >= 0 && dt.index < du->number);
if (rda>0) { if (reduced_damage>0) {
df->person[dt.index].hp -= rda; df->person[dt.index].hp -= reduced_damage;
if (u_race(au) == get_race(RC_DAEMON)) { if (u_race(au) == get_race(RC_DAEMON)) {
vampirism(at, rda); vampirism(at, reduced_damage);
} }
if (b->turn>1) { if (b->turn>1) {
/* someone on the ship got damaged, damage the ship */ /* someone on the ship got damaged, damage the ship */

View File

@ -233,7 +233,10 @@ extern "C" {
int count_enemies(struct battle *b, const struct fighter *af, int count_enemies(struct battle *b, const struct fighter *af,
int minrow, int maxrow, int select); int minrow, int maxrow, int select);
int natural_armor(struct unit * u); int natural_armor(struct unit * u);
int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, union variant *magres); const struct armor_type *select_armor(struct troop t, bool shield);
struct weapon *select_weapon(const struct troop t, bool attacking, bool ismissile);
int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, const struct armor_type *armor, const struct armor_type *shield, bool magic);
union variant calculate_resistance(struct troop dt, const struct weapon_type *dwtype, const struct armor_type *armor, const struct armor_type *shield);
bool terminate(troop dt, troop at, int type, const char *damage, bool terminate(troop dt, troop at, int type, const char *damage,
bool missile); bool missile);
void message_all(battle * b, struct message *m); void message_all(battle * b, struct message *m);

View File

@ -365,7 +365,10 @@ static void test_calculate_armor(CuTest * tc)
dt.index = 0; dt.index = 0;
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
CuAssertIntEquals_Msg(tc, "default ac", 0, calculate_armor(dt, 0, 0, &magres)); CuAssertIntEquals_Msg(tc, "default ac", 0, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[0], magres.sa[1]); CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[0], magres.sa[1]);
free_battle(b); free_battle(b);
@ -373,10 +376,10 @@ static void test_calculate_armor(CuTest * tc)
i_change(&du->items, ibelt, 1); i_change(&du->items, ibelt, 1);
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
CuAssertIntEquals_Msg(tc, "without natural armor", 0, natural_armor(du)); CuAssertIntEquals_Msg(tc, "without natural armor", 0, natural_armor(du));
CuAssertIntEquals_Msg(tc, "magical armor", 1, calculate_armor(dt, 0, 0, 0)); CuAssertIntEquals_Msg(tc, "magical armor", 1, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
rc->armor = 2; rc->armor = 2;
CuAssertIntEquals_Msg(tc, "with natural armor", 2, natural_armor(du)); CuAssertIntEquals_Msg(tc, "with natural armor", 2, natural_armor(du));
CuAssertIntEquals_Msg(tc, "natural armor", 3, calculate_armor(dt, 0, 0, 0)); CuAssertIntEquals_Msg(tc, "natural armor", 3, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
rc->armor = 0; rc->armor = 0;
free_battle(b); free_battle(b);
@ -385,28 +388,34 @@ static void test_calculate_armor(CuTest * tc)
i_change(&du->items, ichain, 1); i_change(&du->items, ichain, 1);
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
rc->battle_flags &= ~BF_EQUIPMENT; rc->battle_flags &= ~BF_EQUIPMENT;
CuAssertIntEquals_Msg(tc, "require BF_EQUIPMENT", 1, calculate_armor(dt, 0, 0, 0)); CuAssertIntEquals_Msg(tc, "require BF_EQUIPMENT", 1, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
free_battle(b); free_battle(b);
b = NULL; b = NULL;
rc->battle_flags |= BF_EQUIPMENT; rc->battle_flags |= BF_EQUIPMENT;
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
CuAssertIntEquals_Msg(tc, "stack equipment rc", 5, calculate_armor(dt, 0, 0, 0)); CuAssertIntEquals_Msg(tc, "stack equipment rc", 5, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
rc->armor = 2; rc->armor = 2;
CuAssertIntEquals_Msg(tc, "natural armor adds 50%", 6, calculate_armor(dt, 0, 0, 0)); CuAssertIntEquals_Msg(tc, "natural armor adds 50%", 6, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), false));
wtype->flags = WTF_NONE; wtype->flags = WTF_NONE;
CuAssertIntEquals_Msg(tc, "regular weapon has no effect", 6, calculate_armor(dt, 0, wtype, 0)); CuAssertIntEquals_Msg(tc, "regular weapon has no effect", 6, calculate_armor(dt, 0, wtype, select_armor(dt, false), select_armor(dt, true), false));
wtype->flags = WTF_ARMORPIERCING; wtype->flags = WTF_ARMORPIERCING;
CuAssertIntEquals_Msg(tc, "armor piercing weapon", 3, calculate_armor(dt, 0, wtype, 0)); CuAssertIntEquals_Msg(tc, "armor piercing weapon", 3, calculate_armor(dt, 0, wtype, select_armor(dt, false), select_armor(dt, true), false));
wtype->flags = WTF_NONE; wtype->flags = WTF_NONE;
CuAssertIntEquals_Msg(tc, "magical attack", 3, calculate_armor(dt, 0, 0, &magres)); CuAssertIntEquals_Msg(tc, "magical attack", 3, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), true));
magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[1], magres.sa[0]); CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[1], magres.sa[0]);
ashield->flags |= ATF_LAEN; ashield->flags |= ATF_LAEN;
achain->flags |= ATF_LAEN; achain->flags |= ATF_LAEN;
magres = frac_one;
CuAssertIntEquals_Msg(tc, "laen armor", 3, calculate_armor(dt, 0, 0, &magres)); CuAssertIntEquals_Msg(tc, "laen armor", 3, calculate_armor(dt, 0, 0, select_armor(dt, false), select_armor(dt, true), true));
magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssertIntEquals_Msg(tc, "laen magres bonus", 4, magres.sa[1]); CuAssertIntEquals_Msg(tc, "laen magres bonus", 4, magres.sa[1]);
free_battle(b); free_battle(b);
test_teardown(); test_teardown();
@ -437,14 +446,18 @@ static void test_magic_resistance(CuTest *tc)
i_change(&du->items, ishield, 1); i_change(&du->items, ishield, 1);
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssertIntEquals_Msg(tc, "no magres reduction", magres.sa[1], magres.sa[0]); CuAssertIntEquals_Msg(tc, "no magres reduction", magres.sa[1], magres.sa[0]);
magres = magic_resistance(du); magres = magic_resistance(du);
CuAssertIntEquals_Msg(tc, "no magres reduction", 0, magres.sa[0]); CuAssertIntEquals_Msg(tc, "no magres reduction", 0, magres.sa[0]);
ashield->flags |= ATF_LAEN; ashield->flags |= ATF_LAEN;
ashield->magres = v10p; ashield->magres = v10p;
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssert(tc, "laen reduction => 10%%", frac_equal(frac_make(9, 10), magres)); CuAssert(tc, "laen reduction => 10%%", frac_equal(frac_make(9, 10), magres));
free_battle(b); free_battle(b);
@ -455,7 +468,9 @@ static void test_magic_resistance(CuTest *tc)
ashield->flags |= ATF_LAEN; ashield->flags |= ATF_LAEN;
ashield->magres = v10p; ashield->magres = v10p;
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssert(tc, "2x laen reduction => 81%%", frac_equal(frac_make(81, 100), magres)); CuAssert(tc, "2x laen reduction => 81%%", frac_equal(frac_make(81, 100), magres));
free_battle(b); free_battle(b);
@ -464,12 +479,16 @@ static void test_magic_resistance(CuTest *tc)
i_change(&du->items, ichain, -1); i_change(&du->items, ichain, -1);
set_level(du, SK_MAGIC, 2); set_level(du, SK_MAGIC, 2);
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssert(tc, "skill reduction => 90%%", frac_equal(magres, frac_make(9, 10))); CuAssert(tc, "skill reduction => 90%%", frac_equal(magres, frac_make(9, 10)));
magres = magic_resistance(du); magres = magic_resistance(du);
CuAssert(tc, "skill reduction", frac_equal(magres, v10p)); CuAssert(tc, "skill reduction", frac_equal(magres, v10p));
rc->magres = v50p; /* percentage, gets added to skill bonus */ rc->magres = v50p; /* percentage, gets added to skill bonus */
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssert(tc, "race reduction => 40%%", frac_equal(magres, frac_make(4, 10))); CuAssert(tc, "race reduction => 40%%", frac_equal(magres, frac_make(4, 10)));
magres = magic_resistance(du); magres = magic_resistance(du);
CuAssert(tc, "race bonus => 60%%", frac_equal(magres, frac_make(60, 100))); CuAssert(tc, "race bonus => 60%%", frac_equal(magres, frac_make(60, 100)));
@ -477,7 +496,9 @@ static void test_magic_resistance(CuTest *tc)
rc->magres = frac_make(15, 10); /* 150% resistance should not cause negative damage multiplier */ rc->magres = frac_make(15, 10); /* 150% resistance should not cause negative damage multiplier */
magres = magic_resistance(du); magres = magic_resistance(du);
CuAssert(tc, "magic resistance is never > 0.9", frac_equal(magres, frac_make(9, 10))); CuAssert(tc, "magic resistance is never > 0.9", frac_equal(magres, frac_make(9, 10)));
calculate_armor(dt, 0, 0, &magres); magres = calculate_resistance(dt,
select_weapon(dt, false, true) ? select_weapon(dt, false, true)->type : 0,
select_armor(dt, false), select_armor(dt, true));
CuAssert(tc, "damage reduction is never < 0.1", frac_equal(magres, frac_make(1, 10))); CuAssert(tc, "damage reduction is never < 0.1", frac_equal(magres, frac_make(1, 10)));
free_battle(b); free_battle(b);
@ -513,12 +534,12 @@ static void test_projectile_armor(CuTest * tc)
dt.fighter = setup_fighter(&b, du); dt.fighter = setup_fighter(&b, du);
wtype->flags = WTF_MISSILE; wtype->flags = WTF_MISSILE;
achain->projectile = 1.0; achain->projectile = 1.0;
CuAssertIntEquals_Msg(tc, "projectile armor", -1, calculate_armor(dt, 0, wtype, 0)); CuAssertIntEquals_Msg(tc, "projectile armor", -1, calculate_armor(dt, 0, wtype, select_armor(dt, false), select_armor(dt, true), false));
achain->projectile = 0.0; achain->projectile = 0.0;
ashield->projectile = 1.0; ashield->projectile = 1.0;
CuAssertIntEquals_Msg(tc, "projectile shield", -1, calculate_armor(dt, 0, wtype, 0)); CuAssertIntEquals_Msg(tc, "projectile shield", -1, calculate_armor(dt, 0, wtype, select_armor(dt, false), select_armor(dt, true), false));
wtype->flags = WTF_NONE; wtype->flags = WTF_NONE;
CuAssertIntEquals_Msg(tc, "no projectiles", 4, calculate_armor(dt, 0, wtype, 0)); CuAssertIntEquals_Msg(tc, "no projectiles", 4, calculate_armor(dt, 0, wtype, select_armor(dt, false), select_armor(dt, true), false));
free_battle(b); free_battle(b);
test_teardown(); test_teardown();
} }