import random from tft.sim import combat def prof(off, dfn, defensive=True, name="u"): return {"off": off, "def": dfn, "defensive": defensive, "unit": {"api_name": name, "stars": 1, "items": []}} CFG = { "combat": {"max_frames": 1800}, "damage": {"stage_base": [0, 2, 5, 8, 10, 12, 17, 17], "per_surviving_unit": 1, "player_hp": 100}, } def test_kill_time_matches_dps_at_60fps(): # Def 10 gegen Gesamt-Off 5 -> 2 s = 120 Frames. a = [prof(5, 1000)] b = [prof(0, 10)] res = combat.fight(a, b, random.Random(1), CFG) assert res.winner == "a" assert res.frames == 120 assert res.survivors_b == [] def test_overflow_carries_to_next_unit(): # Zwei Units à 10 Def gegen Off 5 -> exakt 4 s, kein Schaden verpufft. a = [prof(5, 1000)] b = [prof(0, 10), prof(0, 10)] res = combat.fight(a, b, random.Random(1), CFG) assert res.winner == "a" assert res.frames == 240 def test_dead_units_stop_contributing_offense(): # B killt As Front nach 2 s; danach kämpft A nur noch mit halber Offense. a = [prof(6, 12, defensive=True), prof(6, 1000, defensive=False)] b = [prof(6, 60)] res = combat.fight(a, b, random.Random(1), CFG) assert res.winner == "a" assert res.frames == 480 # 2 s + 36/6 s statt 60/12 s bei konstanter Offense assert len(res.survivors_a) == 1 def test_queue_targets_defensive_units_first(): team = [prof(1, 1, defensive=False, name="carry1"), prof(1, 1, defensive=True, name="tank1"), prof(1, 1, defensive=False, name="carry2"), prof(1, 1, defensive=True, name="tank2")] q = combat._queue(team, random.Random(5)) assert [p["defensive"] for p in q] == [True, True, False, False] def test_simultaneous_last_kill_is_draw(): a = [prof(5, 10)] b = [prof(5, 10)] res = combat.fight(a, b, random.Random(1), CFG) assert res.winner is None assert res.survivors_a == [] and res.survivors_b == [] def test_empty_boards(): res = combat.fight([], [], random.Random(1), CFG) assert res.winner is None and res.frames == 0 res = combat.fight([prof(1, 1)], [], random.Random(1), CFG) assert res.winner == "a" def test_stall_hits_time_limit_more_defense_wins(): a = [prof(0, 100)] b = [prof(0, 50)] res = combat.fight(a, b, random.Random(1), CFG) assert res.winner == "a" assert res.frames == CFG["combat"]["max_frames"] def test_same_seed_same_result(): team_a = [prof(7, 300), prof(12, 150, defensive=False), prof(5, 400)] team_b = [prof(9, 250), prof(10, 200, defensive=False)] r1 = combat.fight(team_a, team_b, random.Random(42), CFG) r2 = combat.fight(team_a, team_b, random.Random(42), CFG) assert (r1.winner, r1.frames) == (r2.winner, r2.frames) assert [p["api_name"] for p in r1.survivors_a] == \ [p["api_name"] for p in r2.survivors_a] def test_player_damage_counts_exact_survivors(): survivors = [{"api_name": f"u{i}"} for i in range(4)] assert combat.player_damage(3, survivors, CFG) == 5 + 4 assert combat.player_damage(1, [], CFG) == 0