Пример #1
0
class Layout:
    """
    A Layout manages the static information about the game board.
    """
    def __init__(self, layout_text):
        self.width = len(layout_text[0])
        self.height = len(layout_text)
        self.walls = Grid(self.width, self.height, False)
        self.food = Grid(self.width, self.height, False)
        self.capsules = []
        self.agent_positions = []
        self.num_ghosts = 0
        self.process_layout_text(layout_text)
        self.layout_text = layout_text
        self.total_food = len(self.food.as_list())
        # self.initialize_visibility_matrix()

    def get_num_ghosts(self):
        return self.num_ghosts

    def initialize_visibility_matrix(self):
        global VISIBILITY_MATRIX_CACHE
        if reduce(str.__add__,
                  self.layout_text) not in VISIBILITY_MATRIX_CACHE:
            from game import Directions
            vecs = [(-0.5, 0), (0.5, 0), (0, -0.5), (0, 0.5)]
            dirs = [
                Directions.NORTH, Directions.SOUTH, Directions.WEST,
                Directions.EAST
            ]
            vis = Grid(
                self.width, self.height, {
                    Directions.NORTH: set(),
                    Directions.SOUTH: set(),
                    Directions.EAST: set(),
                    Directions.WEST: set(),
                    Directions.STOP: set()
                })
            for x in range(self.width):
                for y in range(self.height):
                    if self.walls[x][y] == False:
                        for vec, direction in zip(vecs, dirs):
                            dx, dy = vec
                            nextx, nexty = x + dx, y + dy
                            while (nextx + nexty) != int(nextx) + \
                                    int(nexty) or not self.walls[int(nextx)][int(nexty)]:
                                vis[x][y][direction].add((nextx, nexty))
                                nextx, nexty = x + dx, y + dy
            self.visibility = vis
            VISIBILITY_MATRIX_CACHE[reduce(str.__add__,
                                           self.layout_text)] = vis
        else:
            self.visibility = VISIBILITY_MATRIX_CACHE[reduce(
                str.__add__, self.layout_text)]

    def is_wall(self, pos):
        x, col = pos
        return self.walls[x][col]

    def get_random_legal_position(self):
        x = random.choice(range(self.width))
        y = random.choice(range(self.height))
        while self.is_wall((x, y)):
            x = random.choice(range(self.width))
            y = random.choice(range(self.height))
        return (x, y)

    def get_random_corner(self):
        poses = [(1, 1), (1, self.height - 2), (self.width - 2, 1),
                 (self.width - 2, self.height - 2)]
        return random.choice(poses)

    def get_furthest_corner(self, pac_pos):
        poses = [(1, 1), (1, self.height - 2), (self.width - 2, 1),
                 (self.width - 2, self.height - 2)]
        dist, pos = max([(manhattan_distance(p, pac_pos), p) for p in poses])
        return pos

    def is_visible_from(self, ghost_pos, pac_pos, pac_direction):
        row, col = [int(x) for x in pac_pos]
        return ghost_pos in self.visibility[row][col][pac_direction]

    def __str__(self):
        return "\n".join(self.layout_text)

    def deep_copy(self):
        return Layout(self.layout_text[:])

    def process_layout_text(self, layout_text):
        """
        Coordinates are flipped from the input format to the (x,y) convention here

        The shape of the maze.  Each character
        represents a different type of object.
         % - Wall
         . - Food
         o - Capsule
         G - Ghost
         P - Pacman
        Other characters are ignored.
        """
        max_y = self.height - 1
        for y in range(self.height):
            for x in range(self.width):
                layout_char = layout_text[max_y - y][x]
                self.process_layout_char(x, y, layout_char)
        self.agent_positions.sort()
        self.agent_positions = [(i == 0, pos)
                                for i, pos in self.agent_positions]

    def process_layout_char(self, x, y, layout_char):
        if layout_char == '%':
            self.walls[x][y] = True
        elif layout_char == '.':
            self.food[x][y] = True
        elif layout_char == 'o':
            self.capsules.append((x, y))
        elif layout_char == 'P':
            self.agent_positions.append((0, (x, y)))
        elif layout_char in ['G']:
            self.agent_positions.append((1, (x, y)))
            self.num_ghosts += 1
        elif layout_char in ['1', '2', '3', '4']:
            self.agent_positions.append((int(layout_char), (x, y)))
            self.num_ghosts += 1