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: -1>, inttype=<Integrations.DEFAULT: <retro.data.DefaultIntegrations object>>, **kwargs)[source]¶ Create a Gym environment for the specified game
-
class
retro.
RetroEnv
(game, state=<State.DEFAULT: -1>, scenario=None, info=None, use_restricted_actions=<Actions.FILTERED: 1>, record=False, players=1, inttype=<Integrations.STABLE: 1>, obs_type=<Observations.IMAGE: 0>)[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:
Actions¶
There are a few possible action spaces included with retro.RetroEnv
:
-
class
retro.
Actions
[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
-
FILTERED
= 1¶ MultiBinary action space with invalid or not allowed actions filtered out
-
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 observate 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)
obs = 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:
obs = env.reset()
env.close()
if __name__ == "__main__":
main()
Replay files¶
Gym 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 Gym 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:
_obs, _rew, done, _info = env.step(env.action_space.sample())
if done:
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)