1 """ Procedural map generation for levels """
8 i = random.randint(0,100)
12 '#': {'floor': {'base': 'cwall',
16 ' ': {'floor': {'base': 'floor',
17 'behaviour': ['walk', 'fly'],
20 'o': {'tunnels': {'base': 'underground',
24 '-': {'tunnels': {'base': 'tunnel',
25 'behaviour': ['walk',],
31 def random_cardinal():
32 """Return a random cardinal direction for random walks."""
33 return random.choice([(0, 1), (0, -1), (1, 0), (-1, 0)])
44 dist_from_other_rooms = 0
47 region_size_in_tiles = 0
49 def __init__(self, width, height, rooms, min_room_size, max_room_size, dist_from_edge,
50 dist_from_other_rooms, region_size_in_tiles):
51 """ Initialize the level parameters
56 self.min_room_size = min_room_size
57 self.max_room_size = max_room_size
58 self.dist_from_edge = dist_from_edge
59 self.dist_from_other_rooms = dist_from_other_rooms
60 self.region_size_in_tiles = region_size_in_tiles
63 """ Generate a random level map
65 self.generate_regions()
66 row = ['#' for x in range(self.width * self.region_size_in_tiles)]
67 self.map = [row[:] for x in range(self.height * self.region_size_in_tiles)]
68 regions_selected = random.sample(range(self.region), min(self.region, self.rooms))
69 print('Regions: %s' % str(regions_selected))
70 for region in regions_selected:
71 self.generate_room(region)
72 self.generate_underlayer()
74 def generate_regions(self):
75 """ Generate a random level region map
77 row = ['#' for x in range(self.width)]
78 self.regions = [row[:] for x in range(self.height)]
79 for h in range(self.height):
80 for w in range(self.width):
81 random_number = random.randint(0, 2)
83 self.regions[h][w] = self.region
88 self.regions[h][w] = self.regions[h][w - 1]
93 self.regions[h][w] = self.region
97 self.regions[h][w] = self.regions[h - 1][w]
99 self.regions[h][w] = self.region
102 if random_number > 1:
103 self.regions[h][w] = self.regions[h - 1][w]
104 elif random_number > 0:
105 self.regions[h][w] = self.regions[h][w - 1]
107 self.regions[h][w] = self.region
110 def generate_underlayer(self):
111 """Generate a small mess of tunnels to have something."""
112 width = len(self.map[0])
113 height = len(self.map)
114 row = ['o' for x in range(width)]
115 self.underlayer = [row[:] for x in range(height)]
116 # we create a set of biased random walks to create the tunnel network
117 for walk in range(random.randint(3, 6)):
118 x = width // 2 + random.randint(-8, 8)
119 y = height // 2 + random.randint(-8, 8)
120 dir_x, dir_y = random_cardinal()
121 max_steps = random.randint(40, width * height // 4)
122 for step in range(20, max_steps):
123 if 0 < x < width - 1:
124 if 0 < y < height - 1:
125 self.underlayer[y][x] = '-'
126 if random.random() > 0.7:
127 dir_x, dir_y = random_cardinal()
131 def generate_room(self, region_selected):
134 for h in range(self.height):
135 for w in range(self.width):
136 if self.regions[h][w] == region_selected:
138 w_dist = self.dist_from_other_rooms
139 elif self.regions[h][w-1] == region_selected:
142 w_dist = self.dist_from_other_rooms
144 if w + 1 == self.width:
145 e_dist = self.region_size_in_tiles - self.dist_from_other_rooms
146 elif self.regions[h][w+1] == region_selected:
147 e_dist = self.region_size_in_tiles
149 e_dist = self.region_size_in_tiles - self.dist_from_other_rooms
152 n_dist = self.dist_from_other_rooms
153 elif self.regions[h-1][w] == region_selected:
156 n_dist = self.dist_from_other_rooms
158 if h + 1 == self.height:
159 s_dist = self.region_size_in_tiles - self.dist_from_other_rooms
160 elif self.regions[h+1][w] == region_selected:
161 s_dist = self.region_size_in_tiles
163 s_dist = self.region_size_in_tiles - self.dist_from_other_rooms
165 for wt in range(w_dist, e_dist):
166 for ht in range(n_dist, s_dist):
167 self.map[h * self.region_size_in_tiles + ht][w * self.region_size_in_tiles + wt] = ' '
170 file = open('map.txt', 'w')
173 file.write(''.join(l))
176 for l in self.underlayer:
178 file.write(''.join(l))
182 for l in self.regions:
187 level['tileset'] = 'bunker'
189 for l, lu in zip(self.map, self.underlayer):
191 for t1, t2 in zip(l, lu):
192 tile = ATTRIBUTE_MAP[t1].copy()
193 tile.update(ATTRIBUTE_MAP[t2])
195 level['tiles'].append(row)
196 # FIXME: Do a lot better here
197 # Crude hack so the level is written into the levels folder
198 name = os.path.join(os.path.dirname(__file__), '..', 'levels', 'map.json')
204 if __name__ == '__main__':
206 level = LevelGenerator(width=8, height=5, rooms=12, min_room_size=5, max_room_size=20,
207 dist_from_edge=2, dist_from_other_rooms=1, region_size_in_tiles=6)
210 input("Press Enter to continue...")