Files
tft/backend/tests/test_traits.py
2026-09-07 07:44:09 +02:00

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) == {}