Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ missing
gambit
.python-version
dist
.venv
11 changes: 10 additions & 1 deletion doc/pygambit.api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ Creating, reading, and writing games
.. autosummary::
:toctree: api/

read_gbt
read_efg
read_nfg
read_agg

Game.new_tree
Game.new_table
Game.from_arrays
Expand All @@ -36,6 +41,10 @@ Creating, reading, and writing games
Game.read_game
Game.parse_game
Game.write
Game.to_efg
Game.to_nfg
Game.to_html
Game.to_latex


Transforming game trees
Expand Down Expand Up @@ -181,7 +190,7 @@ Player behavior
Game.random_strategy_profile
Game.mixed_behavior_profile
Game.random_behavior_profile
Game.support_profile
Game.strategy_support_profile


Representation of strategic behavior
Expand Down
9 changes: 9 additions & 0 deletions src/pygambit/gambit.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,17 @@ cdef extern from "games/behavspt.h":
cdef extern from "util.h":
c_Game ReadGame(char *) except +IOError
c_Game ParseGame(char *) except +IOError
c_Game ParseGbtGame(string) except +IOError
c_Game ParseEfgGame(string) except +IOError
c_Game ParseNfgGame(string) except +IOError
c_Game ParseAggGame(string) except +IOError
string WriteGame(c_Game, string) except +IOError
string WriteGame(c_StrategySupportProfile) except +IOError
string WriteEfgFile(c_Game)
string WriteNfgFile(c_Game)
string WriteLaTeXFile(c_Game)
string WriteHTMLFile(c_Game)
# string WriteGbtFile(c_Game)

c_Rational to_rational(char *) except +

Expand Down
237 changes: 237 additions & 0 deletions src/pygambit/game.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
import io
import itertools
import pathlib

Expand All @@ -27,6 +28,134 @@ import scipy.stats

import pygambit.gameiter

ctypedef string (*GameWriter)(const c_Game &) except +IOError
ctypedef c_Game (*GameParser)(const string &) except +IOError


@cython.cfunc
def read_game(filepath_or_buffer: typing.Union[str, pathlib.Path, io.BytesIO],
parser: GameParser):

g = cython.declare(Game)
if isinstance(filepath_or_buffer, io.BytesIO):
data = filepath_or_buffer.read()
else:
with open(filepath_or_buffer, "rb") as f:
data = f.read()
try:
g = Game.wrap(parser(data))
except Exception as exc:
raise ValueError(f"Parse error in game file: {exc}") from None
return g


def read_gbt(filepath_or_buffer: typing.Union[str, pathlib.Path, io.BytesIO]) -> Game:
"""Construct a game from its serialised representation in a GBT file.

Parameters
----------
filepath_or_buffer : str, Path or BytesIO
The path to the file containing the game representation or file-like object

Returns
-------
Game
A game constructed from the representation in the file.

Raises
------
IOError
If the file cannot be opened or read
ValueError
If the contents of the file are not a valid game representation.

See Also
--------
read_efg, read_nfg, read_agg
"""
return read_game(filepath_or_buffer, parser=ParseGbtGame)


def read_efg(filepath_or_buffer: typing.Union[str, pathlib.Path, io.BytesIO]) -> Game:
"""Construct a game from its serialised representation in an EFG file.

Parameters
----------
filepath_or_buffer : str, Path or BytesIO
The path to the file containing the game representation or file-like object

Returns
-------
Game
A game constructed from the representation in the file.

Raises
------
IOError
If the file cannot be opened or read
ValueError
If the contents of the file are not a valid game representation.

See Also
--------
read_gbt, read_nfg, read_agg
"""
return read_game(filepath_or_buffer, parser=ParseEfgGame)


def read_nfg(filepath_or_buffer: typing.Union[str, pathlib.Path, io.BytesIO]) -> Game:
"""Construct a game from its serialised representation in a NFG file.

Parameters
----------
filepath_or_buffer : str, Path or BytesIO
The path to the file containing the game representation or file-like object

Returns
-------
Game
A game constructed from the representation in the file.

Raises
------
IOError
If the file cannot be opened or read
ValueError
If the contents of the file are not a valid game representation.

See Also
--------
read_gbt, read_efg, read_agg
"""
return read_game(filepath_or_buffer, parser=ParseNfgGame)


def read_agg(filepath_or_buffer: typing.Union[str, pathlib.Path, io.BytesIO]) -> Game:
"""Construct a game from its serialised representation in an AGG file.

Parameters
----------
filepath_or_buffer : str, Path or BytesIO
The path to the file containing the game representation or file-like object

Returns
-------
Game
A game constructed from the representation in the file.

Raises
------
IOError
If the file cannot be opened or read
ValueError
If the contents of the file are not a valid game representation.

See Also
--------
read_gbt, read_efg, read_nfg
"""
return read_game(filepath_or_buffer, parser=ParseAggGame)


@cython.cclass
class GameOutcomes:
Expand Down Expand Up @@ -446,6 +575,10 @@ class Game:
def read_game(cls, filepath: typing.Union[str, pathlib.Path]) -> Game:
"""Construct a game from its serialised representation in a file.

.. deprecated:: 16.3.0
Method `Game.read_game` is deprecated, use one of the respective functions instead:
``read_gbt``, ``read_efg``, ``read_nfg``, ``read_agg``

Parameters
----------
filepath : str or path object
Expand Down Expand Up @@ -1060,9 +1193,113 @@ class Game:
.. versionchanged:: 16.3.0
Removed support for writing Game Theory Explorer format as the XML format
is no longer supported by recent versions of GTE.

.. deprecated:: 16.3.0
Method Game.write is deprecated, use one of the respective methods instead:
``Game.to_efg``, ``Game.to_nfg``, ``Game.to_html``, ``Game.to_latex``
"""
return WriteGame(self.game, format.encode("ascii")).decode("ascii")

@cython.cfunc
def _to_format(
self,
writer: GameWriter,
filepath_or_buffer: typing.Union[str, pathlib.Path, io.BufferedWriter, None] = None
):
serialized_game = writer(self.game)
if filepath_or_buffer is None:
return serialized_game.decode()
if isinstance(filepath_or_buffer, io.BufferedWriter):
filepath_or_buffer.write(serialized_game)
else:
with open(filepath_or_buffer, "wb") as f:
f.write(serialized_game)

def to_efg(self,
filepath_or_buffer: typing.Union[str, pathlib.Path, io.BufferedWriter, None] = None
) -> typing.Union[str, None]:
"""Save the game to an .efg file or return its serialized representation

Parameters
----------
filepath_or_buffer : str or Path or BufferedWriter or None, default None
String, path object, or file-like object implementing a write() function.
If None, the result is returned as a string.

Return
------
String representation of the game or None if the game is saved to a file

See Also
--------
to_nfg, to_html, to_latex
"""
return self._to_format(WriteEfgFile, filepath_or_buffer)

def to_nfg(self,
filepath_or_buffer: typing.Union[str, pathlib.Path, io.BufferedWriter, None] = None
) -> typing.Union[str, None]:
"""Save the game to a .nfg file or return its serialized representation

Parameters
----------
filepath_or_buffer : str or Path or BufferedWriter or None, default None
String, path object, or file-like object implementing a write() function.
If None, the result is returned as a string.

Return
------
String representation of the game or None if the game is saved to a file

See Also
--------
to_efg, to_html, to_latex
"""
return self._to_format(WriteNfgFile, filepath_or_buffer)

def to_html(self,
filepath_or_buffer: typing.Union[str, pathlib.Path, io.BufferedWriter, None] = None
) -> typing.Union[str, None]:
"""Export the game to an .html file or return its serialized representation

Parameters
----------
filepath_or_buffer : str or Path or BufferedWriter or None, default None
String, path object, or file-like object implementing a write() function.
If None, the result is returned as a string.

Return
------
String representation of the game or None if the game is exported to a file

See Also
--------
to_efg, to_nfg, to_latex
"""
return self._to_format(WriteHTMLFile, filepath_or_buffer)

def to_latex(
self,
filepath_or_buffer: typing.Union[str, pathlib.Path, io.BufferedWriter, None] = None
) -> typing.Union[str, None]:
"""Export the game to a .tex file or return its serialized representation

Parameters
----------
filepath_or_buffer : str or Path or BufferedWriter or None, default None
String, path object, or file-like object implementing a write() function.
If None, the result is returned as a string.

Return
------
String representation of the game or None if the game is exported to a file

See Also
--------
to_efg, to_nfg, to_html
"""
return self._to_format(WriteLaTeXFile, filepath_or_buffer)

def _resolve_player(self,
player: typing.Any, funcname: str, argname: str = "player") -> Player:
"""Resolve an attempt to reference a player of the game.
Expand Down
49 changes: 49 additions & 0 deletions src/pygambit/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,55 @@ Game ParseGame(char *s)
return ReadGame(f);
}

Game ParseGbtGame(std::string const &s)
{
std::istringstream f(s);
return ReadGbtFile(f);
}

Game ParseEfgGame(std::string const &s)
{
std::istringstream f(s);
return ReadEfgFile(f);
}

Game ParseNfgGame(std::string const &s)
{
std::istringstream f(s);
return ReadNfgFile(f);
}

Game ParseAggGame(std::string const &s)
{
std::istringstream f(s);
return ReadAggFile(f);
}

std::string WriteEfgFile(const Game &p_game)
{
std::ostringstream f;
p_game->Write(f, "efg");
return f.str();
}

std::string WriteNfgFile(const Game &p_game)
{
std::ostringstream f;
p_game->Write(f, "nfg");
return f.str();
}

std::string WriteHTMLFile(const Game &p_game)
{
return WriteHTMLFile(p_game, p_game->GetPlayer(1), p_game->GetPlayer(2));
}

std::string WriteLaTeXFile(const Game &p_game)
{
return WriteLaTeXFile(p_game, p_game->GetPlayer(1), p_game->GetPlayer(2));
}

/// @deprecated Deprecated in favour of WriteXXXFile
std::string WriteGame(const Game &p_game, const std::string &p_format)
{
if (p_format == "html") {
Expand Down
Loading
Loading