def test_chill_freeze(self): error = "Target was not frozen after 5 applications of Chill" chill = Chill() elemental = CombatElementalBuilder().build() for i in range(5): elemental.add_status_effect(chill) self.assertEqual(elemental.num_status_effects, 2, error)
def test_effect_stats(self): error = "Physical attack StatusEffect didn't add any physical attack" elemental = CombatElementalBuilder().build() physical_att_before = elemental.physical_att buff = GenericBuff() elemental.add_status_effect(buff) self.assertGreater(elemental.physical_att, physical_att_before, error)
def test_charge(self): error = "Charge didn't gain a damage bonus against a max health target" ability = Charge() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertGreater(calculator.bonus_multiplier, 1, error)
def test_different_element_multiplier(self): error = "The Ability being a different element from its user should only grant a 1x multiplier" ability = AbilityBuilder().with_element(Elements.NONE).build() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().with_element(Elements.WATER).build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertEqual(calculator.same_element_multiplier, 1, error)
def test_default_bonus_multiplier(self): error = "Ability bonus_multiplier didn't resolve to 1 by default" ability = AbilityBuilder().build() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertEqual(calculator.bonus_multiplier, 1, error)
def test_no_damage(self): error = "Ability with no base power somehow did damage" ability = AbilityBuilder().with_attack_power(0).build() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertEqual(calculator.final_damage, 0, error)
def test_fireball(self): error = "Fireball didn't gain a damage bonus on a burning target" ability = Fireball() target = CombatElementalBuilder().build() target.add_status_effect(Burn()) actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertGreater(calculator.bonus_multiplier, 1, error)
def test_same_element_multiplier(self): error = "The Ability being the same element as its user should grant a multiplier" ability = AbilityBuilder().with_element( Elements.WATER).with_attack_power(10).build() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().with_element(Elements.WATER).build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertGreater(calculator.same_element_multiplier, 1, error)
def test_block_damage(self): error = "Defend didn't block any damage" ability = AbilityBuilder().with_attack_power(10).build() target = CombatElementalBuilder().build() target.add_status_effect(DefendEffect()) actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertGreater(calculator.damage_blocked, 0, error)
def test_cyclone_bonus(self): error = "Cyclone didn't deal increasing damage with a consecutive hit" elemental = CombatElementalBuilder().build() cyclone_action = ElementalAction(actor=elemental, ability=Cyclone(), combat=self.get_mocked_combat()) elemental.add_action(cyclone_action) bonus = Cyclone().get_bonus_multiplier(Mock(), elemental) self.assertGreater(bonus, 1, error)
def test_effect_duration_self(self): error = "StatusEffect duration wasn't boosted by 1 when self-applied" # The duration decrements on turn end, so it loses 1 duration when applied to self. buff = EnrageEffect() elemental = CombatElementalBuilder().build() buff.applier = elemental duration_before = buff.turns_remaining elemental.add_status_effect(buff) duration_after = buff.turns_remaining self.assertEqual(duration_after - duration_before, 1, error)
def test_stat_multiplier(self): error = "Stat multiplier didn't calculate correctly" ability = AbilityBuilder().with_attack_power(10).with_category( Category.PHYSICAL).build() target = CombatElementalBuilder().build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertEqual(calculator.stat_multiplier, actor.physical_att / target.physical_def, error)
def test_blood_fangs_scaled_healing(self): error = "Blood Fangs didn't scale with missing health" elemental = CombatElementalBuilder().build() elemental.receive_damage(20, Mock()) action = ElementalAction(actor=elemental, ability=BloodFangs(), combat=self.get_mocked_combat()) action._refresh_target() action.execute() self.assertGreater(action.total_healing / elemental.max_hp, 0.1, error)
def test_blood_fangs_healing(self): error = "Blood Fangs didn't heal the actor" elemental = CombatElementalBuilder().build() elemental.receive_damage(10, Mock()) hp_before = elemental.current_hp action = ElementalAction(actor=elemental, ability=BloodFangs(), combat=self.get_mocked_combat()) action._refresh_target() action.execute() hp_after = elemental.current_hp self.assertGreater(hp_after, hp_before, error)
def test_resisted_ability(self): multiplier_error = "Super effective ability didn't apply a correct multiplier" flag_error = "Resisted ability wasn't flagged as such" # Fire is weak against water ability = AbilityBuilder().with_attack_power(10).with_element( Elements.FIRE).build() target = CombatElementalBuilder().with_element(Elements.WATER).build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertEqual(calculator.effectiveness_multiplier, 0.5, multiplier_error) self.assertTrue(calculator.is_resisted, flag_error)
def test_physical_defence(self): error = "Physical defence didn't reduce any damage" low_def = CombatElementalBuilder().with_elemental( ElementalBuilder().with_physical_def(1).build()).build() high_def = CombatElementalBuilder().with_elemental( ElementalBuilder().with_physical_def(30).build()).build() actor = CombatElementalBuilder().build() low_def_calculator = DamageCalculator(low_def, actor, Claw()) low_def_calculator.calculate() high_def_calculator = DamageCalculator(high_def, actor, Claw()) high_def_calculator.calculate() self.assertGreater(low_def_calculator.final_damage, high_def_calculator.final_damage, error)
def test_effective_ability(self): multiplier_error = "Super effective ability didn't apply a correct multiplier" flag_error = "Super effective ability wasn't flagged as such" # Earth is strong against wind ability = AbilityBuilder().with_attack_power(10).with_element( Elements.EARTH).build() target = CombatElementalBuilder().with_element(Elements.WIND).build() actor = CombatElementalBuilder().build() calculator = DamageCalculator(target, actor, ability) calculator.calculate() self.assertGreater(calculator.effectiveness_multiplier, 1, multiplier_error) self.assertTrue(calculator.is_effective, flag_error)
def test_stonehide_debuff_duration(self): error = "Stonehide charge didn't decrement upon receiving damage from a debuff" elemental = CombatElementalBuilder().build() stonehide = StonehideEffect() stonehide.applier = elemental elemental.add_status_effect(stonehide) rend = RendEffect() rend.applier = CombatElementalBuilder().build() elemental.add_status_effect(rend) elemental.end_turn() self.assertEqual(stonehide.charges, 3, error)
def test_unstackable_effect_refresh(self): error = "A !can_add_instances StatusEffect didn't refresh its effect's duration when reapplied" buff = GenericBuff() same_buff = GenericBuff() elemental = CombatElementalBuilder().build() elemental.add_status_effect(buff) duration_before = buff.turns_remaining elemental.end_turn() elemental.add_status_effect(same_buff) self.assertEqual(duration_before, buff.turns_remaining, error)
def test_blood_fangs_base_healing(self): error = "Blood Fangs didn't recover 10% health baseline" elemental = CombatElementalBuilder().build() action = ElementalAction(actor=elemental, ability=BloodFangs(), combat=self.get_mocked_combat()) action._refresh_target() action.execute() self.assertEqual(0.1, action.total_healing / elemental.max_hp, error)
def test_mana_consumption(self): error = "Mana-consuming ability didn't consume mana" elemental = CombatElementalBuilder().build() previous_mana = elemental.current_mana action = ElementalAction(actor=elemental, ability=RazorFangs(), combat=self.get_mocked_combat()) action._refresh_target() action.execute() self.assertLess(elemental.current_mana, previous_mana, error)
def test_active_elemental_action(self): error = "ElementalAction could incorrectly trigger when the elemental forcibly switched." team = make_combat_team() old_active = team.elementals[0] team.change_active_elemental(old_active) team.change_active_elemental(CombatElementalBuilder().build()) action = ElementalAction(actor=old_active, ability=Claw(), combat=Mock()) self.assertFalse(action.can_execute, error)
def test_provoke_applier_switch(self): error = "Provoke didn't clear on opponent changed" applier = CombatElementalBuilder().build() provoke = ProvokeEffect() provoke.applier = applier elemental = CombatElementalBuilder().build() elemental.add_status_effect(provoke) elemental.on_opponent_changed(applier) self.assertEqual(0, elemental.num_status_effects, error)
def test_frost_barrier_chill(self): error = "Attackers were not chilled by Frost Barrier" elemental = CombatElementalBuilder().build() frost_barrier = FrostBarrierEffect() frost_barrier.applier = elemental elemental.add_status_effect(frost_barrier) attacker = CombatElementalBuilder().build() elemental.on_receive_ability(Claw(), attacker) self.assertIsInstance(attacker.status_effects[0], Chill, error)
def test_defend_charge(self): error = "Defend didn't use a defend charge" elemental = CombatElementalBuilder().build() previous_charges = elemental.defend_charges action = ElementalAction(actor=elemental, ability=Defend(), combat=self.get_mocked_combat()) action._refresh_target() action.execute() self.assertEqual(elemental.defend_charges, (previous_charges - 1), error)
def test_knockout_replacement(self): error = "A team whose elemental was knocked out couldn't select a replacement" team_a = make_combat_team() combat = get_mocked_combat(team_a) team_a.active_elemental.receive_damage(10000, Mock()) new_active = CombatElementalBuilder().build() switch = Switch(team=team_a, old_active=team_a.active_elemental, new_active=new_active) combat.request_action(switch) self.assertEqual(team_a.active_elemental, new_active, error)
def test_blessed_rain(self): error = "Blessed Rain didn't heal on turn end" team = make_combat_team() get_mocked_combat(team) effect = BlessedRainEffect() effect.applier = CombatElementalBuilder().build() elemental = team.active_elemental elemental.receive_damage(10, Mock()) team.add_status_effect(effect) health_before = elemental.current_hp team.end_turn() self.assertGreater(elemental.current_hp, health_before, error)
def test_switch_target(self): error = "Attacks didn't retarget after a switch" team_a = make_combat_team() team_b = make_combat_team() combat = get_mocked_combat(team_a, team_b) old_target = team_b.active_elemental target = CombatElementalBuilder().build() combat.request_action( ElementalAction(team_a.active_elemental, Claw(), combat)) hp_before = target.current_hp combat.request_action(Switch(team_b, old_target, target)) hp_after = target.current_hp self.assertLess(hp_after, hp_before, error)
def test_effect_end(self): error = "StatusEffect wasn't removed upon duration end" buff = GenericBuff() elemental = CombatElementalBuilder().build() elemental.add_status_effect(buff) for i in range(buff.turns_remaining): elemental.end_turn() self.assertEqual(elemental.num_status_effects, 0, error)
def test_effect_duration_decrement(self): error = "StatusEffect duration didn't decrement on turn end" buff = EnrageEffect() elemental = CombatElementalBuilder().build() elemental.add_status_effect(buff) duration_before = buff.turns_remaining elemental.end_turn() self.assertLess(buff.turns_remaining, duration_before, error)