from coolrl_lost_cities.games.classic import ( LostCitiesConfig, build_bot, make_policy_factory, play_game_for_evaluation, play_match, ) from coolrl_lost_cities.games.classic.evaluation import MATCH_EVAL_RECORD_TYPE, main def test_play_game_for_evaluation_finishes_small_match() -> None: config = LostCitiesConfig(n_colors=3, n_ranks=5, n_handshakes=1, hand_size=5) state, result = play_game_for_evaluation( build_bot("random", seed=1), build_bot("discard-only", seed=2), config, seed=3, max_steps=200, ) assert state.terminal is True assert result.timed_out is False assert result.steps > 0 assert result.score_diff0 == result.score0 - result.score1 def test_play_match_alternates_seats_and_reports_rates() -> None: config = LostCitiesConfig(n_colors=3, n_ranks=5, n_handshakes=1, hand_size=5) result = play_match( make_policy_factory("random"), make_policy_factory("discard-only"), config, games=4, seed=10, max_steps=200, ) assert result.games == 4 assert result.wins0 + result.wins1 + result.draws == 4 assert result.avg_game_length > 0.0 assert result.games_per_second > 0.0 assert result.steps_per_second > 0.0 def test_evaluation_cli_smoke_json(capsys) -> None: main( [ "--bot0", "random", "--bot1", "discard-only", "--games", "2", "--seed", "20", "--json", ] ) captured = capsys.readouterr() assert f'"type": "{MATCH_EVAL_RECORD_TYPE}"' in captured.out assert '"bots": {' in captured.out assert '"settings": {' in captured.out assert '"result": {' in captured.out assert '"timing": {' in captured.out assert '"games": 2' in captured.out assert '"win_rate0"' in captured.out