gameboy_worlds.emulation.pokemon.emulators
1from gameboy_worlds.emulation.emulator import Emulator, LowLevelActions 2from gameboy_worlds.emulation.pokemon.parsers import PokemonStateParser, AgentState 3from gameboy_worlds.emulation.pokemon.trackers import CorePokemonTracker 4from gameboy_worlds.utils import log_error 5from typing import Tuple 6import numpy as np 7 8 9class PokemonEmulator(Emulator): 10 """ 11 Almost the exact same as Emulator, but forces the agent to not mess with the menu options cursor. Also auto skips naming screens. 12 """ 13 14 REQUIRED_STATE_PARSER = PokemonStateParser 15 REQUIRED_STATE_TRACKER = CorePokemonTracker 16 _MAXIMUM_DIALOGUE_PRESSES = 2000 # For now set a crazy high value 17 """ Maximum number of times the agent will click B to get through a dialogue. """ 18 _SKIP_DIALOGUE = False 19 """ Whether to auto skip dialogue by clicking B repeatedly until we are no longer in dialogue.""" 20 21 def step(self, action=None) -> Tuple[np.ndarray, bool]: 22 frames, done = super().step(action) 23 self.state_parser: PokemonStateParser 24 current_frame = self.get_current_frame() 25 if self.state_parser.is_hovering_over_options_in_menu(current_frame): 26 # WARNING: see the state parser method for details, but this currently does not work before the agent gets the pokedex 27 # force the agent to click the up button to get off the options 28 self.run_action_on_emulator(LowLevelActions.PRESS_ARROW_UP) 29 all_next_frames = [frames] 30 # If we are on a naming screen, just don't pick a name and get out. 31 if self.state_parser.named_region_matches_target( 32 current_frame, name="name_entity_top_left" 33 ): 34 # then enter and get out 35 next_frames = self.run_action_on_emulator( 36 LowLevelActions.PRESS_BUTTON_START 37 ) 38 all_next_frames.append(next_frames) 39 next_frames = self.run_action_on_emulator(LowLevelActions.PRESS_BUTTON_A) 40 all_next_frames.append(next_frames) 41 if ( 42 self._SKIP_DIALOGUE 43 ): # Make this True to auto skip dialogue and accumilate it into the frames returned. 44 current_state = self.state_parser.get_agent_state(current_frame) 45 n_clicks = 0 46 # Clicks through any dialogue popups. 47 while ( 48 n_clicks < self._MAXIMUM_DIALOGUE_PRESSES 49 ) and current_state == AgentState.IN_DIALOGUE: 50 next_frames = self.run_action_on_emulator( 51 LowLevelActions.PRESS_BUTTON_B 52 ) 53 current_state = self.state_parser.get_agent_state(next_frames[-1]) 54 all_next_frames.append(next_frames) 55 n_clicks += 1 56 if len(all_next_frames) > 1: 57 frames = np.concatenate(all_next_frames) 58 self._update_listeners_after_actions( 59 self._get_unique_frames(frames[1:]) 60 ) # Skip the first frame as that is already counted 61 frames = self._get_unique_frames(frames) 62 return frames, done 63 64 def _open_to_first_state(self): 65 self._pyboy.tick(10000, False) # get to opening menu 66 self.run_action_on_emulator( 67 LowLevelActions.PRESS_BUTTON_A 68 ) # press A to get past opening menu 69 self._pyboy.tick(1000, False) # wait for load 70 self.run_action_on_emulator( 71 LowLevelActions.PRESS_BUTTON_A 72 ) # press A to load game 73 self._pyboy.tick(1000, False) # wait for file select 74 self.run_action_on_emulator( 75 LowLevelActions.PRESS_BUTTON_A 76 ) # press A to confirm load 77 self._pyboy.tick(5000, False) # wait for game to load
10class PokemonEmulator(Emulator): 11 """ 12 Almost the exact same as Emulator, but forces the agent to not mess with the menu options cursor. Also auto skips naming screens. 13 """ 14 15 REQUIRED_STATE_PARSER = PokemonStateParser 16 REQUIRED_STATE_TRACKER = CorePokemonTracker 17 _MAXIMUM_DIALOGUE_PRESSES = 2000 # For now set a crazy high value 18 """ Maximum number of times the agent will click B to get through a dialogue. """ 19 _SKIP_DIALOGUE = False 20 """ Whether to auto skip dialogue by clicking B repeatedly until we are no longer in dialogue.""" 21 22 def step(self, action=None) -> Tuple[np.ndarray, bool]: 23 frames, done = super().step(action) 24 self.state_parser: PokemonStateParser 25 current_frame = self.get_current_frame() 26 if self.state_parser.is_hovering_over_options_in_menu(current_frame): 27 # WARNING: see the state parser method for details, but this currently does not work before the agent gets the pokedex 28 # force the agent to click the up button to get off the options 29 self.run_action_on_emulator(LowLevelActions.PRESS_ARROW_UP) 30 all_next_frames = [frames] 31 # If we are on a naming screen, just don't pick a name and get out. 32 if self.state_parser.named_region_matches_target( 33 current_frame, name="name_entity_top_left" 34 ): 35 # then enter and get out 36 next_frames = self.run_action_on_emulator( 37 LowLevelActions.PRESS_BUTTON_START 38 ) 39 all_next_frames.append(next_frames) 40 next_frames = self.run_action_on_emulator(LowLevelActions.PRESS_BUTTON_A) 41 all_next_frames.append(next_frames) 42 if ( 43 self._SKIP_DIALOGUE 44 ): # Make this True to auto skip dialogue and accumilate it into the frames returned. 45 current_state = self.state_parser.get_agent_state(current_frame) 46 n_clicks = 0 47 # Clicks through any dialogue popups. 48 while ( 49 n_clicks < self._MAXIMUM_DIALOGUE_PRESSES 50 ) and current_state == AgentState.IN_DIALOGUE: 51 next_frames = self.run_action_on_emulator( 52 LowLevelActions.PRESS_BUTTON_B 53 ) 54 current_state = self.state_parser.get_agent_state(next_frames[-1]) 55 all_next_frames.append(next_frames) 56 n_clicks += 1 57 if len(all_next_frames) > 1: 58 frames = np.concatenate(all_next_frames) 59 self._update_listeners_after_actions( 60 self._get_unique_frames(frames[1:]) 61 ) # Skip the first frame as that is already counted 62 frames = self._get_unique_frames(frames) 63 return frames, done 64 65 def _open_to_first_state(self): 66 self._pyboy.tick(10000, False) # get to opening menu 67 self.run_action_on_emulator( 68 LowLevelActions.PRESS_BUTTON_A 69 ) # press A to get past opening menu 70 self._pyboy.tick(1000, False) # wait for load 71 self.run_action_on_emulator( 72 LowLevelActions.PRESS_BUTTON_A 73 ) # press A to load game 74 self._pyboy.tick(1000, False) # wait for file select 75 self.run_action_on_emulator( 76 LowLevelActions.PRESS_BUTTON_A 77 ) # press A to confirm load 78 self._pyboy.tick(5000, False) # wait for game to load
Almost the exact same as Emulator, but forces the agent to not mess with the menu options cursor. Also auto skips naming screens.
REQUIRED_STATE_PARSER =
<class 'gameboy_worlds.emulation.pokemon.parsers.PokemonStateParser'>
The minimal functionality StateParser needed for this emulator to run
REQUIRED_STATE_TRACKER =
<class 'gameboy_worlds.emulation.pokemon.trackers.CorePokemonTracker'>
The minimal functionality StateTracker needed for this emulator to run
def
step(self, action=None) -> Tuple[numpy.ndarray, bool]:
22 def step(self, action=None) -> Tuple[np.ndarray, bool]: 23 frames, done = super().step(action) 24 self.state_parser: PokemonStateParser 25 current_frame = self.get_current_frame() 26 if self.state_parser.is_hovering_over_options_in_menu(current_frame): 27 # WARNING: see the state parser method for details, but this currently does not work before the agent gets the pokedex 28 # force the agent to click the up button to get off the options 29 self.run_action_on_emulator(LowLevelActions.PRESS_ARROW_UP) 30 all_next_frames = [frames] 31 # If we are on a naming screen, just don't pick a name and get out. 32 if self.state_parser.named_region_matches_target( 33 current_frame, name="name_entity_top_left" 34 ): 35 # then enter and get out 36 next_frames = self.run_action_on_emulator( 37 LowLevelActions.PRESS_BUTTON_START 38 ) 39 all_next_frames.append(next_frames) 40 next_frames = self.run_action_on_emulator(LowLevelActions.PRESS_BUTTON_A) 41 all_next_frames.append(next_frames) 42 if ( 43 self._SKIP_DIALOGUE 44 ): # Make this True to auto skip dialogue and accumilate it into the frames returned. 45 current_state = self.state_parser.get_agent_state(current_frame) 46 n_clicks = 0 47 # Clicks through any dialogue popups. 48 while ( 49 n_clicks < self._MAXIMUM_DIALOGUE_PRESSES 50 ) and current_state == AgentState.IN_DIALOGUE: 51 next_frames = self.run_action_on_emulator( 52 LowLevelActions.PRESS_BUTTON_B 53 ) 54 current_state = self.state_parser.get_agent_state(next_frames[-1]) 55 all_next_frames.append(next_frames) 56 n_clicks += 1 57 if len(all_next_frames) > 1: 58 frames = np.concatenate(all_next_frames) 59 self._update_listeners_after_actions( 60 self._get_unique_frames(frames[1:]) 61 ) # Skip the first frame as that is already counted 62 frames = self._get_unique_frames(frames) 63 return frames, done
Takes a step in the environment by performing the given action on the emulator. If saving video, starts the video recording on the first step.
Parameters
- action: Lowest level action to perform on the emulator.
Returns
- The stack of frames that passed while performing the action, if rendering is enabled. Is of shape [n_frames (3 right now), height, width, channels]. Otherwise, None. - Is max steps reached.
Inherited Members
- gameboy_worlds.emulation.emulator.Emulator
- Emulator
- game
- headless
- max_steps
- session_path
- wait_ticks
- press_step
- render_headless
- reset_count
- step_count
- screen_shape
- save_video
- video_writer
- state_parser
- state_tracker
- create_first_state
- set_init_state
- reset
- get_current_frame
- get_state_parser
- run_action_on_emulator
- check_if_done
- close
- human_play
- random_play
- save_state
- delete_state
- get_env_variant