"""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]