import pytest from tft.constants.loader import load_constants from tft.model import artifact as artifact_mod from tft.sim.autoplay import play_afk, play_econ from tft.sim.game import Game, InvalidAction from tests.test_sim import make_static @pytest.fixture(scope="module") def art(): static = make_static() static["meta"]["patch"] = "test" return artifact_mod.build(static) @pytest.fixture(scope="module") def cfg(): return load_constants(17) def test_afk_game_terminates_last(art, cfg): placements = [play_afk(Game(art, cfg, seed=s)) for s in range(20)] assert all(1 <= p <= 8 for p in placements) assert sum(placements) / len(placements) > 6.5 def test_econ_beats_afk(art, cfg): afk = [play_afk(Game(art, cfg, seed=s)) for s in range(30)] econ = [play_econ(Game(art, cfg, seed=1000 + s)) for s in range(30)] assert sum(econ) / len(econ) < sum(afk) / len(afk) def test_same_seed_same_outcome(art, cfg): assert play_econ(Game(art, cfg, seed=7)) == play_econ(Game(art, cfg, seed=7)) def test_buy_and_merge(art, cfg): game = Game(art, cfg, seed=1) game.gold = 100 api = next(a for a in game.shop if a) unit = {"api_name": api, "stars": 1, "items": []} game.bench = [dict(unit), dict(unit)] game.pool.take(api, 2) game.shop = [api] * 5 game.buy(0) assert len(game.bench) == 1 assert game.bench[0]["stars"] == 2 def test_sell_refunds_pool_and_gold(art, cfg): game = Game(art, cfg, seed=1) game.gold = 100 game.shop[0] = "U1_0" before_pool = game.pool.available("U1_0") game.buy(0) gold_after_buy = game.gold game.sell("bench", len(game.bench) - 1) assert game.gold == gold_after_buy + 1 assert game.pool.available("U1_0") == before_pool def test_board_cap_is_level(art, cfg): game = Game(art, cfg, seed=1) game.bench = [{"api_name": "U1_0", "stars": 1, "items": []} for _ in range(3)] game.level = 2 game.move("bench", 0) game.move("bench", 0) with pytest.raises(InvalidAction, match="board full"): game.move("bench", 0) def test_invalid_actions_raise(art, cfg): game = Game(art, cfg, seed=1) game.gold = 0 with pytest.raises(InvalidAction): game.reroll() with pytest.raises(InvalidAction): game.buy_xp() with pytest.raises(InvalidAction): game.sell("bench", 0) def test_shop_lock_survives_step(art, cfg): game = Game(art, cfg, seed=2) game.toggle_lock() before = list(game.shop) game.step() assert game.shop == before