A game theory framework with examples and algorithms
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
gamegym
tests
.coveragerc
.gitignore
.style.yapf
.travis.yml
LICENCE
README.md
pytest.ini
setup.py

README.md

Game Gym

MIT Licence Build Status PyPI version codecov Coverage Status

A game theory framework providing a collection of games, common API and a several game-theoretic algorithms.

The goal of the project is to provide tools for buildng complex games (e.g. board games, with partial information or simultaneous moves), computation of approximate strateges and creating artificial intelligence for such games, and to be a base for robust value learning experiments.

Under active development, looking for users, ideas and contributors!

Overview

Algorithms:

  • Outcome sampling MCCFR Nash equilibrium computation
  • Exact best response and exploitability
  • Approximate best response and exploitablity
  • Sparse SGD value learning (with values linear in known features)
  • Plotting strategy development (see plots for Matching Pennies, Rock-Paper-Scissors, Goofspiel(4))

Games:

  • General matrix games (normal form games)
  • Rock-paper-scissors, Matching pennies, Prisoner's dilemma, ...
  • Goofspiel (GOPS)
  • One-card poker

Game interface

For an exploration of API in Rust, see GTCogs.

To implement game you define one class derived from gamegym.Game with the following interface:

class Game:
    """
    Base class for game instances.

    Every descendant must have an attribute `self.players`.
    Players are numbered `0 .. players - 1`.
    """

    def __init__(self):
        self.players = 2

    def initial_state(self) -> Tuple[Any, ActivePlayer]:
        """
        Return the initial internal state and active player.

        Note that the initial game state must be always the same. If the game start
        depends on chance, use a chance node as the first state.
        """
        raise NotImplementedError

    def update_state(self, sit: Situation, action: Any) -> Tuple[Any, ActivePlayer, tuple]:
        """
        Return the updated internal state, active player and per-player observations.

        The observations must have length 0 (no obs for anyone)
        or (players + 1) (last observation is the public one).
        """
        raise NotImplementedError

    # ... more methods provided
    # Use sit1 = game.start() to obtain a starting situation, and
    # sit2 = game.play(sit1, action) to obtain an updated situation.

The main auxiliary structs common to all games are Situation and ActivePlayer.

@attr.s
class Situation:
    """
    One gae history and associated structures: observations, active player and actions, state.
    """
    history = attr.ib(type=tuple)
    history_idx = attr.ib(type=tuple)
    active = attr.ib(type=ActivePlayer)
    observations = attr.ib(type=tuple)
    state = attr.ib(type=Any)
    game = attr.ib(type='Game')

@attr.s
class ActivePlayer:
    """
    Game mode description: active player, actions, payoffs (in terminals), chance distribution.
    """
    CHANCE = -1
    TERMINAL = -2

    player = attr.ib(type=int)
    actions = attr.ib(type=tuple)
    payoff = attr.ib(type=Union[tuple, np.ndarray])
    chance = attr.ib(type=Union[tuple, np.ndarray])

Integration with Gambit

In gamegym.contrib.gambit there is basic integration with Gambit project game library (export Game to .efg, import computed strategy). However, gambit is only suitable for very small games (e.g. <100 states) and is not actively developed anymore.

Installing gambit in Python 3

As of 2018-12, Gambit did not work under Python 3 (see #203) and there were some problems building it with recent GCC (see #220). A fix is pending in #242. A temporary workaround until this is resolved is to use a git branch from the author of the fix:

git clone https://github.com/rhalbersma/gambit gambit-future
cd gambit-future
git checkout future
aclocal && libtoolize && automake --add-missing && autoconf && ./configure
cd src/python
python3 setup.py build
python3 setup.py install