"""Arena: Boards auf das Kampffeld, eigene Positionen, leere Seiten.""" import random from tft.sim.arena import BOARD_COLS from tft.sim import arena, hexgrid STATS = {"hp": 800, "armor": 20, "magicResist": 20, "damage": 50, "damageByStar": [0, 50, 100, 200], "attackSpeed": 1.0, "range": 1, "mana": 0, "initialMana": 0, "critChance": 0.0, "critMultiplier": 1.4} ARTIFACT = {"static": { "units": {"A": {"traits": [], "stats": STATS}, "B": {"traits": [], "stats": {**STATS, "range": 4}}}, "items": {"HP": {"effects": {"Health": 500}}}, "traits": {}, }} def test_front_row_of_both_sides_faces_the_other(): """Reihe 0 des Spielers ist die vorderste — sonst laufen alle aneinander vorbei.""" a = arena.from_hex(3, "a") b = arena.from_hex(3, "b") assert hexgrid.distance((a["col"], a["row"]), (b["col"], b["row"])) == 1 def test_back_row_is_furthest_away(): a = arena.from_hex(3 + 3 * BOARD_COLS, "a") b = arena.from_hex(3 + 3 * BOARD_COLS, "b") assert hexgrid.distance((a["col"], a["row"]), (b["col"], b["row"])) == 7 def test_own_positions_are_used(): board = [{"api_name": "A", "stars": 1, "hex": 3}] out = arena.placed(board, "a", ARTIFACT["static"]["units"]) assert (out[0]["col"], out[0]["row"]) == (3, 3) def test_boards_without_positions_fall_back_to_the_lineup(): """Endboards aus der Riot-API tragen keine Felder.""" board = [{"api_name": "A", "stars": 1}, {"api_name": "B", "stars": 1}] out = arena.placed(board, "a", ARTIFACT["static"]["units"]) assert all("col" in e and "row" in e for e in out) # Nahkämpfer vorne, Fernkämpfer hinten. front = next(e for e in out if e["api_name"] == "A") back = next(e for e in out if e["api_name"] == "B") assert front["row"] > back["row"] def test_two_units_never_share_a_cell(): board = [{"api_name": "A", "stars": 1, "hex": 3}, {"api_name": "A", "stars": 1, "hex": 3}] out = arena.placed(board, "a", ARTIFACT["static"]["units"]) assert len({(e["col"], e["row"]) for e in out}) == 2 def test_an_empty_board_loses_at_once(): board = [{"api_name": "A", "stars": 1, "hex": 0}] res, log = arena.fight([], board, ARTIFACT, random.Random(1)) assert res.winner == "b" and res.frames == 0 and log is None res, _ = arena.fight(board, [], ARTIFACT, random.Random(1)) assert res.winner == "a" assert arena.fight([], [], ARTIFACT, random.Random(1))[0].winner is None def test_items_reach_the_fighters(): board = [{"api_name": "A", "stars": 1, "hex": 0, "items": ["HP"]}] plain = arena.side([{"api_name": "A", "stars": 1, "hex": 0}], "a", ARTIFACT) armed = arena.side(board, "a", ARTIFACT) assert armed[0].max_hp == plain[0].max_hp + 500 def test_the_bigger_board_wins(): big = [{"api_name": "A", "stars": 1, "hex": h} for h in range(4)] small = [{"api_name": "A", "stars": 1, "hex": 0}] assert arena.fight(big, small, ARTIFACT, random.Random(1))[0].winner == "a" def test_replay_returns_a_playable_log(): """Feldmaße, Kämpfer und Ereignisse — mehr braucht die Anzeige nicht.""" a = [{"api_name": "A", "stars": 1, "hex": h} for h in range(3)] b = [{"api_name": "A", "stars": 1, "hex": h} for h in range(2)] _, log = arena.fight(a, b, ARTIFACT, random.Random(1), record=True) assert log["cols"] == hexgrid.COLS and log["rows"] == hexgrid.ROWS assert len(log["units"]) == 5 assert {u["slot"] for u in log["units"]} == set(range(5)) kinds = {e["e"] for e in log["events"]} assert "spawn" in kinds and "hit" in kinds assert log["winner"] == "a" def test_replay_is_none_without_a_fight(): _, log = arena.fight([], [{"api_name": "A", "stars": 1, "hex": 0}], ARTIFACT, random.Random(1), record=True) assert log is None def test_replay_matches_the_fight(): """Sonst zeigt die Anzeige etwas anderes als das Spiel gewertet hat.""" a = [{"api_name": "A", "stars": 1, "hex": h} for h in range(3)] b = [{"api_name": "B", "stars": 1, "hex": h} for h in range(3)] res, log = arena.fight(a, b, ARTIFACT, random.Random(3), record=True) plain, _ = arena.fight(a, b, ARTIFACT, random.Random(3)) assert log["winner"] == res.winner == plain.winner