chameleon / src /player.py
Eric Botti
messages can be assigned to multiple players
2f9cbc8
raw
history blame
2.87 kB
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"]
# Abstraction is a WIP and a little premature, but I'd like to reuse this framework to create more Games in the future
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")