How to implement a new game¶
Implementing the IGame
Interface¶
The Game Class only implements game logic and does not have to handle networking (e.g. collecting actions, disconnected players), matchmaking or database tasks. In general, a Game can also implement a game with more than two players, but the Matchmaking and the Database has to be updated for this.
Start implementing the interface with
from comprl.server.interfaces import IGame, IPlayer
class MyGame(IGame):
def __init__(self, players: list[IPlayer]) -> None:
super().__init__(players)
...
and implement all the necessary methods listed below:
-
Updates the environment
Input: All the collected actions in a dictionary
Returns
True
if the game should endFalse
otherwise
-
Returns
True
if the action is validDisconnects the player if the action is invalid which ends the game
-
Returns the observation that should be sent to this player
Observations can be sent to each player individually (e.g. for left and right players)
-
Returns
True
if the player has won,False
otherwiseShould return
False
for all players in case of a draw
-
Is called at the end of the game
Can be used to communicate Statistics at the end of the game
e.g. scores, disconnects, rounds, …
For the implementation of these methods the following instance variables can be helpful:
players
: a dictionary with all players of the gamescores
: a dictionary with all scores (defaults to all scores 0.0)
Stored game actions¶
The game implementation can store arbitrary information about the game in the dictionary
comprl.server.interfaces.IGame.game_info
. This dictionary is automatically
saved to a pickle file at the end of the game. The file is written to
{data_dir}/game_actions/{game_id}.pkl
(see
comprl.server.config.Config.data_dir
).
Example: Hockey game¶
For a real-life example on how to implement a server for a specific game, see the
implementation in comprl-hockey-game
(in the comprl repository).
API¶
- class comprl.server.interfaces.IGame(players: list[IPlayer])¶
Interface for a game.
- finish_callbacks¶
A list of callbacks to be executed when the game ends.
- Type:¶
list[Callable[[“IGame”], None]]
-
_end(reason=
'unknown'
)¶ Notifies all players that the game has ended and writes all actions in a file.
- abstractmethod _player_stats(id: UUID) list[float] ¶
Returns all stats that should be sent to the player if the game has ended.
- _run()¶
Collects all actions and puts them in the current_actions list.
- abstractmethod _update(actions: dict[UUID, list[float]]) bool ¶
Updates the game with the players’ actions.
- add_finish_callback(callback: Callable[[IGame], None]) None ¶
Adds a callback function to be executed when the game ends.
- get_result() GameResult | None ¶
Returns the result of the game.
- start()¶
Notifies all players that the game has started and starts the game cycle.
- class comprl.server.interfaces.IPlayer¶
Interface for a player
- abstractmethod authenticate(result_callback)¶
authenticates player
- abstractmethod get_action(obv, result_callback) IAction ¶
gets an action from the player
- abstractmethod is_ready(result_callback) bool ¶
checks if the player is ready to play