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
Example #2
0
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
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
Example #4
0
    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"
        },
    }

    build_medium_sphere = {