From: David Sharpe Date: Wed, 2 Mar 2016 07:10:45 +0000 (+0200) Subject: Add passage links to rooms X-Git-Url: https://git.ctpug.org.za/?a=commitdiff_plain;h=3f18bba4fc135cf788409155711e5d53eb14148d;p=koperkapel.git Add passage links to rooms --- diff --git a/koperkapel/generators/maps.py b/koperkapel/generators/maps.py index 6f62b0b..51aae65 100644 --- a/koperkapel/generators/maps.py +++ b/koperkapel/generators/maps.py @@ -6,116 +6,206 @@ import math i = random.randint(0,100) +class Room: + def __init__(self, region): + """ + """ + self.regions = [region] + self.max_connections = 1 + self.passages = [] + self.tunnels = [] + + def is_linked(self): + """ + Check if the room is linked to another room + :return: Whether the room has any links or not + """ + return len(self.passages) + len(self.tunnels) > 0 + + def add_passage(self, room_region, new_region): + """ Add a passage link between rooms + :param room_region: coordinate of region from which we are linking + :param new_region: coordinate of region to which we are linking + :return: + """ + pass + + def add_region(self, region): + """ + Add a new region into an existing room + :param region: region coordinates to be added to room + :return: + """ + self.regions.append(region) + + def connect_rooms(self, other_rooms): + """ Find the nearest rooms to this room + :param other_rooms: list of Rooms objects that we are searching + :return: + """ + distance = [] + other_tile = [] + this_tile = [] + target_rooms = [] + for local_region in self.regions: + for room in other_rooms: + if self == room: + continue + for new_region in room.regions: + distance.append( + math.sqrt((local_region[0] - new_region[0]) ** 2 + + (local_region[1] - new_region[1]) ** 2)) + other_tile.append(new_region) + this_tile.append(local_region) + target_rooms.append(room) + + sorted_indices = [i[0] for i in sorted(enumerate(distance), + key=lambda x:x[0])] + for index in sorted_indices: + if len(self.passages) + len(self.tunnels) >= self.max_connections: + break + if not target_rooms[index].is_linked(): + self.link_passage(this_tile[index], other_tile[index]) + target_rooms[index].link_passage( + other_tile[index], this_tile[index]) + + def link_passage(self, local_tile, foriegn_tile): + """ Link a passage between two rooms + :param local_tile: tile in this room to which we wish to link + :param foriegn_tile: tile in another room to which we wish to link + :return: + """ + self.passages.append([local_tile, foriegn_tile]) + + class LevelGenerator: width = 0 height = 0 - rooms = 0 + no_rooms = 0 + rooms = [] map = None min_room_size = 0 max_room_size = 0 dist_from_edge = 0 dist_from_other_rooms = 0 - regions = None - region = 0 - region_size_in_tiles = 0 + region_map = None + regions = 0 + region_size = 0 - def __init__(self, width, height, rooms, min_room_size, max_room_size, dist_from_edge, - dist_from_other_rooms, region_size_in_tiles): + def __init__(self, width, height, no_rooms, min_room_size, max_room_size, + dist_from_edge, dist_from_other_rooms, region_size): """ Initialize the level parameters """ self.width = width self.height = height - self.rooms = rooms + self.no_rooms = no_rooms self.min_room_size = min_room_size self.max_room_size = max_room_size self.dist_from_edge = dist_from_edge self.dist_from_other_rooms = dist_from_other_rooms - self.region_size_in_tiles = region_size_in_tiles + self.region_size = region_size def generate(self): """ Generate a random level map """ - self.generate_regions() - row = ['#' for x in range(self.width * self.region_size_in_tiles)] - self.map = [row[:] for x in range(self.height * self.region_size_in_tiles)] - regions_selected = random.sample(range(self.region), min(self.region, self.rooms)) + self.generate_rooms() + regions_selected = random.sample(range(self.regions), + min(self.regions, self.no_rooms)) + row = ['#' for x in range(self.width * self.region_size)] + self.map = [row[:] for x in range(self.height * self.region_size)] print('Regions: %s' % str(regions_selected)) for region in regions_selected: - self.generate_room(region) + self.rooms[region].connect_rooms( + [self.rooms[i] for i in regions_selected]) + self.generate_tiles(region) - def generate_regions(self): + def generate_rooms(self): """ Generate a random level region map """ - row = ['#' for x in range(self.width)] - self.regions = [row[:] for x in range(self.height)] + row = [0 for x in range(self.width)] + self.region_map = [row[:] for x in range(self.height)] for h in range(self.height): for w in range(self.width): random_number = random.randint(0, 2) + increment_region = False if w == h == 0: - self.regions[h][w] = self.region - self.region += 1 + self.region_map[h][w] = self.regions + increment_region = True elif h == 0: if random_number > 1: - try: - self.regions[h][w] = self.regions[h][w - 1] - except: - print(h, w) - raise + self.region_map[h][w] = self.region_map[h][w - 1] else: - self.regions[h][w] = self.region - self.region += 1 + self.region_map[h][w] = self.regions + increment_region = True elif w == 0: if random_number > 1: - self.regions[h][w] = self.regions[h - 1][w] + self.region_map[h][w] = self.region_map[h - 1][w] else: - self.regions[h][w] = self.region - self.region += 1 + self.region_map[h][w] = self.regions + increment_region = True else: if random_number > 1: - self.regions[h][w] = self.regions[h - 1][w] + self.region_map[h][w] = self.region_map[h - 1][w] + elif random_number > 0: - self.regions[h][w] = self.regions[h][w - 1] + self.region_map[h][w] = self.region_map[h][w - 1] else: - self.regions[h][w] = self.region - self.region += 1 + self.region_map[h][w] = self.regions + increment_region = True + if increment_region: + self.regions += 1 + r = Room([h, w]) + self.rooms.append(r) + else: + self.rooms[-1].add_region([h,w]) - def generate_room(self, region_selected): + def generate_tiles(self, region_selected): """ + :param region_selected: + :return: """ for h in range(self.height): for w in range(self.width): - if self.regions[h][w] == region_selected: + if self.region_map[h][w] == region_selected: if w == 0: w_dist = self.dist_from_other_rooms - elif self.regions[h][w-1] == region_selected: + elif self.region_map[h][w-1] == region_selected: w_dist = 0 else: w_dist = self.dist_from_other_rooms if w + 1 == self.width: - e_dist = self.region_size_in_tiles - self.dist_from_other_rooms - elif self.regions[h][w+1] == region_selected: - e_dist = self.region_size_in_tiles + e_dist = self.region_size - self.dist_from_other_rooms + elif self.region_map[h][w+1] == region_selected: + e_dist = self.region_size else: - e_dist = self.region_size_in_tiles - self.dist_from_other_rooms + e_dist = self.region_size - self.dist_from_other_rooms if h == 0: n_dist = self.dist_from_other_rooms - elif self.regions[h-1][w] == region_selected: + elif self.region_map[h-1][w] == region_selected: n_dist = 0 else: n_dist = self.dist_from_other_rooms if h + 1 == self.height: - s_dist = self.region_size_in_tiles - self.dist_from_other_rooms - elif self.regions[h+1][w] == region_selected: - s_dist = self.region_size_in_tiles + s_dist = self.region_size - self.dist_from_other_rooms + elif self.region_map[h+1][w] == region_selected: + s_dist = self.region_size else: - s_dist = self.region_size_in_tiles - self.dist_from_other_rooms + s_dist = self.region_size - self.dist_from_other_rooms for wt in range(w_dist, e_dist): for ht in range(n_dist, s_dist): - self.map[h * self.region_size_in_tiles + ht][w * self.region_size_in_tiles + wt] = ' ' + self.map[h * self.region_size + ht]\ + [w * self.region_size + wt] = ' ' + + def generate_passage_tiles(self): + """ Generate the tiles that form the passages between the rooms + :return: + """ + + def display(self): file = open('map.txt', 'w') @@ -124,14 +214,16 @@ class LevelGenerator: file.write(''.join(l)) file.write('\n') file.close() - for l in self.regions: + for l in self.region_map: print(l) if __name__ == '__main__': while True: - level = LevelGenerator(width=8, height=5, rooms=12, min_room_size=5, max_room_size=20, - dist_from_edge=2, dist_from_other_rooms=1, region_size_in_tiles=6) + level = LevelGenerator(width=4, height=3, no_rooms=4, + min_room_size=5, max_room_size=20, + dist_from_edge=1, dist_from_other_rooms=1, + region_size=5) level.generate() level.display() input("Press Enter to continue...")