Exemple #1
0
    def dig_in_direction(self, direction: Direction):
        """Try digging towards a direction"""
        dig_mapping = {
            Direction.up: turtle.digUp,
            Direction.down: turtle.digDown,
            Direction.front: turtle.dig
        }

        if direction not in dig_mapping:
            raise ValueError(f"You can't dig in the direction: {direction}")

        # Actually dig the block
        try:
            lua_errors.run(dig_mapping[direction])
        except lua_errors.UnbreakableBlockError as e:
            e.direction = direction
            raise e

        # Mark all slots as unconfirmed, since we don't know where that material
        # moved to
        self.inventory.mark_all_slots_unconfirmed()

        # Since the block was successfully removed, remove it as a potential
        # obstacle in the map.
        with self.state as state:
            map = state.map.read()
            obstacle_position = math_utils.coordinate_in_turtle_direction(
                curr_pos=map.position,
                curr_angle=map.direction,
                direction=direction)
            map.remove_obstacle(obstacle_position)
            state.map.write(map)
Exemple #2
0
    def place_in_direction(self, direction: Direction):
        place_mapping = {
            Direction.up: turtle.placeUp,
            Direction.down: turtle.placeDown,
            Direction.front: turtle.place
        }
        if direction not in place_mapping:
            raise ValueError(f"You can't place in the direction: {direction}")

        lua_errors.run(place_mapping[direction])

        # Track the change in inventory, since no errors occurred
        self.inventory.selected.refresh()
Exemple #3
0
    def drop_in_direction(self, direction: Direction, amount=None):
        drop_mapping = {
            Direction.up: turtle.dropUp,
            Direction.down: turtle.dropDown,
            Direction.front: turtle.drop
        }

        if direction not in drop_mapping:
            raise ValueError(f"You can't drop in the direction: {direction}")

        lua_errors.run(drop_mapping[direction], amount)

        # Now that items have been potentially dropped, update the inventory:
        self.inventory.selected.refresh()
Exemple #4
0
    def suck_in_direction(self, direction: Direction, amount=None):
        suck_mapping = {
            Direction.up: turtle.suckUp,
            Direction.down: turtle.suckDown,
            Direction.front: turtle.suck
        }

        if direction not in suck_mapping:
            raise ValueError(f"You can't suck in the direction: {direction}")

        lua_errors.run(suck_mapping[direction], amount=amount)

        # Mark all slots as unconfirmed, since we don't know where that material
        # moved to
        self.inventory.mark_all_slots_unconfirmed()
Exemple #5
0
    def __init__(self):
        # First, ensure state is retrieved via GPS initially
        gps_loc = gps.locate()
        if gps_loc is None:
            raise StateRecoveryError(
                "The turtle must have a wireless modem and be "
                "within range of GPS satellites!")

        self.computer_id = lua_errors.run(os.getComputerID)
        self.state = StateFile(computer_id=self.computer_id)
        """Representing (x, y, z) positions"""
        """Direction on the XZ plane in degrees. A value between 0-360 """
        self.state.map = StateAttr(self.state, "map",
                                   Map(position=gps_loc, direction=0))
        self.direction_verified = False
        """This is set to True if the Turtle ever moves and is able to verify 
        that the angle it thinks is pointing is actually the angle it is 
        pointing. It uses GPS to verify two points before and after a move to 
        do this. """

        self.inventory = Inventory.from_turtle(selected_slot=1)
        """This will scan the entire inventory and record the contents, and 
        leave the turtle with selected_slot selected"""

        self._maybe_recover_location(gps_loc)
Exemple #6
0
    def move_in_direction(self, direction: Direction):
        """Move forwards or backwards in the sign of direction"""
        direction_mapping = {
            Direction.front: turtle.forward,
            Direction.back: turtle.back,
            Direction.up: turtle.up,
            Direction.down: turtle.down,
        }
        if direction not in direction_mapping:
            raise ValueError(f"You can't move in the direction: {direction}")

        map = self.state.map.read()
        old_position = map.position
        new_position = math_utils.coordinate_in_turtle_direction(
            curr_pos=map.position,
            curr_angle=map.direction,
            direction=direction)

        with self.state as state:

            try:
                lua_errors.run(direction_mapping[direction])
            except lua_errors.TurtleBlockedError as e:
                # TODO: Think of something smart to do when direction isn't
                #   verified but the turtle is still blocked!
                map.add_obstacle(new_position)
                state.map.write(map)
                e.direction = direction
                raise e

            horizontal_dirs = (Direction.front, Direction.back)
            if not self.direction_verified and direction in horizontal_dirs:
                gps_position = gps.locate()
                # If the move_sign is negative, flip the order of to/from
                # to represent a move backwards
                sign = 1 if direction is Direction.front else -1
                to_from = (old_position, gps_position)[::sign]
                verified_direction = math_utils.get_angle(*to_from)
                new_position = gps_position
                map.direction = verified_direction

                # Flag the turtle as super verified and ready to roll
                self.direction_verified = True

            map.move_to(new_position)
            state.map.write(map)
Exemple #7
0
    def turn_degrees(self, degrees: int):
        """Turn `degrees` amount. The direction is determined by the sign.
        Only 90, 0, or -90 is allowed. 0 performs nothing
        """
        if degrees == 0:
            return
        if degrees not in (90, -90):
            raise ValueError(f"Invalid value for degrees! {degrees}")
        map = self.state.map.read()
        map.direction = (map.direction + degrees) % 360

        with self.state:
            if degrees == 90:
                lua_errors.run(turtle.turnRight)
            elif degrees == -90:
                lua_errors.run(turtle.turnLeft)
            self.state.map.write(map)
Exemple #8
0
    def inspect_in_direction(self, direction: Direction) \
            -> Optional[Dict[bytes, bytes]]:
        inspect_mapping = {
            Direction.up: turtle.inspectUp,
            Direction.down: turtle.inspectDown,
            Direction.front: turtle.inspect
        }

        if direction not in inspect_mapping:
            raise ValueError(
                f"You can't inspect in the direction: {direction}")

        return lua_errors.run(inspect_mapping[direction])
Exemple #9
0
def maybe_refuel(nav_turtle: NavigationTurtle, refuel_spot, destructive=False):
    """Top off fuel if necessary. This function roughly predicts the distance to
    refuel and decides if it's necessary to refuel"""
    fuel_level = lua_errors.run(turtle.getFuelLevel)

    if fuel_level < TURTLE_FUEL_LIMIT * 0.5:
        # Whether we are consuming fuel or getting it from a chest, we always
        # want to do so from the fuel slot
        nav_turtle.select(FUEL_SLOT)

        if nav_turtle.inventory.selected.count > 1:
            nav_turtle.refuel(1)

        # Go grab fuel
        nav_turtle.move_toward(to_pos=refuel_spot, destructive=destructive)
        nav_turtle.suck_in_direction(Direction.down, end_step=False)
        nav_turtle.inventory.slot(FUEL_SLOT).refresh()
Exemple #10
0
    def __init__(self, computer_id: int = None):
        self.dict = None
        """When being held, this shows all the key/value pairs of state"""

        self._last_saved_dict = None
        """Used to prevent saving to the StateFile when it's deemed unnecessary
        """

        self.being_held = 0
        """When this hits 0 on __exit__, all things are saved to the file"""

        computer_id = computer_id or lua_errors.run(os.getComputerID)
        self._state_path = STATE_DIR / str(computer_id) / STATE_FILE
        """The location to cache all the turtles states. The reason the 
        CC filesystem isn't used is because it's unreliable during program 
        startup and shutdown, leading to inconsistent states."""
        self._state_path.parent.mkdir(exist_ok=True, parents=True)
Exemple #11
0
 def refuel(self, fuel_amount):
     lua_errors.run(turtle.refuel, fuel_amount)
     self.inventory.selected.refresh()
Exemple #12
0
 def select(self, slot_id):
     if self.inventory.selected.slot_id is not slot_id:
         lua_errors.run(turtle.select, slot_id)
         self.inventory.selected_id = slot_id