gameboy_worlds.interface.bomberman.controllers
1from typing import Dict, Type 2 3from gameboy_worlds.interface.action import HighLevelAction 4from gameboy_worlds.interface.bomberman.actions import ( 5 BombermanMaxBattleAction, 6 BombermanMaxCloseMenuAction, 7 BombermanMaxKickBombAction, 8 BombermanMaxMoveAction, 9 BombermanMaxNavigateMenuAction, 10 BombermanMaxOpenMenuAction, 11 BombermanMaxPlaceBombAction, 12 BombermanPocketClosePauseMenuAction, 13 BombermanPocketJumpAction, 14 BombermanPocketMoveAction, 15 BombermanPocketOpenPauseMenuAction, 16 BombermanPocketPlaceBombAction, 17 BombermanQuestBattleAction, 18 BombermanQuestCloseMenuAction, 19 BombermanQuestMoveAction, 20 BombermanQuestNavigateMenuAction, 21 BombermanQuestOpenMenuAction, 22 BombermanQuestPlaceBombAction, 23 BombermanQuestUseBButtonItemAction, 24) 25from gameboy_worlds.interface.controller import Controller 26 27MAX_MENU_METRIC = ("bomberman_max_core", "is_in_menu") 28MAX_BATTLE_METRIC = ("bomberman_max_core", "is_in_battle") 29POCKET_MENU_METRIC = ("bomberman_pocket_core", "is_in_menu") 30QUEST_MENU_METRIC = ("bomberman_quest_core", "is_in_menu") 31QUEST_BATTLE_METRIC = ("bomberman_quest_core", "is_in_battle") 32 33 34class BombermanMaxStateWiseController(Controller): 35 ACTIONS = [ 36 BombermanMaxMoveAction, 37 BombermanMaxPlaceBombAction, 38 BombermanMaxKickBombAction, 39 BombermanMaxOpenMenuAction, 40 BombermanMaxCloseMenuAction, 41 BombermanMaxNavigateMenuAction, 42 BombermanMaxBattleAction, 43 ] 44 45 def string_to_high_level_action(self, input_str): 46 text = input_str.lower().strip() 47 if "(" not in text or ")" not in text: 48 return None, None 49 action_name = text.split("(")[0].strip() 50 action_args_str = text.split("(")[1].split(")")[0].strip() 51 if action_name == "move": 52 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 53 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 54 return BombermanMaxMoveAction, {"direction": parts[0], "steps": int(parts[1])} 55 elif action_name == "placebomb": 56 return BombermanMaxPlaceBombAction, {} 57 elif action_name == "kickbomb": 58 return BombermanMaxKickBombAction, {} 59 elif action_name == "openmenu": 60 return BombermanMaxOpenMenuAction, {} 61 elif action_name == "closemenu": 62 return BombermanMaxCloseMenuAction, {} 63 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 64 return BombermanMaxNavigateMenuAction, {"menu_action": action_args_str} 65 elif action_name == "battle" and action_args_str in ["bomb", "up", "down", "left", "right"]: 66 return BombermanMaxBattleAction, {"battle_action": action_args_str} 67 return None, None 68 69 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 70 free_roam_strings = { 71 BombermanMaxMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 72 BombermanMaxPlaceBombAction: "placebomb(): Place a bomb (A button).", 73 BombermanMaxKickBombAction: "kickbomb(): Kick bomb or use B-button power-up.", 74 BombermanMaxOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 75 } 76 menu_strings = { 77 BombermanMaxNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 78 BombermanMaxCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 79 } 80 battle_strings = { 81 BombermanMaxBattleAction: "battle(<bomb/up/down/left/right>): Act during a Charabom battle.", 82 } 83 if return_all: 84 return {**free_roam_strings, **menu_strings, **battle_strings} 85 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_MENU_METRIC): 86 return menu_strings 87 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_BATTLE_METRIC): 88 return battle_strings 89 return free_roam_strings 90 91 92class BombermanPocketStateWiseController(Controller): 93 ACTIONS = [ 94 BombermanPocketMoveAction, 95 BombermanPocketJumpAction, 96 BombermanPocketPlaceBombAction, 97 BombermanPocketOpenPauseMenuAction, 98 BombermanPocketClosePauseMenuAction, 99 ] 100 101 def string_to_high_level_action(self, input_str): 102 text = input_str.lower().strip() 103 if "(" not in text or ")" not in text: 104 return None, None 105 action_name = text.split("(")[0].strip() 106 action_args_str = text.split("(")[1].split(")")[0].strip() 107 if action_name == "move": 108 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 109 if len(parts) == 2 and parts[0] in ["left", "right"] and parts[1].isdigit(): 110 return BombermanPocketMoveAction, {"direction": parts[0], "steps": int(parts[1])} 111 elif action_name == "jump": 112 return BombermanPocketJumpAction, {} 113 elif action_name == "placebomb": 114 return BombermanPocketPlaceBombAction, {} 115 elif action_name == "openpausemenu": 116 return BombermanPocketOpenPauseMenuAction, {} 117 elif action_name == "closepausemenu": 118 return BombermanPocketClosePauseMenuAction, {} 119 return None, None 120 121 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 122 gameplay_strings = { 123 BombermanPocketMoveAction: "move(<left/right> <steps>): Move left or right for N steps.", 124 BombermanPocketJumpAction: "jump(): Jump (B button).", 125 BombermanPocketPlaceBombAction: "placebomb(): Place a bomb at current position (A button).", 126 BombermanPocketOpenPauseMenuAction: "openpausemenu(): Open the pause menu (Start).", 127 } 128 pause_menu_strings = { 129 BombermanPocketClosePauseMenuAction: "closepausemenu(): Close the pause menu (Start).", 130 } 131 if return_all: 132 return {**gameplay_strings, **pause_menu_strings} 133 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(POCKET_MENU_METRIC): 134 return pause_menu_strings 135 return gameplay_strings 136 137 138class BombermanQuestStateWiseController(Controller): 139 ACTIONS = [ 140 BombermanQuestMoveAction, 141 BombermanQuestPlaceBombAction, 142 BombermanQuestUseBButtonItemAction, 143 BombermanQuestOpenMenuAction, 144 BombermanQuestCloseMenuAction, 145 BombermanQuestNavigateMenuAction, 146 BombermanQuestBattleAction, 147 ] 148 149 def string_to_high_level_action(self, input_str): 150 text = input_str.lower().strip() 151 if "(" not in text or ")" not in text: 152 return None, None 153 action_name = text.split("(")[0].strip() 154 action_args_str = text.split("(")[1].split(")")[0].strip() 155 if action_name == "move": 156 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 157 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 158 return BombermanQuestMoveAction, {"direction": parts[0], "steps": int(parts[1])} 159 elif action_name == "placebomb": 160 return BombermanQuestPlaceBombAction, {} 161 elif action_name == "usebitem": 162 return BombermanQuestUseBButtonItemAction, {} 163 elif action_name == "openmenu": 164 return BombermanQuestOpenMenuAction, {} 165 elif action_name == "closemenu": 166 return BombermanQuestCloseMenuAction, {} 167 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 168 return BombermanQuestNavigateMenuAction, {"menu_action": action_args_str} 169 elif action_name == "battle" and action_args_str in ["bomb", "item", "up", "down", "left", "right"]: 170 return BombermanQuestBattleAction, {"battle_action": action_args_str} 171 return None, None 172 173 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 174 free_roam_strings = { 175 BombermanQuestMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 176 BombermanQuestPlaceBombAction: "placebomb(): Place a bomb / use A-button item.", 177 BombermanQuestUseBButtonItemAction: "usebitem(): Use B-button item.", 178 BombermanQuestOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 179 } 180 menu_strings = { 181 BombermanQuestNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 182 BombermanQuestCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 183 } 184 battle_strings = { 185 BombermanQuestBattleAction: "battle(<bomb/item/up/down/left/right>): Act during a monster battle.", 186 } 187 if return_all: 188 return {**free_roam_strings, **menu_strings, **battle_strings} 189 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_MENU_METRIC): 190 return menu_strings 191 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_BATTLE_METRIC): 192 return battle_strings 193 return free_roam_strings
35class BombermanMaxStateWiseController(Controller): 36 ACTIONS = [ 37 BombermanMaxMoveAction, 38 BombermanMaxPlaceBombAction, 39 BombermanMaxKickBombAction, 40 BombermanMaxOpenMenuAction, 41 BombermanMaxCloseMenuAction, 42 BombermanMaxNavigateMenuAction, 43 BombermanMaxBattleAction, 44 ] 45 46 def string_to_high_level_action(self, input_str): 47 text = input_str.lower().strip() 48 if "(" not in text or ")" not in text: 49 return None, None 50 action_name = text.split("(")[0].strip() 51 action_args_str = text.split("(")[1].split(")")[0].strip() 52 if action_name == "move": 53 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 54 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 55 return BombermanMaxMoveAction, {"direction": parts[0], "steps": int(parts[1])} 56 elif action_name == "placebomb": 57 return BombermanMaxPlaceBombAction, {} 58 elif action_name == "kickbomb": 59 return BombermanMaxKickBombAction, {} 60 elif action_name == "openmenu": 61 return BombermanMaxOpenMenuAction, {} 62 elif action_name == "closemenu": 63 return BombermanMaxCloseMenuAction, {} 64 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 65 return BombermanMaxNavigateMenuAction, {"menu_action": action_args_str} 66 elif action_name == "battle" and action_args_str in ["bomb", "up", "down", "left", "right"]: 67 return BombermanMaxBattleAction, {"battle_action": action_args_str} 68 return None, None 69 70 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 71 free_roam_strings = { 72 BombermanMaxMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 73 BombermanMaxPlaceBombAction: "placebomb(): Place a bomb (A button).", 74 BombermanMaxKickBombAction: "kickbomb(): Kick bomb or use B-button power-up.", 75 BombermanMaxOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 76 } 77 menu_strings = { 78 BombermanMaxNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 79 BombermanMaxCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 80 } 81 battle_strings = { 82 BombermanMaxBattleAction: "battle(<bomb/up/down/left/right>): Act during a Charabom battle.", 83 } 84 if return_all: 85 return {**free_roam_strings, **menu_strings, **battle_strings} 86 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_MENU_METRIC): 87 return menu_strings 88 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_BATTLE_METRIC): 89 return battle_strings 90 return free_roam_strings
Abstract base class for controllers interfacing with the emulator. Handles conversion between high level actions and Gym action spaces.
A list of HighLevelAction classes that define the possible high level actions. This is (almost) always, the only part that must be customized in subclasses.
46 def string_to_high_level_action(self, input_str): 47 text = input_str.lower().strip() 48 if "(" not in text or ")" not in text: 49 return None, None 50 action_name = text.split("(")[0].strip() 51 action_args_str = text.split("(")[1].split(")")[0].strip() 52 if action_name == "move": 53 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 54 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 55 return BombermanMaxMoveAction, {"direction": parts[0], "steps": int(parts[1])} 56 elif action_name == "placebomb": 57 return BombermanMaxPlaceBombAction, {} 58 elif action_name == "kickbomb": 59 return BombermanMaxKickBombAction, {} 60 elif action_name == "openmenu": 61 return BombermanMaxOpenMenuAction, {} 62 elif action_name == "closemenu": 63 return BombermanMaxCloseMenuAction, {} 64 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 65 return BombermanMaxNavigateMenuAction, {"menu_action": action_args_str} 66 elif action_name == "battle" and action_args_str in ["bomb", "up", "down", "left", "right"]: 67 return BombermanMaxBattleAction, {"battle_action": action_args_str} 68 return None, None
Provide a way to map a string input to a HighLevelAction and parameters.
Implement if you want to use the human_step_play method, or if you want to allow a LM based agent to give its actions in text. Must return None, None if the input_str does not map to an action.
70 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 71 free_roam_strings = { 72 BombermanMaxMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 73 BombermanMaxPlaceBombAction: "placebomb(): Place a bomb (A button).", 74 BombermanMaxKickBombAction: "kickbomb(): Kick bomb or use B-button power-up.", 75 BombermanMaxOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 76 } 77 menu_strings = { 78 BombermanMaxNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 79 BombermanMaxCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 80 } 81 battle_strings = { 82 BombermanMaxBattleAction: "battle(<bomb/up/down/left/right>): Act during a Charabom battle.", 83 } 84 if return_all: 85 return {**free_roam_strings, **menu_strings, **battle_strings} 86 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_MENU_METRIC): 87 return menu_strings 88 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(MAX_BATTLE_METRIC): 89 return battle_strings 90 return free_roam_strings
Provide a way to verbalize the allowed high level actions, along with the format of the input parameters. Useful for prompting a VLM to choose an action.
This should match the mapping in string_to_high_level_action
Parameters
- return_all: If True, returns all possible actions and parameter formats. If False, returns only the actions that are valid in the current state.
Returns
A dictionary mapping high level actions to their verbalizations and input formats.
Inherited Members
- gameboy_worlds.interface.controller.Controller
- Controller
- actions
- REQUIRED_STATE_TRACKER
- action_space
- seed
- unassign_emulator
- assign_emulator
- get_action_space
- sample
- is_valid
- get_valid_high_level_actions
- get_valid_space_actions
- get_possibly_valid_high_level_actions
- execute_space_action
- execute
- string_to_space_action
- execute_string
93class BombermanPocketStateWiseController(Controller): 94 ACTIONS = [ 95 BombermanPocketMoveAction, 96 BombermanPocketJumpAction, 97 BombermanPocketPlaceBombAction, 98 BombermanPocketOpenPauseMenuAction, 99 BombermanPocketClosePauseMenuAction, 100 ] 101 102 def string_to_high_level_action(self, input_str): 103 text = input_str.lower().strip() 104 if "(" not in text or ")" not in text: 105 return None, None 106 action_name = text.split("(")[0].strip() 107 action_args_str = text.split("(")[1].split(")")[0].strip() 108 if action_name == "move": 109 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 110 if len(parts) == 2 and parts[0] in ["left", "right"] and parts[1].isdigit(): 111 return BombermanPocketMoveAction, {"direction": parts[0], "steps": int(parts[1])} 112 elif action_name == "jump": 113 return BombermanPocketJumpAction, {} 114 elif action_name == "placebomb": 115 return BombermanPocketPlaceBombAction, {} 116 elif action_name == "openpausemenu": 117 return BombermanPocketOpenPauseMenuAction, {} 118 elif action_name == "closepausemenu": 119 return BombermanPocketClosePauseMenuAction, {} 120 return None, None 121 122 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 123 gameplay_strings = { 124 BombermanPocketMoveAction: "move(<left/right> <steps>): Move left or right for N steps.", 125 BombermanPocketJumpAction: "jump(): Jump (B button).", 126 BombermanPocketPlaceBombAction: "placebomb(): Place a bomb at current position (A button).", 127 BombermanPocketOpenPauseMenuAction: "openpausemenu(): Open the pause menu (Start).", 128 } 129 pause_menu_strings = { 130 BombermanPocketClosePauseMenuAction: "closepausemenu(): Close the pause menu (Start).", 131 } 132 if return_all: 133 return {**gameplay_strings, **pause_menu_strings} 134 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(POCKET_MENU_METRIC): 135 return pause_menu_strings 136 return gameplay_strings
Abstract base class for controllers interfacing with the emulator. Handles conversion between high level actions and Gym action spaces.
A list of HighLevelAction classes that define the possible high level actions. This is (almost) always, the only part that must be customized in subclasses.
102 def string_to_high_level_action(self, input_str): 103 text = input_str.lower().strip() 104 if "(" not in text or ")" not in text: 105 return None, None 106 action_name = text.split("(")[0].strip() 107 action_args_str = text.split("(")[1].split(")")[0].strip() 108 if action_name == "move": 109 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 110 if len(parts) == 2 and parts[0] in ["left", "right"] and parts[1].isdigit(): 111 return BombermanPocketMoveAction, {"direction": parts[0], "steps": int(parts[1])} 112 elif action_name == "jump": 113 return BombermanPocketJumpAction, {} 114 elif action_name == "placebomb": 115 return BombermanPocketPlaceBombAction, {} 116 elif action_name == "openpausemenu": 117 return BombermanPocketOpenPauseMenuAction, {} 118 elif action_name == "closepausemenu": 119 return BombermanPocketClosePauseMenuAction, {} 120 return None, None
Provide a way to map a string input to a HighLevelAction and parameters.
Implement if you want to use the human_step_play method, or if you want to allow a LM based agent to give its actions in text. Must return None, None if the input_str does not map to an action.
122 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 123 gameplay_strings = { 124 BombermanPocketMoveAction: "move(<left/right> <steps>): Move left or right for N steps.", 125 BombermanPocketJumpAction: "jump(): Jump (B button).", 126 BombermanPocketPlaceBombAction: "placebomb(): Place a bomb at current position (A button).", 127 BombermanPocketOpenPauseMenuAction: "openpausemenu(): Open the pause menu (Start).", 128 } 129 pause_menu_strings = { 130 BombermanPocketClosePauseMenuAction: "closepausemenu(): Close the pause menu (Start).", 131 } 132 if return_all: 133 return {**gameplay_strings, **pause_menu_strings} 134 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(POCKET_MENU_METRIC): 135 return pause_menu_strings 136 return gameplay_strings
Provide a way to verbalize the allowed high level actions, along with the format of the input parameters. Useful for prompting a VLM to choose an action.
This should match the mapping in string_to_high_level_action
Parameters
- return_all: If True, returns all possible actions and parameter formats. If False, returns only the actions that are valid in the current state.
Returns
A dictionary mapping high level actions to their verbalizations and input formats.
Inherited Members
- gameboy_worlds.interface.controller.Controller
- Controller
- actions
- REQUIRED_STATE_TRACKER
- action_space
- seed
- unassign_emulator
- assign_emulator
- get_action_space
- sample
- is_valid
- get_valid_high_level_actions
- get_valid_space_actions
- get_possibly_valid_high_level_actions
- execute_space_action
- execute
- string_to_space_action
- execute_string
139class BombermanQuestStateWiseController(Controller): 140 ACTIONS = [ 141 BombermanQuestMoveAction, 142 BombermanQuestPlaceBombAction, 143 BombermanQuestUseBButtonItemAction, 144 BombermanQuestOpenMenuAction, 145 BombermanQuestCloseMenuAction, 146 BombermanQuestNavigateMenuAction, 147 BombermanQuestBattleAction, 148 ] 149 150 def string_to_high_level_action(self, input_str): 151 text = input_str.lower().strip() 152 if "(" not in text or ")" not in text: 153 return None, None 154 action_name = text.split("(")[0].strip() 155 action_args_str = text.split("(")[1].split(")")[0].strip() 156 if action_name == "move": 157 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 158 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 159 return BombermanQuestMoveAction, {"direction": parts[0], "steps": int(parts[1])} 160 elif action_name == "placebomb": 161 return BombermanQuestPlaceBombAction, {} 162 elif action_name == "usebitem": 163 return BombermanQuestUseBButtonItemAction, {} 164 elif action_name == "openmenu": 165 return BombermanQuestOpenMenuAction, {} 166 elif action_name == "closemenu": 167 return BombermanQuestCloseMenuAction, {} 168 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 169 return BombermanQuestNavigateMenuAction, {"menu_action": action_args_str} 170 elif action_name == "battle" and action_args_str in ["bomb", "item", "up", "down", "left", "right"]: 171 return BombermanQuestBattleAction, {"battle_action": action_args_str} 172 return None, None 173 174 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 175 free_roam_strings = { 176 BombermanQuestMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 177 BombermanQuestPlaceBombAction: "placebomb(): Place a bomb / use A-button item.", 178 BombermanQuestUseBButtonItemAction: "usebitem(): Use B-button item.", 179 BombermanQuestOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 180 } 181 menu_strings = { 182 BombermanQuestNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 183 BombermanQuestCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 184 } 185 battle_strings = { 186 BombermanQuestBattleAction: "battle(<bomb/item/up/down/left/right>): Act during a monster battle.", 187 } 188 if return_all: 189 return {**free_roam_strings, **menu_strings, **battle_strings} 190 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_MENU_METRIC): 191 return menu_strings 192 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_BATTLE_METRIC): 193 return battle_strings 194 return free_roam_strings
Abstract base class for controllers interfacing with the emulator. Handles conversion between high level actions and Gym action spaces.
A list of HighLevelAction classes that define the possible high level actions. This is (almost) always, the only part that must be customized in subclasses.
150 def string_to_high_level_action(self, input_str): 151 text = input_str.lower().strip() 152 if "(" not in text or ")" not in text: 153 return None, None 154 action_name = text.split("(")[0].strip() 155 action_args_str = text.split("(")[1].split(")")[0].strip() 156 if action_name == "move": 157 parts = [x.strip() for x in action_args_str.replace(",", " ").split() if x.strip()] 158 if len(parts) == 2 and parts[0] in ["up", "down", "left", "right"] and parts[1].isdigit(): 159 return BombermanQuestMoveAction, {"direction": parts[0], "steps": int(parts[1])} 160 elif action_name == "placebomb": 161 return BombermanQuestPlaceBombAction, {} 162 elif action_name == "usebitem": 163 return BombermanQuestUseBButtonItemAction, {} 164 elif action_name == "openmenu": 165 return BombermanQuestOpenMenuAction, {} 166 elif action_name == "closemenu": 167 return BombermanQuestCloseMenuAction, {} 168 elif action_name == "navigatemenu" and action_args_str in ["up", "down", "left", "right", "confirm", "back"]: 169 return BombermanQuestNavigateMenuAction, {"menu_action": action_args_str} 170 elif action_name == "battle" and action_args_str in ["bomb", "item", "up", "down", "left", "right"]: 171 return BombermanQuestBattleAction, {"battle_action": action_args_str} 172 return None, None
Provide a way to map a string input to a HighLevelAction and parameters.
Implement if you want to use the human_step_play method, or if you want to allow a LM based agent to give its actions in text. Must return None, None if the input_str does not map to an action.
174 def get_action_strings(self, return_all: bool = False) -> Dict[Type[HighLevelAction], str]: 175 free_roam_strings = { 176 BombermanQuestMoveAction: "move(<up/down/left/right> <steps>): Move in a direction for N steps.", 177 BombermanQuestPlaceBombAction: "placebomb(): Place a bomb / use A-button item.", 178 BombermanQuestUseBButtonItemAction: "usebitem(): Use B-button item.", 179 BombermanQuestOpenMenuAction: "openmenu(): Open the pause/item menu (Start).", 180 } 181 menu_strings = { 182 BombermanQuestNavigateMenuAction: "navigatemenu(<up/down/left/right/confirm/back>): Navigate the pause menu.", 183 BombermanQuestCloseMenuAction: "closemenu(): Close the pause/item menu (Start).", 184 } 185 battle_strings = { 186 BombermanQuestBattleAction: "battle(<bomb/item/up/down/left/right>): Act during a monster battle.", 187 } 188 if return_all: 189 return {**free_roam_strings, **menu_strings, **battle_strings} 190 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_MENU_METRIC): 191 return menu_strings 192 if hasattr(self, "_state_tracker") and self._state_tracker.get_episode_metric(QUEST_BATTLE_METRIC): 193 return battle_strings 194 return free_roam_strings
Provide a way to verbalize the allowed high level actions, along with the format of the input parameters. Useful for prompting a VLM to choose an action.
This should match the mapping in string_to_high_level_action
Parameters
- return_all: If True, returns all possible actions and parameter formats. If False, returns only the actions that are valid in the current state.
Returns
A dictionary mapping high level actions to their verbalizations and input formats.
Inherited Members
- gameboy_worlds.interface.controller.Controller
- Controller
- actions
- REQUIRED_STATE_TRACKER
- action_space
- seed
- unassign_emulator
- assign_emulator
- get_action_space
- sample
- is_valid
- get_valid_high_level_actions
- get_valid_space_actions
- get_possibly_valid_high_level_actions
- execute_space_action
- execute
- string_to_space_action
- execute_string