1 """ Procedural map generation for levels """
8 i = random.randint(0,100)
13 def __init__(self, region):
16 self.regions = [region]
17 self.max_connections = 1
23 Check if the room is linked to another room
24 :return: Whether the room has any links or not
26 return len(self.passages) + len(self.tunnels) > 0
28 def add_passage(self, room_region, new_region):
29 """ Add a passage link between rooms
30 :param room_region: coordinate of region from which we are linking
31 :param new_region: coordinate of region to which we are linking
36 def add_region(self, region):
38 Add a new region into an existing room
39 :param region: region coordinates to be added to room
42 self.regions.append(region)
44 def connect_rooms(self, other_rooms):
45 """ Find the nearest rooms to this room
46 :param other_rooms: list of Rooms objects that we are searching
53 for local_region in self.regions:
54 for room in other_rooms:
57 for new_region in room.regions:
59 math.sqrt((local_region[0] - new_region[0]) ** 2 +
60 (local_region[1] - new_region[1]) ** 2))
61 other_tile.append(new_region)
62 this_tile.append(local_region)
63 target_rooms.append(room)
65 sorted_indices = [i[0] for i in sorted(enumerate(distance),
67 for index in sorted_indices:
68 if len(self.passages) + len(self.tunnels) >= self.max_connections:
70 if not target_rooms[index].is_linked():
71 self.link_passage(this_tile[index], other_tile[index])
72 target_rooms[index].link_passage(
73 other_tile[index], this_tile[index])
75 def link_passage(self, local_tile, foriegn_tile):
76 """ Link a passage between two rooms
77 :param local_tile: tile in this room to which we wish to link
78 :param foriegn_tile: tile in another room to which we wish to link
81 self.passages.append([local_tile, foriegn_tile])
84 '#': {'base': 'cwall',
87 ' ': {'base': 'floor',
88 'behaviour': ['walk', 'fly'],
91 >>>>>>> 0b2149fff63b346192148b7eb334e00ad3b9283d
103 dist_from_other_rooms = 0
108 def __init__(self, width, height, no_rooms, min_room_size, max_room_size,
109 dist_from_edge, dist_from_other_rooms, region_size):
110 """ Initialize the level parameters
114 self.no_rooms = no_rooms
115 self.min_room_size = min_room_size
116 self.max_room_size = max_room_size
117 self.dist_from_edge = dist_from_edge
118 self.dist_from_other_rooms = dist_from_other_rooms
119 self.region_size = region_size
122 """ Generate a random level map
124 self.generate_rooms()
125 regions_selected = random.sample(range(self.regions),
126 min(self.regions, self.no_rooms))
127 row = ['#' for x in range(self.width * self.region_size)]
128 self.map = [row[:] for x in range(self.height * self.region_size)]
129 print('Regions: %s' % str(regions_selected))
130 for region in regions_selected:
131 self.rooms[region].connect_rooms(
132 [self.rooms[i] for i in regions_selected])
133 self.generate_tiles(region)
135 def generate_rooms(self):
136 """ Generate a random level region map
138 row = [0 for x in range(self.width)]
139 self.region_map = [row[:] for x in range(self.height)]
140 for h in range(self.height):
141 for w in range(self.width):
142 random_number = random.randint(0, 2)
143 increment_region = False
145 self.region_map[h][w] = self.regions
146 increment_region = True
148 if random_number > 1:
149 self.region_map[h][w] = self.region_map[h][w - 1]
151 self.region_map[h][w] = self.regions
152 increment_region = True
154 if random_number > 1:
155 self.region_map[h][w] = self.region_map[h - 1][w]
157 self.region_map[h][w] = self.regions
158 increment_region = True
160 if random_number > 1:
161 self.region_map[h][w] = self.region_map[h - 1][w]
163 elif random_number > 0:
164 self.region_map[h][w] = self.region_map[h][w - 1]
166 self.region_map[h][w] = self.regions
167 increment_region = True
173 self.rooms[-1].add_region([h,w])
175 def generate_tiles(self, region_selected):
177 :param region_selected:
180 for h in range(self.height):
181 for w in range(self.width):
182 if self.region_map[h][w] == region_selected:
184 w_dist = self.dist_from_other_rooms
185 elif self.region_map[h][w-1] == region_selected:
188 w_dist = self.dist_from_other_rooms
190 if w + 1 == self.width:
191 e_dist = self.region_size - self.dist_from_other_rooms
192 elif self.region_map[h][w+1] == region_selected:
193 e_dist = self.region_size
195 e_dist = self.region_size - self.dist_from_other_rooms
198 n_dist = self.dist_from_other_rooms
199 elif self.region_map[h-1][w] == region_selected:
202 n_dist = self.dist_from_other_rooms
204 if h + 1 == self.height:
205 s_dist = self.region_size - self.dist_from_other_rooms
206 elif self.region_map[h+1][w] == region_selected:
207 s_dist = self.region_size
209 s_dist = self.region_size - self.dist_from_other_rooms
211 for wt in range(w_dist, e_dist):
212 for ht in range(n_dist, s_dist):
213 self.map[h * self.region_size + ht]\
214 [w * self.region_size + wt] = ' '
216 def generate_passage_tiles(self):
217 """ Generate the tiles that form the passages between the rooms
224 file = open('map.txt', 'w')
227 file.write(''.join(l))
231 for l in self.region_map:
234 for l in self.regions:
235 >>>>>>> 0b2149fff63b346192148b7eb334e00ad3b9283d
244 row.append(ATTRIBUTE_MAP[t])
245 level['tiles'].append(row)
246 name = os.path.join(os.path.dirname(__file__), '..', 'levels', 'map.json')
247 # FIXME: Do a lot better here
248 # Crude hack so the level is written into the levels folder
254 if __name__ == '__main__':
256 level = LevelGenerator(width=4, height=3, no_rooms=4,
257 min_room_size=5, max_room_size=20,
258 dist_from_edge=1, dist_from_other_rooms=1,
262 input("Press Enter to continue...")