gameboy_worlds.interface.pokemon.environments
1from typing import Optional, Dict, Any, List, Tuple 2 3from gymnasium import spaces 4 5from gameboy_worlds.emulation.pokemon.base_metrics import CorePokemonMetrics 6from gameboy_worlds.utils import load_parameters, log_dict, log_info 7from gameboy_worlds.emulation.pokemon.emulators import PokemonEmulator 8from gameboy_worlds.emulation.pokemon.trackers import ( 9 PokemonRedStarterTracker, 10 PokemonOCRTracker, 11) 12from gameboy_worlds.interface.environment import ( 13 DummyEnvironment, 14 Environment, 15 TestEnvironmentMixin, 16 TrainEnvironmentMixin, 17) 18from gameboy_worlds.interface.controller import Controller 19 20import gymnasium as gym 21import numpy as np 22 23 24class PokemonEnvironment(DummyEnvironment): 25 """ 26 A basic Pokemon Environment. 27 """ 28 29 REQUIRED_EMULATOR = PokemonEmulator 30 REQUIRED_STATE_TRACKER = CorePokemonMetrics 31 32 33class PokemonOCREnvironment(PokemonEnvironment): 34 """ 35 A Pokemon Environment that includes OCR region captures and agent state. 36 """ 37 38 REQUIRED_STATE_TRACKER = PokemonOCRTracker 39 REQUIRED_EMULATOR = PokemonEmulator 40 41 @staticmethod 42 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 43 Environment.override_state_tracker_class( 44 emulator_kwargs, PokemonOCREnvironment.REQUIRED_STATE_TRACKER 45 ) 46 return emulator_kwargs 47 48 49class PokemonTestEnvironment(TestEnvironmentMixin, PokemonOCREnvironment): 50 pass 51 52 53class PokemonTrainEnvironment(TrainEnvironmentMixin, PokemonOCREnvironment): 54 pass 55 56 57class PokemonRedStarterChoiceEnvironment(PokemonOCREnvironment): 58 """ 59 An environment which starts at the starter selection point in PokemonRed and terminates when the player selects a starter Pokemon. 60 """ 61 62 REQUIRED_TRACKER = PokemonRedStarterTracker 63 64 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 65 """ 66 Override default emulator keyword arguments for this environment. 67 """ 68 Environment.override_state_tracker_class( 69 emulator_kwargs, PokemonRedStarterTracker 70 ) 71 emulator_kwargs["init_state"] = "starter" 72 return emulator_kwargs 73 74 def determine_terminated( 75 self, 76 start_state, 77 *, 78 action=None, 79 action_kwargs=None, 80 transition_states=None, 81 action_success=None, 82 ) -> bool: 83 super_terminated = super().determine_terminated( 84 start_state=start_state, 85 action=action, 86 action_kwargs=action_kwargs, 87 transition_states=transition_states, 88 action_success=action_success, 89 ) 90 if transition_states is None: 91 return super_terminated 92 states = transition_states 93 for state in states: 94 starter_chosen = state["pokemon_red_starter"]["current_starter"] 95 if starter_chosen is not None: 96 return True 97 return super_terminated 98 99 100class PokemonRedChooseCharmanderEnvironment(PokemonRedStarterChoiceEnvironment): 101 """ 102 Reward the agent for choosing Charmander as quickly as possible. 103 """ 104 105 STEP_WISE_REWARD = False 106 107 def determine_reward( 108 self, 109 start_state, 110 *, 111 action=None, 112 action_kwargs=None, 113 transition_states=None, 114 action_success=None, 115 ) -> float: 116 """ 117 Reward the agent for choosing Charmander as quickly as possible. 118 """ 119 from gameboy_worlds.interface.action import LowLevelAction, LowLevelActions 120 121 if transition_states is None: 122 return 0.0 123 current_state = transition_states[-1] 124 starter_chosen = current_state["pokemon_red_starter"]["current_starter"] 125 n_steps = current_state["core"]["steps"] 126 if starter_chosen is None: 127 if action == LowLevelAction and self.STEP_WISE_REWARD: 128 if "low_level_action" in action_kwargs: 129 # reward for pressing A, penalty for pressing anything else 130 low_level_action = action_kwargs["low_level_action"] 131 if low_level_action == LowLevelActions.PRESS_BUTTON_A: 132 return 0.5 133 else: 134 return -0.1 135 if n_steps >= self._emulator.max_steps - 2: # some safety 136 return -1.0 # Penalty for not choosing a starter within max steps 137 else: 138 return 0.0 139 step_bonus = min(0.25 / (n_steps + 1), 0.5) 140 if starter_chosen == "charmander": 141 return 0.5 + step_bonus 142 else: 143 return ( 144 0.25 + step_bonus 145 ) # Penalty for choosing the wrong starter. For now, just less reward. 146 147 148class PokemonRedChooseCharmanderEasyEnvironment(PokemonRedChooseCharmanderEnvironment): 149 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 150 """ 151 Override default emulator keyword arguments for this environment. 152 """ 153 Environment.override_state_tracker_class( 154 emulator_kwargs, PokemonRedStarterTracker 155 ) 156 emulator_kwargs["init_state"] = "test_starter_easy" 157 return emulator_kwargs 158 159 160class PokemonRedChooseCharmanderHardEnvironment(PokemonRedChooseCharmanderEnvironment): 161 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 162 """ 163 Override default emulator keyword arguments for this environment. 164 """ 165 Environment.override_state_tracker_class( 166 emulator_kwargs, PokemonRedStarterTracker 167 ) 168 emulator_kwargs["init_state"] = "test_starter_hard" 169 return emulator_kwargs
25class PokemonEnvironment(DummyEnvironment): 26 """ 27 A basic Pokemon Environment. 28 """ 29 30 REQUIRED_EMULATOR = PokemonEmulator 31 REQUIRED_STATE_TRACKER = CorePokemonMetrics
A basic Pokemon Environment.
The highest level emulator that the environment can interface with.
The state tracker that tracks the minimal state information required for the environment to function.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- determine_reward
- determine_terminated
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_emulator_kwargs
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
34class PokemonOCREnvironment(PokemonEnvironment): 35 """ 36 A Pokemon Environment that includes OCR region captures and agent state. 37 """ 38 39 REQUIRED_STATE_TRACKER = PokemonOCRTracker 40 REQUIRED_EMULATOR = PokemonEmulator 41 42 @staticmethod 43 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 44 Environment.override_state_tracker_class( 45 emulator_kwargs, PokemonOCREnvironment.REQUIRED_STATE_TRACKER 46 ) 47 return emulator_kwargs
A Pokemon Environment that includes OCR region captures and agent state.
The state tracker that tracks the minimal state information required for the environment to function.
The highest level emulator that the environment can interface with.
42 @staticmethod 43 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 44 Environment.override_state_tracker_class( 45 emulator_kwargs, PokemonOCREnvironment.REQUIRED_STATE_TRACKER 46 ) 47 return emulator_kwargs
Override default emulator keyword arguments for this environment.
Override this method in subclasses to modify the default emulator keyword arguments.
You may want to use override_state_tracker_class or that style to ensure compatibility of state tracker classes.
Arguments:
- emulator_kwargs (dict): Incoming emulator keyword arguments.
Returns:
dict: The overridden emulator keyword arguments.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- determine_reward
- determine_terminated
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
Mixin class for testing environments. Ensures the State Tracker used is a TestTrackerMixin and checks these for termination / truncation.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- determine_reward
- render_obs
- render_info
- gameboy_worlds.interface.environment.TestEnvironmentMixin
- REQUIRED_STATE_TRACKER
- determine_truncated
- determine_terminated
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
Mixin class for training environments. Records the allowed initial states for training and random shuffles between them when resetting.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- determine_reward
- determine_terminated
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
58class PokemonRedStarterChoiceEnvironment(PokemonOCREnvironment): 59 """ 60 An environment which starts at the starter selection point in PokemonRed and terminates when the player selects a starter Pokemon. 61 """ 62 63 REQUIRED_TRACKER = PokemonRedStarterTracker 64 65 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 66 """ 67 Override default emulator keyword arguments for this environment. 68 """ 69 Environment.override_state_tracker_class( 70 emulator_kwargs, PokemonRedStarterTracker 71 ) 72 emulator_kwargs["init_state"] = "starter" 73 return emulator_kwargs 74 75 def determine_terminated( 76 self, 77 start_state, 78 *, 79 action=None, 80 action_kwargs=None, 81 transition_states=None, 82 action_success=None, 83 ) -> bool: 84 super_terminated = super().determine_terminated( 85 start_state=start_state, 86 action=action, 87 action_kwargs=action_kwargs, 88 transition_states=transition_states, 89 action_success=action_success, 90 ) 91 if transition_states is None: 92 return super_terminated 93 states = transition_states 94 for state in states: 95 starter_chosen = state["pokemon_red_starter"]["current_starter"] 96 if starter_chosen is not None: 97 return True 98 return super_terminated
An environment which starts at the starter selection point in PokemonRed and terminates when the player selects a starter Pokemon.
65 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 66 """ 67 Override default emulator keyword arguments for this environment. 68 """ 69 Environment.override_state_tracker_class( 70 emulator_kwargs, PokemonRedStarterTracker 71 ) 72 emulator_kwargs["init_state"] = "starter" 73 return emulator_kwargs
Override default emulator keyword arguments for this environment.
75 def determine_terminated( 76 self, 77 start_state, 78 *, 79 action=None, 80 action_kwargs=None, 81 transition_states=None, 82 action_success=None, 83 ) -> bool: 84 super_terminated = super().determine_terminated( 85 start_state=start_state, 86 action=action, 87 action_kwargs=action_kwargs, 88 transition_states=transition_states, 89 action_success=action_success, 90 ) 91 if transition_states is None: 92 return super_terminated 93 states = transition_states 94 for state in states: 95 starter_chosen = state["pokemon_red_starter"]["current_starter"] 96 if starter_chosen is not None: 97 return True 98 return super_terminated
Determines whether the episode reaches the goal / terminal state based on the transition from start_state through transition_states. This method is NOT meant to be used to determine if the step count has exceeded the maximum.
Arguments:
- start_state (Dict[str, Dict[str, Any]]): The state before the action was taken.
- action (HighLevelAction): The HighLevelAction action taken.
- action_kwargs (dict): The keyword arguments used for the action.
- transition_states (List[Dict[str, Dict[str, Any]]]): A list of states observed during the action execution.
- action_success (bool): Whether the action was successful.
Returns:
bool: Whether the episode is terminated.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- determine_reward
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
101class PokemonRedChooseCharmanderEnvironment(PokemonRedStarterChoiceEnvironment): 102 """ 103 Reward the agent for choosing Charmander as quickly as possible. 104 """ 105 106 STEP_WISE_REWARD = False 107 108 def determine_reward( 109 self, 110 start_state, 111 *, 112 action=None, 113 action_kwargs=None, 114 transition_states=None, 115 action_success=None, 116 ) -> float: 117 """ 118 Reward the agent for choosing Charmander as quickly as possible. 119 """ 120 from gameboy_worlds.interface.action import LowLevelAction, LowLevelActions 121 122 if transition_states is None: 123 return 0.0 124 current_state = transition_states[-1] 125 starter_chosen = current_state["pokemon_red_starter"]["current_starter"] 126 n_steps = current_state["core"]["steps"] 127 if starter_chosen is None: 128 if action == LowLevelAction and self.STEP_WISE_REWARD: 129 if "low_level_action" in action_kwargs: 130 # reward for pressing A, penalty for pressing anything else 131 low_level_action = action_kwargs["low_level_action"] 132 if low_level_action == LowLevelActions.PRESS_BUTTON_A: 133 return 0.5 134 else: 135 return -0.1 136 if n_steps >= self._emulator.max_steps - 2: # some safety 137 return -1.0 # Penalty for not choosing a starter within max steps 138 else: 139 return 0.0 140 step_bonus = min(0.25 / (n_steps + 1), 0.5) 141 if starter_chosen == "charmander": 142 return 0.5 + step_bonus 143 else: 144 return ( 145 0.25 + step_bonus 146 ) # Penalty for choosing the wrong starter. For now, just less reward.
Reward the agent for choosing Charmander as quickly as possible.
108 def determine_reward( 109 self, 110 start_state, 111 *, 112 action=None, 113 action_kwargs=None, 114 transition_states=None, 115 action_success=None, 116 ) -> float: 117 """ 118 Reward the agent for choosing Charmander as quickly as possible. 119 """ 120 from gameboy_worlds.interface.action import LowLevelAction, LowLevelActions 121 122 if transition_states is None: 123 return 0.0 124 current_state = transition_states[-1] 125 starter_chosen = current_state["pokemon_red_starter"]["current_starter"] 126 n_steps = current_state["core"]["steps"] 127 if starter_chosen is None: 128 if action == LowLevelAction and self.STEP_WISE_REWARD: 129 if "low_level_action" in action_kwargs: 130 # reward for pressing A, penalty for pressing anything else 131 low_level_action = action_kwargs["low_level_action"] 132 if low_level_action == LowLevelActions.PRESS_BUTTON_A: 133 return 0.5 134 else: 135 return -0.1 136 if n_steps >= self._emulator.max_steps - 2: # some safety 137 return -1.0 # Penalty for not choosing a starter within max steps 138 else: 139 return 0.0 140 step_bonus = min(0.25 / (n_steps + 1), 0.5) 141 if starter_chosen == "charmander": 142 return 0.5 + step_bonus 143 else: 144 return ( 145 0.25 + step_bonus 146 ) # Penalty for choosing the wrong starter. For now, just less reward.
Reward the agent for choosing Charmander as quickly as possible.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
149class PokemonRedChooseCharmanderEasyEnvironment(PokemonRedChooseCharmanderEnvironment): 150 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 151 """ 152 Override default emulator keyword arguments for this environment. 153 """ 154 Environment.override_state_tracker_class( 155 emulator_kwargs, PokemonRedStarterTracker 156 ) 157 emulator_kwargs["init_state"] = "test_starter_easy" 158 return emulator_kwargs
Reward the agent for choosing Charmander as quickly as possible.
150 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 151 """ 152 Override default emulator keyword arguments for this environment. 153 """ 154 Environment.override_state_tracker_class( 155 emulator_kwargs, PokemonRedStarterTracker 156 ) 157 emulator_kwargs["init_state"] = "test_starter_easy" 158 return emulator_kwargs
Override default emulator keyword arguments for this environment.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play
161class PokemonRedChooseCharmanderHardEnvironment(PokemonRedChooseCharmanderEnvironment): 162 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 163 """ 164 Override default emulator keyword arguments for this environment. 165 """ 166 Environment.override_state_tracker_class( 167 emulator_kwargs, PokemonRedStarterTracker 168 ) 169 emulator_kwargs["init_state"] = "test_starter_hard" 170 return emulator_kwargs
Reward the agent for choosing Charmander as quickly as possible.
162 def override_emulator_kwargs(emulator_kwargs: dict) -> dict: 163 """ 164 Override default emulator keyword arguments for this environment. 165 """ 166 Environment.override_state_tracker_class( 167 emulator_kwargs, PokemonRedStarterTracker 168 ) 169 emulator_kwargs["init_state"] = "test_starter_hard" 170 return emulator_kwargs
Override default emulator keyword arguments for this environment.
Inherited Members
- gameboy_worlds.interface.environment.DummyEnvironment
- DummyEnvironment
- observation_space
- get_observation
- render_obs
- render_info
- gameboy_worlds.interface.environment.Environment
- override_state_tracker_class
- action_space
- actions
- render_mode
- save_custom_state
- delete_custom_state
- load_custom_state
- get_info
- get_final_info
- reset
- determine_truncated
- before_step
- after_step
- step
- step_high_level_action
- step_str
- string_to_high_level_action
- sim
- sim_str
- sim_high_level_action
- close
- render
- seed
- get_action_strings
- human_step_play