From: David Sharpe Date: Thu, 3 Mar 2016 22:31:06 +0000 (+0200) Subject: Merge of doom X-Git-Url: https://git.ctpug.org.za/?p=koperkapel.git;a=commitdiff_plain;h=acc9b01b638c88871d67ea84476eae2bdf8bdd1b Merge of doom --- acc9b01b638c88871d67ea84476eae2bdf8bdd1b diff --cc koperkapel/generators/maps.py index bbb6d13,4647fb0..6e6bdbd --- a/koperkapel/generators/maps.py +++ b/koperkapel/generators/maps.py @@@ -5,128 -5,33 +5,139 @@@ import mat import json import os -i = random.randint(0,100) - - ATTRIBUTE_MAP = { - '#': {'base': 'cwall', - 'behaviour': [], - }, - ' ': {'base': 'floor', - 'behaviour': ['walk', 'fly'], - '#': {'floor': {'base': 'cwall', - 'behaviour': [], - }, -- }, + ' ': {'floor': {'base': 'floor', - 'behaviour': ['walk', 'fly'], - }, - }, ++ 'behaviour': ['walk', 'fly'], ++ }, ++ }, + 'o': {'tunnels': {'base': 'underground', + 'behaviour': [], - } - }, ++ } ++ }, + '-': {'tunnels': {'base': 'tunnel', - 'behaviour': ['walk',], - }, - }, ++ 'behaviour': ['walk', ], ++ }, ++ }, } +class Room: + def __init__(self, coordinates, region): + """ + """ + self.coordinates = [coordinates] + self.region = 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_region(self, coordinates): + """ + Add a new region into an existing room + :param coordinates: region coordinates to be added to room + :return: + """ + self.coordinates.append(coordinates) + + 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 coord in self.coordinates: + for room in other_rooms: + if self == room: + continue + for new_coord in room.coordinates: + distance.append( + math.sqrt((coord[0] - new_coord[0]) ** 2 + + (coord[1] - new_coord[1]) ** 2)) + other_tile.append(new_coord) + this_tile.append(coord) + 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): ++ def link_passage(self, local_tile, foreign_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 ++ :param foreign_tile: tile in another room to which we wish to link + :return: + """ - self.passages.append([local_tile, foriegn_tile]) ++ self.passages.append([local_tile, foreign_tile]) + + def render_region(self, region, room_dist, region_size, tile_map, x, y): + """ Check if a region is in this room and return the required tiles + :param region: Region that we wish to render + :param room_dist: Tile separation distance from other rooms + :param region_size: Region size in tiles ++ :param tile_map: Tile map to update ++ :param x: X coordinate ++ :param y: Y coordinate + :return: + """ + if region in self.coordinates: - print(region) - print(self.region) + print(self.coordinates) + for ht in range(room_dist, region_size - room_dist): + for wt in range(room_dist, region_size - room_dist): + tile_map[x + ht][y + wt] = ' ' + + # if w == 0: + # w_dist = self.dist_from_other_rooms + # 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 - 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 - self.dist_from_other_rooms + # + # if h == 0: + # n_dist = self.dist_from_other_rooms + # 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 - 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 - 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 + ht]\ + # [w * self.region_size + wt] = ' ' + + def random_cardinal(): + """Return a random cardinal direction for random walks.""" + return random.choice([(0, 1), (0, -1), (1, 0), (-1, 0)]) + class LevelGenerator: width = 0 @@@ -154,73 -62,74 +165,118 @@@ 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)] + self.map2 = [row[:] for x in range(self.height * self.region_size)] print('Regions: %s' % str(regions_selected)) for region in regions_selected: + self.rooms[region].connect_rooms( + [self.rooms[i] for i in regions_selected]) - self.generate_tiles(region) + self.generate_room(region) - self.generate_underlayer() + region_coordinates_selected = [p for p in self.region_coordinates if + p[0] in regions_selected] + print('Coords: %s' % str(region_coordinates_selected)) + for coord in region_coordinates_selected: + print(str(coord)) - # self.rooms[coord[0]].render_region( - # coord[1], self.dist_from_other_rooms, self.region_size, - # self.map2, coord[1][0] * self.region_size, - # coord[1][1] * self.region_size) ++ self.rooms[coord[0]].render_region( ++ coord[1], self.dist_from_other_rooms, self.region_size, ++ self.map2, coord[1][0] * self.region_size, ++ coord[1][1] * self.region_size) ++ # self.generate_underlayer() - 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 + update_value = 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 + update_value = self.region_map[h][w - 1] else: - self.regions[h][w] = self.region - self.region += 1 + update_value = self.regions + increment_region = True elif w == 0: if random_number > 1: - self.regions[h][w] = self.regions[h - 1][w] + update_value = self.region_map[h - 1][w] else: - self.regions[h][w] = self.region - self.region += 1 + update_value = self.regions + increment_region = True else: if random_number > 1: - self.regions[h][w] = self.regions[h - 1][w] + update_value = self.region_map[h - 1][w] elif random_number > 0: - self.regions[h][w] = self.regions[h][w - 1] + update_value = self.region_map[h][w - 1] else: - self.regions[h][w] = self.region - self.region += 1 + update_value = self.regions + increment_region = True + self.region_map[h][w] = update_value + if increment_region: - r = Room([h, w], self.regions) ++ r = Room([h, w], update_value) + self.rooms.append(r) + self.region_coordinates.append([update_value, [h, w]]) + self.regions += 1 + else: - self.rooms[-1].add_region([h, w]) ++ for r in self.rooms: ++ if r.region == update_value: ++ r.add_region([h, w]) + self.region_coordinates.append([update_value, [h, w]]) + def generate_underlayer(self): + """Generate a small mess of tunnels to have something.""" + width = len(self.map[0]) + height = len(self.map) + row = ['o' for x in range(width)] + self.underlayer = [row[:] for x in range(height)] + # we create a set of biased random walks to create the tunnel network + for walk in range(random.randint(3, 6)): + x = width // 2 + random.randint(-8, 8) + y = height // 2 + random.randint(-8, 8) + dir_x, dir_y = random_cardinal() + max_steps = random.randint(40, width * height // 4) + for step in range(20, max_steps): + if 0 < x < width - 1: + if 0 < y < height - 1: + self.underlayer[y][x] = '-' + if random.random() > 0.7: + dir_x, dir_y = random_cardinal() + x += dir_x + y += dir_y + + def generate_tiles(self, region_selected): ++ """Generate a small mess of tunnels to have something.""" ++ width = len(self.map[0]) ++ height = len(self.map) ++ row = ['o' for x in range(width)] ++ self.underlayer = [row[:] for x in range(height)] ++ # we create a set of biased random walks to create the tunnel network ++ for walk in range(random.randint(3, 6)): ++ x = width // 2 + random.randint(-8, 8) ++ y = height // 2 + random.randint(-8, 8) ++ dir_x, dir_y = random_cardinal() ++ max_steps = random.randint(40, width * height // 4) ++ for step in range(20, max_steps): ++ if 0 < x < width - 1: ++ if 0 < y < height - 1: ++ self.underlayer[y][x] = '-' ++ if random.random() > 0.7: ++ dir_x, dir_y = random_cardinal() ++ x += dir_x ++ y += dir_y ++ + def generate_room(self, region_selected): """ + :param region_selected: + :return: """ for h in range(self.height): for w in range(self.width): @@@ -270,10 -177,9 +326,17 @@@ print(''.join(l)) file.write(''.join(l)) file.write('\n') + print('-----------------') ++ try: ++ for l in self.underlayer: ++ print(''.join(l)) ++ file.write(''.join(l)) ++ file.write('\n') ++ except AttributeError: ++ pass file.close() - self._to_json() - for l in self.regions: + for l in self.region_map: + # self._to_json() print(l) def _to_json(self):