|
from typing import Literal, List, Type |
|
|
|
from pydantic import BaseModel, Field |
|
|
|
from agent_interfaces import HumanAgentCLI, BaseAgentInterface |
|
from message import MessageType |
|
|
|
Role = Literal["chameleon", "herd"] |
|
|
|
|
|
|
|
class Player(BaseModel): |
|
"""Base class for a player""" |
|
|
|
name: str |
|
"""The name of the player.""" |
|
player_id: str |
|
"""The id of the player.""" |
|
game_id: str |
|
"""The id of the game the player is in.""" |
|
interface: BaseAgentInterface = Field(exclude=True) |
|
"""The interface used by the agent controlling the player to communicate with the game.""" |
|
message_level: str = "info" |
|
"""The level of messages that the player will receive. Can be "info", "verbose", or "debug".""" |
|
|
|
def can_receive_message(self, message_type: MessageType) -> bool: |
|
"""Returns True if the player can receive a message of the type.""" |
|
if message_type == "verbose" and self.message_level not in ["verbose", "debug"]: |
|
return False |
|
elif message_type == "debug" and self.message_level != "debug": |
|
return False |
|
else: |
|
return True |
|
|
|
@classmethod |
|
def observer( |
|
cls, |
|
game_id: str, |
|
message_level: str = "verbose", |
|
interface_type: Type[BaseAgentInterface] = HumanAgentCLI, |
|
log_messages: bool = False |
|
): |
|
"""Creates an observer player.""" |
|
name = "Observer" |
|
player_id = f"{game_id}-observer" |
|
interface = interface_type(agent_id=player_id, game_id=game_id) |
|
|
|
return cls(name=name, player_id=player_id, game_id=game_id, interface=interface, message_level=message_level) |
|
|
|
|
|
class PlayerSubclass(Player): |
|
@classmethod |
|
def from_player(cls, player: Player): |
|
"""Creates a new instance of the subclass from a player instance.""" |
|
fields = player.model_dump() |
|
fields['interface'] = player.interface |
|
return cls(**fields) |
|
|
|
|
|
class ChameleonPlayer(PlayerSubclass): |
|
"""A player in the game Chameleon""" |
|
|
|
points: int = 0 |
|
"""The number of points the player has.""" |
|
roles: List[Role] = [] |
|
"""The role of the player in the game. Can be "chameleon" or "herd". This changes every round.""" |
|
|
|
def assign_role(self, role: Role): |
|
self.roles.append(role) |
|
|
|
@property |
|
def role(self) -> Role: |
|
"""The current role of the player.""" |
|
return self.roles[-1] |
|
|
|
@property |
|
def rounds_played_as_chameleon(self) -> int: |
|
"""The number of times the player has been the Chameleon.""" |
|
return self.roles.count("chameleon") |
|
|
|
@property |
|
def rounds_played_as_herd(self) -> int: |
|
"""The number of times the player has been in the Herd.""" |
|
return self.roles.count("herd") |
|
|