Ejemplo n.º 1
0
 def __init__(self, tape=None):
     self.inputs = []
     if tape is not None:
         self.computer = Interpreter(tape)
         self.computer.set_uplink_to(self)
     self.board = None
     self.amount_of_dust = 0
Ejemplo n.º 2
0
 def program(self, program):
     if isinstance(program, Tape):
         self._program = program
         # computer is the Repair Droid
         self.computer = Interpreter(self._program, self.outputs)
         self.computer.set_uplink_to(self)
     else:
         raise ValueError(f"Can not set program from object of type {type(program)}")
Ejemplo n.º 3
0
 def __init__(self, program, canvas):
     self.program = program
     self.verbose = False
     self.inputs = []
     self.outputs = []
     self.computer = Interpreter(self.program, self.outputs)
     #self.computer.verbose = self.verbose
     self.computer.set_uplink_to(self)
     self.canvas = canvas
     self.operations = [self.do_paint, self.do_turn]
     self.current_operation_index = -1
     self.turns = [[-1, 0], [0, 1], [1, 0], [0, -1]]  # up,right,down,left
     self.turns_index = 0
     self.running = 0  # (0,1) idle,running
     self.num_iterations = 0
     self.on_paint = None
Ejemplo n.º 4
0
class BoardBuilder(object):
    def __init__(self, tape=None):
        self.inputs = []
        if tape is not None:
            self.computer = Interpreter(tape)
            self.computer.set_uplink_to(self)
        self.board = None
        self.amount_of_dust = 0

    def execute(self):
        rows = []
        row = []

        while not self.computer.finished:
            self.computer.execute()

            while len(self.inputs) > 0:
                code = self.inputs.pop(0)

                if code > 127:
                    # Here we catch the value that is not the image pixel but the amount
                    # of dust the robot has collected, as per the instruction:
                    # > Once the cleanong robot finishes the programmed set of movements
                    # > it will return to its docking station and report the amount of space
                    # > dust it collected as a large, non-ASCII value in a single output
                    # > instruction.
                    self.amount_of_dust = code
                else:
                    ch = chr(code)
                    print(ch, end='', flush=True)

                    if chr(code) == '\n':
                        if len(row) > 0:
                            rows.append(row)
                        row = []
                    else:
                        row.append(code)

        self.board = Board()
        self.board.matrix = np.array(rows)

        return self.board
Ejemplo n.º 5
0
    def execute(self, beam):
        self.beam = beam
        readings = []

        for self.coord in self.positions():
            if self.finished():
                break

            y,x = self.coord
            self._vprint(f"Position: {(x,y)}")

            tape = Tape(self.tape)
            tape.rewind() # TODO: necessary?

            computer = Interpreter(tape, inputs=[x,y], outputs=readings)
            computer.execute()
            if readings.pop(0) == 1:
                self.beam.add((y,x))

            self._vprint(str(self.beam))
Ejemplo n.º 6
0
class RemoteControl(object):

    # movement instructions to the RepairDroid
    NORTH, SOUTH, WEST, EAST = 1, 2, 3, 4
    MOVEMENTS = [NORTH, SOUTH, WEST, EAST]

    # Status codes received from the RepairDroid, describing what the current position is
    WALL  = 0 # The repair droid hit a wall. Its position has not changed.
    EMPTY = 1 # The repair droid has moved one step in the requested direction.
    GOAL  = 2 # The repair droid has moved one step in the requested direction;
              # its new position is the location of the oxygen system (GOAL).

    def __init__(self, program=None):
        self.computer = None
        self._program = None
        self.inputs = []
        self.outputs = []
        if program is not None:
            self.program = program
        self.verbose = False
        self.show_progress = False
        self.board = None
        self.goal_found = False

    @property
    def movement_commands(self):
        """
        This is just an alias that allows to think in domain terms
        """
        return self.outputs

    @property
    def droid_status_codes(self):
        """
        This is just an alias that allows to think in domain terms
        """
        return self.inputs

    @property
    def program(self):
        return self._program

    @program.setter
    def program(self, program):
        if isinstance(program, Tape):
            self._program = program
            # computer is the Repair Droid
            self.computer = Interpreter(self._program, self.outputs)
            self.computer.set_uplink_to(self)
        else:
            raise ValueError(f"Can not set program from object of type {type(program)}")

    def execute(self):
        self._vprint("RemoteControl running")

        while not self.finished:
            # repair droid accepts a movement instruction (0-4) and outputs status code (0-3)

            self.generate_movement_instruction()
            self.computer.execute()
            self.interpret_status_code()

            if self.show_progress:
                msg  = "---------- Board state ----------\n"
                msg += self.board.visualize()
                msg += "\n---------------------------------"
                print(msg)

    @property
    def finished(self):
        #return self.goal_found
        return self.goal_found and self.board.player == self.board.origin

    def generate_movement_instruction(self):
        """
        Decide where to move and put corresponding code into <movement_commands>.
        """

        # prefer an UNKNOWN cell over any other
        # if there are no unknown cells remaining, choose an OPEN path
        # TODO: when choosing an OPEN path, disfavour the one from where we have come
        moves = [(self.board[self.attempted_position(mc)], mc) for mc in self.MOVEMENTS]
        for g in [Board.UNKNOWN, Board.OPEN]:
            _moves = [m for m in moves if m[0] == g]
            if len(_moves) > 0:
                self.movement_command = random.choice(_moves)[1]
                break

        self.movement_commands.append(self.movement_command)
        self._vprint(f"State of movement commands (remote control -> droid): {self.movement_commands}")

    def interpret_status_code(self):
        """
        Interpret the status code from the repair droid
        """
        self._vprint(f"Droid is at {self.board.player} (distance: {self.board.distance_to(self.board.player)}) and emits status code: {self.droid_status_codes}")
        code = self.droid_status_codes.pop(0)

        pos = self.attempted_position()

        if code == self.WALL:
            self.board.mark_as(pos, Board.WALL)
            self._mark_dead_end_path()

        elif code == self.EMPTY:
            self.board.mark_as(pos, Board.OPEN)
            self._mark_dead_end_path()
            self.board.move_player_to(pos)

        elif code == self.GOAL:
            self.board.move_player_to(pos)
            self.board.mark_as(pos, Board.GOAL)
            self.goal_found = True

        else:
            raise ValueError(f"Illegal code received from Repair Droid: {code}")

    def _mark_dead_end_path(self):
        """
        Inspect current player position and mark is as DEADEND.
        Doing this will help us direct the droid at subsequent steps by preventing
        the the droid is sent in the direction of a DEADEND.
        """

        if self.board.is_dead_end(self.board.player):
            self.board.mark_as(self.board.player, Board.DEADEND)

    def attempted_position(self, mc=None):
        """
        Position to which the Repair Droid attempted to move
        """
        mc = mc or self.movement_command

        if   mc == self.NORTH: return self.board.north_of()
        elif mc == self.SOUTH: return self.board.south_of()
        elif mc == self.WEST:  return self.board.west_of()
        elif mc == self.EAST:  return self.board.east_of()
        else:
            raise ValueError("Oh shit")

    def _vprint(self, msg):
        if self.verbose:
            print(msg)
Ejemplo n.º 7
0
class PaintingRobot(object):
    # robots language
    BLACK = 0
    WHITE = 1

    TLEFT = 0
    TRIGHT = 1

    def __init__(self, program, canvas):
        self.program = program
        self.verbose = False
        self.inputs = []
        self.outputs = []
        self.computer = Interpreter(self.program, self.outputs)
        #self.computer.verbose = self.verbose
        self.computer.set_uplink_to(self)
        self.canvas = canvas
        self.operations = [self.do_paint, self.do_turn]
        self.current_operation_index = -1
        self.turns = [[-1, 0], [0, 1], [1, 0], [0, -1]]  # up,right,down,left
        self.turns_index = 0
        self.running = 0  # (0,1) idle,running
        self.num_iterations = 0
        self.on_paint = None

    def move_to(self, pos):
        self.position = pos

    def execute(self):

        if self.running == 0:
            self.running = 1
            color = self.canvas[self.position]
            self.outputs.append(color)
            self._vprint(
                f"Robot starts over cell {self.position} of color {color}:\n{self._show_canvas()}"
            )

        while True:
            self.num_iterations += 1
            self._vprint(
                f"[Iteration #{self.num_iterations}] State of input buffer: {self.inputs}"
            )

            if len(self.inputs) == 2:
                self.do_paint(self.inputs.pop(0))
                self.do_turn(self.inputs.pop(0))
                color = self.canvas[self.position]
                self._vprint(
                    f"Robot ends up over cell {self.position} of color {color}:\n{self._show_canvas()}"
                )
                self.outputs.append(color)

            elif len(self.inputs) > 2:
                self._vprint(
                    "OOPS: too many instructions in the robots input buffer")

            self._vprint(
                f"Running computer with inputs {self.computer.inputs} ({self.computer.status})"
            )
            self.computer.execute()

            if self.computer.finished:
                self._vprint(f"Finished: {self.computer.finished}")
                break

    def read_input(self):
        code = None
        if len(self.inputs) > 0:
            code = self.inputs.pop(0)
        return arg

    def do_paint(self, color=None):
        _oldcolor = self.canvas[self.position]
        if color is None:
            color = self.inputs.pop(0)
        self.canvas[self.position] = color
        if self.on_paint is not None:
            self.on_paint(self.position, _oldcolor, color)
        self._vprint(f"Painting {self.position} from {_oldcolor} to {color}")

    def do_turn(self, code=None):
        """
        Turn acccording to the instruction and move one step
        """
        if code is None:
            code = self.inputs.pop(0)

        if code == 0: self.turns_index -= 1
        elif code == 1: self.turns_index += 1

        if self.turns_index < 0: self.turns_index = 3
        elif self.turns_index > 3: self.turns_index = 0

        step = self.turns[self.turns_index]
        self.position = (self.position[0] + step[0],
                         self.position[1] + step[1])
        self._vprint(
            f"Turn code {code}, turns index {self.turns_index} is {step}, end up in {self.position}"
        )

    def _set_current_operation(self):
        self.current_operation_index += 1
        if self.current_operation_index >= len(self.operations):
            self.current_operation_index = 0
        self.current_operation = self.operations[self.current_operation_index]

    def _vprint(self, msg):
        if self.verbose:
            print(msg, file=sys.stderr)

    def _show_canvas(self):
        kopy = np.copy(self.canvas)
        kopy[self.position] = 5
        kopy = np.array2string(kopy, max_line_width=10000)
        return kopy