"""Balance floor regression: the greedy bot must keep the difficulty gradient alive. Small seed counts — these guard against catastrophic balance breaks, not 1% drift.""" from balance.sim import simulate, standard_decks, winrate from scrypt.data import load_content from scrypt.engine.combat import Result def test_simulator_is_deterministic(): content = load_content() deck = standard_decks(content)["vanilla"] side = [content.card("bit")] * 10 script = content.encounters["first_blood"]["script"] a = simulate(deck, side, script, seed=11) b = simulate(deck, side, script, seed=11) assert a.result is b.result and a.turn == b.turn def test_first_encounter_is_winnable_floor(): content = load_content() deck = standard_decks(content)["vanilla"] r = winrate(content, deck, "first_blood", seeds=30) assert r["winrate"] >= 0.7, f"first encounter too hard for the floor bot: {r}" assert r["stall"] == 0, "fights must end" def test_final_encounter_is_a_wall_for_the_floor_bot(): content = load_content() deck = standard_decks(content)["vanilla"] r = winrate(content, deck, "scheduled_doom", seeds=30) assert r["winrate"] <= 0.6, f"finale too easy: {r}" def test_every_fight_terminates(): content = load_content() side = [content.card("bit")] * 10 for deck in standard_decks(content).values(): for enc in content.encounters.values(): state = simulate(deck, side, enc["script"], seed=3) assert state.result is not Result.UNDECIDED