def perceive(self, force=False):
        # FIXME (low pri) remove these in code, get from sql
        self.agent.pos = to_block_pos(pos_to_np(self.agent.get_player().pos))

        if self.agent.count % self.perceive_freq == 0 or force:
            for mob in self.agent.get_mobs():
                if euclid_dist(self.agent.pos, pos_to_np(
                        mob.pos)) < self.memory.perception_range:
                    self.memory.set_mob_position(mob)
            item_stack_set = set()
            for item_stack in self.agent.get_item_stacks():
                item_stack_set.add(item_stack.entityId)
                if (euclid_dist(self.agent.pos, pos_to_np(item_stack.pos)) <
                        self.memory.perception_range):
                    self.memory.set_item_stack_position(item_stack)
            old_item_stacks = self.memory.get_all_item_stacks()
            if old_item_stacks:
                for old_item_stack in old_item_stacks:
                    memid = old_item_stack[0]
                    eid = old_item_stack[1]
                    if eid not in item_stack_set:
                        self.memory.untag(memid, "_on_ground")
                    else:
                        self.memory.tag(memid, "_on_ground")

        # note: no "force"; these run on every perceive call.  assumed to be fast
        self.update_self_memory()
        self.update_other_players(self.agent.get_other_players())

        # use safe_get_changed_blocks to deal with pointing
        for (xyz, idm) in self.agent.safe_get_changed_blocks():
            self.on_block_changed(xyz, idm)
Example #2
0
def compute_location_heuristic(player_look, player_pos, mems, steps, reldir):
    loc = mems[0].get_pos()
    if reldir is not None:
        steps = steps or DEFAULT_NUM_STEPS
        if reldir == "BETWEEN":
            loc = (np.add(mems[0].get_pos(), mems[1].get_pos())) / 2
            loc = (loc[0], loc[1], loc[2])
        elif reldir == "INSIDE":
            for i in range(len(mems)):
                mem = mems[i]
                locs = heuristic_perception.find_inside(mem)
                if len(locs) > 0:
                    break
            if len(locs) == 0:
                raise ErrorWithResponse("I don't know how to go inside there")
            else:
                loc = locs[0]
        elif reldir == "NEAR":
            pass
        elif reldir == "AROUND":
            pass
        else:  # LEFT, RIGHT, etc...
            reldir_vec = rotation.DIRECTIONS[reldir]
            # this should be an inverse transform so we set inverted=True
            dir_vec = rotation.transform(reldir_vec,
                                         player_look.yaw,
                                         0,
                                         inverted=True)
            loc = steps * np.array(dir_vec) + to_block_center(loc)
    elif steps is not None:
        loc = to_block_center(loc) + [0, 0, steps]
    return to_block_pos(loc)
Example #3
0
 def __init__(self, agent, task_data):
     super(Move, self).__init__()
     if self.finished:
         return
     self.target = to_block_pos(np.array(task_data["target"]))
     self.approx = task_data.get("approx", 1)
     self.path = None
     self.replace = set()
     self.last_stepped_time = agent.memory.get_time()
Example #4
0
    def handle_fill(self, speaker, d) -> Tuple[Optional[str], Any]:
        """This function reads the dictionary, resolves the missing details using memory
        and perception and handles a 'fill' command by either pushing a dialogue object
        or pushing a Fill task to the task stack. 

        Args:
            speaker: speaker_id or name.
            d: the complete action dictionary
        """
        r = d.get("reference_object")
        self.finished = True
        if not r.get("filters"):
            r["filters"] = {"location", SPEAKERLOOK}

        # Get the reference location
        location_d = r["filters"].get("location", SPEAKERLOOK)
        mems = self.subinterpret["reference_locations"](self, speaker, location_d)
        steps, reldir = interpret_relative_direction(self, location_d)
        location, _ = self.subinterpret["specify_locations"](self, speaker, mems, steps, reldir)

        # Get nearby holes
        holes: List[Hole] = heuristic_perception.get_all_nearby_holes(self.agent, location)
        candidates: List[Tuple[XYZ, Hole]] = [
            (to_block_pos(np.mean(hole[0], axis=0)), hole) for hole in holes
        ]

        # Choose the best ones to fill
        repeat = get_repeat_num(d)
        holes = filter_by_sublocation(self, speaker, candidates, r, limit=repeat, loose=True)
        if holes is None:
            self.dialogue_stack.append_new(
                Say, "I don't understand what holes you want me to fill."
            )
            return None, None
        for hole in holes:
            _, hole_info = hole
            poss, hole_idm = hole_info
            # FIXME use filters properly...
            triples = d.get("triples", [])
            block_types = [
                t.get("obj_text") for t in triples if t.get("pred_text", "") == "has_block_type"
            ]
            try:
                fill_idm = get_block_type(block_types[0])
            except:
                fill_idm = hole_idm
            task_data = {"action_dict": d, "schematic": poss, "block_idm": fill_idm}
            self.append_new_task(self.task_objects["fill"], task_data)
        if len(holes) > 1:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill up the holes.")
        else:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill that hole up.")
        self.finished = True
        return None, None
Example #5
0
    def __call__(
            self,
            interpreter,
            speaker,
            mems,
            steps,
            reldir,
            repeat_num=1,
            repeat_dir=None,
            objects=[],
            padding=(1, 1, 1),
            enable_geoscorer=False,
    ):
        agent = interpreter.agent
        repeat_num = max(repeat_num, len(objects))
        player_look = agent.perception_modules[
            "low_level"].get_player_struct_by_name(speaker).look
        player_pos = pos_to_np(agent.get_player().pos)
        speaker_pos = pos_to_np(
            agent.perception_modules["low_level"].get_player_struct_by_name(
                speaker).pos)
        origin = compute_location_heuristic(player_look, player_pos, mems,
                                            steps, reldir)
        agent_geoscorer = agent.on_demand_perception["geoscorer"]
        if enable_geoscorer and agent_geoscorer is not None and agent_geoscorer.use(
                steps, reldir):
            r = agent_geoscorer.radius
            # Use heuristic to get starting point only for for between and inside
            if reldir not in ("BETWEEN", "INSIDE"):
                origin = to_block_pos(mems[0].get_pos())

            minc = (origin[0] - r, origin[1] - r, origin[2] - r)
            maxc = (minc[0] + 2 * r - 1, minc[1] + 2 * r - 1,
                    minc[2] + 2 * r - 1)
            context = agent.get_blocks(minc[0], maxc[0], minc[1], maxc[1],
                                       minc[2], maxc[2])
            origin, offsets = agent_geoscorer.produce_object_positions(
                objects, context, minc, reldir, speaker_pos)
        else:
            if repeat_num > 1:
                schematic = None if len(objects) == 0 else objects[0][0]
                offsets = get_repeat_arrangement(player_look, repeat_num,
                                                 repeat_dir, mems, schematic,
                                                 padding)
            else:
                offsets = [(0, 0, 0)]
        origin = post_process_loc(origin, interpreter)
        offsets = [post_process_loc(o, interpreter) for o in offsets]
        return origin, offsets
Example #6
0
    def handle_fill(self, speaker, d) -> Tuple[Optional[str], Any]:
        r = d.get("reference_object")
        self.finished = True
        if not r.get("filters"):
            r["filters"] = {"location", SPEAKERLOOK}

        # Get the reference location
        location_d = r["filters"].get("location", SPEAKERLOOK)
        mems = interpret_reference_location(self, speaker, location_d)
        steps, reldir = interpret_relative_direction(self, location_d)
        location, _ = compute_locations(self, speaker, mems, steps, reldir)

        # Get nearby holes
        holes: List[Hole] = heuristic_perception.get_all_nearby_holes(self.agent, location)
        candidates: List[Tuple[XYZ, Hole]] = [
            (to_block_pos(np.mean(hole[0], axis=0)), hole) for hole in holes
        ]

        # Choose the best ones to fill
        repeat = get_repeat_num(d)
        holes = filter_by_sublocation(self, speaker, candidates, r, limit=repeat, loose=True)
        if holes is None:
            self.dialogue_stack.append_new(
                Say, "I don't understand what holes you want me to fill."
            )
            return None, None
        for hole in holes:
            _, hole_info = hole
            poss, hole_idm = hole_info
            fill_idm = get_block_type(d["has_block_type"]) if "has_block_type" in d else hole_idm
            task_data = {"action_dict": d, "schematic": poss, "block_idm": fill_idm}
            self.append_new_task(tasks.Fill, task_data)
        if len(holes) > 1:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill up the holes.")
        else:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill that hole up.")
        self.finished = True
        return None, None
Example #7
0
def get_repeat_arrangement(player_look,
                           repeat_num,
                           repeat_dir,
                           ref_mems,
                           schematic=None,
                           padding=(1, 1, 1)):
    shapeparams = {}
    # default repeat dir is LEFT
    if not repeat_dir:
        repeat_dir = "LEFT"
    # eventually fix this to allow number based on shape
    shapeparams["N"] = repeat_num

    if repeat_dir == "AROUND":
        # TODO vertical "around"
        shapeparams["orient"] = "xy"
        shapeparams["extra_space"] = max(padding)
        central_object = ref_mems[0]
        bounds = central_object.get_bounds()
        b = max(bounds[1] - bounds[0], bounds[3] - bounds[2],
                bounds[5] - bounds[4])
        shapeparams["encircled_object_radius"] = b

        offsets = shapes.arrange("circle", schematic, shapeparams)
    else:

        reldir_vec = rotation.DIRECTIONS[repeat_dir]
        # this should be an inverse transform so we set inverted=True
        dir_vec = rotation.transform(reldir_vec,
                                     player_look.yaw,
                                     0,
                                     inverted=True)
        max_ind = np.argmax(dir_vec)
        shapeparams["extra_space"] = padding[max_ind]
        shapeparams["orient"] = dir_vec
        offsets = shapes.arrange("line", schematic, shapeparams)
    offsets = [tuple(to_block_pos(o)) for o in offsets]
    return offsets
Example #8
0
def find_inside(entity):
    """Return a point inside the entity if it can find one.
    TODO: heuristic quick check to find that there aren't any,
    and maybe make this not d^3"""

    # is this a negative object? if yes, just return its mean:
    if hasattr(entity, "blocks"):
        if all(b == (0, 0) for b in entity.blocks.values()):
            m = np.mean(list(entity.blocks.keys()), axis=0)
            return [to_block_pos(m)]
    l = get_locs_from_entity(entity)
    if l is None:
        return []
    m = np.round(np.mean(l, axis=0))
    maxes = np.max(l, axis=0)
    mins = np.min(l, axis=0)
    inside = []
    for x in range(mins[0], maxes[0] + 1):
        for y in range(mins[1], maxes[1] + 1):
            for z in range(mins[2], maxes[2] + 1):
                if check_inside([(x, y, z), entity]):
                    inside.append((x, y, z))
    return sorted(inside, key=lambda x: euclid_dist(x, m))
Example #9
0
def post_process_loc(loc, interpreter):
    return to_block_pos(loc)
Example #10
0
 def target_to_memory(self, target):
     return to_block_pos(np.array(target))
Example #11
0
    def handle_fill(self, speaker, d) -> Tuple[Any, Optional[str], Any]:
        """This function reads the dictionary, resolves the missing details using memory
        and perception and handles a 'fill' command by either pushing a dialogue object
        or pushing a Fill task to the task stack. 

        Args:
            speaker: speaker_id or name.
            d: the complete action dictionary
        """
        tasks = []
        r = d.get("reference_object")
        if not r.get("filters"):
            r["filters"] = {"location", SPEAKERLOOK}

        # Get the reference location
        location_d = r["filters"].get("location", SPEAKERLOOK)
        mems = self.subinterpret["reference_locations"](self, speaker,
                                                        location_d)
        steps, reldir = interpret_relative_direction(self, location_d)
        location, _ = self.subinterpret["specify_locations"](self, speaker,
                                                             mems, steps,
                                                             reldir)

        # Get nearby holes
        holes: List[Hole] = heuristic_perception.get_all_nearby_holes(
            self.agent, location)
        candidates: List[Tuple[XYZ, Hole]] = [
            (to_block_pos(np.mean(hole[0], axis=0)), hole) for hole in holes
        ]

        # Choose the best ones to fill
        repeat = get_repeat_num(d)
        holes = filter_by_sublocation(self,
                                      speaker,
                                      candidates,
                                      r,
                                      limit=repeat,
                                      loose=True)
        if holes is None:
            self.dialogue_stack.append_new(
                Say, "I don't understand what holes you want me to fill.")
            return None, None, None
        tasks = []
        for hole in holes:
            _, hole_info = hole
            poss, hole_idm = hole_info
            schematic, tags = interpret_fill_schematic(self, speaker,
                                                       d.get("schematic", {}),
                                                       poss, hole_idm)
            origin = np.min([xyz for (xyz, bid) in schematic], axis=0)
            task_data = {
                "blocks_list": schematic,
                "force": True,
                "origin": origin,
                "verbose": False,
                "embed": True,
                "fill_message": True,
                "schematic_tags": tags,
            }

            tasks.append(self.task_objects["build"](self.agent, task_data))

        if len(holes) > 1:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill up the holes.")
        else:
            self.dialogue_stack.append_new(Say, "Ok. I'll fill that hole up.")

        return maybe_task_list_to_control_block(tasks, self.agent), None, None