"""A collection of player classes.
Includes:
* Player
* FixedPolicyPlayer
"""
from abc import ABC, abstractmethod
from enum import Enum
from typing import Sequence
import numpy as np
from imperfecto.misc.utils import get_action
[docs]class Player(ABC):
"""
An abstract player class.
Attributes:
name (str): The name of the player.
strategy (dict): map from instostate to np.array of shape (n_actions,).
"""
def __init__(self, name=""):
self.name = name
self.strategy = {}
def __str__(self) -> str:
if self.name == "":
return self.__class__.__name__
else:
return "Player(" + self.name + ")"
def __repr__(self) -> str:
if self.name is None:
return self.__class__.__name__
else:
return "Player(" + self.name + ")"
[docs] def act(self, infostate: str) -> int:
"""
Returns the action to take given an infostate.
Args:
infostate: The infostate to take the action in.
Returns:
The action to take.
"""
if infostate not in self.strategy:
# uniform
self.strategy[infostate] = np.ones(
len(self.game.actions)) / len(self.game.actions)
return get_action(self.strategy[infostate])
[docs] @abstractmethod
def update_strategy(self, history: Sequence[Enum], player_id: int) -> None:
"""Update the strategy of the player at the end of the game.
Args:
history: The history of the game, which *must* be a terminal node.
player_id: The id of the player to update (i.e., my id).
"""
pass
@property
def game(self):
return self._game
@game.setter
def game(self, game):
self._game = game
@property
def strategy(self):
"""A dict with key = infostate and value = np.array of shape (n_actions,)."""
return self._strategy
@strategy.setter
def strategy(self, strategy: dict):
self._strategy = strategy
[docs]class FixedPolicyPlayer(Player):
"""A player with a given fixed strategy.
Args:
name: The name of the player.
strategy: The fixed strategy of the player.
Attributes:
name (str): The name of the player.
strategy (dict): The fixed strategy of the player.
"""
def __init__(self, name: str, strategy: dict):
super().__init__(name)
self.strategy = strategy
[docs] def update_strategy(self, history: Sequence[Enum], player_id: int) -> None:
del history, player_id # do nothing
pass