99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
"""Trait-Boni: Zählung, Stufen, Reichweite des Bonus."""
|
|
|
|
from tft.sim import battle, traits
|
|
|
|
UNITS = {
|
|
"A": {"traits": ["PANZER"], "stats": {"hp": 1000, "armor": 20, "damage": 50,
|
|
"attackSpeed": 1.0, "range": 1}},
|
|
"B": {"traits": ["PANZER"], "stats": {"hp": 1000, "armor": 20, "damage": 50,
|
|
"attackSpeed": 1.0, "range": 1}},
|
|
"C": {"traits": ["ANDERE"], "stats": {"hp": 1000, "armor": 20, "damage": 50,
|
|
"attackSpeed": 1.0, "range": 1}},
|
|
}
|
|
TRAITS = {
|
|
"PANZER": {"breakpoints": [
|
|
{"min_units": 2, "variables": {"DefenderDefenseGain": 25}},
|
|
{"min_units": 3, "variables": {"DefenderDefenseGain": 60}},
|
|
]},
|
|
"ANDERE": {"breakpoints": [
|
|
{"min_units": 1, "variables": {"TeamManaRegen": 2}},
|
|
]},
|
|
}
|
|
|
|
|
|
def board(*keys):
|
|
return [{"api_name": k, "stars": 1} for k in keys]
|
|
|
|
|
|
def fighters(*keys):
|
|
return [battle.to_fighter({"api_name": k, "stars": 1, "col": 0, "row": 0},
|
|
"a", UNITS) for k in keys]
|
|
|
|
|
|
def test_a_trait_needs_enough_units():
|
|
assert traits.active(board("A"), UNITS, TRAITS) == {}
|
|
assert "PANZER" in traits.active(board("A", "B"), UNITS, TRAITS)
|
|
|
|
|
|
def test_copies_of_the_same_champion_count_once():
|
|
"""Zwei Kopien von A sind ein Trait-Träger, nicht zwei."""
|
|
assert traits.active(board("A", "A"), UNITS, TRAITS) == {}
|
|
|
|
|
|
def test_the_highest_reached_step_wins():
|
|
step = traits.active(board("A", "B", "C"), UNITS, TRAITS)["PANZER"]
|
|
assert step["variables"]["DefenderDefenseGain"] == 25
|
|
UNITS["C"]["traits"].append("PANZER")
|
|
try:
|
|
step = traits.active(board("A", "B", "C"), UNITS, TRAITS)["PANZER"]
|
|
assert step["variables"]["DefenderDefenseGain"] == 60
|
|
finally:
|
|
UNITS["C"]["traits"].remove("PANZER")
|
|
|
|
|
|
def test_the_bonus_only_reaches_its_own_units():
|
|
fa, fb, fc = fighters("A", "B", "C")
|
|
traits.apply([fa, fb, fc], board("A", "B", "C"), UNITS, TRAITS)
|
|
assert fa.armor == 45 and fb.armor == 45 # 20 + 25
|
|
assert fc.armor == 20
|
|
|
|
|
|
def test_team_bonuses_reach_everyone():
|
|
"""Steht "Team" im Namen, gilt der Bonus für das ganze Board."""
|
|
fa, fb, fc = fighters("A", "B", "C")
|
|
traits.apply([fa, fb, fc], board("A", "B", "C"), UNITS, TRAITS)
|
|
assert fa.mana_regen == 2 and fc.mana_regen == 2
|
|
|
|
|
|
def test_percent_and_flat_are_told_apart():
|
|
"""Derselbe Name trägt beide Skalen — unter 1 Anteil, darüber flach."""
|
|
assert traits.effects_of({"ADAP": 0.3})["attack_damage_pct"] == 0.3
|
|
assert traits.effects_of({"ADAP": 30})["attack_damage_pct"] == 0.3
|
|
|
|
|
|
def test_unknown_variables_are_ignored():
|
|
assert traits.effects_of({"OverrunCombats": 3, "RengarGold": 5}) == {}
|
|
|
|
|
|
def test_durability_reduces_incoming_damage():
|
|
gains = traits.effects_of({"JuggernautDurability": 0.2})
|
|
assert gains["durability"] == 0.2
|
|
|
|
|
|
def test_the_panel_and_the_fight_count_the_same():
|
|
"""Zwei Kopien desselben Champions sind ein Trait-Träger.
|
|
|
|
Zählt das UI anders als der Kampf, zeigt es Stufen an, die im
|
|
Gefecht nicht wirken.
|
|
"""
|
|
board = [{"api_name": "A", "stars": 1}, {"api_name": "A", "stars": 2},
|
|
{"api_name": "B", "stars": 1}]
|
|
assert traits.counts(board, UNITS)["PANZER"] == 2
|
|
step = traits.active(board, UNITS, TRAITS)["PANZER"]
|
|
assert step["units"] == 2 and step["step"] == 1
|
|
|
|
|
|
def test_unknown_units_do_not_count():
|
|
board = [{"api_name": "GIBTS_NICHT", "stars": 1}]
|
|
assert traits.counts(board, UNITS) == {}
|