106 lines
3.0 KiB
Python
106 lines
3.0 KiB
Python
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", 99)
|
|
|
|
|
|
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
|
|
|
|
|
|
def test_carousel_never_a_planning_round(art, cfg):
|
|
game = Game(art, cfg, seed=5)
|
|
seen = []
|
|
while not game.over:
|
|
seen.append(game.round["kind"])
|
|
game.step()
|
|
assert "carousel" not in seen
|
|
assert seen[0] == "pve" # Spiel startet bei 1-2
|
|
|
|
|
|
def test_carousel_grants_unit_and_loot(art, cfg):
|
|
game = Game(art, cfg, seed=5)
|
|
assert len(game.bench) == 1 # Unit vom 1-1-Carousel
|
|
assert len(game.items) == 1 # Item-Komponente vom Carousel
|