Python API#
RetroEnv#
The Python API consists primarily of retro.make()
, retro.RetroEnv
, and a few enums. The main function most users will want is retro.make()
.
- retro.make(game, state=State.DEFAULT, inttype=retro.data.Integrations.DEFAULT, **kwargs)[source]#
Create a Gym environment for the specified game
- class retro.RetroEnv(game, state=retro.State.DEFAULT, scenario=None, info=None, use_restricted_actions=retro.Actions.FILTERED, record=False, players=1, inttype=retro.data.Integrations.STABLE, obs_type=retro.Observations.IMAGE, render_mode='human')[source]#
Gym Retro environment class
Provides a Gym interface to classic video games
If you want to specify either the default state named in the game integration’s metadata.json
or specify that you want to start from the initial power on state of the console, you can use the retro.State
enum:
- class retro.State(value)[source]#
Special values for setting the restart state of the environment. You can also specify a string that is the name of the
.state
file- DEFAULT = -1#
Start the game at the default savestate from
metadata.json
- NONE = 0#
Start the game at the power on screen for the emulator
Actions#
There are a few possible action spaces included with retro.RetroEnv
:
- class retro.Actions(value)[source]#
Different settings for the action space of the environment
- ALL = 0#
MultiBinary action space with no filtered actions
- DISCRETE = 2#
Discrete action space for filtered actions
- MULTI_DISCRETE = 3#
MultiDiscete action space for filtered actions
You can also create your own action spaces derived from these. For an example, see discretizer.py. This file shows how to use retro.Actions.Discrete
as well as how to make a custom wrapper that reduces the action space from 126
actions to 7
Observations#
The default observations are RGB images of the game, but you can view RAM values instead (often much smaller than the RGB images and also your agent can observe the game state more directly). If you want variable values, any variables defined in data.json
will appear in the info
dict after each step.
Multiplayer Environments#
A small number of games support multiplayer. To use this feature, pass players=<n>
to retro.RetroEnv
. Here is an example random agent that controls both paddles in Pong-Atari2600
:
import retro
def main():
env = retro.make(game="Pong-Atari2600", players=2)
env.reset()
while True:
# action_space will by MultiBinary(16) now instead of MultiBinary(8)
# the bottom half of the actions will be for player 1 and the top half for player 2
obs, rew, done, info = env.step(env.action_space.sample())
# rew will be a list of [player_1_rew, player_2_rew]
# done and info will remain the same
env.render()
if done:
env.reset()
env.close()
if __name__ == "__main__":
main()
Replay files#
Stable Retro can create .bk2 files which are recordings of an initial game state and a series of button presses. Because the emulators are deterministic, you will see the same output each time you play back this file. Because it only stores button presses, the file can be about 1000 times smaller than storing the full video.
In addition, if you wish to use the stored button presses for training, they may be useful. For example, there are replay files for each Sonic The Hedgehog level that were made available for the Stable Retro Contest.
You can create and view replay files using the The Integration UI (Game > Play Movie…). If you want to use replay files from Python, see the following sections.
Record#
If you have an agent playing a game, you can record the gameplay to a .bk2
file for later processing:
import retro
env = retro.make(game='Airstriker-Genesis', record='.')
env.reset()
while True:
_, _, terminate, truncate, _ = env.step(env.action_space.sample())
if terminate or truncate:
break
Playback#
Given a .bk2
file you can load it in python and either play it back or use the actions for training.
import retro
movie = retro.Movie('Airstriker-Genesis-Level1-000000.bk2')
movie.step()
env = retro.make(
game=movie.get_game(),
state=None,
# bk2s can contain any button presses, so allow everything
use_restricted_actions=retro.Actions.ALL,
players=movie.players,
)
env.initial_state = movie.get_state()
env.reset()
while movie.step():
keys = []
for p in range(movie.players):
for i in range(env.num_buttons):
keys.append(movie.get_key(i, p))
env.step(keys)
Render to Video#
This requires ffmpeg to be installed and writes the output to the directory that the input file is located in.
python3 -m retro.scripts.playback_movie Airstriker-Genesis-Level1-000000.bk2