gameboy_worlds.interface.registry

Keeps a record of:

  • Available Controllers for each game, with string identifiers. There is NO default controller for any game.
  • Available Environments for each game, with string identifiers and a default environment for each game.

Provides methods to access these.

  1"""
  2Keeps a record of:
  3- Available `Controller`s for each game, with string identifiers. There is NO default controller for any game.
  4- Available `Environment`s for each game, with string identifiers and a default environment for each game.
  5
  6Provides methods to access these.
  7"""
  8
  9from typing import Dict, Type, Optional, Union, Mapping, List
 10from gameboy_worlds.utils import (
 11    log_error,
 12    load_parameters,
 13    log_warn,
 14)
 15from gameboy_worlds.emulation.registry import (
 16    get_emulator,
 17    AVAILABLE_GAMES,
 18    infer_game,
 19    get_available_init_states,
 20    _merge_into_dict,
 21)
 22from gameboy_worlds.interface.controller import Controller, _ALWAYS_VALID_CONTROLLERS
 23from gameboy_worlds.interface.environment import Environment, DummyEnvironment
 24
 25from gameboy_worlds.interface.pokemon import registry as pokemon_registry
 26from gameboy_worlds.interface.legend_of_zelda import registry as zelda_registry
 27from gameboy_worlds.interface.sword_of_hope import registry as sword_of_hope_registry
 28from gameboy_worlds.interface.deja_vu import registry as deja_vu_registry
 29from gameboy_worlds.interface.hamtaro import registry as hamtaro_registry
 30from gameboy_worlds.interface.harvest_moon import registry as harvest_moon_registry
 31from gameboy_worlds.interface.runes_of_virtue import registry as runes_of_virtue_registry
 32from gameboy_worlds.interface.harry_potter import registry as harry_potter_registry
 33from gameboy_worlds.interface.bomberman import registry as bomberman_registry
 34from gameboy_worlds.interface.survival_kids import registry as survival_kids_registry
 35
 36_project_parameters = load_parameters()
 37
 38_game_registries = [
 39    hamtaro_registry,
 40    pokemon_registry,
 41    zelda_registry,
 42    sword_of_hope_registry,
 43    deja_vu_registry,
 44    harvest_moon_registry,
 45    runes_of_virtue_registry,
 46    harry_potter_registry,
 47    bomberman_registry,
 48    survival_kids_registry,
 49]
 50
 51AVAILABLE_ENVIRONMENTS: Dict[str, Dict[str, Type[Environment]]] = {}
 52""" Mapping of game names to their available Environment classes with string identifiers. Each game should have a 'default' environment variant. """
 53
 54
 55AVAILABLE_CONTROLLERS: Dict[str, Dict[str, Type[Controller]]] = {}
 56""" Mapping of game names to their available Controller classes with string identifiers. The default controller for every game is the LowLevelController. """
 57
 58
 59for registry in _game_registries:
 60    if hasattr(registry, "AVAILABLE_ENVIRONMENTS"):
 61        _merge_into_dict(AVAILABLE_ENVIRONMENTS, registry.AVAILABLE_ENVIRONMENTS)
 62    else:
 63        log_error(
 64            f"Registry module '{registry.__name__}' does not have an AVAILABLE_ENVIRONMENTS dictionary. You must create one, even if it is empty.",
 65            _project_parameters,
 66        )
 67    if hasattr(registry, "AVAILABLE_CONTROLLERS"):
 68        _merge_into_dict(AVAILABLE_CONTROLLERS, registry.AVAILABLE_CONTROLLERS)
 69    else:
 70        log_error(
 71            f"Registry module '{registry.__name__}' does not have an AVAILABLE_CONTROLLERS dictionary. You must create one, even if it is empty.",
 72            _project_parameters,
 73        )
 74
 75for game in AVAILABLE_GAMES:
 76    if game not in AVAILABLE_ENVIRONMENTS:
 77        log_warn(
 78            f"No environments registered for game variant '{game}'. Will error out if you try to get an environment for this game variant.",
 79            _project_parameters,
 80        )
 81    if game not in AVAILABLE_CONTROLLERS:
 82        AVAILABLE_CONTROLLERS[game] = {}
 83    for valid_controller_key in _ALWAYS_VALID_CONTROLLERS:
 84        if valid_controller_key in AVAILABLE_CONTROLLERS[game]:
 85            log_error(
 86                f"Controller key '{valid_controller_key}' for game variant '{game}' is reserved for always valid controllers. Do not add a controller with this key in the registry.",
 87                _project_parameters,
 88            )
 89        AVAILABLE_CONTROLLERS[game][valid_controller_key] = _ALWAYS_VALID_CONTROLLERS[
 90            valid_controller_key
 91        ]
 92
 93
 94def get_controller(
 95    game: str,
 96    *,
 97    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
 98    parameters: dict = None,
 99) -> Type[Controller]:
100    """
101    Factory function to get a Controller class for the specified game variant and controller variant.
102
103    Args:
104        game (str): The variant of the game to emulate.
105        controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
106        parameters (dict, optional): Additional parameters for error logging.
107
108    Returns:
109        Controller: An instance of the requested Controller class.
110    """
111    parameters = load_parameters(parameters)
112    game = infer_game(game, parameters)
113    if game not in AVAILABLE_CONTROLLERS:
114        log_error(f"No controllers registered for game variant '{game}'.", parameters)
115    available_controllers = AVAILABLE_CONTROLLERS[game]
116    if isinstance(controller_variant, str):
117        if controller_variant not in available_controllers:
118            log_error(
119                f"Unsupported controller variant '{controller_variant}' for game variant '{game}'. Available variants are: {list(available_controllers.keys())}",
120                parameters,
121            )
122        return available_controllers[controller_variant](parameters=parameters)
123    available_variants = [cls for cls in available_controllers.values()]
124    is_eqs = [controller_variant == cls for cls in available_variants]
125    is_inst = [isinstance(controller_variant, cls) for cls in available_variants]
126    if not any(is_eqs) and not any(is_inst):
127        log_error(
128            f"The provided controller_variant is not a registered Controller class for game variant '{game}'. Available variants are: {list(available_controllers.keys())}",
129            parameters,
130        )
131    else:
132        if any(is_inst):
133            return controller_variant
134        else:  # then it must be a class that matches one of the available variants
135            return controller_variant(parameters=parameters)
136
137
138def get_environment(
139    game: str,
140    *,
141    environment_variant: str,
142    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
143    parameters: dict = None,
144    **emulator_kwargs,
145) -> Environment:
146    """
147    Factory function to get an Environment instance for the specified game variant and environment variant.
148
149    Args:
150        game (str): The variant of the game to emulate.
151        environment_variant (str): The variant of the environment to create.
152        controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
153        parameters (dict, optional): Additional parameters for the environment and error logging. Must come from `load_parameters`.
154        **emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method.
155
156    Returns:
157        Environment: An instance of the requested Environment class.
158    """
159    parameters = load_parameters(parameters)
160    game = infer_game(game, parameters)
161    if game not in AVAILABLE_ENVIRONMENTS:
162        log_error(f"No environments registered for game variant '{game}'.", parameters)
163    available_environments = AVAILABLE_ENVIRONMENTS[game]
164    if environment_variant not in available_environments:
165        log_error(
166            f"Unsupported environment variant '{environment_variant}' for game variant '{game}'. Available variants are: {list(available_environments.keys())}. Make sure to add your environment to the registry if you think this is a mistake.",
167            parameters,
168        )
169    controller = get_controller(
170        game, controller_variant=controller_variant, parameters=parameters
171    )
172    environment_class = available_environments[environment_variant]
173    emulator_kwargs["game"] = game
174    emulator_kwargs = environment_class.override_emulator_kwargs(emulator_kwargs)
175    emulator = get_emulator(parameters=parameters, **emulator_kwargs)
176    return environment_class(
177        emulator=emulator, controller=controller, parameters=parameters
178    )
179
180
181def get_test_environment(
182    row: Mapping,
183    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
184    parameters: dict = None,
185    **emulator_kwargs,
186) -> Environment:
187    """
188    Creates an Environment instance based on a row from the benchmark tasks / questions DataFrame.
189
190    :param row: A row from the benchmark tasks / questions DataFrame.
191    :type row: Mapping
192    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
193    :type controller_variant: Union[str, Type[Controller], Controller]
194    :param parameters: Additional parameters for error logging.
195    :type parameters: dict, optional
196    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
197    :return: An instance of the requested Environment class.
198    :rtype: Environment
199
200    """
201    parameters = load_parameters(parameters)
202    return get_environment(
203        game=row["game"],
204        environment_variant="test",
205        controller_variant=controller_variant,
206        init_state=row["init_state"],
207        state_tracker_class=row["state_tracker_class"],
208        parameters=parameters,
209        **emulator_kwargs,
210    )
211
212
213def get_training_environments_kwargs(
214    row: Mapping,
215    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
216    parameters: dict = None,
217    **emulator_kwargs,
218) -> List[Dict[str, str]]:
219    """
220    Creates a list of keyword arguments that can be passed into `get_environment` to create same-game training environments for the given benchmark task.
221    This method does *not* return environments for the `shifted_environments` setting. For that, see `get_shifted_environments_kwargs`.
222
223    :param row: A row from the benchmark tasks / questions DataFrame.
224    :type row: Mapping
225    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
226    :type controller_variant: Union[str, Type[Controller], Controller]
227    :param parameters: Additional parameters for error logging.
228    :type parameters: dict, optional
229    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
230    :return: A list of keyword argument dictionaries for creating training environments.
231    :rtype: List[Dict[str, str]]
232    """
233    parameters = load_parameters(parameters)
234    common_kwargs = {
235        "game": row["game"],
236        "controller_variant": controller_variant,
237        "environment_variant": "default",
238        "state_tracker_class": "default",
239        **emulator_kwargs,
240    }
241    disallowed_init_states = [
242        state.strip() for state in row["other_disallowed_states"].split(",")
243    ] + [
244        row["init_state"],
245        "starter",
246    ]  # TODO: I literally ONLY have this in here to avoid the agent going to options and messing up stuff. Fix properly later.
247    training_envs_kwargs = []
248    for init_state in get_available_init_states(row["game"]):
249        if init_state not in disallowed_init_states and not init_state.startswith(
250            "test_"
251        ):
252            env_kwargs = common_kwargs.copy()
253            env_kwargs["init_state"] = init_state
254            training_envs_kwargs.append(env_kwargs)
255    if len(training_envs_kwargs) == 0:
256        log_error(
257            f"No available training environments found for benchmark task '{row['task_name']}' in game '{row['game']}'. Please ensure that there are available initial states for this game that are not in the disallowed states list.",
258            parameters,
259        )
260    return training_envs_kwargs
261
262
263def get_shifted_environments_kwargs(
264    row: Mapping,
265    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
266    parameters: dict = None,
267    **emulator_kwargs,
268) -> List[Dict[str, str]]:
269    """
270    Creates a list of keyword arguments that can be passed into `get_environment` to create shifted environments for the given benchmark task.
271    For same-game training environments, see `get_training_environments_kwargs`.
272
273    :param row: A row from the benchmark tasks / questions DataFrame.
274    :type row: Mapping
275    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
276
277    :type controller_variant: Union[str, Type[Controller], Controller]
278    :param parameters: Additional parameters for error logging.
279    :type parameters: dict, optional
280    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
281    :return: A list of keyword argument dictionaries for creating shifted environments.
282    :rtype: List[Dict[str, str]]
283    """
284    parameters = load_parameters(parameters)
285    common_kwargs = {
286        "controller_variant": controller_variant,
287        "environment_variant": "default",
288        "state_tracker_class": "default",
289        **emulator_kwargs,
290    }
291    allowed_games = [game.strip() for game in row["shifted_training_games"].split(",")]
292    if row["game"] in allowed_games:
293        allowed_games.remove(row["game"])
294    disallowed_init_states = [
295        state.strip() for state in row["other_disallowed_states"].split(",")
296    ] + [
297        row["init_state"],
298        "starter",
299    ]  # TODO: Same as above.
300    shifted_envs_kwargs = []
301    for game in allowed_games:
302        for init_state in get_available_init_states(game):
303            if init_state not in disallowed_init_states:
304                env_kwargs = common_kwargs.copy()
305                env_kwargs["game"] = game
306                env_kwargs["init_state"] = init_state
307                shifted_envs_kwargs.append(env_kwargs)
308    if len(shifted_envs_kwargs) == 0:
309        log_error(
310            f"No available shifted environments found for benchmark task '{row['task_name']}' in games '{allowed_games}'. Please ensure that there are available initial states for these games that are not in the disallowed states list.",
311            parameters,
312        )
313    return shifted_envs_kwargs
314
315
316import os
317
318AVAILABLE_BENCHMARKS = [
319    item.strip(".csv")
320    for item in os.listdir(_project_parameters["project_root"] + "/benchmark/tests")
321]
322""" List of available benchmark names. Populated by the files in benchmark/tests. """
AVAILABLE_ENVIRONMENTS: Dict[str, Dict[str, Type[gameboy_worlds.interface.environment.Environment]]] = {'hamtaro_ham_hams_unite': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.hamtaro.environments.HamtaroEnvironment'>}, 'pokemon_red': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'charmander': <class 'gameboy_worlds.interface.pokemon.environments.PokemonRedChooseCharmanderEnvironment'>, 'charmander_easy': <class 'gameboy_worlds.interface.pokemon.environments.PokemonRedChooseCharmanderEasyEnvironment'>, 'charmander_hard': <class 'gameboy_worlds.interface.pokemon.environments.PokemonRedChooseCharmanderHardEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_brown': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_starbeasts': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_starbeasts_comet': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_crystal': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_prism': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'pokemon_fools_gold': {'default': <class 'gameboy_worlds.interface.pokemon.environments.PokemonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.pokemon.environments.PokemonEnvironment'>, 'train': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.pokemon.environments.PokemonTestEnvironment'>}, 'legend_of_zelda_links_awakening': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.legend_of_zelda.environments.LegendOfZeldaTestEnvironment'>}, 'legend_of_zelda_the_oracle_of_seasons': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.legend_of_zelda.environments.LegendOfZeldaTestEnvironment'>}, 'sword_of_hope_1': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.sword_of_hope.environments.SwordOfHope1TestEnvironment'>}, 'sword_of_hope_2': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.sword_of_hope.environments.SwordOfHope2TestEnvironment'>}, 'deja_vu_1': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuEnvironment'>, 'test': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuTestEnvironment'>}, 'deja_vu_2': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuEnvironment'>, 'test': <class 'gameboy_worlds.interface.deja_vu.environments.DejaVuTestEnvironment'>}, 'harvest_moon_1': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonEnvironment'>, 'train': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTestEnvironment'>}, 'harvest_moon_2': {'default': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonEnvironment'>, 'train': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTestEnvironment'>}, 'harvest_moon_3': {'default': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonEnvironment'>, 'train': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.harvest_moon.environments.HarvestMoonTestEnvironment'>}, 'runes_of_virtue_1': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueEnvironment'>, 'ocr': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueOCREnvironment'>, 'train': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueTestEnvironment'>}, 'runes_of_virtue_2': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueEnvironment'>, 'ocr': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueOCREnvironment'>, 'train': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueTrainEnvironment'>, 'test': <class 'gameboy_worlds.interface.runes_of_virtue.environments.RunesOfVirtueTestEnvironment'>}, 'harry_potter_philosophers_stone': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.harry_potter.environments.HarryPotterTestEnvironment'>}, 'harry_potter_chamber_of_secrets': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'test': <class 'gameboy_worlds.interface.harry_potter.environments.HarryPotterTestEnvironment'>}, 'bomberman_max': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.bomberman.environments.BombermanMaxEnvironment'>, 'test': <class 'gameboy_worlds.interface.bomberman.environments.BombermanMaxTestEnvironment'>}, 'bomberman_pocket': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.bomberman.environments.BombermanPocketEnvironment'>, 'test': <class 'gameboy_worlds.interface.bomberman.environments.BombermanPocketTestEnvironment'>}, 'bomberman_quest': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.bomberman.environments.BombermanQuestEnvironment'>, 'test': <class 'gameboy_worlds.interface.bomberman.environments.BombermanQuestTestEnvironment'>}, 'survival_kids_1': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsEnvironment'>, 'test': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsTestEnvironment'>, 'train': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsTrainEnvironment'>}, 'survival_kids_2': {'dummy': <class 'gameboy_worlds.interface.environment.DummyEnvironment'>, 'default': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsOCREnvironment'>, 'basic': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsEnvironment'>, 'test': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsTestEnvironment'>, 'train': <class 'gameboy_worlds.interface.survival_kids.environments.SurvivalKidsTrainEnvironment'>}}

Mapping of game names to their available Environment classes with string identifiers. Each game should have a 'default' environment variant.

AVAILABLE_CONTROLLERS: Dict[str, Dict[str, Type[gameboy_worlds.interface.controller.Controller]]] = {'pokemon_red': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_brown': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_crystal': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_starbeasts': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_starbeasts_comet': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_prism': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'pokemon_fools_gold': {'state_wise': <class 'gameboy_worlds.interface.pokemon.controllers.PokemonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'state_wise': <class 'gameboy_worlds.interface.deja_vu.controllers.DejaVuStateWiseController'>, 'harvest_moon_1': {'state_wise': <class 'gameboy_worlds.interface.harvest_moon.controllers.HarvestMoonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'harvest_moon_2': {'state_wise': <class 'gameboy_worlds.interface.harvest_moon.controllers.HarvestMoonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'harvest_moon_3': {'state_wise': <class 'gameboy_worlds.interface.harvest_moon.controllers.HarvestMoonStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'runes_of_virtue_1': {'state_wise': <class 'gameboy_worlds.interface.runes_of_virtue.controllers.RunesOfVirtueStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'runes_of_virtue_2': {'state_wise': <class 'gameboy_worlds.interface.runes_of_virtue.controllers.RunesOfVirtueStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'bomberman_max': {'state_wise': <class 'gameboy_worlds.interface.bomberman.controllers.BombermanMaxStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'bomberman_pocket': {'state_wise': <class 'gameboy_worlds.interface.bomberman.controllers.BombermanPocketStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'bomberman_quest': {'state_wise': <class 'gameboy_worlds.interface.bomberman.controllers.BombermanQuestStateWiseController'>, 'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'hamtaro_ham_hams_unite': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'legend_of_zelda_links_awakening': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'legend_of_zelda_the_oracle_of_seasons': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'sword_of_hope_1': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'sword_of_hope_2': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'deja_vu_1': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'deja_vu_2': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'survival_kids_1': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'survival_kids_2': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'harry_potter_philosophers_stone': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}, 'harry_potter_chamber_of_secrets': {'low_level': <class 'gameboy_worlds.interface.controller.LowLevelController'>, 'low_level_play': <class 'gameboy_worlds.interface.controller.LowLevelPlayController'>, 'random_play': <class 'gameboy_worlds.interface.controller.RandomPlayController'>}}

Mapping of game names to their available Controller classes with string identifiers. The default controller for every game is the LowLevelController.

def get_controller( game: str, *, controller_variant: Union[str, Type[gameboy_worlds.interface.controller.Controller], gameboy_worlds.interface.controller.Controller] = 'low_level', parameters: dict = None) -> Type[gameboy_worlds.interface.controller.Controller]:
 95def get_controller(
 96    game: str,
 97    *,
 98    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
 99    parameters: dict = None,
100) -> Type[Controller]:
101    """
102    Factory function to get a Controller class for the specified game variant and controller variant.
103
104    Args:
105        game (str): The variant of the game to emulate.
106        controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
107        parameters (dict, optional): Additional parameters for error logging.
108
109    Returns:
110        Controller: An instance of the requested Controller class.
111    """
112    parameters = load_parameters(parameters)
113    game = infer_game(game, parameters)
114    if game not in AVAILABLE_CONTROLLERS:
115        log_error(f"No controllers registered for game variant '{game}'.", parameters)
116    available_controllers = AVAILABLE_CONTROLLERS[game]
117    if isinstance(controller_variant, str):
118        if controller_variant not in available_controllers:
119            log_error(
120                f"Unsupported controller variant '{controller_variant}' for game variant '{game}'. Available variants are: {list(available_controllers.keys())}",
121                parameters,
122            )
123        return available_controllers[controller_variant](parameters=parameters)
124    available_variants = [cls for cls in available_controllers.values()]
125    is_eqs = [controller_variant == cls for cls in available_variants]
126    is_inst = [isinstance(controller_variant, cls) for cls in available_variants]
127    if not any(is_eqs) and not any(is_inst):
128        log_error(
129            f"The provided controller_variant is not a registered Controller class for game variant '{game}'. Available variants are: {list(available_controllers.keys())}",
130            parameters,
131        )
132    else:
133        if any(is_inst):
134            return controller_variant
135        else:  # then it must be a class that matches one of the available variants
136            return controller_variant(parameters=parameters)

Factory function to get a Controller class for the specified game variant and controller variant.

Arguments:
  • game (str): The variant of the game to emulate.
  • controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
  • parameters (dict, optional): Additional parameters for error logging.
Returns:

Controller: An instance of the requested Controller class.

def get_environment( game: str, *, environment_variant: str, controller_variant: Union[str, Type[gameboy_worlds.interface.controller.Controller], gameboy_worlds.interface.controller.Controller] = 'low_level', parameters: dict = None, **emulator_kwargs) -> gameboy_worlds.interface.environment.Environment:
139def get_environment(
140    game: str,
141    *,
142    environment_variant: str,
143    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
144    parameters: dict = None,
145    **emulator_kwargs,
146) -> Environment:
147    """
148    Factory function to get an Environment instance for the specified game variant and environment variant.
149
150    Args:
151        game (str): The variant of the game to emulate.
152        environment_variant (str): The variant of the environment to create.
153        controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
154        parameters (dict, optional): Additional parameters for the environment and error logging. Must come from `load_parameters`.
155        **emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method.
156
157    Returns:
158        Environment: An instance of the requested Environment class.
159    """
160    parameters = load_parameters(parameters)
161    game = infer_game(game, parameters)
162    if game not in AVAILABLE_ENVIRONMENTS:
163        log_error(f"No environments registered for game variant '{game}'.", parameters)
164    available_environments = AVAILABLE_ENVIRONMENTS[game]
165    if environment_variant not in available_environments:
166        log_error(
167            f"Unsupported environment variant '{environment_variant}' for game variant '{game}'. Available variants are: {list(available_environments.keys())}. Make sure to add your environment to the registry if you think this is a mistake.",
168            parameters,
169        )
170    controller = get_controller(
171        game, controller_variant=controller_variant, parameters=parameters
172    )
173    environment_class = available_environments[environment_variant]
174    emulator_kwargs["game"] = game
175    emulator_kwargs = environment_class.override_emulator_kwargs(emulator_kwargs)
176    emulator = get_emulator(parameters=parameters, **emulator_kwargs)
177    return environment_class(
178        emulator=emulator, controller=controller, parameters=parameters
179    )

Factory function to get an Environment instance for the specified game variant and environment variant.

Arguments:
  • game (str): The variant of the game to emulate.
  • environment_variant (str): The variant of the environment to create.
  • controller_variant (Union[str, Type[Controller], Controller]): The variant of the controller to create or the Controller class itself or an instance of Controller.
  • parameters (dict, optional): Additional parameters for the environment and error logging. Must come from load_parameters.
  • **emulator_kwargs: Additional keyword arguments passed to the get_emulator method.
Returns:

Environment: An instance of the requested Environment class.

def get_test_environment( row: Mapping, controller_variant: Union[str, Type[gameboy_worlds.interface.controller.Controller], gameboy_worlds.interface.controller.Controller] = 'low_level', parameters: dict = None, **emulator_kwargs) -> gameboy_worlds.interface.environment.Environment:
182def get_test_environment(
183    row: Mapping,
184    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
185    parameters: dict = None,
186    **emulator_kwargs,
187) -> Environment:
188    """
189    Creates an Environment instance based on a row from the benchmark tasks / questions DataFrame.
190
191    :param row: A row from the benchmark tasks / questions DataFrame.
192    :type row: Mapping
193    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
194    :type controller_variant: Union[str, Type[Controller], Controller]
195    :param parameters: Additional parameters for error logging.
196    :type parameters: dict, optional
197    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
198    :return: An instance of the requested Environment class.
199    :rtype: Environment
200
201    """
202    parameters = load_parameters(parameters)
203    return get_environment(
204        game=row["game"],
205        environment_variant="test",
206        controller_variant=controller_variant,
207        init_state=row["init_state"],
208        state_tracker_class=row["state_tracker_class"],
209        parameters=parameters,
210        **emulator_kwargs,
211    )

Creates an Environment instance based on a row from the benchmark tasks / questions DataFrame.

Parameters
  • row: A row from the benchmark tasks / questions DataFrame.
  • controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
  • parameters: Additional parameters for error logging.
  • emulator_kwargs: Additional keyword arguments passed to the get_emulator method (e.g. save_video).
Returns

An instance of the requested Environment class.

def get_training_environments_kwargs( row: Mapping, controller_variant: Union[str, Type[gameboy_worlds.interface.controller.Controller], gameboy_worlds.interface.controller.Controller] = 'low_level', parameters: dict = None, **emulator_kwargs) -> List[Dict[str, str]]:
214def get_training_environments_kwargs(
215    row: Mapping,
216    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
217    parameters: dict = None,
218    **emulator_kwargs,
219) -> List[Dict[str, str]]:
220    """
221    Creates a list of keyword arguments that can be passed into `get_environment` to create same-game training environments for the given benchmark task.
222    This method does *not* return environments for the `shifted_environments` setting. For that, see `get_shifted_environments_kwargs`.
223
224    :param row: A row from the benchmark tasks / questions DataFrame.
225    :type row: Mapping
226    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
227    :type controller_variant: Union[str, Type[Controller], Controller]
228    :param parameters: Additional parameters for error logging.
229    :type parameters: dict, optional
230    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
231    :return: A list of keyword argument dictionaries for creating training environments.
232    :rtype: List[Dict[str, str]]
233    """
234    parameters = load_parameters(parameters)
235    common_kwargs = {
236        "game": row["game"],
237        "controller_variant": controller_variant,
238        "environment_variant": "default",
239        "state_tracker_class": "default",
240        **emulator_kwargs,
241    }
242    disallowed_init_states = [
243        state.strip() for state in row["other_disallowed_states"].split(",")
244    ] + [
245        row["init_state"],
246        "starter",
247    ]  # TODO: I literally ONLY have this in here to avoid the agent going to options and messing up stuff. Fix properly later.
248    training_envs_kwargs = []
249    for init_state in get_available_init_states(row["game"]):
250        if init_state not in disallowed_init_states and not init_state.startswith(
251            "test_"
252        ):
253            env_kwargs = common_kwargs.copy()
254            env_kwargs["init_state"] = init_state
255            training_envs_kwargs.append(env_kwargs)
256    if len(training_envs_kwargs) == 0:
257        log_error(
258            f"No available training environments found for benchmark task '{row['task_name']}' in game '{row['game']}'. Please ensure that there are available initial states for this game that are not in the disallowed states list.",
259            parameters,
260        )
261    return training_envs_kwargs

Creates a list of keyword arguments that can be passed into get_environment to create same-game training environments for the given benchmark task. This method does not return environments for the shifted_environments setting. For that, see get_shifted_environments_kwargs.

Parameters
  • row: A row from the benchmark tasks / questions DataFrame.
  • controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
  • parameters: Additional parameters for error logging.
  • emulator_kwargs: Additional keyword arguments passed to the get_emulator method (e.g. save_video).
Returns

A list of keyword argument dictionaries for creating training environments.

def get_shifted_environments_kwargs( row: Mapping, controller_variant: Union[str, Type[gameboy_worlds.interface.controller.Controller], gameboy_worlds.interface.controller.Controller] = 'low_level', parameters: dict = None, **emulator_kwargs) -> List[Dict[str, str]]:
264def get_shifted_environments_kwargs(
265    row: Mapping,
266    controller_variant: Union[str, Type[Controller], Controller] = "low_level",
267    parameters: dict = None,
268    **emulator_kwargs,
269) -> List[Dict[str, str]]:
270    """
271    Creates a list of keyword arguments that can be passed into `get_environment` to create shifted environments for the given benchmark task.
272    For same-game training environments, see `get_training_environments_kwargs`.
273
274    :param row: A row from the benchmark tasks / questions DataFrame.
275    :type row: Mapping
276    :param controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.
277
278    :type controller_variant: Union[str, Type[Controller], Controller]
279    :param parameters: Additional parameters for error logging.
280    :type parameters: dict, optional
281    :param emulator_kwargs: Additional keyword arguments passed to the `get_emulator` method (e.g. `save_video`).
282    :return: A list of keyword argument dictionaries for creating shifted environments.
283    :rtype: List[Dict[str, str]]
284    """
285    parameters = load_parameters(parameters)
286    common_kwargs = {
287        "controller_variant": controller_variant,
288        "environment_variant": "default",
289        "state_tracker_class": "default",
290        **emulator_kwargs,
291    }
292    allowed_games = [game.strip() for game in row["shifted_training_games"].split(",")]
293    if row["game"] in allowed_games:
294        allowed_games.remove(row["game"])
295    disallowed_init_states = [
296        state.strip() for state in row["other_disallowed_states"].split(",")
297    ] + [
298        row["init_state"],
299        "starter",
300    ]  # TODO: Same as above.
301    shifted_envs_kwargs = []
302    for game in allowed_games:
303        for init_state in get_available_init_states(game):
304            if init_state not in disallowed_init_states:
305                env_kwargs = common_kwargs.copy()
306                env_kwargs["game"] = game
307                env_kwargs["init_state"] = init_state
308                shifted_envs_kwargs.append(env_kwargs)
309    if len(shifted_envs_kwargs) == 0:
310        log_error(
311            f"No available shifted environments found for benchmark task '{row['task_name']}' in games '{allowed_games}'. Please ensure that there are available initial states for these games that are not in the disallowed states list.",
312            parameters,
313        )
314    return shifted_envs_kwargs

Creates a list of keyword arguments that can be passed into get_environment to create shifted environments for the given benchmark task. For same-game training environments, see get_training_environments_kwargs.

Parameters
  • row: A row from the benchmark tasks / questions DataFrame.
  • controller_variant: The variant of the controller to create or the Controller class itself or an instance of Controller.

  • parameters: Additional parameters for error logging.

  • emulator_kwargs: Additional keyword arguments passed to the get_emulator method (e.g. save_video).
Returns

A list of keyword argument dictionaries for creating shifted environments.

AVAILABLE_BENCHMARKS = ['deja_vu', 'urvival_kid', 'legend_of_zelda', 'pokemon', 'word_of_hope', 'bomberman', 'harry_potter', 'harvest_moon', 'runes_of_virtue']

List of available benchmark names. Populated by the files in benchmark/tests.