Esempio n. 1
0
class Hull:
    def __init__(self, intc, initial=0):
        self.computer = Intcode(intc, initial)
        self.computer.max_outputs = 2
        self.computer.robot = self
        self.x = 0
        self.y = 0
        self.dir = 'up'  # down right left
        self.map = {}  # dvojice (x, y): barva pocatek je v 0, 0
        self.computer.process()

    def interpret(self, outputs):
        color, direction = outputs
        self.paint(color)
        self.turn_and_move(direction)
        return self.getcolor()

    def paint(self, color):

        self.map[(self.x, self.y)] = color

    def turn_and_move(self, direction):
        '''
        direction the robot should turn: 0 means it should turn left 90 degrees, and 1 means it should turn right 90 degrees.
        '''
        if self.dir == 'up':
            self.dir = 'left' if direction == 0 else 'right'
        elif self.dir == 'down':
            self.dir = 'right' if direction == 0 else 'left'
        elif self.dir == 'left':
            self.dir = 'down' if direction == 0 else 'up'
        elif self.dir == 'right':
            self.dir = 'up' if direction == 0 else 'down'

        if self.dir == 'up':
            self.y -= 1
        elif self.dir == 'down':
            self.y += 1
        elif self.dir == 'right':
            self.x += 1
        elif self.dir == 'left':
            self.x -= 1

    def getcolor(self):
        try:
            return self.map[(self.x, self.y)]
        except KeyError:
            return 0

    def showmap(self):
        l = [str() for _ in range(6)]
        for k, v in sorted(self.map.items()):
            x, y = k
            l[y] += '.' if v == 0 else '#'

        return '\n'.join(l)
Esempio n. 2
0
class Arcade:
    def __init__(self, intc):
        self.comp = Intcode(intc, 0)
        self.comp.max_outputs = 3
        self.comp.robot = self
        self.blocks = []
        self.map = {}
        self.score = 0

        self.comp.process()

    def interpret(self, outputs):
        x, y, tileid = outputs
        tiles = {0: ' ', 1: '#', 2: 'M', 3: '-', 4: 'O'}
        if x == -1 and y == 0:
            self.score = tileid
        else:
            if tileid == 2:
                self.blocks.append((x, y, tileid))
            #build map
            self.map[(x, y)] = tiles.get(tileid)
        #print(self.showmap())

    def provide_input(self):
        # position of joystick 0 neutral, -1 left, 1 right
        print(self.showmap())
        # based on x of tileid 4 and x of tileid 3
        # if x of tileid 4 < x tileid 3, move left (-1)
        # if x of tileid 4 > x tileid 3, move right (1)
        ball_x, ball_y = next(
            ((x, y) for (x, y), tile in self.map.items() if tile == 'O'), None)
        paddle_x, paddle_y = next(
            ((x, y) for (x, y), tile in self.map.items() if tile == '-'), None)
        if ball_x > paddle_x:
            return 1
        elif ball_x < paddle_x:
            return -1

        #return int(input('paddle move (-1 left; 0 no move; 1 right: '))

    def showmap(self):
        # 39x24
        lines = [str() for _ in range(25)]
        for (x, y), value in sorted(self.map.items()):
            lines[y] += str(value)
        return '\n'.join(lines)
Esempio n. 3
0
class Droid:
    def __init__(self, intc):
        self.comp = Intcode(intc)
        self.comp.max_outputs = 1
        self.comp.robot = self
        self.map = defaultdict(unknown)
        self.visited = defaultdict(unknown)
        self.map[(0, 0)] = 1
        self.x = 0
        self.y = 0
        self.sc = 0
        self.input = 1
        self.path = [1]
        self.new_x = 0
        self.new_y = 0
        self.at_start = 0
        self.strings = {
            0: '#',
            1: '.',
            2: 'O',
            3: ' ',
        }

        self.comp.process()

    def showmap(self):
        lines = []
        try:
            xs = [x for (x, y), val in self.map.items()]
            ys = [y for (x, y), val in self.map.items()]
            for y in range(min(ys), max(ys) + 1):
                line = str()
                for x in range(min(xs), max(xs) + 1):
                    if x == 0 and y == 0:
                        line += 'S'
                    elif x == self.x and y == self.y:
                        line += 'X'
                    elif self.visited[(x, y)] == True:
                        line += 'o'
                    else:
                        line += self.strings.get(self.map[(x, y)])
                lines.append(line)
            return '\n'.join(lines)
        except ValueError:
            pass

    @property
    def last(self):
        if self.sc == 0:
            #naposledy jsme sli posledni element path
            return self.path[-1]
        else:
            #naposledy jsem sli self.input
            return self.input

    @property
    def left(self):
        if self.last == 1: return 3
        if self.last == 2: return 4
        if self.last == 3: return 2
        if self.last == 4: return 1

    @property
    def right(self):
        if self.last == 1: return 4
        if self.last == 2: return 3
        if self.last == 3: return 1
        if self.last == 4: return 2

    @property
    def head(self):
        return self.last

    @property
    def back(self):
        if self.last == 1: return 2
        if self.last == 2: return 1
        if self.last == 3: return 4
        if self.last == 4: return 3

    def interpret(self, outputs):
        '''
        0 wall did not change position,
        1 has moved in direction
        2 has moved in direction
            new position is the location of the oxygen system
        3 land of unknown
        '''
        # na pozici self.input je self.sc... co dal? left-hand rule wall follower
        self.sc = outputs[0]
        # zanes do mapy souradnice a status code
        self.map[(self.new_x, self.new_y)] = self.sc
        if self.sc in (1, 2):
            # hnuli jsme se v input smeru
            self.x = self.new_x
            self.y = self.new_y
            self.path.append(self.input)
        if self.x == 0 and self.y == 0:
            self.at_start += 1

    def where(self):
        '''
        navrhuje na zaklade aktualni pozice a okolnich bodu,
        jakym smerem se dat
        wall follower left-hand rule
        jdu dopredu (n) pokud to jde a kontroluju zed na levo
        pokud na levo neni zed, jdu na levo
        '''
        if self.at_start > 2: return None

        dirs = {
            1: self.map[(self.x, self.y + 1)],
            2: self.map[(self.x, self.y - 1)],
            3: self.map[(self.x + 1, self.y)],
            4: self.map[(self.x - 1, self.y)]
        }

        if dirs.get(self.left) == 3:
            return self.left
        if dirs.get(self.left) == 0 and dirs.get(self.head) == 0 and dirs.get(
                self.right) == 0:
            return self.back
        if dirs.get(self.left) == 0 and dirs.get(self.head) == 0:
            return self.right
        if dirs.get(self.left) == 0:
            return self.head

        if dirs.get(self.left) == 1:
            return self.left

    def provide_input(self):
        '''
        1 north
        2 south
        3 west
        4 east
        '''
        #print(self.map)
        print(self.showmap())
        self.input = self.where()
        #print(f'moving {self.input}')

        if self.input == 1:  # north
            self.new_y = self.y + 1
            self.new_x = self.x
        elif self.input == 2:  # south
            self.new_y = self.y - 1
            self.new_x = self.x
        elif self.input == 3:  # west
            self.new_x = self.x + 1
            self.new_y = self.y
        elif self.input == 4:  # east
            self.new_x = self.x - 1
            self.new_y = self.y
        return self.input

    def calc_distance(self):
        src = (0, 0)
        self.visited[src] = True
        q = [(src, 0)]
        while q:
            (x, y), distance = q.pop(0)
            print(self.showmap())
            if self.map[(x, y)] == 2:
                return distance
            # enqueue adjacent cells if is valid, has path and not visited yet
            north = (x, y + 1)
            south = (x, y - 1)
            west = (x - 1, y)
            east = (x + 1, y)
            for cell in [north, south, west, east]:
                if self.map[cell] in (1, 2) and self.visited[cell] is not True:
                    self.visited[cell] = True
                    q.append((cell, distance + 1))

    @property
    def oxygen(self):
        for (x, y), sc in self.map.items():
            if sc == 2:
                return (x, y)

    @property
    def number_of_cells(self):
        return len([cell for cell, sc in self.map.items() if sc in (1, 2)])

    @property
    def number_of_cells_visited(self):
        return len([cell for cell, sc in self.visited.items() if sc == True])

    def get_max_distance(self):
        src = self.oxygen
        self.visited = defaultdict(unknown)
        self.visited[src] = True
        q = [(src, 0)]
        dst = 0
        while q:
            (x, y), distance = q.pop(0)
            print(self.showmap())
            if distance > dst: dst = distance
            if self.number_of_cells_visited == self.number_of_cells:
                return dst

            north = (x, y + 1)
            south = (x, y - 1)
            west = (x - 1, y)
            east = (x + 1, y)
            for cell in [north, south, west, east]:
                if self.map[cell] in (1, 2) and self.visited[cell] is not True:
                    self.visited[cell] = True
                    q.append((cell, distance + 1))