def test_destroy_that(self):
        d = DESTROY_COMMANDS["destroy where I am looking"]
        self.handle_logical_form(d)

        # Check that cube_right is destroyed
        self.assertEqual(
            set(self.get_idm_at_locs(strip_idmeta(self.cube_right)).values()), set([(0, 0)])
        )
Example #2
0
 def post_process(m):
     if (m.__class__.__name__ == "BlockObjectNode"
             or m.__class__.__name__ == "ComponentObjectNode"):
         m_pos = to_block_pos(
             np.mean(strip_idmeta(m.blocks.items()), axis=0))
     elif m.__class__.__name__ == "InstSegNode":
         m_pos = to_block_pos(np.mean(m.locs, axis=0))
     else:
         return None
     return (m_pos, m)
Example #3
0
    def test_destroy_that(self):
        d = {
            "dialogue_type": "HUMAN_GIVE_COMMAND",
            "action": self.possible_actions["destroy_speaker_look"],
        }
        self.handle_logical_form(d)

        # Check that cube_right is destroyed
        self.assertEqual(
            set(self.get_idm_at_locs(strip_idmeta(self.cube_right)).values()),
            set([(0, 0)]))
Example #4
0
    def test_destroy_that(self):
        d = {
            "dialogue_type": "HUMAN_GIVE_COMMAND",
            "action": {
                "action_type": "DESTROY",
                "reference_object": {
                    "location": {
                        "location_type": "SPEAKER_LOOK"
                    }
                },
            },
        }
        self.handle_action_dict(d)

        # Check that cube_right is destroyed
        self.assertEqual(
            set(self.get_blocks(strip_idmeta(self.cube_right)).values()),
            set([(0, 0)]))
Example #5
0
    def __init__(self, agent, task_data, featurizer=None):
        super(Destroy, self).__init__(featurizer=featurizer)
        self.schematic = task_data["schematic"]  # list[(xyz, idm)]
        self.xyz_remaining = set(util.strip_idmeta(self.schematic))
        self.dig_message = True if "dig_message" in task_data else False

        # is it destroying a whole block object? if so, save its tags
        self.destroyed_block_object_triples = []
        mem = agent.memory.get_block_object_by_xyz(next(iter(self.xyz_remaining)))
        if mem and all(xyz in self.xyz_remaining for xyz in mem.blocks.keys()):
            for pred in ["has_tag", "has_name", "has_colour"]:
                self.destroyed_block_object_triples.extend(
                    agent.memory.get_triples(subj=mem.memid, pred=pred)
                )
            logging.info(
                "Destroying block object {} tags={}".format(
                    mem.memid, self.destroyed_block_object_triples
                )
            )
Example #6
0
    def step(self, agent):
        self.interrupted = False

        # get blocks occupying build area
        ox, oy, oz = self.origin
        sy, sz, sx, _ = self.schematic.shape
        current = agent.get_blocks(ox, ox + sx - 1, oy, oy + sy - 1, oz, oz + sz - 1)

        # save state for undo()
        if self.old_blocks_list is None:
            self.old_blocks_list = npy_to_blocks_list(current, self.origin)
            if len(self.old_blocks_list) > 0:
                self.old_origin = np.min(util.strip_idmeta(self.old_blocks_list), axis=0)

        # are we done?
        # TODO: diff ignores block meta right now because placing stairs and
        # chests in the appropriate orientation is non-trivial
        diff = (
            (current[:, :, :, 0] != self.schematic[:, :, :, 0])
            & (self.attempts > 0)
            & np.isin(current[:, :, :, 0], BUILD_IGNORE_BLOCKS, invert=True)
        )
        if self.embed:
            diff &= self.schematic[:, :, :, 0] != 0  # don't delete blocks
        for pair in BUILD_INTERCHANGEABLE_PAIRS:
            diff &= np.isin(current[:, :, :, 0], pair, invert=True) | np.isin(
                self.schematic[:, :, :, 0], pair, invert=True
            )
        if not np.any(diff):
            self.finish(agent)
            return

        # blocks that would need to be removed
        remove_mask = diff & (current[:, :, :, 0] != 0)

        # destroy any blocks in the way first
        rel_yzxs = np.argwhere(remove_mask)
        xyzs = [
            (x + self.origin[0], y + self.origin[1], z + self.origin[2]) for (y, z, x) in rel_yzxs
        ]
        if xyzs:
            logging.info("Excavating {} blocks first".format(len(xyzs)))
            agent.memory.task_stack_push(
                Destroy(agent, {"schematic": util.fill_idmeta(agent, xyzs)}),
                parent_memid=self.memid,
            )
            return

        # get next block to place
        yzx = self.get_next_target(agent, current, diff)
        idm = self.schematic[tuple(yzx)]
        current_idm = current[tuple(yzx)]

        # try placing block
        target = yzx[[2, 0, 1]] + self.origin
        logging.debug("trying to place {} @ {}".format(idm, target))
        if tuple(target) in (tuple(agent.pos), tuple(agent.pos + [0, 1, 0])):
            # can't place block where you're standing, so step out of the way
            self.step_any_dir(agent)
            return
        if util.manhat_dist(agent.pos, target) <= self.PLACE_REACH:
            # block is within reach
            assert current_idm[0] != idm[0], "current={} idm={}".format(current_idm, idm)
            if current_idm[0] != 0:
                logging.debug(
                    "removing block {} @ {} from {}".format(current_idm, target, agent.pos)
                )
                agent.dig(*target)
            if idm[0] != 0:
                agent.set_held_item(idm)
                logging.debug("placing block {} @ {} from {}".format(idm, target, agent.pos))
                x, y, z = target
                if agent.place_block(x, y, z):
                    B = agent.get_blocks(x, x, y, y, z, z)
                    if B[0, 0, 0, 0] == idm[0]:
                        agent.memory.pending_agent_placed_blocks.add((x, y, z))
                    else:
                        logging.error(
                            "failed to place block {} @ {}, but place_block returned True. \
                                Got {} instead.".format(
                                idm, target, B[0, 0, 0, :]
                            )
                        )
                    self.new_blocks.append(((x, y, z), idm))
                else:
                    logging.warn("failed to place block {} from {}".format(target, agent.pos))
            self.attempts[tuple(yzx)] -= 1
            if self.attempts[tuple(yzx)] == 0 and not self.giving_up_message_sent:
                agent.send_chat(
                    "I'm skipping a block because I can't place it. Maybe something is in the way."
                )
                self.giving_up_message_sent = True
        else:
            # too far to place; move first
            task = Move(agent, {"target": target, "approx": self.PLACE_REACH}, self.featurizer)
            agent.memory.task_stack_push(task, parent_memid=self.memid)
 def post_process(objs):
     obj_poss = [
         to_block_pos(np.mean(strip_idmeta(b.blocks.items()), axis=0))
         for b in objs
     ]
     return list(zip(obj_poss, objs))
Example #8
0
    def __init__(self, agent, task_data):
        super(Build, self).__init__()
        self.task_data = task_data
        self.embed = task_data.get("embed", False)
        self.schematic, _ = blocks_list_to_npy(task_data["blocks_list"])
        self.origin = task_data["origin"]
        self.verbose = task_data.get("verbose", True)
        self.relations = task_data.get("relations", [])
        self.default_behavior = task_data.get("default_behavior")
        self.force = task_data.get("force", False)
        self.attempts = 3 * np.ones(self.schematic.shape[:3], dtype=np.uint8)
        self.fill_message = task_data.get("fill_message", False)
        self.schematic_memid = task_data.get("schematic_memid", None)
        self.schematic_tags = task_data.get("schematic_tags", [])
        self.giving_up_message_sent = False
        self.wait = False
        self.old_blocks_list = None
        self.old_origin = None
        self.PLACE_REACH = task_data.get("PLACE_REACH", 3)

        # negative schematic related
        self.is_destroy_schm = task_data.get("is_destroy_schm", False)
        self.dig_message = task_data.get("dig_message", False)
        self.blockobj_memid = None
        self.DIG_REACH = task_data.get("DIG_REACH", 3)
        self.last_stepped_time = agent.memory.get_time()

        if self.is_destroy_schm:
            # is it destroying a whole block object? if so, save its tags
            self.destroyed_block_object_triples = []
            xyzs = set(util.strip_idmeta(task_data["blocks_list"]))
            mem = agent.memory.get_block_object_by_xyz(next(iter(xyzs)))
            # TODO what if there are several objects being destroyed?
            if mem and all(xyz in xyzs for xyz in mem.blocks.keys()):
                for pred in ["has_tag", "has_name", "has_colour"]:
                    self.destroyed_block_object_triples.extend(
                        agent.memory.get_triples(subj=mem.memid,
                                                 pred_text=pred))
                logging.info("Destroying block object {} tags={}".format(
                    mem.memid, self.destroyed_block_object_triples))

        # modify the schematic to avoid placing certain blocks
        for bad, good in BUILD_BLOCK_REPLACE_MAP.items():
            self.schematic[self.schematic[:, :, :, 0] == bad] = good
        self.new_blocks = []  # a list of (xyz, idm) of newly placed blocks

        # snap origin to ground if bottom level has dirt blocks
        # NOTE(kavyasrinet): except for when we are rebuilding the old dirt blocks, we
        # don't want to change the origin then, hence the self.force check.
        if not self.force and not self.embed and np.isin(
                self.schematic[:, :, :, 0], (2, 3)).any():
            h = ground_height(agent, self.origin, 0)
            self.origin[1] = h[0, 0]

        # get blocks occupying build area and save state for undo()
        ox, oy, oz = self.origin
        sy, sz, sx, _ = self.schematic.shape
        current = agent.get_blocks(ox, ox + sx - 1, oy, oy + sy - 1, oz,
                                   oz + sz - 1)
        self.old_blocks_list = npy_to_blocks_list(current, self.origin)
        if len(self.old_blocks_list) > 0:
            self.old_origin = np.min(util.strip_idmeta(self.old_blocks_list),
                                     axis=0)