def setUp(self): self.memory = AgentMemory( load_minecraft_specs=False) # don't load specs, it's slow self.agent = FakeAgent(self.memory) self.dialogue_manager = TtadModelDialogueManager( self.agent, None, None, None, no_ground_truth_actions=True) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value")) # Add a speaker at position (5, 63, 5) looking in the +x direction self.memory.update(self.agent) self.speaker = list(self.memory.other_players.values())[0].name
def setUp(self, agent_opts=None): spec = {"players": [SimpleHuman(make_human_opts())], "agent": {"pos": (0, 0)}} world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value" ) ) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive()
def setUp(self, agent_opts=None): spec = { "players": [Player(42, "SPEAKER", Pos(5, 63, 5), Look(270, 0), Item(0, 0))], "mobs": [], "item_stacks": [], "ground_generator": flat_ground_generator, "agent": {"pos": (0, 63, 0)}, "coord_shift": (-16, 54, -16), } world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) self.set_looking_at((0, 63, 0)) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive()
def setUp(self): self.testing_agent = FakeAgent()
class BaseCraftassistTestCase(unittest.TestCase): def setUp(self): self.memory = AgentMemory( load_minecraft_specs=False) # don't load specs, it's slow self.agent = FakeAgent(self.memory) self.dialogue_manager = TtadModelDialogueManager( self.agent, None, None, None, no_ground_truth_actions=True) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value")) # Add a speaker at position (5, 63, 5) looking in the +x direction self.memory.update(self.agent) self.speaker = list(self.memory.other_players.values())[0].name def handle_action_dict(self, d, answer: str = None, stop_on_chat=False, max_steps=10000) -> Dict[XYZ, IDM]: """Handle an action dict and call self.flush() If "answer" is specified and a question is asked by the agent, respond with this string. If "stop_on_chat" is specified, stop iterating if the agent says anything """ self.add_incoming_chat("TEST {}".format(d)) obj = self.dialogue_manager.handle_action_dict(self.speaker, d) if obj is not None: self.dialogue_manager.dialogue_stack.append(obj) changes = self.flush(max_steps, stop_on_chat=stop_on_chat) if len(self.dialogue_manager.dialogue_stack ) != 0 and answer is not None: self.add_incoming_chat(answer) changes.update(self.flush(max_steps, stop_on_chat=stop_on_chat)) return changes def flush(self, max_steps=10000, stop_on_chat=False) -> Dict[XYZ, IDM]: """Update memory and step the dialogue and task stacks until they are empty If "stop_on_chat" is specified, stop iterating if the agent says anything Return the set of blocks that were changed. """ if stop_on_chat: self.agent.clear_outgoing_chats() world_before = self.agent._world.copy() for _ in range(max_steps): if (len(self.dialogue_manager.dialogue_stack) == 0 and not self.memory.task_stack_peek()): break self.memory.update(self.agent) self.dialogue_manager.dialogue_stack.step() self.agent.task_step() if (isinstance(self.dialogue_manager.dialogue_stack.peek(), AwaitResponse) and not self.dialogue_manager.dialogue_stack.peek().finished ) or (stop_on_chat and self.agent.get_last_outgoing_chat()): break self.memory.update(self.agent) # get changes world_after = self.agent._world.copy() changes = dict(set(world_after.items()) - set(world_before.items())) changes.update({ k: (0, 0) for k in set(world_before.keys()) - set(world_after.keys()) }) return changes def set_looking_at(self, xyz: XYZ): """Set the return value for C++ call to get_player_line_of_sight""" self.agent.get_player_line_of_sight = Mock(return_value=Pos(*xyz)) def set_blocks(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)): """Change the state of the world, block by block""" for xyz, idm in xyzbms: abs_xyz = tuple(np.array(xyz) + origin) self.memory.on_block_changed(abs_xyz, idm) self.agent._world[abs_xyz] = idm def add_object(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)) -> ObjectNode: """Add an object to memory as if it was placed block by block Args: - xyzbms: a list of relative (xyz, idm) - origin: (x, y, z) of the corner Returns an ObjectNode """ self.set_blocks(xyzbms, origin) abs_xyz = tuple(np.array(xyzbms[0][0]) + origin) memid = self.memory.get_block_object_ids_by_xyz(abs_xyz)[0] return self.memory.get_object_by_id(memid) def get_blocks(self, xyzs: Sequence[XYZ]) -> Dict[XYZ, IDM]: """Return the ground truth block state""" d = {} for (x, y, z) in xyzs: B = self.agent.get_blocks(x, x, y, y, z, z) d[(x, y, z)] = tuple(B[0, 0, 0, :]) return d def add_incoming_chat(self, chat: str): """Add a chat to memory as if it was just spoken by SPEAKER""" self.memory.add_chat( self.memory.get_player_by_name(self.speaker).memid, chat) def assert_schematics_equal(self, a, b): """Check equality between two list[(xyz, idm)] schematics N.B. this compares the shapes and idms, but ignores absolute position offsets. """ a, _ = to_relative_pos(a) b, _ = to_relative_pos(b) self.assertEqual(set(a), set(b)) def last_outgoing_chat(self) -> str: return self.agent.get_last_outgoing_chat() def get_speaker_pos(self) -> XYZ: return tuple( pos_to_np(self.memory.get_player_struct_by_name(self.speaker).pos))
def setUp(self): self.memory = AgentMemory(load_minecraft_specs=False) # don't load specs, it's slow self.agent = FakeAgent(self.memory) self.dialogue_manager = TtadModelDialogueManager( self.agent, None, None, None, None, None, no_ground_truth_actions=True ) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value" ) ) # Add a speaker at position (5, 63, 5) looking in the +x direction self.memory.update(self.agent) self.speaker = list(self.memory.other_players.values())[0].name # Combinable actions to be used in test cases self.possible_actions = { "destroy_speaker_look": { "action_type": "DESTROY", "reference_object": {"location": {"location_type": "SPEAKER_LOOK"}}, }, "copy_speaker_look_to_agent_pos": { "action_type": "BUILD", "reference_object": {"location": {"location_type": "SPEAKER_LOOK"}}, "location": {"location_type": "AGENT_POS"}, }, "build_small_sphere": { "action_type": "BUILD", "schematic": {"has_name": "sphere", "has_size": "small"}, }, "build_1x1x1_cube": { "action_type": "BUILD", "schematic": {"has_name": "cube", "has_size": "1 x 1 x 1"}, }, "move_speaker_pos": { "action_type": "MOVE", "location": {"location_type": "SPEAKER_POS"}, }, "build_diamond": {"action_type": "BUILD", "schematic": {"has_name": "diamond"}}, "build_gold_cube": { "action_type": "BUILD", "schematic": {"has_block_type": "gold", "has_name": "cube"}, }, "fill_all_holes_speaker_look": { "action_type": "FILL", "location": {"location_type": "SPEAKER_LOOK"}, "repeat": {"repeat_key": "ALL"}, }, "go_to_tree": { "action_type": "MOVE", "location": { "location_type": "REFERENCE_OBJECT", "reference_object": {"has_name": "tree"}, }, }, "build_square_height_1": { "action_type": "BUILD", "schematic": {"has_name": "square", "has_height": "1"}, }, "stop": {"action_type": "STOP"}, "fill_speaker_look": { "action_type": "FILL", "location": {"location_type": "SPEAKER_LOOK"}, }, "fill_speaker_look_gold": { "action_type": "FILL", "has_block_type": "gold", "location": {"location_type": "SPEAKER_LOOK"}, }, }
class BaseCraftassistTestCase(unittest.TestCase): def setUp(self, agent_opts=None): spec = { "players": [Player(42, "SPEAKER", Pos(5, 63, 5), Look(270, 0), Item(0, 0))], "mobs": [], "item_stacks": [], "ground_generator": flat_ground_generator, "agent": { "pos": (0, 63, 0) }, "coord_shift": (-16, 54, -16), } world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) self.set_looking_at((0, 63, 0)) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive() def handle_logical_form(self, d, chatstr: str = "", answer: str = None, stop_on_chat=False, max_steps=10000) -> Dict[XYZ, IDM]: """Handle a logical form and call self.flush() If "answer" is specified and a question is asked by the agent, respond with this string. If "stop_on_chat" is specified, stop iterating if the agent says anything """ chatstr = chatstr or "TEST {}".format(d) self.add_incoming_chat(chatstr, self.speaker) self.agent.set_logical_form(d, chatstr, self.speaker) changes = self.flush(max_steps, stop_on_chat=stop_on_chat) if len(self.agent.dialogue_manager.dialogue_stack ) != 0 and answer is not None: self.add_incoming_chat(answer, self.speaker) changes.update(self.flush(max_steps, stop_on_chat=stop_on_chat)) return changes def flush(self, max_steps=10000, stop_on_chat=False) -> Dict[XYZ, IDM]: """Run the agant's step until task and dialogue stacks are empty If "stop_on_chat" is specified, stop iterating if the agent says anything Return the set of blocks that were changed. """ if stop_on_chat: self.agent.clear_outgoing_chats() world_before = self.agent.world.blocks_to_dict() for _ in range(max_steps): self.agent.step() if self.agent_should_stop(stop_on_chat): break # get changes world_after = self.world.blocks_to_dict() changes = dict(set(world_after.items()) - set(world_before.items())) changes.update({ k: (0, 0) for k in set(world_before.keys()) - set(world_after.keys()) }) return changes def agent_should_stop(self, stop_on_chat=False): stop = False if (len(self.agent.dialogue_manager.dialogue_stack) == 0 and not self.agent.memory.task_stack_peek()): stop = True # stuck waiting for answer? if (isinstance(self.agent.dialogue_manager.dialogue_stack.peek(), AwaitResponse) and not self.agent.dialogue_manager.dialogue_stack.peek().finished ): stop = True if stop_on_chat and self.agent.get_last_outgoing_chat(): stop = True return stop def set_looking_at(self, xyz: XYZ): """Set the return value for C++ call to get_player_line_of_sight""" self.agent.get_player_line_of_sight = Mock(return_value=Pos(*xyz)) def set_blocks(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)): self.agent.set_blocks(xyzbms, origin) def add_object(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0), relations={}) -> VoxelObjectNode: return self.agent.add_object(xyzbms=xyzbms, origin=origin, relations=relations) def add_incoming_chat(self, chat: str, speaker_name: str): """Add a chat to memory as if it was just spoken by SPEAKER""" self.world.chat_log.append("<" + speaker_name + ">" + " " + chat) # self.agent.memory.add_chat(self.agent.memory.get_player_by_name(self.speaker).memid, chat) def assert_schematics_equal(self, a, b): """Check equality between two list[(xyz, idm)] schematics N.B. this compares the shapes and idms, but ignores absolute position offsets. """ a, _ = to_relative_pos(a) b, _ = to_relative_pos(b) self.assertEqual(set(a), set(b)) def get_idm_at_locs(self, xyzs: Sequence[XYZ]) -> Dict[XYZ, IDM]: return self.world.get_idm_at_locs(xyzs) def last_outgoing_chat(self) -> str: return self.agent.get_last_outgoing_chat() def get_speaker_pos(self) -> XYZ: return self.agent.memory.get_player_by_name(self.speaker).pos
def setUp(self, agent_opts=None): spec = { "players": [Player(42, "SPEAKER", Pos(5, 63, 5), Look(270, 0), Item(0, 0))], "mobs": [], "ground_generator": flat_ground_generator, "agent": { "pos": (0, 63, 0) }, "coord_shift": (-16, 54, -16), } world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value")) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive() # Combinable actions to be used in test cases self.possible_actions = { "destroy_speaker_look": { "action_type": "DESTROY", "reference_object": { "location": { "location_type": "SPEAKER_LOOK" } }, }, "copy_speaker_look_to_agent_pos": { "action_type": "BUILD", "reference_object": { "location": { "location_type": "SPEAKER_LOOK" } }, "location": { "location_type": "AGENT_POS" }, }, "build_small_sphere": { "action_type": "BUILD", "schematic": { "has_name": "sphere", "has_size": "small" }, }, "build_1x1x1_cube": { "action_type": "BUILD", "schematic": { "has_name": "cube", "has_size": "1 x 1 x 1" }, }, "move_speaker_pos": { "action_type": "MOVE", "location": { "location_type": "SPEAKER_POS" }, }, "build_diamond": { "action_type": "BUILD", "schematic": { "has_name": "diamond" } }, "build_gold_cube": { "action_type": "BUILD", "schematic": { "has_block_type": "gold", "has_name": "cube" }, }, "fill_all_holes_speaker_look": { "action_type": "FILL", "location": { "location_type": "SPEAKER_LOOK" }, "repeat": { "repeat_key": "ALL" }, }, "go_to_tree": { "action_type": "MOVE", "location": { "location_type": "REFERENCE_OBJECT", "reference_object": { "has_name": "tree" }, }, }, "build_square_height_1": { "action_type": "BUILD", "schematic": { "has_name": "square", "has_height": "1" }, }, "stop": { "action_type": "STOP" }, "fill_speaker_look": { "action_type": "FILL", "location": { "location_type": "SPEAKER_LOOK" }, }, "fill_speaker_look_gold": { "action_type": "FILL", "has_block_type": "gold", "location": { "location_type": "SPEAKER_LOOK" }, }, }
class BaseCraftassistTestCase(unittest.TestCase): def setUp(self, agent_opts=None): spec = { "players": [Player(42, "SPEAKER", Pos(5, 63, 5), Look(270, 0), Item(0, 0))], "mobs": [], "ground_generator": flat_ground_generator, "agent": { "pos": (0, 63, 0) }, "coord_shift": (-16, 54, -16), } world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value")) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive() # Combinable actions to be used in test cases self.possible_actions = { "destroy_speaker_look": { "action_type": "DESTROY", "reference_object": { "location": { "location_type": "SPEAKER_LOOK" } }, }, "copy_speaker_look_to_agent_pos": { "action_type": "BUILD", "reference_object": { "location": { "location_type": "SPEAKER_LOOK" } }, "location": { "location_type": "AGENT_POS" }, }, "build_small_sphere": { "action_type": "BUILD", "schematic": { "has_name": "sphere", "has_size": "small" }, }, "build_1x1x1_cube": { "action_type": "BUILD", "schematic": { "has_name": "cube", "has_size": "1 x 1 x 1" }, }, "move_speaker_pos": { "action_type": "MOVE", "location": { "location_type": "SPEAKER_POS" }, }, "build_diamond": { "action_type": "BUILD", "schematic": { "has_name": "diamond" } }, "build_gold_cube": { "action_type": "BUILD", "schematic": { "has_block_type": "gold", "has_name": "cube" }, }, "fill_all_holes_speaker_look": { "action_type": "FILL", "location": { "location_type": "SPEAKER_LOOK" }, "repeat": { "repeat_key": "ALL" }, }, "go_to_tree": { "action_type": "MOVE", "location": { "location_type": "REFERENCE_OBJECT", "reference_object": { "has_name": "tree" }, }, }, "build_square_height_1": { "action_type": "BUILD", "schematic": { "has_name": "square", "has_height": "1" }, }, "stop": { "action_type": "STOP" }, "fill_speaker_look": { "action_type": "FILL", "location": { "location_type": "SPEAKER_LOOK" }, }, "fill_speaker_look_gold": { "action_type": "FILL", "has_block_type": "gold", "location": { "location_type": "SPEAKER_LOOK" }, }, } def handle_logical_form(self, d, chatstr: str = "", answer: str = None, stop_on_chat=False, max_steps=10000) -> Dict[XYZ, IDM]: """Handle a logical form and call self.flush() If "answer" is specified and a question is asked by the agent, respond with this string. If "stop_on_chat" is specified, stop iterating if the agent says anything """ dummy_chat = "TEST {}".format(d) self.add_incoming_chat(dummy_chat, self.speaker) self.agent.set_logical_form(d, dummy_chat, self.speaker) changes = self.flush(max_steps, stop_on_chat=stop_on_chat) if len(self.agent.dialogue_manager.dialogue_stack ) != 0 and answer is not None: self.add_incoming_chat(answer, self.speaker) changes.update(self.flush(max_steps, stop_on_chat=stop_on_chat)) return changes def flush(self, max_steps=10000, stop_on_chat=False) -> Dict[XYZ, IDM]: """Run the agant's step until task and dialogue stacks are empty If "stop_on_chat" is specified, stop iterating if the agent says anything Return the set of blocks that were changed. """ if stop_on_chat: self.agent.clear_outgoing_chats() world_before = self.agent.world.blocks_to_dict() for _ in range(max_steps): self.agent.step() if self.agent_should_stop(stop_on_chat): break # get changes world_after = self.world.blocks_to_dict() changes = dict(set(world_after.items()) - set(world_before.items())) changes.update({ k: (0, 0) for k in set(world_before.keys()) - set(world_after.keys()) }) return changes def agent_should_stop(self, stop_on_chat=False): stop = False if (len(self.agent.dialogue_manager.dialogue_stack) == 0 and not self.agent.memory.task_stack_peek()): stop = True # stuck waiting for answer? if (isinstance(self.agent.dialogue_manager.dialogue_stack.peek(), AwaitResponse) and not self.agent.dialogue_manager.dialogue_stack.peek().finished ): stop = True if stop_on_chat and self.agent.get_last_outgoing_chat(): stop = True return stop def set_looking_at(self, xyz: XYZ): """Set the return value for C++ call to get_player_line_of_sight""" self.agent.get_player_line_of_sight = Mock(return_value=Pos(*xyz)) def set_blocks(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)): self.agent.set_blocks(xyzbms, origin) def add_object(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)) -> ObjectNode: return self.agent.add_object(xyzbms, origin) def add_incoming_chat(self, chat: str, speaker_name: str): """Add a chat to memory as if it was just spoken by SPEAKER""" self.world.chat_log.append("<" + speaker_name + ">" + " " + chat) # self.agent.memory.add_chat(self.agent.memory.get_player_by_name(self.speaker).memid, chat) def assert_schematics_equal(self, a, b): """Check equality between two list[(xyz, idm)] schematics N.B. this compares the shapes and idms, but ignores absolute position offsets. """ a, _ = to_relative_pos(a) b, _ = to_relative_pos(b) self.assertEqual(set(a), set(b)) def get_idm_at_locs(self, xyzs: Sequence[XYZ]) -> Dict[XYZ, IDM]: return self.world.get_idm_at_locs(xyzs) def last_outgoing_chat(self) -> str: return self.agent.get_last_outgoing_chat() def get_speaker_pos(self) -> XYZ: return self.agent.memory.get_player_by_name(self.speaker).pos
class BaseFakeAgentTestCase(unittest.TestCase): def setUp(self, agent_opts=None): spec = {"players": [SimpleHuman(make_human_opts())], "agent": {"pos": (0, 0)}} world_opts = Opt() world_opts.sl = 32 self.world = World(world_opts, spec) self.agent = FakeAgent(self.world, opts=agent_opts) # More helpful error message to encourage test writers to use self.set_looking_at() self.agent.get_player_line_of_sight = Mock( side_effect=NotImplementedError( "Cannot call into C++ function in this unit test. " + "Call self.set_looking_at() to set the return value" ) ) self.speaker = self.agent.get_other_players()[0].name self.agent.perceive() def handle_logical_form( self, d, chatstr: str = "", answer: str = None, stop_on_chat=False, max_steps=10000 ): """Handle a logical form and call self.flush() If "answer" is specified and a question is asked by the agent, respond with this string. If "stop_on_chat" is specified, stop iterating if the agent says anything """ chatstr = chatstr or "TEST {}".format(d) self.add_incoming_chat(chatstr, self.speaker) self.agent.set_logical_form(d, chatstr, self.speaker) changes = self.flush(max_steps, stop_on_chat=stop_on_chat) if len(self.agent.dialogue_manager.dialogue_stack) != 0 and answer is not None: self.add_incoming_chat(answer, self.speaker) new_changes = self.flush(max_steps, stop_on_chat=stop_on_chat) changes[1] = new_changes[1] return changes def flush(self, max_steps=10000, stop_on_chat=False): """Run the agant's step until task and dialogue stacks are empty. If "stop_on_chat" is specified, stop iterating if the agent says anything Return the set of blocks that were changed. """ if stop_on_chat: self.agent.clear_outgoing_chats() world_before = copy.deepcopy(self.agent.world.get_info()) for _ in range(max_steps): self.agent.step() if self.agent_should_stop(stop_on_chat): break # get changes world_after = copy.deepcopy(self.world.get_info()) changes = [world_before, world_after] return changes def agent_should_stop(self, stop_on_chat=False): stop = False if ( len(self.agent.dialogue_manager.dialogue_stack) == 0 and not self.agent.memory.task_stack_peek() ): stop = True # stuck waiting for answer? if ( isinstance(self.agent.dialogue_manager.dialogue_stack.peek(), AwaitResponse) and not self.agent.dialogue_manager.dialogue_stack.peek().finished ): stop = True if stop_on_chat and self.agent.get_last_outgoing_chat(): stop = True return stop def set_looking_at(self, xyz): """Set the return value for C++ call to get_player_line_of_sight; xyz is a tuple of floats.""" self.agent.get_player_line_of_sight = Mock(return_value=xyz) # def add_object(self, xyzbms: List[Block], origin: XYZ = (0, 0, 0)) -> VoxelObjectNode: # return self.agent.add_object(xyzbms, origin) def add_incoming_chat(self, chat: str, speaker_name: str): """Add a chat to memory as if it was just spoken by SPEAKER.""" self.world.chat_log.append("<" + speaker_name + ">" + " " + chat) # self.agent.memory.add_chat(self.agent.memory.get_player_by_name(self.speaker).memid, chat) def last_outgoing_chat(self) -> str: return self.agent.get_last_outgoing_chat() def get_speaker_pos(self): return self.agent.memory.get_player_by_name(self.speaker).pos
opts = Opt() opts.sl = 32 spec = { "players": [Player(42, "SPEAKER", Pos(0, 68, 0), Look(270, 80), Item(0, 0))], "mobs": [SimpleMob(make_mob_opts("cow")), SimpleMob(make_mob_opts("chicken"))], "agent": { "pos": (1, 68, 1) }, "coord_shift": (-opts.sl // 2, 63 - opts.sl // 2, -opts.sl // 2), } world = World(opts, spec) agent = FakeAgent(world, opts=None) speaker_name = agent.get_other_players()[0].name move_speaker_pos = { "action_type": "MOVE", "location": { "location_type": "SPEAKER_POS" } } build_small_sphere = { "action_type": "BUILD", "schematic": { "has_name": "sphere", "has_size": "small" }, }