def clear_floor(self, x, y, w, h): for room_x in range(x - 1, x + w + 1): for room_y in range(y - 1, y + h + 1): try: create_floor(self.game_map, room_x, room_y) except: pass
def create_tunnel(self, point1, point2, current_cave, map_width, map_height): # run a heavily weighted random Walk # from point1 to point1 print('create_tunnel random walk') drunkard_x = point2[0] drunkard_y = point2[1] while (drunkard_x, drunkard_y) not in current_cave: # ==== Choose Direction ==== north = 1.0 south = 1.0 east = 1.0 west = 1.0 weight = 1 # weight the random walk against edges if drunkard_x < point1[0]: # drunkard is left of point1 east += weight elif drunkard_x > point1[0]: # drunkard is right of point1 west += weight if drunkard_y < point1[1]: # drunkard is above point1 south += weight elif drunkard_y > point1[1]: # drunkard is below point1 north += weight # normalize probabilities so they form a range from 0 to 1 total = north + south + east + west north /= total south /= total east /= total west /= total # choose the direction choice = random() if 0 <= choice < north: dx = 0 dy = -1 elif north <= choice < (north + south): dx = 0 dy = 1 elif (north + south) <= choice < (north + south + east): dx = 1 dy = 0 else: dx = -1 dy = 0 # ==== Walk ==== # check collision at edges if (0 < drunkard_x + dx < map_width - 1) and (0 < drunkard_y + dy < map_height - 1): drunkard_x += dx drunkard_y += dy if self.game_map.is_blocked(drunkard_x, drunkard_y): create_floor(self.game_map, drunkard_x, drunkard_y)
def generate_level(self, game_map, dungeon_level, max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, particles, particle_systems, item_table, mob_table): # Creates an empty 2D array or clears existing array self.walk_iterations = max(self.walk_iterations, (map_width * map_height * 10)) self.game_map = game_map self.dungeon_level = dungeon_level self.radius = max(map_width // 10, map_height // 10) self.random_walk_x = randint(self.radius, map_width - self.radius - 1) self.random_walk_y = randint(self.radius, map_height - self.radius - 1) # Modify Percent Goal Depending on Dungeon Level self._percentGoal = 0.1 + (self.dungeon_level * 0.015) self.filledGoal = map_width * map_height * self._percentGoal # Place Player at 1st Location # TODO: Sometimes player spawns inside a wall? x, y = self.random_walk_x, self.random_walk_y player.position.x, player.position.y = x, y self.game_map.tile_cost[y][x] = 99 create_floor(game_map, x, y) self.encounters.append((x, y)) for i in range(self.walk_iterations): self.walk(map_width, map_height) # Check for Encounter if self._filled % self.encounter_interval == 0: if self.encounter_within_proximity(self.random_walk_x, self.random_walk_y): if self.radius < self.random_walk_x < map_width - self.radius and self.radius < self.random_walk_y < map_height - self.radius: room = Circle(game_map, self.random_walk_x, self.random_walk_y, self.radius, len(game_map.rooms) + 1) game_map.rooms.append(room) place_entities(self.game_map, self.dungeon_level, room, entities, item_table, mob_table) self.encounters.append( (self.random_walk_x, self.random_walk_y)) else: # TODO: Find a way to not allow multiple iteration checks for encounter_within_proximity # Note: The below line is a lie. We're not really filling up more spaces. self._filled += 1 if self._filled >= self.filledGoal: break # Place Stairs at Last Location place_stairs(game_map, self.dungeon_level, self.random_walk_x, self.random_walk_y)
def clean_up_map(self, map_width, map_height): if self.smooth_edges: for i in range(0, 5): # Look at each cell individually and check for smoothness for x in range(2, map_width - 2): for y in range(2, map_height - 2): if self.game_map.is_blocked( x, y) and self.get_adjacent_walls_simple( x, y) <= self.smoothing: create_floor(self.game_map, x, y)
def get_caves(self, map_width, map_height): # locate all the caves within self.game_map.tiles and store them in self.caves # print('locate all the caves within self.game_map.tiles and store them in self.caves') for x in range(1, map_width - 1): for y in range(1, map_height - 1): if not self.game_map.is_blocked(x, y): self.flood_fill(x, y) for tile_set in self.caves: for x, y in tile_set: create_floor(self.game_map, x, y) # check for 2 that weren't changed. """
def generate_castle_entrance(self): x = self.end_area.x y = self.end_area.y w = self.end_area.width h = self.end_area.height self.create_walled_room(x - w // 2, y, w, h, False) for _y in range(y + 1, y + w - 1): place_tile(self.game_map, _y + (x - w // 2), 0, "47") for i in range(1 + x - w // 2, x + w // 2): place_tile(self.game_map, i, y + h - 1, "35") create_floor(self.game_map, x, y + h - 1) for i in range(1 + x - w // 2, x + w // 2): create_floor(self.game_map, i, y + h)
def generate_door(self, x, y, w, h, entities, particles): # Door poss_locations = [] # Top poss_locations.extend((i, y) for i in range(x + 1, x + w - 1)) # # Bottom poss_locations.extend((i, y + h - 1) for i in range(x + 1, x + w - 1)) # # Left poss_locations.extend((x, j) for j in range(y + 1, y + h - 1)) # # Right poss_locations.extend((x + w - 1, j) for j in range(y + 1, y + h - 1)) # print('poss_locations:', poss_locations) # Two Doors shuffle(poss_locations) if randint(0, 4) == 1: door_x, door_y = poss_locations.pop() # print('door:', door_x, door_y) create_floor(self.game_map, door_x, door_y) door_index = "5" door_stats = TILESET.get(door_index) generate_object(door_x, door_y, entities, self.game_map.map_objects, particles, self.game_map, door_stats, door_index, item_list=None) door_x, door_y = poss_locations.pop() # print('door:', door_x, door_y) create_floor(self.game_map, door_x, door_y) door_index = "5" door_stats = TILESET.get(door_index) generate_object(door_x, door_y, entities, self.game_map.map_objects, particles, self.game_map, door_stats, door_index, item_list=None) return door_x, door_y
def assign_tiles(self, mold=False): # Assign Tiles from Grid for x in range(self.width): for y in range(self.height): if self.grid[x][y] == 1: if randint(0, 6) == 1 and mold: place_tile(self.game_map, x, y, '46') # normal tree else: place_tile(self.game_map, x, y, '13') # moldfy tree elif self.grid[x][y] == 0: if randint(0, 4) == 1: place_tile(self.game_map, x, y, '44') # normal grass elif randint(0, 6) == 1 and mold: place_tile(self.game_map, x, y, '45') # fungus grass else: create_floor(self.game_map, x, y)
def create_caves(self, map_width, map_height): # ==== Create distinct caves ==== for i in range(0, self.iterations): # Pick a random point with a buffer around the edges of the map tile_x = randint(2, map_width - 3) # (2,map_width-3) tile_y = randint(2, map_height - 3) # (2,map_height-3) # if the cell's neighboring walls > self.neighbors, set it to 1 if self.get_adjacent_walls(tile_x, tile_y) > self.neighbors: # self.game_map.tiles[tile_x][tile_y] = 1 create_wall(self.game_map, tile_x, tile_y) # or set it to 0 elif self.get_adjacent_walls(tile_x, tile_y) < self.neighbors: create_floor(self.game_map, tile_x, tile_y) # ==== Clean Up Map ==== self.clean_up_map(map_width, map_height)
def generate_level(self, game_map, dungeon_level, max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, item_table, mob_table): # def generate_level(self, game_map, map_width, map_height): # Creates an empty 2D array or clears existing array self.game_map = game_map self.dungeon_level = dungeon_level self.map_width = map_width self.map_height = map_height print('Random Fill Map') self.random_fill_map(map_width, map_height) print('Create Caves') self.create_caves(map_width, map_height) print('Get Caves') self.get_caves(map_width, map_height) print('Connect Caves') self.connect_caves(map_width, map_height) print('Clean Up Map') self.clean_up_map(map_width, map_height) # Find Center of Caves print('find_cave_centers') self.find_cave_centers() # Check if Caves were Actually Generation, Recall Same Generation if not self.cave_centers: print('Couldn\'t generate caves. Restarting...') self.reset_generation() entities = [player] self.generate_level(game_map, dungeon_level, max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, item_table, mob_table) return False # Place Player and Stairs, Open Floor # TODO: Connect caves 1 and 2 player.position.x, player.position.y = self.cave_centers[0].center create_floor(game_map, player.position.x, player.position.y) x, y = self.cave_centers[-1].center entities.append(place_stairs(self.dungeon_level, x, y)) create_floor(game_map, x, y) # TODO: Ensure there is a path for player and path to stairs # Spawn Entities for cave in self.cave_centers: place_entities(game_map, dungeon_level, cave, entities, item_table, mob_table) # debug find centers # cx, cy = cave.center # print('cave center at: (%s, %s)' % (cx, cy)) create_floor(game_map, cave.x, cave.y) # create_floor(game_map, cave.x, cave.y) # print('cave center at: (%s, %s)' % (cave.x, cave.y)) self.print_generation_stats(entities)
def create_walled_room(self, room_x, room_y, room_width, room_height, ruined=True): # Sets Tiles in to Become Passable, but add walls around for x in range(room_x, room_x + room_width): for y in range(room_y, room_y + room_height): if x == room_x or \ x == room_x + room_width - 1 or \ y == room_y or \ y == room_y + room_height - 1: if ruined: if randint(0, 100) < 80: create_wall(self.game_map, x, y) else: create_wall(self.game_map, x, y) else: if ruined and randint(0, 100) < 25: create_floor(self.game_map, x, y) else: place_tile(self.game_map, x, y, "47")
def create_v_tunnel(game_map, y1, y2, x): for y in range(min(y1, y2), max(y1, y2) + 1): create_floor(game_map, x, y)
def create_h_tunnel(game_map, x1, x2, y): for x in range(min(x1, x2), max(x1, x2) + 1): create_floor(game_map, x, y)
def random_fill_map(self, map_width, map_height): for y in range(2, map_height - 2): for x in range(2, map_width - 2): # print("(",x,y,") = ",self.game_map.tiles[x][y]) if random() >= self.wall_probability: create_floor(self.game_map, x, y)
def walk(self, map_width, map_height): # ==== Choose Direction ==== north = 1.0 south = 1.0 east = 1.0 west = 1.0 # weight the random walk against edges if self.random_walk_x < map_width * 0.25: # random walk is at far left side of map east += self.weighted_toward_center elif self.random_walk_x > map_width * 0.75: # random walk is at far right side of map west += self.weighted_toward_center if self.random_walk_y < map_height * 0.25: # random walk is at the top of the map south += self.weighted_toward_center elif self.random_walk_y > map_height * 0.75: # random walk is at the bottom of the map north += self.weighted_toward_center # weight the random walk in favor of the previous direction if self._previousDirection == "north": north += self.weighted_toward_previous_generation if self._previousDirection == "south": south += self.weighted_toward_previous_generation if self._previousDirection == "east": east += self.weighted_toward_previous_generation if self._previousDirection == "west": west += self.weighted_toward_previous_generation # normalize probabilities so they form a range from 0 to 1 total = north + south + east + west north /= total south /= total east /= total west /= total # choose the direction choice = random() if 0 <= choice < north: dx = 0 dy = -1 direction = "north" elif north <= choice < north + south: dx = 0 dy = 1 direction = "south" elif north + south <= choice < north + south + east: dx = 1 dy = 0 direction = "east" else: dx = -1 dy = 0 direction = "west" # ==== Walk ==== # check collision at edges if 0 < self.random_walk_x + dx < map_width - 1 and 0 < self.random_walk_y + dy < map_height - 1: self.random_walk_x += dx self.random_walk_y += dy # if self.game_map.tiles[self.random_walk_x][self.random_walk_y].blocked: if not self.game_map.walkable[self.random_walk_y][ self.random_walk_x]: create_floor(self.game_map, self.random_walk_x, self.random_walk_y) self._filled += 1 self._previousDirection = direction