Source code for imperfecto.games.rock_paper_scissor

"""A collection of 2-player rock paper scissor games.

This includes:
    - A Standard Rock Paper Scissor class.
    - An Asymmetric Rock Paper Scissor class.
"""
from enum import IntEnum
from typing import Sequence

from imperfecto.games.game import NormalFormGame
from imperfecto.misc.utils import lessVerboseEnum


[docs]class ROCK_PAPER_SCISSOR_ACTIONS(lessVerboseEnum, IntEnum): """Available actions for the rock-paper-scissors game.""" ROCK = 0 PAPER = 1 SCISSOR = 2
[docs]class RockPaperScissorGame(NormalFormGame): """A (standard) 2-player rock-paper-scissor (extensive-form) game. Payoff: Rock beats scissors, scissors beats paper, and paper beats rock. Winner gets +1 payoff, loser gets -1 payoff. Nash Equilibrium: The nash strategy (unexploitable) is (1/3, 1/3, 1/3) (payoff = 0 for all) """ actions = ROCK_PAPER_SCISSOR_ACTIONS n_players = 2
[docs] def get_payoffs(self, history: Sequence[ROCK_PAPER_SCISSOR_ACTIONS]) -> Sequence[float]: assert self.is_terminal(history) history_str = self.history_to_str(history) match history_str: case "ROCK-PAPER": return [-1, 1] case "ROCK-SCISSOR": return [1, -1] case "PAPER-ROCK": return [1, -1] case "PAPER-SCISSOR": return [-1, 1] case "SCISSOR-ROCK": return [-1, 1] case "SCISSOR-PAPER": return [1, -1] return [0, 0]
[docs]class AsymmetricRockPaperScissorGame(RockPaperScissorGame): """An asymmetric 2-player rock-paper-scissors (extensive-form) game. Payoff: Rock beats scissors, scissors beats paper, and paper beats rock. **But** winner gets +2 payoff, loser gets -2 payoff when someone plays scissor. Otherwise, winner gets +1 payoff, loser gets -1 payoff. Nash Equilibrium: The Nash strategy (unexploitable) is (0.4, 0.4, 0.2) (payoff = 0 for all) """
[docs] def get_payoffs(self, history: Sequence[ROCK_PAPER_SCISSOR_ACTIONS]) -> Sequence[float]: """Override the get_payoffs function of standard rock-paper-scissors. The winner gets +2 payoff, loser gets -2 payoff when someone plays scissor. Otherwise, winner gets +1 payoff, loser gets -1 payoff. Args: history: The history of the game. Returns: The payoffs of the players. """ assert self.is_terminal(history) if len(history) > 2: raise ValueError("Invalid history " + str(history)) history_str = self.history_to_str(history) match history_str: case "ROCK-PAPER": return [-1, 1] case "ROCK-SCISSOR": return [2, -2] case "PAPER-ROCK": return [1, -1] case "PAPER-SCISSOR": return [-2, 2] case "SCISSOR-ROCK": return [-2, 2] case "SCISSOR-PAPER": return [2, -2] return [0, 0]