Пример #1
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        current_row, current_col = (randrange(1, self.H,
                                              2), randrange(1, self.W, 2))
        grid[current_row][current_col] = 0
        active = self._find_neighbors(current_row, current_col, grid, True)
        active = [(current_row, current_col)]

        # continue until you have no more neighbors to move to
        while active:
            if random() < self.backtrack_chance:
                current_row, current_col = active[-1]
            else:
                current_row, current_col = choice(active)

            # find a visited neighbor
            next_neighbors = self._find_neighbors(current_row, current_col,
                                                  grid, True)
            if len(next_neighbors) == 0:
                active = [a for a in active if a != (current_row, current_col)]
                continue

            nn_row, nn_col = choice(next_neighbors)
            active += [(nn_row, nn_col)]

            grid[nn_row][nn_col] = 0
            grid[(current_row + nn_row) // 2][(current_col + nn_col) // 2] = 0

        return grid
Пример #2
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        # choose a random starting position
        current_row, current_col = randrange(1, self.H, 2), randrange(1, self.W, 2)
        grid[current_row][current_col] = 0

        # created a weighted list of all vertices connected in the graph
        neighbors = self._find_neighbors(current_row, current_col, grid, True)

        # loop over all current neighbors, until empty
        visited = 1

        while visited < self.h * self.w:
            # find neighbor with lowest weight, make it current
            nn = randrange(len(neighbors))
            current_row, current_col = neighbors[nn]
            visited += 1
            grid[current_row][current_col] = 0
            neighbors = neighbors[:nn] + neighbors[nn + 1:]
            # connect that neighbor to a random neighbor with grid[posi] == 0
            nearest_n = self._find_neighbors(current_row, current_col, grid)[0]
            grid[(current_row + nearest_n[0]) // 2][(current_col + nearest_n[1]) // 2] = 0

            # find all unvisited neighbors of current, add them to neighbors
            unvisited = self._find_neighbors(current_row, current_col, grid, True)
            neighbors = list(set(neighbors + unvisited))

        return grid
Пример #3
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        # The first row is always empty, because you can't carve North
        for col in range(1, self.W - 1):
            grid[1][col] = 0

        # loop through the remaining rows and columns
        for row in range(3, self.H, 2):
            # create a run of cells
            run = []

            for col in range(1, self.W, 2):
                # remove the wall to the current cell
                grid[row][col] = 0
                # add the current cell to the run
                run.append((row, col))

                carve_east = random() > self.skew
                # carve East or North (can't carve East into the East wall
                if carve_east and col < (self.W - 2):
                    grid[row][col + 1] = 0
                else:
                    north = choice(run)
                    grid[north[0] - 1][north[1]] = 0
                    run = []

        return grid
Пример #4
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(0)
        # fill borders
        a[0, :] = a[-1, :] = 1
        a[:, 0] = a[:, -1] = 1
        grid = a

        # adjust complexity and density relative to maze size
        if self.complexity <= 1.0:
            self.complexity = self.complexity * 10 * (self.H + self.W)
        if self.density <= 1.0:
            self.density = self.density * (self.h * self.w)

        # create walls
        for i in range(int(self.density)):
            y, x = randrange(0, self.H, 2), randrange(0, self.W, 2)
            grid[y][x] = 1
            for j in range(int(self.complexity)):
                neighbors = self._find_neighbors(y, x, grid, True)  # is wall
                if len(neighbors) > 0 and len(neighbors) < 5:
                    neighbors = self._find_neighbors(y, x, grid)  # is open
                    if not len(neighbors):
                        continue
                    r, c = choice(neighbors)
                    if grid[r][c] == 0:
                        grid[r][c] = 1
                        grid[r + (y - r) // 2][c + (x - c) // 2] = 1
                        x, y = c, r

        return grid
Пример #5
0
    def generate(self):
        # create empty grid, with walls
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        crow = randrange(1, self.H, 2)
        ccol = randrange(1, self.W, 2)
        track = [(crow, ccol)]
        grid[crow][ccol] = 0

        while track:
            (crow, ccol) = track[-1]
            neighbors = self._find_neighbors(crow, ccol, grid, True)

            if len(neighbors) == 0:
                track = track[:-1]
            else:
                nrow, ncol = neighbors[0]
                grid[nrow][ncol] = 0
                grid[(nrow + crow) // 2][(ncol + ccol) // 2] = 0

                track += [(nrow, ncol)]

        return grid
Пример #6
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        forest = []
        for row in range(1, self.H - 1, 2):
            for col in range(1, self.W - 1, 2):
                forest.append([(row, col)])
                grid[row][col] = 0

        edges = []
        for row in range(2, self.H - 1, 2):
            for col in range(1, self.W - 1, 2):
                edges.append((row, col))
        for row in range(1, self.H - 1, 2):
            for col in range(2, self.W - 1, 2):
                edges.append((row, col))

        shuffle(edges)

        while len(forest) > 1:
            ce_row, ce_col = edges[0]
            edges = edges[1:]

            tree1 = -1
            tree2 = -1

            if ce_row % 2 == 0:  # even-numbered row: vertical wall
                tree1 = sum([
                    i if (ce_row - 1, ce_col) in j else 0
                    for i, j in enumerate(forest)
                ])
                tree2 = sum([
                    i if (ce_row + 1, ce_col) in j else 0
                    for i, j in enumerate(forest)
                ])
            else:  # odd-numbered row: horizontal wall
                tree1 = sum([
                    i if (ce_row, ce_col - 1) in j else 0
                    for i, j in enumerate(forest)
                ])
                tree2 = sum([
                    i if (ce_row, ce_col + 1) in j else 0
                    for i, j in enumerate(forest)
                ])

            if tree1 != tree2:
                new_tree = forest[tree1] + forest[tree2]
                temp1 = list(forest[tree1])
                temp2 = list(forest[tree2])
                forest = [x for x in forest
                          if x != temp1]  # faster than forest.remove(temp1)
                forest = [x for x in forest if x != temp2]
                forest.append(new_tree)
                grid[ce_row][ce_col] = 0

        return grid
Пример #7
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        grid = self.sub_gen(grid)

        return grid
Пример #8
0
    def generate(self):
        # create empty grid
        grid = np.empty((self.H, self.W), dtype=np.int8)
        grid.fill(0)
        # fill borders
        grid[0, :] = grid[-1, :] = 1
        grid[:, 0] = grid[:, -1] = 1

        region_stack = [((1, 1), (self.H - 2, self.W - 2))]

        while region_stack:
            current_region = region_stack[-1]
            region_stack = region_stack[:-1]
            min_y = current_region[0][0]
            max_y = current_region[1][0]
            min_x = current_region[0][1]
            max_x = current_region[1][1]
            height = max_y - min_y + 1
            width = max_x - min_x + 1

            if height <= 1 or width <= 1:
                continue

            if width < height:
                cut_direction = HORIZONTAL  # with 100% chance
            elif width > height:
                cut_direction = VERTICAL    # with 100% chance
            else:
                if width == 2: continue
                cut_direction = randrange(2)

            # make cut
            #   select cut position (can't be completely on the edge of the region)
            cut_length = (height, width)[(cut_direction + 1) % 2]
            if cut_length < 3: continue
            cut_posi = randrange(1, cut_length, 2)
            #   select new door position
            door_posi = randrange(0, (height, width)[cut_direction], 2)
            #   add walls to correct places
            if cut_direction == 0: # vertical
                for row in range(min_y, max_y + 1):
                    grid[row, min_x + cut_posi] = 1
                grid[min_y + door_posi, min_x + cut_posi] = 0
            else: # horizontal
                for col in range(min_x, max_x + 1):
                    grid[min_y + cut_posi, col] = 1
                grid[min_y + cut_posi, min_x + door_posi] = 0

            #   add new regions to stack
            if cut_direction == 0:  # vertical
                region_stack.append(((min_y, min_x), (max_y, min_x + cut_posi - 1)))
                region_stack.append(((min_y, min_x + cut_posi + 1), (max_y, max_x)))
            else: # horizontal
                region_stack.append(((min_y, min_x), (min_y + cut_posi - 1, max_x)))
                region_stack.append(((min_y + cut_posi + 1, min_x), (max_y, max_x)))

        return grid
Пример #9
0
    def generate(self):
        # create empty grid
        grid = np.empty((self.H, self.W), dtype=np.int8)
        grid.fill(0)
        # fill borders
        grid[0, :] = grid[-1, :] = 1
        grid[:, 0] = grid[:, -1] = 1

        region_stack = [((1, 1), (self.H - 2, self.W - 2))]

        while region_stack:
            current_region = region_stack[-1]
            region_stack = region_stack[:-1]
            min_y = current_region[0][0]
            max_y = current_region[1][0]
            min_x = current_region[0][1]
            max_x = current_region[1][1]
            height = max_y - min_y + 1
            width = max_x - min_x + 1

            if height <= 1 or width <= 1:
                continue

            if width < height:
                cut_direction = HORIZONTAL  # with 100% chance
            elif width > height:
                cut_direction = VERTICAL    # with 100% chance
            else:
                if width == 2: continue
                cut_direction = randrange(2)

            # make cut
            #   select cut position (can't be completely on the edge of the region)
            cut_length = (height, width)[(cut_direction + 1) % 2]
            if cut_length < 3: continue
            cut_posi = randrange(1, cut_length, 2)
            #   select new door position
            door_posi = randrange(0, (height, width)[cut_direction], 2)
            #   add walls to correct places
            if cut_direction == 0: # vertical
                for row in range(min_y, max_y + 1):
                    grid[row, min_x + cut_posi] = 1
                grid[min_y + door_posi, min_x + cut_posi] = 0
            else: # horizontal
                for col in range(min_x, max_x + 1):
                    grid[min_y + cut_posi, col] = 1
                grid[min_y + cut_posi, min_x + door_posi] = 0

            #   add new regions to stack
            if cut_direction == 0:  # vertical
                region_stack.append(((min_y, min_x), (max_y, min_x + cut_posi - 1)))
                region_stack.append(((min_y, min_x + cut_posi + 1), (max_y, max_x)))
            else: # horizontal
                region_stack.append(((min_y, min_x), (min_y + cut_posi - 1, max_x)))
                region_stack.append(((min_y + cut_posi + 1, min_x), (max_y, max_x)))

        return grid
Пример #10
0
    def generate(self):
        # create empty grid, with walls
        grid = np.empty((self.H, self.W), dtype=np.int8)
        grid.fill(1)

        for row in range(1, self.H, 2):
            for col in range(1, self.W, 2):
                grid[row][col] = 0
                neighbor_row, neighbor_col = self._find_neighbor(row, col)
                grid[neighbor_row][neighbor_col] = 0

        return grid
Пример #11
0
    def generate(self):
        # create empty grid, with walls
        grid = np.empty((self.H, self.W), dtype=np.int8)
        grid.fill(1)

        for row in range(1, self.H, 2):
            for col in range(1, self.W, 2):
                grid[row][col] = 0
                neighbor_row, neighbor_col = self._find_neighbor(row, col)
                grid[neighbor_row][neighbor_col] = 0

        return grid
Пример #12
0
    def _create_grid_from_sets(self, sets):
        """ translate the maze sets into a maze grid """
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(0)
        grid = a

        for r in range(self.H):
            for c in range(self.W):
                if sets[r][c] == -1:
                    grid[r][c] = 1

        return grid
Пример #13
0
    def generate(self):
        """ highest-level method that implements the maze-generating algorithm

        Returns:
            np.array: returned matrix
        """
        # create empty grid, with walls
        grid = np.empty((self.H, self.W), dtype=np.int8)
        grid.fill(1)

        for row in range(1, self.H, 2):
            for col in range(1, self.W, 2):
                grid[row][col] = 0
                neighbor_row, neighbor_col = self._find_neighbor(row, col)
                grid[neighbor_row][neighbor_col] = 0

        return grid
Пример #14
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        # find an arbitrary starting position
        current_row, current_col = (randrange(1, self.H, 2), randrange(1, self.W, 2))
        grid[current_row][current_col] = 0

        # perform many random walks, to fill the maze
        num_trials = 0
        while (current_row, current_col) != (-1, -1):
            self._walk(grid, current_row, current_col)
            current_row, current_col = self._hunt(grid, num_trials)
            num_trials += 1

        return grid
Пример #15
0
    def generate(self):
        # create empty grid
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        # find an arbitrary starting position
        grid[randrange(1, self.H, 2)][randrange(1, self.W, 2)] = 0
        num_visited = 1
        row, col = self._hunt(grid, num_visited)

        # perform many random walks, to fill the maze
        while row != -1 and col != -1:
            walk = self._generate_random_walk(grid, (row, col))
            num_visited += self._solve_random_walk(grid, walk, (row, col))
            (row, col) = self._hunt(grid, num_visited)

        return grid
Пример #16
0
    def generate(self):
        # create empty grid, with walls
        a = np.empty((self.H, self.W), dtype=np.dtype('i'))
        a.fill(-1)
        sets = a

        # initialize the first row cells to each exist in their own set
        max_set_number = 0

        # process all but the last row
        for r in range(1, self.H - 1, 2):
            max_set_number = self._init_row(sets, r, max_set_number)
            self._merge_one_row(sets, r)
            self._merge_down_a_row(sets, r)

        # process last row
        max_set_number = self._init_row(sets, self.H - 2, max_set_number)
        self._process_last_row(sets)

        # translate grid cell sets into a maze
        return self._create_grid_from_sets(sets)
Пример #17
0
    def __init__(self, h0, w0, rooms=None, grid=None, hunt_order='random'):
        # if the user provides a grid, that overrides h & w
        if grid is not None:
            h = (grid.shape[0] - 1) // 2
            w = (grid.shape[1] - 1) // 2
            self.backup_grid = grid.copy()
        else:
            h = h0
            w = w0
            a = np.empty((2 * h + 1, 2 * w + 1), dtype=np.int8)
            a.fill(1)
            self.backup_grid = a
        self.grid = None
        self.rooms = rooms
        super(DungeonRooms, self).__init__(h, w)

        # the user can define what order to hunt for the next cell in
        if hunt_order == 'random':
            self._hunt_order = self._hunt_random
        elif hunt_order == 'serpentine':
            self._hunt_order = self._hunt_serpentine
        else:
            self._hunt_order = self._hunt_random
Пример #18
0
    def generate(self):
        # create empty grid, with walls
        a = np.empty((self.H, self.W), dtype=np.int8)
        a.fill(1)
        grid = a

        crow = randrange(1, self.H, 2)
        ccol = randrange(1, self.W, 2)
        grid[crow][ccol] = 0
        num_visited = 1

        while num_visited < self.h * self.w:
            # find neighbors
            neighbors = self._find_neighbors(crow, ccol, grid, True)

            # how many neighbors have already been visited?
            if len(neighbors) == 0:
                # mark random neighbor as current
                (crow, ccol) = choice(self._find_neighbors(crow, ccol, grid))
                continue

            # loop through neighbors
            for nrow, ncol in neighbors:
                if grid[nrow][ncol] > 0:
                    # open up wall to new neighbor
                    grid[(nrow + crow) // 2][(ncol + ccol) // 2] = 0
                    # mark neighbor as visited
                    grid[nrow][ncol] = 0
                    # bump the number visited
                    num_visited += 1
                    # current becomes new neighbor
                    crow = nrow
                    ccol = ncol
                    # break loop
                    break

        return grid