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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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
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