from __future__ import annotations from catan.data import Resource from catan.game import GameConfig, Phase from catan.sdk import ActionType, CatanEnv from tests.utils import find_initial_spot def _auto_setup(env: CatanEnv) -> None: game = env.game while game.phase != Phase.MAIN: corner, road = find_initial_spot(game) game.place_initial_settlement(corner, road) def test_bank_trade_action_and_port_ratio() -> None: env = CatanEnv(GameConfig(player_names=["Alice", "Bob", "Cara"], seed=5)) _auto_setup(env) game = env.game game.phase = Phase.MAIN game.has_rolled = True alice = game.players[0] board = game.board # Remove any accidental port bonuses from initial placements. for corner_id in list(alice.settlements): board.corners[corner_id].port = None # Base bank trade (4:1) alice.resources[Resource.BRICK] = 4 actions = env.legal_actions() bank_actions = [ action for action in actions if action.type == ActionType.TRADE_BANK ] base_ratios = [ action.payload["ratio"] for action in bank_actions if action.payload["give"] == "brick" ] assert base_ratios and min(base_ratios) == 4 # Attach Alice to a brick port for 2:1 ratio. port_corner = next( corner_id for corner_id, corner in board.corners.items() if corner.port and corner.port.resource == Resource.BRICK ) board.corners[port_corner].owner = alice.name board.corners[port_corner].building = "settlement" alice.settlements.add(port_corner) alice.resources[Resource.BRICK] = 2 actions = env.legal_actions() bank_actions = [ action for action in actions if action.type == ActionType.TRADE_BANK ] assert any(action.payload["give"] == "brick" and action.payload["ratio"] == 2 for action in bank_actions) def test_player_trade_actions_available() -> None: env = CatanEnv(GameConfig(player_names=["Alice", "Bob", "Cara"], seed=11)) _auto_setup(env) game = env.game game.phase = Phase.MAIN game.has_rolled = True alice = game.player_by_name("Alice") bob = game.player_by_name("Bob") alice.resources[Resource.WOOL] = 1 bob.resources[Resource.ORE] = 1 actions = env.legal_actions() trade_actions = [ action for action in actions if action.type == ActionType.TRADE_PLAYER ] assert trade_actions, "Expected player trade actions" assert any( action.payload["target"] == "Bob" and action.payload["offer"] == {"wool": 1} and action.payload["request"] == {"ore": 1} for action in trade_actions )