from __future__ import annotations from catan.cli import CLIController from catan.game import Game, GameConfig, Phase from catan.ml.agents import RandomAgent from tests.utils import find_initial_spot def _resolve_robber(controller: CLIController) -> None: game = controller.game board = game.board for hex_id, tile in board.hexes.items(): if hex_id == board.robber_hex: continue victims = { board.corners[corner].owner for corner in tile.corners if board.corners[corner].owner and board.corners[corner].owner != game.current_player.name } victim = next(iter(victims)) if victims else None game.move_robber(hex_id, victim) return def test_human_vs_random_bot_session() -> None: controller = CLIController( Game(GameConfig(player_names=["Human", "Bot", "Companion"], seed=9)), bots={"Bot": RandomAgent(seed=3), "Companion": RandomAgent(seed=5)}, ) # Complete setup: human manually places, bot uses random agent. while controller.game.phase != Phase.MAIN: current = controller.game.current_player.name if current == "Human": corner, road = find_initial_spot(controller.game) controller.handle_command(f"place {corner} {road}") else: controller._run_bot_turn(current) # noqa: SLF001 - exercising CLI internals # Play a few rounds: human rolls and ends, bots play automatically. for _ in range(2): assert controller.game.current_player.name == "Human" controller.handle_command("roll") if controller.game.robber_move_required: _resolve_robber(controller) controller.handle_command("end") for name in ("Bot", "Companion"): assert controller.game.current_player.name == name controller._run_bot_turn(name) # noqa: SLF001 # Ensure bot activity is recorded in history. assert any(log.player in {"Bot", "Companion"} for log in controller.game.history)