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)
    def test_move_here(self):
        d = MOVE_COMMANDS["move here"]
        self.handle_logical_form(d)

        # check that agent moved
        self.assertLessEqual(
            euclid_dist(self.agent.pos, self.get_speaker_pos()), 1)
    def test_build_sphere_move_here(self):
        d = COMBINED_COMMANDS["build a small sphere then move here"]
        changes = self.handle_logical_form(d)

        # check that a small object was built
        self.assertGreater(len(changes), 0)
        self.assertLess(len(changes), 30)

        # check that agent moved
        self.assertLessEqual(
            euclid_dist(self.agent.pos, self.get_speaker_pos()), 1)
    def test_stop(self):
        # start moving
        target = (20, 63, 20)
        d = MOVE_COMMANDS["move to 20 63 20"]
        self.handle_logical_form(d, max_steps=5)

        # stop
        d = OTHER_COMMANDS["stop"]
        self.handle_logical_form(d)

        # assert that move did not complete
        self.assertGreater(euclid_dist(self.agent.pos, target), 1)
 def is_placed_block_interesting(self, xyz: XYZ,
                                 bid: int) -> Tuple[bool, bool, bool]:
     """Return three values:
     - bool: is the placed block interesting?
     - bool: is it interesting because it was placed by a player?
     - bool: is it interesting because it was placed by the agent?
     """
     interesting = False
     player_placed = False
     agent_placed = False
     # TODO record *which* player placed it
     if xyz in self.pending_agent_placed_blocks:
         interesting = True
         agent_placed = True
     for player_struct in self.agent.get_other_players():
         if (euclid_dist(pos_to_np(player_struct.pos), xyz) < 5
                 and player_struct.mainHand.id == bid):
             interesting = True
             if not agent_placed:
                 player_placed = True
     if bid not in BORING_BLOCKS:
         interesting = True
     return interesting, player_placed, agent_placed
示例#6
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))
示例#7
0
def check_between(entities, fat_scale=0.2):
    """ Heuristic check if entities[0] is between entities[1] and entities[2]
    by checking if the locs of enitity[0] are in the convex hull of
    union of the max cardinal points of entity[1] and entity[2]"""
    locs = []
    means = []
    for e in entities:
        l = get_locs_from_entity(e)
        if l is not None:
            locs.append(l)
            means.append(np.mean(l, axis=0))
        else:
            # this is not a thing we know how to assign 'between' to
            return False
    mean_separation = euclid_dist(means[1], means[2])
    fat = fat_scale * mean_separation
    bounding_locs = []
    for l in locs:
        if len(l) > 1:
            bl = []
            idx = np.argmax(l, axis=0)
            for i in range(3):
                f = np.zeros(3)
                f[i] = fat
                bl.append(np.array(l[idx[i]]) + fat)
            idx = np.argmin(l, axis=0)
            for i in range(3):
                f = np.zeros(3)
                f[i] = fat
                bl.append(np.array(l[idx[i]]) - fat)
            bounding_locs.append(np.vstack(bl))
        else:
            bounding_locs.append(np.array(l))
    x = np.mean(bounding_locs[0], axis=0)
    points = np.vstack([bounding_locs[1], bounding_locs[2]])
    return in_hull(points, x)
    def test_move_coordinates(self):
        d = MOVE_COMMANDS["move to -7 63 -8"]
        self.handle_logical_form(d)

        # check that agent moved
        self.assertLessEqual(euclid_dist(self.agent.pos, (-7, 63, -8)), 1)
 def test_action_sequence_order(self):
     d = COMBINED_COMMANDS["move to 3 63 2 then 7 63 7"]
     self.handle_logical_form(d)
     self.assertLessEqual(euclid_dist(self.agent.pos, (7, 63, 7)), 1)
示例#10
0
    def test_come_here(self):
        chat = "come here"
        self.add_incoming_chat(chat, self.speaker)
        self.flush()

        self.assertLessEqual(euclid_dist(self.agent.pos, self.get_speaker_pos()), 1)
def filter_by_sublocation(
    interpreter,
    speaker,
    candidates: List[Tuple[XYZ, T]],
    d: Dict,
    limit=1,
    all_proximity=10,
    loose=False,
) -> List[Tuple[XYZ, T]]:
    """Select from a list of candidate (xyz, object) tuples given a sublocation

    If limit == 'ALL', return all matching candidates

    Returns a list of (xyz, mem) tuples
    """
    F = d.get("filters")
    assert F is not None, "no filters".format(d)
    location = F.get("location", SPEAKERLOOK)
    if limit == 1:
        limit = get_repeat_num(d)

    # handle SPEAKER_LOOK separately due to slightly different semantics
    # (proximity to ray instead of point)
    if location.get("location_type") == "SPEAKER_LOOK":
        player_struct = interpreter.agent.perception_modules[
            "low_level"].get_player_struct_by_name(speaker)
        return object_looked_at(interpreter.agent,
                                candidates,
                                player_struct,
                                limit=limit,
                                loose=loose)

    reldir = location.get("relative_direction")
    if reldir:
        if reldir == "INSIDE":
            if location.get("reference_object"):
                # this is ugly, should probably return from interpret_reference_location...
                ref_mems = interpret_reference_object(
                    interpreter, speaker, location["reference_object"])
                for l, candidate_mem in candidates:
                    if heuristic_perception.check_inside(
                        [candidate_mem, ref_mems[0]]):
                        return [(l, candidate_mem)]
            raise ErrorWithResponse("I can't find something inside that")
        elif reldir == "AWAY":
            raise ErrorWithResponse("I don't know which object you mean")
        elif reldir == "NEAR":
            pass  # fall back to no reference direction
        elif reldir == "BETWEEN":
            mems = interpret_reference_location(interpreter, speaker, location)
            steps, reldir = interpret_relative_direction(interpreter, d)
            ref_loc, _ = compute_locations(interpreter, speaker, mems, steps,
                                           reldir)
            candidates.sort(key=lambda c: euclid_dist(c[0], ref_loc))
            return candidates[:limit]
        else:
            # reference object location, i.e. the "X" in "left of X"
            mems = interpret_reference_location(interpreter, speaker, location)
            ref_loc = mems[0].get_pos()

            # relative direction, i.e. the "LEFT" in "left of X"
            reldir_vec = rotation.DIRECTIONS[reldir]

            # transform each object into the speaker look coordinate system,
            # and project onto the reldir vector
            look = (interpreter.agent.perception_modules["low_level"].
                    get_player_struct_by_name(speaker).look)
            proj = [
                rotation.transform(np.array(l) - ref_loc, look.yaw, 0)
                @ reldir_vec for (l, _) in candidates
            ]

            # filter by relative dir, e.g. "left of Y"
            proj_cands = [(p, c) for (p, c) in zip(proj, candidates) if p > 0]

            # "the X left of Y" = the right-most X that is left of Y
            if limit == "ALL":
                limit = len(proj_cands)
            return [c for (_, c) in sorted(proj_cands, key=lambda p: p[0])
                    ][:limit]
    else:  # is it even possible to end up in this branch? FIXME?
        # no reference direction: choose the closest
        mems = interpret_reference_location(interpreter, speaker, location)
        steps, reldir = interpret_relative_direction(interpreter, d)
        ref_loc, _ = compute_locations(interpreter, speaker, mems, steps,
                                       reldir)
        if limit == "ALL":
            return list(
                filter(lambda c: euclid_dist(c[0], ref_loc) <= all_proximity,
                       candidates))
        else:
            candidates.sort(key=lambda c: euclid_dist(c[0], ref_loc))
            return candidates[:limit]
    return []  # this fixes flake but seems awful?