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
MAX_MENU_METRIC = ('bomberman_max_core', 'is_in_menu')
MAX_BATTLE_METRIC = ('bomberman_max_core', 'is_in_battle')
POCKET_MENU_METRIC = ('bomberman_pocket_core', 'is_in_menu')
QUEST_MENU_METRIC = ('bomberman_quest_core', 'is_in_menu')
QUEST_BATTLE_METRIC = ('bomberman_quest_core', 'is_in_battle')
class BombermanMaxStateWiseController(gameboy_worlds.interface.controller.Controller):
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.

def string_to_high_level_action(self, input_str):
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.

def get_action_strings( self, return_all: bool = False) -> Dict[Type[gameboy_worlds.interface.action.HighLevelAction], str]:
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.

class BombermanPocketStateWiseController(gameboy_worlds.interface.controller.Controller):
 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.

def string_to_high_level_action(self, input_str):
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.

def get_action_strings( self, return_all: bool = False) -> Dict[Type[gameboy_worlds.interface.action.HighLevelAction], str]:
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.

class BombermanQuestStateWiseController(gameboy_worlds.interface.controller.Controller):
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.

def string_to_high_level_action(self, input_str):
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.

def get_action_strings( self, return_all: bool = False) -> Dict[Type[gameboy_worlds.interface.action.HighLevelAction], str]:
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.