diff --git a/.gitignore b/.gitignore
index d2f3fe5797..9d37e0d3b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,5 @@ doc/tutorials/*.png
Gambit.app/*
*.ipynb_checkpoints
*.ef
+build_support/msw/gambit.wxs
+build_support/osx/Info.plist
diff --git a/Makefile.am b/Makefile.am
index fe3fc232f2..b0680a7d72 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -100,147 +100,152 @@ EXTRA_DIST = \
src/gui/bitmaps/zoomout.xpm \
src/gui/bitmaps/zoom1.xpm \
src/gui/bitmaps/gambitrc.rc \
- contrib/games/2s2x2x2.efg \
- contrib/games/2smp.efg \
- contrib/games/2x2x2.efg \
- contrib/games/4cards.efg \
- contrib/games/artist1.efg \
- contrib/games/artist2.efg \
- contrib/games/badgame1.efg \
- contrib/games/badgame2.efg \
- contrib/games/bayes1a.efg \
- contrib/games/bayes2a.efg \
- contrib/games/bcp2.efg \
- contrib/games/bcp3.efg \
- contrib/games/bcp4.efg \
- contrib/games/bhg1.efg \
- contrib/games/bhg2.efg \
- contrib/games/bhg3.efg \
- contrib/games/bhg4.efg \
- contrib/games/bhg5.efg \
- contrib/games/caro2.efg \
- contrib/games/cent2.efg \
- contrib/games/cent3.efg \
- contrib/games/cent4.efg \
- contrib/games/cent6.efg \
- contrib/games/centcs10.efg \
- contrib/games/centcs6.efg \
- contrib/games/condjury.efg \
- contrib/games/coord2.efg \
- contrib/games/coord2ts.efg \
- contrib/games/coord3.efg \
- contrib/games/coord4.efg \
- contrib/games/cross.efg \
- contrib/games/cs.efg \
- contrib/games/e01.efg \
- contrib/games/e02.efg \
- contrib/games/e03.efg \
- contrib/games/e04.efg \
- contrib/games/e05.efg \
- contrib/games/e06.efg \
- contrib/games/e07.efg \
- contrib/games/e08.efg \
- contrib/games/e09.efg \
- contrib/games/e10a.efg \
- contrib/games/e10.efg \
- contrib/games/e13.efg \
- contrib/games/e16.efg \
- contrib/games/e17.efg \
- contrib/games/e18.efg \
- contrib/games/g1.efg \
- contrib/games/g2.efg \
- contrib/games/g3.efg \
- contrib/games/holdout7.efg \
- contrib/games/holdout.efg \
- contrib/games/hs1.efg \
- contrib/games/jury_mr.efg \
- contrib/games/jury_un.efg \
- contrib/games/km1.efg \
- contrib/games/km2.efg \
- contrib/games/km3.efg \
- contrib/games/km6.efg \
- contrib/games/montyhal.efg \
- contrib/games/my_2-1.efg \
- contrib/games/my_2-4.efg \
- contrib/games/my_2-8.efg \
- contrib/games/my_3-3a.efg \
- contrib/games/my_3-3b.efg \
- contrib/games/my_3-3c.efg \
- contrib/games/my_3-3d.efg \
- contrib/games/my_3-3e.efg \
- contrib/games/my_3-4.efg \
- contrib/games/myerson.efg \
- contrib/games/nim7.efg \
- contrib/games/nim.efg \
- contrib/games/palf2.efg \
- contrib/games/palf3.efg \
- contrib/games/palf.efg \
- contrib/games/poker2.efg \
- contrib/games/poker.efg \
- contrib/games/pvw2.efg \
- contrib/games/pvw.efg \
- contrib/games/sh3.efg \
- contrib/games/sww1.efg \
- contrib/games/sww2.efg \
- contrib/games/sww3.efg \
- contrib/games/tim.efg \
- contrib/games/ttt.efg \
- contrib/games/vd.efg \
- contrib/games/w_ex1.efg \
- contrib/games/w_ex2.efg \
- contrib/games/wilson1.efg \
- contrib/games/work1.efg \
- contrib/games/work2.efg \
- contrib/games/work3.efg \
- contrib/games/2x2a.nfg \
- contrib/games/2x2const.nfg \
- contrib/games/2x2.nfg \
- contrib/games/2x2x2.nfg \
- contrib/games/2x2x2x2.nfg \
- contrib/games/2x2x2x2x2.nfg \
- contrib/games/3x3x3.nfg \
- contrib/games/5x4x3.nfg \
- contrib/games/8x2x2.nfg \
- contrib/games/8x8.nfg \
- contrib/games/cent2.nfg \
- contrib/games/coord2.nfg \
- contrib/games/coord333.nfg \
- contrib/games/coord3.nfg \
- contrib/games/coord4.nfg \
- contrib/games/csg1.nfg \
- contrib/games/csg2.nfg \
- contrib/games/csg3.nfg \
- contrib/games/csg4.nfg \
- contrib/games/deg1.nfg \
- contrib/games/deg2.nfg \
- contrib/games/e01.nfg \
- contrib/games/e02.nfg \
- contrib/games/e04.nfg \
- contrib/games/e07.nfg \
- contrib/games/g1.nfg \
- contrib/games/g2.nfg \
- contrib/games/g3.nfg \
- contrib/games/loopback.nfg \
- contrib/games/mixdom2.nfg \
- contrib/games/mixdom.nfg \
- contrib/games/oneill.nfg \
- contrib/games/pd.nfg \
- contrib/games/perfect1.nfg \
- contrib/games/perfect2.nfg \
- contrib/games/perfect3.nfg \
- contrib/games/poker.nfg \
- contrib/games/sh3.nfg \
- contrib/games/stengel.nfg \
- contrib/games/sww1.nfg \
- contrib/games/todd1.nfg \
- contrib/games/todd2.nfg \
- contrib/games/todd3.nfg \
- contrib/games/vd.nfg \
- contrib/games/wink3.nfg \
- contrib/games/winkels.nfg \
- contrib/games/yamamoto.nfg \
- contrib/games/zero.nfg \
- src/README.rst
+ src/README.rst \
+ src/pygambit/catalog_game_files/2s2x2x2.efg \
+ src/pygambit/catalog_game_files/2smp.efg \
+ src/pygambit/catalog_game_files/2x2.nfg \
+ src/pygambit/catalog_game_files/2x2a.nfg \
+ src/pygambit/catalog_game_files/2x2const.nfg \
+ src/pygambit/catalog_game_files/2x2x2-nau.nfg \
+ src/pygambit/catalog_game_files/2x2x2.efg \
+ src/pygambit/catalog_game_files/2x2x2.nfg \
+ src/pygambit/catalog_game_files/2x2x2x2.nfg \
+ src/pygambit/catalog_game_files/2x2x2x2x2.nfg \
+ src/pygambit/catalog_game_files/3x3x3.nfg \
+ src/pygambit/catalog_game_files/4cards.efg \
+ src/pygambit/catalog_game_files/5x4x3.nfg \
+ src/pygambit/catalog_game_files/8x2x2.nfg \
+ src/pygambit/catalog_game_files/8x8.nfg \
+ src/pygambit/catalog_game_files/artist1.efg \
+ src/pygambit/catalog_game_files/artist2.efg \
+ src/pygambit/catalog_game_files/badgame1.efg \
+ src/pygambit/catalog_game_files/badgame2.efg \
+ src/pygambit/catalog_game_files/bagwell.efg \
+ src/pygambit/catalog_game_files/bayes1a.efg \
+ src/pygambit/catalog_game_files/bayes2a.efg \
+ src/pygambit/catalog_game_files/bcp2.efg \
+ src/pygambit/catalog_game_files/bcp3.efg \
+ src/pygambit/catalog_game_files/bcp4.efg \
+ src/pygambit/catalog_game_files/bhg1.efg \
+ src/pygambit/catalog_game_files/bhg2.efg \
+ src/pygambit/catalog_game_files/bhg3.efg \
+ src/pygambit/catalog_game_files/bhg4.efg \
+ src/pygambit/catalog_game_files/bhg5.efg \
+ src/pygambit/catalog_game_files/caro2.efg \
+ src/pygambit/catalog_game_files/cent2.efg \
+ src/pygambit/catalog_game_files/cent2.nfg \
+ src/pygambit/catalog_game_files/cent3.efg \
+ src/pygambit/catalog_game_files/cent4.efg \
+ src/pygambit/catalog_game_files/cent6.efg \
+ src/pygambit/catalog_game_files/centcs10.efg \
+ src/pygambit/catalog_game_files/centcs6.efg \
+ src/pygambit/catalog_game_files/condjury.efg \
+ src/pygambit/catalog_game_files/coord2.efg \
+ src/pygambit/catalog_game_files/coord2.nfg \
+ src/pygambit/catalog_game_files/coord2ts.efg \
+ src/pygambit/catalog_game_files/coord3.efg \
+ src/pygambit/catalog_game_files/coord3.nfg \
+ src/pygambit/catalog_game_files/coord333.nfg \
+ src/pygambit/catalog_game_files/coord4.efg \
+ src/pygambit/catalog_game_files/coord4.nfg \
+ src/pygambit/catalog_game_files/cross.efg \
+ src/pygambit/catalog_game_files/cs.efg \
+ src/pygambit/catalog_game_files/csg1.nfg \
+ src/pygambit/catalog_game_files/csg2.nfg \
+ src/pygambit/catalog_game_files/csg3.nfg \
+ src/pygambit/catalog_game_files/csg4.nfg \
+ src/pygambit/catalog_game_files/deg1.nfg \
+ src/pygambit/catalog_game_files/deg2.nfg \
+ src/pygambit/catalog_game_files/e01.efg \
+ src/pygambit/catalog_game_files/e01.nfg \
+ src/pygambit/catalog_game_files/e02.efg \
+ src/pygambit/catalog_game_files/e02.nfg \
+ src/pygambit/catalog_game_files/e03.efg \
+ src/pygambit/catalog_game_files/e04.efg \
+ src/pygambit/catalog_game_files/e04.nfg \
+ src/pygambit/catalog_game_files/e05.efg \
+ src/pygambit/catalog_game_files/e06.efg \
+ src/pygambit/catalog_game_files/e07.efg \
+ src/pygambit/catalog_game_files/e07.nfg \
+ src/pygambit/catalog_game_files/e08.efg \
+ src/pygambit/catalog_game_files/e09.efg \
+ src/pygambit/catalog_game_files/e10.efg \
+ src/pygambit/catalog_game_files/e10a.efg \
+ src/pygambit/catalog_game_files/e13.efg \
+ src/pygambit/catalog_game_files/e16.efg \
+ src/pygambit/catalog_game_files/e17.efg \
+ src/pygambit/catalog_game_files/e18.efg \
+ src/pygambit/catalog_game_files/g1.efg \
+ src/pygambit/catalog_game_files/g1.nfg \
+ src/pygambit/catalog_game_files/g2.efg \
+ src/pygambit/catalog_game_files/g2.nfg \
+ src/pygambit/catalog_game_files/g3.efg \
+ src/pygambit/catalog_game_files/g3.nfg \
+ src/pygambit/catalog_game_files/holdout.efg \
+ src/pygambit/catalog_game_files/holdout7.efg \
+ src/pygambit/catalog_game_files/hs1.efg \
+ src/pygambit/catalog_game_files/jury_mr.efg \
+ src/pygambit/catalog_game_files/jury_un.efg \
+ src/pygambit/catalog_game_files/km1.efg \
+ src/pygambit/catalog_game_files/km2.efg \
+ src/pygambit/catalog_game_files/km3.efg \
+ src/pygambit/catalog_game_files/km6.efg \
+ src/pygambit/catalog_game_files/loopback.nfg \
+ src/pygambit/catalog_game_files/mixdom.nfg \
+ src/pygambit/catalog_game_files/mixdom2.nfg \
+ src/pygambit/catalog_game_files/montyhal.efg \
+ src/pygambit/catalog_game_files/my_2-1.efg \
+ src/pygambit/catalog_game_files/my_2-4.efg \
+ src/pygambit/catalog_game_files/my_2-8.efg \
+ src/pygambit/catalog_game_files/my_3-3a.efg \
+ src/pygambit/catalog_game_files/my_3-3b.efg \
+ src/pygambit/catalog_game_files/my_3-3c.efg \
+ src/pygambit/catalog_game_files/my_3-3d.efg \
+ src/pygambit/catalog_game_files/my_3-3e.efg \
+ src/pygambit/catalog_game_files/my_3-4.efg \
+ src/pygambit/catalog_game_files/myerson.efg \
+ src/pygambit/catalog_game_files/myerson_fig_4_2.efg \
+ src/pygambit/catalog_game_files/nim.efg \
+ src/pygambit/catalog_game_files/nim7.efg \
+ src/pygambit/catalog_game_files/oneill.nfg \
+ src/pygambit/catalog_game_files/palf.efg \
+ src/pygambit/catalog_game_files/palf2.efg \
+ src/pygambit/catalog_game_files/palf3.efg \
+ src/pygambit/catalog_game_files/pbride.efg \
+ src/pygambit/catalog_game_files/pd.nfg \
+ src/pygambit/catalog_game_files/perfect1.nfg \
+ src/pygambit/catalog_game_files/perfect2.nfg \
+ src/pygambit/catalog_game_files/perfect3.nfg \
+ src/pygambit/catalog_game_files/poker.efg \
+ src/pygambit/catalog_game_files/poker.nfg \
+ src/pygambit/catalog_game_files/poker2.efg \
+ src/pygambit/catalog_game_files/pvw.efg \
+ src/pygambit/catalog_game_files/pvw2.efg \
+ src/pygambit/catalog_game_files/sh3.efg \
+ src/pygambit/catalog_game_files/sh3.nfg \
+ src/pygambit/catalog_game_files/spence.efg \
+ src/pygambit/catalog_game_files/stengel.nfg \
+ src/pygambit/catalog_game_files/sww1.efg \
+ src/pygambit/catalog_game_files/sww1.nfg \
+ src/pygambit/catalog_game_files/sww2.efg \
+ src/pygambit/catalog_game_files/sww3.efg \
+ src/pygambit/catalog_game_files/tim.efg \
+ src/pygambit/catalog_game_files/todd1.nfg \
+ src/pygambit/catalog_game_files/todd2.nfg \
+ src/pygambit/catalog_game_files/todd3.nfg \
+ src/pygambit/catalog_game_files/ttt.efg \
+ src/pygambit/catalog_game_files/vd.efg \
+ src/pygambit/catalog_game_files/vd.nfg \
+ src/pygambit/catalog_game_files/w_ex1.efg \
+ src/pygambit/catalog_game_files/w_ex2.efg \
+ src/pygambit/catalog_game_files/wilson1.efg \
+ src/pygambit/catalog_game_files/wink3.nfg \
+ src/pygambit/catalog_game_files/winkels.nfg \
+ src/pygambit/catalog_game_files/work1.efg \
+ src/pygambit/catalog_game_files/work2.efg \
+ src/pygambit/catalog_game_files/work3.efg \
+ src/pygambit/catalog_game_files/yamamoto.nfg \
+ src/pygambit/catalog_game_files/zero.nfg
core_SOURCES = \
src/core/core.h \
diff --git a/doc/catalog.rst b/doc/catalog.rst
new file mode 100644
index 0000000000..c9e73ea3bb
--- /dev/null
+++ b/doc/catalog.rst
@@ -0,0 +1,12 @@
+Catalog of games
+================
+
+.. raw:: html
+
+
+
+.. note::
+ If you are not redirected automatically, see
+ `Games Catalog `.
diff --git a/doc/developer.catalog.rst b/doc/developer.catalog.rst
new file mode 100644
index 0000000000..264e3d37bd
--- /dev/null
+++ b/doc/developer.catalog.rst
@@ -0,0 +1,184 @@
+.. _update-the-catlog:
+
+Updating the Games Catalog
+==========================
+
+This page covers the process for contributing to and updating Gambit's :ref:`Games Catalog `.
+To do so, you will need to have the `gambit` GitHub repo cloned and be able to submit pull request via GitHub;
+you may wish to first review the :ref:`contributor guidelines `.
+
+You can add games to the catalog saved in a valid representation :ref:`format `, e.g. for `.efg` for extensive form games.
+Alternatively, you can define games for the catalog in *pygambit* code.
+You may wish to first review the :ref:`pygambit ` docs pages.
+
+Both options for adding to the catalog below include an optional step for adding metadata to the catalog for your game(s).
+Adding metadata to games will create a new filter for the :func:`pygambit.catalog.games` that users can search the catalog with.
+
+.. dropdown:: Add game files to the catalog
+ :class-container: sd-border-0
+
+ 1. **Create the game file:**
+
+ Use either :ref:`pygambit `, the Gambit :ref:`CLI ` or :ref:`GUI ` to create and save game in a valid representation :ref:`format `.
+
+ 2. **Add the game file:**
+
+ Create a new branch in the `gambit` repo and commit the new game to `src/pygambit/catalog_game_files`
+
+ 3. **Update the catalog:**
+
+ Use the `catalog_update.py` script to update the catalog and associated documatation & build files.
+
+ .. code-block:: bash
+
+ pip install ruamel.yaml
+ cd src/pygambit
+ python catalog_update.py
+
+ .. note::
+ Run this script in a Python environment where `pygambit` itself is also :ref:`installed `
+
+ 4. **[Optional] Edit the catalog entry:**
+
+ Open `src/pygambit/catalog.yml` and find the new entry that was created in the previous step.
+ The entry will be named after the game file, but in camel case, with "Game" prefixed if the file started with a number.
+
+ If the game file doesn't already include a description ("comments" in older versions of Gambit) you should add a description field:
+
+ .. code-block:: yaml
+
+ MyGame:
+ file: my_game.nfg
+ description: "A game that... originally created by Author (2000)."
+
+ 5. **[Optional] Add custom metadata to catalog games:**
+
+ Open `src/pygambit/catalog.py` and add update the `CatalogGame` base class with the new metadata field.
+ Include a type hint, a default value and a docstring.
+
+ .. code-block:: python
+
+ # Metadata fields
+ my_metadata: int | None = None
+ """Explanation of my_metadata field."""
+
+ Open `src/pygambit/catalog.yml` and add the field under the `metadata` for the game you added, and any others that shouldn't have the default.
+
+ .. code-block:: yaml
+
+ MyGame:
+ file: my_game.efg
+ metadata:
+ my_metadata: 17
+
+ 6. **Submit a pull request to GitHub with all changes:**
+
+ .. warning::
+ If you made changes in step 4 or 5 above, re-run the update script from step 3.
+
+ .. warning::
+ Make sure you commit all changed files e.g. run `git add --all` before committing and pushing.
+
+.. dropdown:: Code games for the catalog
+ :class-container: sd-border-0
+
+ 1. **Write the pygambit code:**
+
+ Write code for your game with :ref:`pygambit `.
+ Your code should create a ``Game`` object with a title and description.
+
+ .. note::
+ Test your game by visualising it in `draw_tree` and running Gambit's solvers.
+
+ 2. **Create a new Python class for your game:**
+
+ Create a new branch in the `gambit` repo and open `src/pygambit/catalog_games.py`.
+ Add a subclass of `CatalogGame` with your code implemented as the `_game` function,
+ which should be defined as a `staticmethod` returning a ``Game`` object.
+ You can optionally include paramaters to generate game variants.
+
+ .. code-block:: python
+
+ class MyGame(gbt.catalog.CatalogGame):
+
+ @staticmethod
+ def _game(some_param: bool = False) -> gbt.Game:
+ """
+ Docstring for _game function.
+
+ Parameters
+ ----------
+ some_param : bool, optional
+ Description of optional paramater.
+ Defaults to False.
+
+ Returns
+ -------
+ gbt.Game
+ The constructed game.
+
+ Examples
+ --------
+ >>> MyGame(some_param=False) # Constructs the standard game
+ >>> MyGame(some_param=True) # Constructs the alternate game
+ """
+ g = gbt.Game.new_tree(
+ players=["Buyer", "Seller"], title="My game"
+ )
+ g.description = "Longer description of My game, originally by Author (2000)."
+ g.append_move(g.root, "Buyer", ["Trust", "Not trust"])
+ g.append_move(g.root.children[0], "Seller", ["Honor", "Abuse"])
+ g.set_outcome(g.root.children[0].children[0], g.add_outcome([1, 1], label="Trustworthy"))
+ if some_param:
+ g.set_outcome(
+ g.root.children[0].children[1], g.add_outcome(["1/2", 2], label="Untrustworthy")
+ )
+ else:
+ g.set_outcome(
+ g.root.children[0].children[1], g.add_outcome([-1, 2], label="Untrustworthy")
+ )
+ g.set_outcome(g.root.children[1], g.add_outcome([0, 0], label="Opt-out"))
+ return g
+
+ .. note::
+ If you add a docstring to the class itself, this will be used in the API reference docs as the game description instead of `g.description`
+
+ 3. **Update the catalog:**
+
+ Use the `catalog_update.py` script to update the catalog and associated documatation & build files.
+
+ .. code-block:: bash
+
+ pip install ruamel.yaml
+ cd src/pygambit
+ python catalog_update.py
+
+ .. note::
+ Run this script in a Python environment where `pygambit` itself is also :ref:`installed `
+
+ 4. **[Optional] Add custom metadata to catalog games:**
+
+ Open `src/pygambit/catalog.py` and add update the `CatalogGame` base class with the new metadata field.
+ Include a type hint, a default value and a docstring.
+
+ .. code-block:: python
+
+ # Metadata fields
+ my_metadata: int | None = None
+ """Explanation of my_metadata field."""
+
+ Open `src/pygambit/catalog_games.py` and add a value for the field as a class attribute for the game(s) you added.
+
+ .. code-block:: python
+
+ class MyGame(gbt.catalog.CatalogGame):
+ my_metadata = 17
+ ...
+
+ 6. **Submit a pull request to GitHub with all changes:**
+
+ .. warning::
+ If you made changes in step 4 above, re-run the update script from step 3.
+
+ .. warning::
+ Make sure you commit all changed files e.g. run `git add --all` before committing and pushing.
diff --git a/doc/developer.contributing.rst b/doc/developer.contributing.rst
index f86939850d..02ca377471 100644
--- a/doc/developer.contributing.rst
+++ b/doc/developer.contributing.rst
@@ -1,3 +1,5 @@
+.. _contributing:
+
Contributing to Gambit
======================
diff --git a/doc/developer.rst b/doc/developer.rst
index 0a15126590..b954f08508 100644
--- a/doc/developer.rst
+++ b/doc/developer.rst
@@ -11,3 +11,4 @@ This section contains information for developers who want to contribute to the G
developer.build
developer.contributing
+ developer.catalog
diff --git a/doc/index.rst b/doc/index.rst
index 79076153ae..50aa0bc7a5 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -64,7 +64,7 @@ We recommended most new users install the PyGambit Python package and read the a
pygambit
tools
gui
- samples
+ catalog
developer
formats
biblio
diff --git a/doc/pygambit.api.rst b/doc/pygambit.api.rst
index ae029bae72..fc36aac62e 100644
--- a/doc/pygambit.api.rst
+++ b/doc/pygambit.api.rst
@@ -95,7 +95,7 @@ Information about the game
:toctree: api/
Game.title
- Game.comment
+ Game.description
Game.is_const_sum
Game.is_tree
Game.is_perfect_recall
@@ -325,3 +325,161 @@ Computation of quantal response equilibria
logit_estimate
LogitQREMixedStrategyFitResult
LogitQREMixedBehaviorFitResult
+
+
+.. _pygambit-catalog:
+
+Catalog of games
+~~~~~~~~~~~~~~~~
+
+.. currentmodule:: pygambit.catalog
+
+.. autosummary::
+ :toctree: api/
+
+ games
+ Artist1
+ Artist2
+ Badgame1
+ Badgame2
+ Bagwell
+ Bayes1a
+ Bayes2a
+ Bcp2
+ Bcp3
+ Bcp4
+ Bhg1
+ Bhg2
+ Bhg3
+ Bhg4
+ Bhg5
+ Caro2
+ Cent2
+ Cent2NFG
+ Cent3
+ Cent4
+ Cent6
+ Centcs10
+ Centcs6
+ Condjury
+ Coord2
+ Coord2NFG
+ Coord2ts
+ Coord3
+ Coord333
+ Coord3NFG
+ Coord4
+ Coord4NFG
+ Cross
+ Cs
+ Csg1
+ Csg2
+ Csg3
+ Csg4
+ Deg1
+ Deg2
+ E01
+ E01NFG
+ E02
+ E02NFG
+ E03
+ E04
+ E04NFG
+ E05
+ E06
+ E07
+ E07NFG
+ E08
+ E09
+ E10
+ E10a
+ E13
+ E16
+ E17
+ E18
+ G1
+ G1NFG
+ G2
+ G2NFG
+ G3
+ G3NFG
+ Game2s2x2x2
+ Game2smp
+ Game2x2
+ Game2x2a
+ Game2x2const
+ Game2x2x2
+ Game2x2x2NFG
+ Game2x2x2_nau
+ Game2x2x2x2
+ Game2x2x2x2x2
+ Game3x3x3
+ Game4cards
+ Game5x4x3
+ Game8x2x2
+ Game8x8
+ Holdout
+ Hs1
+ Jury_mr
+ Jury_un
+ Km1
+ Km2
+ Km3
+ Km6
+ Loopback
+ Mixdom
+ Mixdom2
+ Montyhal
+ My_2_1
+ My_2_4
+ My_2_8
+ My_3_3a
+ My_3_3b
+ My_3_3c
+ My_3_3d
+ My_3_3e
+ My_3_4
+ Myerson
+ Myerson_fig_4_2
+ Nim
+ Nim7
+ OneShotTrust
+ Oneill
+ Palf
+ Palf2
+ Palf3
+ Pbride
+ Perfect1
+ Perfect2
+ Perfect3
+ Poker
+ Poker2
+ PokerNFG
+ PrisonersDilemma
+ Pvw
+ Pvw2
+ Sh3
+ Sh3NFG
+ Spence
+ Stengel
+ Sww1
+ Sww1NFG
+ Sww2
+ Sww3
+ Tim
+ Todd1
+ Todd2
+ Todd3
+ Ttt
+ Vd
+ VdNFG
+ W_ex1
+ W_ex2
+ Wilson1
+ Wink3
+ Winkels
+ Work1
+ Work2
+ Work3
+ Yamamoto
+ Zero
diff --git a/doc/tools.enummixed.rst b/doc/tools.enummixed.rst
index c3ad6df128..f57ffbbc88 100644
--- a/doc/tools.enummixed.rst
+++ b/doc/tools.enummixed.rst
@@ -64,7 +64,7 @@ points.
feature that has not been widely tested.
Computing the equilibria, in mixed strategies, of :download:`e02.nfg
-<../contrib/games/e02.nfg>`, the reduced strategic form of the example
+<../src/pygambit/catalog_game_files/e02.nfg>`, the reduced strategic form of the example
in Figure 2 of Selten (International Journal of Game Theory,
1975)
diff --git a/doc/tools.enumpoly.rst b/doc/tools.enumpoly.rst
index a04362e982..23875d684b 100644
--- a/doc/tools.enumpoly.rst
+++ b/doc/tools.enumpoly.rst
@@ -92,7 +92,7 @@ support of some set of equilibria.
default, no information about supports is printed.
Computing equilibria of the strategic game :download:`e01.nfg
-<../contrib/games/e01.efg>`, the example in Figure 1 of Selten
+<../src/pygambit/catalog_game_files/e01.efg>`, the example in Figure 1 of Selten
(International Journal of Game Theory, 1975) sometimes called
"Selten's horse"
diff --git a/doc/tools.enumpure.rst b/doc/tools.enumpure.rst
index c653bc7bde..1a03109fed 100644
--- a/doc/tools.enumpure.rst
+++ b/doc/tools.enumpure.rst
@@ -53,7 +53,7 @@ pure-strategy Nash equilibria.
Computing the pure-strategy equilibria of extensive game :download:`e02.efg
-<../contrib/games/e02.efg>`, the example in Figure 2 of Selten
+<../src/pygambit/catalog_game_files/e02.efg>`, the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
$ gambit-enumpure e02.efg
diff --git a/doc/tools.gnm.rst b/doc/tools.gnm.rst
index 7bd63c3cc7..b70c3beee6 100644
--- a/doc/tools.gnm.rst
+++ b/doc/tools.gnm.rst
@@ -81,7 +81,7 @@ subsets of equilibria being found.
Show intermediate output of the algorithm. If this option is
not specified, only the equilibria found are reported.
-Computing an equilibrium of :download:`e02.nfg <../contrib/games/e02.nfg>`,
+Computing an equilibrium of :download:`e02.nfg <../src/pygambit/catalog_game_files/e02.nfg>`,
the reduced strategic form of the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
diff --git a/doc/tools.ipa.rst b/doc/tools.ipa.rst
index adac09b2fd..2790a6a3f7 100644
--- a/doc/tools.ipa.rst
+++ b/doc/tools.ipa.rst
@@ -48,7 +48,7 @@ equilibria being found.
output of equilibria (excluding the initial NE tag).
-Computing an equilibrium of :download:`e02.nfg <../contrib/games/e02.nfg>`,
+Computing an equilibrium of :download:`e02.nfg <../src/pygambit/catalog_game_files/e02.nfg>`,
the reduced strategic form of the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
diff --git a/doc/tools.lcp.rst b/doc/tools.lcp.rst
index 19b62d812e..55e161f239 100644
--- a/doc/tools.lcp.rst
+++ b/doc/tools.lcp.rst
@@ -76,7 +76,7 @@ game.
Computing an equilibrium of extensive game :download:`e02.efg
-<../contrib/games/e02.efg>`, the example in Figure 2 of Selten
+<../src/pygambit/catalog_game_files/e02.efg>`, the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
$ gambit-lcp e02.efg
diff --git a/doc/tools.liap.rst b/doc/tools.liap.rst
index fdac11f51f..10cab5043d 100644
--- a/doc/tools.liap.rst
+++ b/doc/tools.liap.rst
@@ -96,7 +96,7 @@ not guaranteed to find all, or even any, Nash equilibria.
equilibria found.
Computing an equilibrium in mixed strategies of :download:`e02.efg
-<../contrib/games/e02.efg>`, the example in Figure 2 of Selten
+<../src/pygambit/catalog_game_files/e02.efg>`, the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
$ gambit-liap e02.nfg
diff --git a/doc/tools.logit.rst b/doc/tools.logit.rst
index 908cb201c0..2f19a71b1d 100644
--- a/doc/tools.logit.rst
+++ b/doc/tools.logit.rst
@@ -102,7 +102,7 @@ the beliefs at such information sets as being uniform across all member nodes.
equilibrium at the end of the branch is output.
Computing the principal branch, in mixed strategies, of :download:`e02.nfg
-<../contrib/games/e02.nfg>`, the reduced strategic form of the example
+<../src/pygambit/catalog_game_files/e02.nfg>`, the reduced strategic form of the example
in Figure 2 of Selten (International Journal of Game Theory,
1975)
diff --git a/doc/tools.lp.rst b/doc/tools.lp.rst
index f09e97663e..e637cbaa91 100644
--- a/doc/tools.lp.rst
+++ b/doc/tools.lp.rst
@@ -53,7 +53,7 @@ points of that set.
Suppresses printing of the banner at program launch.
Computing an equilibrium of the game :download:`2x2const.nfg
-<../contrib/games/2x2const.nfg>`, a game with two players with two
+<../src/pygambit/catalog_game_files/2x2const.nfg>`, a game with two players with two
strategies each, with a unique equilibrium in mixed strategies
$ gambit-lp 2x2const.nfg
diff --git a/doc/tools.simpdiv.rst b/doc/tools.simpdiv.rst
index ccebe633c1..8c65c68105 100644
--- a/doc/tools.simpdiv.rst
+++ b/doc/tools.simpdiv.rst
@@ -87,7 +87,7 @@ options to specify additional starting points for the algorithm.
Computing an equilibrium in mixed strategies of :download:`e02.efg
-<../contrib/games/e02.efg>`, the example in Figure 2 of Selten
+<../src/pygambit/catalog_game_files/e02.efg>`, the example in Figure 2 of Selten
(International Journal of Game Theory, 1975)
$ gambit-simpdiv e02.nfg
diff --git a/doc/tutorials/01_quickstart.ipynb b/doc/tutorials/01_quickstart.ipynb
index 06ec6f91ea..23e07731ca 100644
--- a/doc/tutorials/01_quickstart.ipynb
+++ b/doc/tutorials/01_quickstart.ipynb
@@ -38,7 +38,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"id": "c58d382d",
"metadata": {},
"outputs": [],
@@ -50,7 +50,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"id": "2060c1ed",
"metadata": {},
"outputs": [
@@ -60,7 +60,7 @@
"pygambit.gambit.Game"
]
},
- "execution_count": 1,
+ "execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -83,7 +83,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 3,
"id": "9d8203e8",
"metadata": {},
"outputs": [],
@@ -111,7 +111,7 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 4,
"id": "61030607",
"metadata": {},
"outputs": [],
@@ -135,7 +135,7 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 5,
"id": "caecc334",
"metadata": {},
"outputs": [
@@ -149,7 +149,7 @@
"Game(title='Prisoner's Dilemma')"
]
},
- "execution_count": 4,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -189,7 +189,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"id": "843ba7f3",
"metadata": {},
"outputs": [
@@ -203,7 +203,7 @@
"Game(title='Another Prisoner's Dilemma')"
]
},
- "execution_count": 5,
+ "execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -233,7 +233,7 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 7,
"id": "5ee752c4",
"metadata": {},
"outputs": [
@@ -270,7 +270,7 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 8,
"id": "a81c06c7",
"metadata": {},
"outputs": [
@@ -280,7 +280,7 @@
"pygambit.nash.NashComputationResult"
]
},
- "execution_count": 7,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -300,7 +300,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 9,
"id": "bd395180",
"metadata": {},
"outputs": [
@@ -310,7 +310,7 @@
"1"
]
},
- "execution_count": 8,
+ "execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
@@ -329,7 +329,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 10,
"id": "76570ebc",
"metadata": {},
"outputs": [
@@ -342,7 +342,7 @@
"[[Rational(0, 1), Rational(1, 1)], [Rational(0, 1), Rational(1, 1)]]"
]
},
- "execution_count": 9,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -354,7 +354,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 11,
"id": "6e8cfcde",
"metadata": {},
"outputs": [
@@ -364,7 +364,7 @@
"pygambit.gambit.MixedStrategyProfileRational"
]
},
- "execution_count": 10,
+ "execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
@@ -385,7 +385,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 12,
"id": "980bf6b1",
"metadata": {},
"outputs": [
@@ -417,11 +417,89 @@
},
{
"cell_type": "markdown",
- "id": "24f36b0d",
+ "id": "15ab8d84",
"metadata": {},
"source": [
"The equilibrium shows that both players are playing their dominant strategy, which is to defect. This is because defecting is the best response to the other player's strategy, regardless of what that strategy is.\n",
"\n",
+ "Loading games from the catalog\n",
+ "------------------------------\n",
+ "\n",
+ "Gambit includes a catalog of standard games that can be loaded directly by name.\n",
+ "You can list all the available games and filtering on the game type and number of players in the catalog like so:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "701aa52a",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['Coord2NFG',\n",
+ " 'Game2x2',\n",
+ " 'Game2x2a',\n",
+ " 'Game2x2const',\n",
+ " 'Loopback',\n",
+ " 'PrisonersDilemma',\n",
+ " 'Sww1NFG',\n",
+ " 'Zero']"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "gbt.catalog.games(\n",
+ " is_tree=False,\n",
+ " num_strategies=4,\n",
+ " num_players=2\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a919ddf7",
+ "metadata": {},
+ "source": [
+ "You can then load a specific game by its name. For example, to load the \"Prisoner's Dilemma\" game from the catalog, you would do the following:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "6db7a29a",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "Two person Prisoner's Dilemma game
\n",
+ "\n"
+ ],
+ "text/plain": [
+ "Game(title='Two person Prisoner's Dilemma game')"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "g = gbt.catalog.PrisonersDilemma()\n",
+ "g"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24f36b0d",
+ "metadata": {},
+ "source": [
"Saving and reading strategic form games to and from file\n",
"--------------------\n",
"\n",
@@ -433,7 +511,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 15,
"id": "f58eaa77",
"metadata": {},
"outputs": [],
@@ -451,23 +529,12 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 16,
"id": "4119a2ac",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "pygambit.gambit.Game"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
- "# gbt.read_nfg(\"test_games/prisoners_dilemma.nfg\")"
+ "# gbt.read_nfg(\"prisoners_dilemma.nfg\")"
]
}
],
diff --git a/doc/tutorials/02_extensive_form.ipynb b/doc/tutorials/02_extensive_form.ipynb
index 528970c617..ce84fe0f38 100644
--- a/doc/tutorials/02_extensive_form.ipynb
+++ b/doc/tutorials/02_extensive_form.ipynb
@@ -31,7 +31,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 22,
"id": "5946289b",
"metadata": {},
"outputs": [],
@@ -51,7 +51,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 23,
"id": "91ed4dfb",
"metadata": {},
"outputs": [],
@@ -72,27 +72,27 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 24,
"id": "3cd94917",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
- "