From 15ff621cbb7d64aac19bc0508de4f42fca87799d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 3 Nov 2015 14:22:50 +0100 Subject: [PATCH] refactor: extract damage calculation from terminate start writing tests (WIP) --- src/battle.c | 166 ++++++++++++++++++++++++---------------------- src/battle.h | 5 +- src/battle.test.c | 26 ++++++++ 3 files changed, 116 insertions(+), 81 deletions(-) diff --git a/src/battle.c b/src/battle.c index f4d3bc5a7..cf8cf9b35 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1078,66 +1078,14 @@ static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_ return modifier; } -bool -terminate(troop dt, troop at, int type, const char *damage, bool missile) -{ - item **pitm; - fighter *df = dt.fighter; - fighter *af = at.fighter; - unit *au = af->unit; - unit *du = df->unit; - battle *b = df->side->battle; - int heiltrank = 0; +int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awtype, double *magres) { static int rule_armor = -1; - - /* Schild */ - side *ds = df->side; - int hp; - + fighter *df = dt.fighter; + unit *du = df->unit; int ar = 0, an, am; const armor_type *armor = select_armor(dt, false); const armor_type *shield = select_armor(dt, true); - const weapon_type *dwtype = NULL; - const weapon_type *awtype = NULL; - const weapon *weapon; - - int rda, sk = 0, sd; - bool magic = false; - int da = dice_rand(damage); - - assert(du->number > 0); - ++at.fighter->hits; - - switch (type) { - case AT_STANDARD: - weapon = select_weapon(at, true, missile); - sk = weapon_effskill(at, dt, weapon, true, missile); - if (weapon) - awtype = weapon->type; - if (awtype && fval(awtype, WTF_MAGICAL)) - magic = true; - break; - case AT_NATURAL: - sk = weapon_effskill(at, dt, NULL, true, missile); - break; - case AT_SPELL: - case AT_COMBATSPELL: - magic = true; - break; - default: - break; - } - weapon = select_weapon(dt, false, true); /* missile=true to get the unmodified best weapon she has */ - sd = weapon_effskill(dt, at, weapon, false, false); - if (weapon != NULL) - dwtype = weapon->type; - - if (is_riding(at) && (awtype == NULL || (fval(awtype, WTF_HORSEBONUS) - && !fval(awtype, WTF_MISSILE)))) { - da += CavalryBonus(au, dt, BONUS_DAMAGE); - } - if (armor) { ar += armor->prot; if (armor->projectile > 0 && chance(armor->projectile)) { @@ -1182,6 +1130,90 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) ar += am; + if (magres) { + /* magic_resistance gib x% Resistenzbonus zurück */ + double res = *magres - magic_resistance(du) * 3.0; + + if (u_race(du)->battle_flags & BF_EQUIPMENT) { + /* der Effekt von Laen steigt nicht linear */ + if (armor && fval(armor, ATF_LAEN)) + res *= (1 - armor->magres); + if (shield && fval(shield, ATF_LAEN)) + res *= (1 - shield->magres); + if (dwtype) + res *= (1 - dwtype->magres); + } + + /* gegen Magie wirkt nur natürliche und magische Rüstung */ + ar = an + am; + *magres = res; + } + + return ar; +} + +bool +terminate(troop dt, troop at, int type, const char *damage, bool missile) +{ + item **pitm; + fighter *df = dt.fighter; + fighter *af = at.fighter; + unit *au = af->unit; + unit *du = df->unit; + battle *b = df->side->battle; + int heiltrank = 0; + + /* Schild */ + side *ds = df->side; + int hp, ar; + + const weapon_type *dwtype = NULL; + const weapon_type *awtype = NULL; + const weapon *weapon; + double res = 0.0; + + int rda, sk = 0, sd; + bool magic = false; + int da = dice_rand(damage); + + assert(du->number > 0); + ++at.fighter->hits; + + switch (type) { + case AT_STANDARD: + weapon = select_weapon(at, true, missile); + sk = weapon_effskill(at, dt, weapon, true, missile); + if (weapon) + awtype = weapon->type; + if (awtype && fval(awtype, WTF_MAGICAL)) + magic = true; + break; + case AT_NATURAL: + sk = weapon_effskill(at, dt, NULL, true, missile); + break; + case AT_SPELL: + case AT_COMBATSPELL: + magic = true; + break; + default: + break; + } + weapon = select_weapon(dt, false, true); /* missile=true to get the unmodified best weapon she has */ + sd = weapon_effskill(dt, at, weapon, false, false); + if (weapon != NULL) + dwtype = weapon->type; + + if (is_riding(at) && (awtype == NULL || (fval(awtype, WTF_HORSEBONUS) + && !fval(awtype, WTF_MISSILE)))) { + da += CavalryBonus(au, dt, BONUS_DAMAGE); + } + + ar = calculate_armor(dt, dwtype, awtype, magic ? &res : 0); + + if (magic) { + da = (int)(_max(da * res, 0)); + } + if (type != AT_COMBATSPELL && type != AT_SPELL) { if (damage_rules & DAMAGE_CRITICAL) { double kritchance = (sk * 3 - sd) / 200.0; @@ -1218,30 +1250,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) } } - if (magic) { - /* Magischer Schaden durch Spruch oder magische Waffe */ - double res = 1.0; - - /* magic_resistance gib x% Resistenzbonus zurück */ - res -= magic_resistance(du) * 3.0; - - if (u_race(du)->battle_flags & BF_EQUIPMENT) { - /* der Effekt von Laen steigt nicht linear */ - if (armor && fval(armor, ATF_LAEN)) - res *= (1 - armor->magres); - if (shield && fval(shield, ATF_LAEN)) - res *= (1 - shield->magres); - if (dwtype) - res *= (1 - dwtype->magres); - } - - if (res > 0) { - da = (int)(_max(da * res, 0)); - } - /* gegen Magie wirkt nur natürliche und magische Rüstung */ - ar = an + am; - } - rda = _max(da - ar, 0); if ((u_race(du)->battle_flags & BF_INV_NONMAGIC) && !magic) diff --git a/src/battle.h b/src/battle.h index 618850d31..36f4898b7 100644 --- a/src/battle.h +++ b/src/battle.h @@ -241,9 +241,10 @@ extern "C" { extern troop select_ally(struct fighter *af, int minrow, int maxrow, int allytype); - extern 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); - extern bool terminate(troop dt, troop at, int type, const char *damage, + int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, double *magres); + bool terminate(troop dt, troop at, int type, const char *damage, bool missile); extern void message_all(battle * b, struct message *m); extern int hits(troop at, troop dt, weapon * awp); diff --git a/src/battle.test.c b/src/battle.test.c index 264e9c0be..bb76d4d61 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -204,6 +204,31 @@ static void test_building_defence_bonus(CuTest * tc) test_cleanup(); } +static void test_calculate_armor(CuTest * tc) +{ + troop dt; + battle *b; + region *r; + unit *du; + side *ds; + fighter *df; + weapon_type *awtype = 0, *dwtype = 0; + int result; + + test_cleanup(); + r = test_create_region(0, 0, 0); + du = test_create_unit(test_create_faction(NULL), r); + + b = make_battle(r); + ds = make_side(b, du->faction, 0, 0, 0); + df = make_fighter(b, du, ds, false); + dt.fighter = df; + dt.index = 0; + result = calculate_armor(dt, dwtype, awtype, 0); + CuAssertIntEquals(tc, 0, result); + test_cleanup(); +} + CuSuite *get_battle_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -212,5 +237,6 @@ CuSuite *get_battle_suite(void) SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus); SUITE_ADD_TEST(suite, test_building_bonus_respects_size); SUITE_ADD_TEST(suite, test_building_defence_bonus); + SUITE_ADD_TEST(suite, test_calculate_armor); return suite; }