PyCatan-AI / tests /unit /test_ai_user.py
shon
1
1d4d416
"""Unit tests for AIUser action translation."""
from dataclasses import dataclass
import pytest
from pycatan.ai.ai_user import AIUser
from pycatan.management.actions import ActionType
@dataclass
class DummyAgent:
player_name: str
player_id: int
player_color: str = ""
recent_events: list = None
def __post_init__(self):
if self.recent_events is None:
self.recent_events = []
def add_event(self, event_type, message, data=None):
event = {"type": event_type, "message": message}
if data:
event["data"] = data
self.recent_events.append(event)
class DummyAIManager:
def __init__(self):
self.agents = {}
def register_agent(self, name, user_id, color):
self.agents[name] = DummyAgent(name, user_id, color)
def get_agent(self, name):
return self.agents.get(name)
def make_ai_user():
manager = DummyAIManager()
manager.register_agent("Alice", 0, "red")
manager.register_agent("Bob", 1, "blue")
manager.register_agent("Charlie", 2, "green")
return AIUser("Bob", 1, manager, "blue")
def test_steal_card_resolves_target_player_name_to_id():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "steal_card",
"parameters": {"target_player": "Charlie"},
},
["STEAL_CARD"],
)
assert action.action_type == ActionType.STEAL_CARD
assert action.parameters["target_player"] == 2
def test_steal_card_resolves_target_player_color_to_id():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "steal_card",
"parameters": {"target_player": "green"},
},
["STEAL_CARD"],
)
assert action.parameters["target_player"] == 2
def test_steal_card_maps_unknown_target_player_to_invalid_id():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "steal_card",
"parameters": {"target_player": "Nobody"},
},
["STEAL_CARD"],
)
assert action.parameters["target_player"] == -1
def test_trade_propose_resolves_target_player_name_to_id():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "trade_propose",
"parameters": {
"target_player": "Charlie",
"offer": {"sheep": 1},
"request": {"wood": 1},
},
},
["TRADE_PROPOSE"],
)
assert action.action_type == ActionType.TRADE_PROPOSE
assert action.parameters["target_player"] == 2
assert action.parameters["offer"] == {"sheep": 1}
assert action.parameters["request"] == {"wood": 1}
def test_trade_propose_accepts_target_alias():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "trade_propose",
"parameters": {
"to": "green",
"offer": {"sheep": 1},
"request": {"wood": 1},
},
},
["TRADE_PROPOSE"],
)
assert action.parameters["target_player"] == 2
def test_trade_bank_give_receive_converts_to_engine_offer_request():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "trade_bank",
"parameters": {"give": "wheat", "receive": "ore"},
},
["TRADE_BANK"],
)
assert action.action_type == ActionType.TRADE_BANK
assert action.parameters == {"offer": {"wheat": 4}, "request": {"ore": 1}}
def test_failed_action_is_added_to_agent_events():
user = make_ai_user()
action = user._decision_to_action(
{
"action_type": "steal_card",
"parameters": {"target_player": "Charlie"},
},
["STEAL_CARD"],
)
user.notify_action(action, success=False, message="Invalid target")
event = user.ai_manager.get_agent("Bob").recent_events[-1]
assert event["type"] == "action_failed"
assert "Invalid target" in event["message"]
assert event["data"]["action_type"] == "STEAL_CARD"
def test_action_processing_error_is_added_to_agent_events():
user = make_ai_user()
user.notify_action_processing_error("missing required parameters: ['target_player']")
event = user.ai_manager.get_agent("Bob").recent_events[-1]
assert event["type"] == "action_failed"
assert "could not be processed" in event["message"]
assert "target_player" in event["data"]["error"]
def test_wait_for_response_maps_to_end_turn_action():
user = make_ai_user()
action = user._decision_to_action(
{"action_type": "wait_for_response", "parameters": {}},
["END_TURN"],
)
assert action.action_type == ActionType.END_TURN