gameboy_worlds.interface.harvest_moon.controllers
1from gameboy_worlds.utils import log_error, log_info 2from gameboy_worlds.interface.harvest_moon.actions import ( 3 MoveStepsAction, 4 InteractAction, 5 PassDialogueAction, 6 MoveGridAction, 7) 8from gameboy_worlds.interface.controller import Controller 9from gameboy_worlds.interface.action import HighLevelAction 10from gameboy_worlds.emulation.harvest_moon.parsers import AgentState 11from typing import Dict, Any 12 13 14class HarvestMoonStateWiseController(Controller): 15 """ 16 High Level Actions for the Harvest Moon Environment: 17 18 - In Free Roam: 19 - MoveStepsAction(direction: str, steps: int): Move in a particular direction by a specified number of grid steps. 20 - InteractAction(): Interact with cell directly in front of you. Only works if there is something to interact with. 21 22 - In Dialogue: 23 - PassDialogueAction(): Advance the dialogue by one step. 24 """ 25 26 ACTIONS = [ 27 MoveStepsAction, 28 InteractAction, 29 PassDialogueAction, 30 ] 31 32 def string_to_high_level_action(self, input_str): 33 input_str = input_str.lower().strip() 34 if "(" not in input_str or ")" not in input_str: 35 return None, None # Invalid format 36 action_name = input_str.split("(")[0].strip() 37 action_args_str = input_str.split("(")[1].split(")")[0].strip() 38 # First handle the no arg actions 39 if action_name == "interact": 40 return InteractAction, {} 41 if action_name == "passdialogue": 42 return PassDialogueAction, {} 43 44 if action_name == "move": 45 cardinal = None 46 if "up" in action_args_str: 47 cardinal = "up" 48 if "down" in action_args_str: 49 if cardinal is not None: 50 return None, None 51 cardinal = "down" 52 if "left" in action_args_str: 53 if cardinal is not None: 54 return None, None 55 cardinal = "left" 56 if "right" in action_args_str: 57 if cardinal is not None: 58 return None, None 59 cardinal = "right" 60 if cardinal is None: 61 return None, None 62 steps_part = action_args_str.replace(cardinal, "").strip() 63 if not steps_part.isnumeric(): 64 return None, None 65 steps = int(steps_part) 66 return MoveStepsAction, {"direction": cardinal, "steps": steps} 67 return None, None 68 69 def get_action_strings( 70 self, return_all: bool = False 71 ) -> Dict[HighLevelAction, str]: 72 current_state = self._emulator.state_parser.get_agent_state( 73 self._emulator.get_current_frame() 74 ) 75 free_roam_action_strings = { 76 MoveStepsAction: "move(<up, down, right or left> <steps: int>): Move in a particular direction by a specified number of grid steps.", 77 InteractAction: "interact(): Interact with cell directly in front of you. Only works if there is something to interact with.", 78 } 79 dialogue_action_strings = { 80 PassDialogueAction: "passdialogue(): Advance the dialogue by one step.", 81 } 82 if return_all: 83 actions = { 84 **free_roam_action_strings, 85 **dialogue_action_strings, 86 } 87 else: 88 if current_state == AgentState.FREE_ROAM: 89 actions = free_roam_action_strings 90 elif current_state == AgentState.IN_DIALOGUE: 91 actions = dialogue_action_strings 92 else: 93 log_error( 94 f"Unknown agent state {current_state} when getting action strings." 95 ) 96 actions = {} 97 return actions
15class HarvestMoonStateWiseController(Controller): 16 """ 17 High Level Actions for the Harvest Moon Environment: 18 19 - In Free Roam: 20 - MoveStepsAction(direction: str, steps: int): Move in a particular direction by a specified number of grid steps. 21 - InteractAction(): Interact with cell directly in front of you. Only works if there is something to interact with. 22 23 - In Dialogue: 24 - PassDialogueAction(): Advance the dialogue by one step. 25 """ 26 27 ACTIONS = [ 28 MoveStepsAction, 29 InteractAction, 30 PassDialogueAction, 31 ] 32 33 def string_to_high_level_action(self, input_str): 34 input_str = input_str.lower().strip() 35 if "(" not in input_str or ")" not in input_str: 36 return None, None # Invalid format 37 action_name = input_str.split("(")[0].strip() 38 action_args_str = input_str.split("(")[1].split(")")[0].strip() 39 # First handle the no arg actions 40 if action_name == "interact": 41 return InteractAction, {} 42 if action_name == "passdialogue": 43 return PassDialogueAction, {} 44 45 if action_name == "move": 46 cardinal = None 47 if "up" in action_args_str: 48 cardinal = "up" 49 if "down" in action_args_str: 50 if cardinal is not None: 51 return None, None 52 cardinal = "down" 53 if "left" in action_args_str: 54 if cardinal is not None: 55 return None, None 56 cardinal = "left" 57 if "right" in action_args_str: 58 if cardinal is not None: 59 return None, None 60 cardinal = "right" 61 if cardinal is None: 62 return None, None 63 steps_part = action_args_str.replace(cardinal, "").strip() 64 if not steps_part.isnumeric(): 65 return None, None 66 steps = int(steps_part) 67 return MoveStepsAction, {"direction": cardinal, "steps": steps} 68 return None, None 69 70 def get_action_strings( 71 self, return_all: bool = False 72 ) -> Dict[HighLevelAction, str]: 73 current_state = self._emulator.state_parser.get_agent_state( 74 self._emulator.get_current_frame() 75 ) 76 free_roam_action_strings = { 77 MoveStepsAction: "move(<up, down, right or left> <steps: int>): Move in a particular direction by a specified number of grid steps.", 78 InteractAction: "interact(): Interact with cell directly in front of you. Only works if there is something to interact with.", 79 } 80 dialogue_action_strings = { 81 PassDialogueAction: "passdialogue(): Advance the dialogue by one step.", 82 } 83 if return_all: 84 actions = { 85 **free_roam_action_strings, 86 **dialogue_action_strings, 87 } 88 else: 89 if current_state == AgentState.FREE_ROAM: 90 actions = free_roam_action_strings 91 elif current_state == AgentState.IN_DIALOGUE: 92 actions = dialogue_action_strings 93 else: 94 log_error( 95 f"Unknown agent state {current_state} when getting action strings." 96 ) 97 actions = {} 98 return actions
High Level Actions for the Harvest Moon Environment:
In Free Roam:
- MoveStepsAction(direction: str, steps: int): Move in a particular direction by a specified number of grid steps.
- InteractAction(): Interact with cell directly in front of you. Only works if there is something to interact with.
In Dialogue:
- PassDialogueAction(): Advance the dialogue by one step.
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.
33 def string_to_high_level_action(self, input_str): 34 input_str = input_str.lower().strip() 35 if "(" not in input_str or ")" not in input_str: 36 return None, None # Invalid format 37 action_name = input_str.split("(")[0].strip() 38 action_args_str = input_str.split("(")[1].split(")")[0].strip() 39 # First handle the no arg actions 40 if action_name == "interact": 41 return InteractAction, {} 42 if action_name == "passdialogue": 43 return PassDialogueAction, {} 44 45 if action_name == "move": 46 cardinal = None 47 if "up" in action_args_str: 48 cardinal = "up" 49 if "down" in action_args_str: 50 if cardinal is not None: 51 return None, None 52 cardinal = "down" 53 if "left" in action_args_str: 54 if cardinal is not None: 55 return None, None 56 cardinal = "left" 57 if "right" in action_args_str: 58 if cardinal is not None: 59 return None, None 60 cardinal = "right" 61 if cardinal is None: 62 return None, None 63 steps_part = action_args_str.replace(cardinal, "").strip() 64 if not steps_part.isnumeric(): 65 return None, None 66 steps = int(steps_part) 67 return MoveStepsAction, {"direction": cardinal, "steps": steps} 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( 71 self, return_all: bool = False 72 ) -> Dict[HighLevelAction, str]: 73 current_state = self._emulator.state_parser.get_agent_state( 74 self._emulator.get_current_frame() 75 ) 76 free_roam_action_strings = { 77 MoveStepsAction: "move(<up, down, right or left> <steps: int>): Move in a particular direction by a specified number of grid steps.", 78 InteractAction: "interact(): Interact with cell directly in front of you. Only works if there is something to interact with.", 79 } 80 dialogue_action_strings = { 81 PassDialogueAction: "passdialogue(): Advance the dialogue by one step.", 82 } 83 if return_all: 84 actions = { 85 **free_roam_action_strings, 86 **dialogue_action_strings, 87 } 88 else: 89 if current_state == AgentState.FREE_ROAM: 90 actions = free_roam_action_strings 91 elif current_state == AgentState.IN_DIALOGUE: 92 actions = dialogue_action_strings 93 else: 94 log_error( 95 f"Unknown agent state {current_state} when getting action strings." 96 ) 97 actions = {} 98 return actions
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