… | |
… | |
60 | }; |
60 | }; |
61 | |
61 | |
62 | /* global variables that everyone needs: don't want to pass them in |
62 | /* global variables that everyone needs: don't want to pass them in |
63 | as parameters every time. */ |
63 | as parameters every time. */ |
64 | static point *seed_list; |
64 | static point *seed_list; |
65 | static int seed_size; |
65 | static int seed_max, seed_size; |
66 | static int xsize, ysize; |
66 | static int xsize, ysize; |
67 | static char **maze; |
67 | static char **maze; |
|
|
68 | |
|
|
69 | static void |
|
|
70 | push (point p) |
|
|
71 | { |
|
|
72 | assert (seed_size < seed_max); |
|
|
73 | |
|
|
74 | seed_list [seed_size++] = p; |
|
|
75 | |
|
|
76 | maze [p.x][p.y] = '#'; |
|
|
77 | } |
68 | |
78 | |
69 | /* the free wall points are those outer points which aren't corners or |
79 | /* the free wall points are those outer points which aren't corners or |
70 | near corners, and don't have a maze wall growing out of them already. */ |
80 | near corners, and don't have a maze wall growing out of them already. */ |
71 | static void |
81 | static void |
72 | make_wall_free_list () |
82 | push_walls () |
73 | { |
83 | { |
74 | // xsize * ysize is plenty too much, but it's temporary |
|
|
75 | seed_list = salloc<point> (xsize * ysize); |
|
|
76 | seed_size = 0; |
|
|
77 | |
|
|
78 | /* top and bottom wall */ |
84 | /* top and bottom wall */ |
79 | for (int x = 2; x < xsize - 2; x++) |
85 | for (int x = 2; x < xsize - 2; x++) |
80 | { |
86 | { |
81 | seed_list [seed_size++] = point (x, 0); |
87 | push (point (x, 0)); |
82 | seed_list [seed_size++] = point (x, ysize - 1); |
88 | push (point (x, ysize - 1)); |
83 | } |
89 | } |
84 | |
90 | |
85 | /* left and right wall */ |
91 | /* left and right wall */ |
86 | for (int y = 2; y < ysize - 2; y++) |
92 | for (int y = 2; y < ysize - 2; y++) |
87 | { |
93 | { |
88 | seed_list [seed_size++] = point (0, y); |
94 | push (point ( 0, y)); |
89 | seed_list [seed_size++] = point (xsize - 1, y); |
95 | push (point (xsize - 1, y)); |
90 | } |
96 | } |
91 | } |
97 | } |
92 | |
98 | |
93 | /* randomly returns one of the elements from the wall point list */ |
99 | /* randomly returns one of the elements from the wall point list */ |
94 | static point |
100 | static point |
95 | pop_point () |
101 | pop_rand () |
96 | { |
102 | { |
97 | int index = rmg_rndm (seed_size); |
103 | int index = rmg_rndm (seed_size); |
98 | |
104 | |
99 | point p = seed_list [index]; |
105 | point p = seed_list [index]; |
100 | |
106 | |
… | |
… | |
185 | } |
191 | } |
186 | |
192 | |
187 | return 1; |
193 | return 1; |
188 | } |
194 | } |
189 | |
195 | |
190 | /* recursive routine which will fill every available space in the maze |
|
|
191 | with walls*/ |
|
|
192 | static void |
|
|
193 | fill_maze_full (point p) |
|
|
194 | { |
|
|
195 | point pc; |
|
|
196 | |
|
|
197 | /* write a wall here */ |
|
|
198 | maze[p.x][p.y] = '#'; |
|
|
199 | |
|
|
200 | /* decide if we're going to pick from the wall_free_list */ |
|
|
201 | if (rmg_rndm (2) && seed_size) |
|
|
202 | fill_maze_full (pop_point ()); |
|
|
203 | |
|
|
204 | /* change the while to an if for a sparse maze. */ |
|
|
205 | while (find_free_point (pc, p) != -1) |
|
|
206 | fill_maze_full (pc); |
|
|
207 | } |
|
|
208 | |
|
|
209 | /* recursive routine which will fill much of the maze, but will leave |
|
|
210 | some free spots (possibly large) toward the center.*/ |
|
|
211 | static void |
|
|
212 | fill_maze_sparse (point p) |
|
|
213 | { |
|
|
214 | point pc; |
|
|
215 | |
|
|
216 | /* write a wall here */ |
|
|
217 | maze[p.x][p.y] = '#'; |
|
|
218 | |
|
|
219 | /* decide if we're going to pick from the wall_free_list */ |
|
|
220 | if (rmg_rndm (2) && seed_size) |
|
|
221 | fill_maze_full (pop_point ()); |
|
|
222 | |
|
|
223 | /* change the if to a while for a complete maze. */ |
|
|
224 | if (find_free_point (pc, p) != -1) |
|
|
225 | fill_maze_full (pc); |
|
|
226 | } |
|
|
227 | |
|
|
228 | /* the outsize interface routine: accepts sizes, returns a char |
196 | /* the outsize interface routine: accepts sizes, returns a char |
229 | ** maze. option is a flag for either a sparse or a full maze. Sparse |
197 | ** maze. option is a flag for either a sparse or a full maze. Sparse |
230 | mazes have sizable rooms. option = 1, full, 0, sparse.*/ |
198 | mazes have sizable rooms. option = 3=full, 2=braided, 1=sparse, 0=rooms.*/ |
231 | void |
199 | void |
232 | maze_gen (Layout maze, int full) |
200 | maze_gen (Layout maze, int subtype) |
233 | { |
201 | { |
234 | xsize = maze->w; |
202 | xsize = maze->w; |
235 | ysize = maze->h; |
203 | ysize = maze->h; |
236 | ::maze = maze; |
204 | ::maze = maze; |
237 | |
205 | |
… | |
… | |
239 | maze->border (); |
207 | maze->border (); |
240 | |
208 | |
241 | if (xsize < 4 || ysize < 4) |
209 | if (xsize < 4 || ysize < 4) |
242 | return; |
210 | return; |
243 | |
211 | |
244 | make_wall_free_list (); |
212 | seed_max = xsize * ysize; |
|
|
213 | seed_size = 0; |
|
|
214 | seed_list = salloc<point> (seed_max); |
|
|
215 | |
|
|
216 | if (subtype > 0) |
|
|
217 | push_walls (); |
|
|
218 | |
|
|
219 | if (subtype == 0 || subtype == 2) |
|
|
220 | for (int i = (xsize + ysize) / 2; i; --i) |
|
|
221 | push (point (rmg_rndm (1, xsize - 2), rmg_rndm (1, ysize - 2))); |
|
|
222 | |
|
|
223 | bool full = subtype == 3; |
245 | |
224 | |
246 | /* recursively generate the walls of the maze */ |
225 | /* recursively generate the walls of the maze */ |
247 | /* first pop a random starting point */ |
226 | /* first pop a random starting point */ |
248 | while (seed_size) |
227 | while (seed_size) |
|
|
228 | { |
|
|
229 | point p = pop_rand (); |
|
|
230 | |
|
|
231 | for (;;) |
|
|
232 | { |
|
|
233 | point pc; |
|
|
234 | |
|
|
235 | maze [p.x][p.y] = '#'; |
|
|
236 | |
|
|
237 | if (find_free_point (pc, p) < 0) |
|
|
238 | break; |
|
|
239 | |
249 | if (full) |
240 | if (full) |
250 | fill_maze_full (pop_point ()); |
241 | push (p); |
251 | else |
242 | |
252 | fill_maze_sparse (pop_point ()); |
243 | if (!rmg_rndm (8)) |
|
|
244 | { |
|
|
245 | if (!full) |
|
|
246 | push (pc); |
|
|
247 | |
|
|
248 | break; |
|
|
249 | } |
|
|
250 | |
|
|
251 | p = pc; |
|
|
252 | } |
|
|
253 | } |
253 | |
254 | |
254 | /* clean up our intermediate data structures. */ |
255 | /* clean up our intermediate data structures. */ |
255 | sfree (seed_list, xsize * ysize); |
256 | sfree (seed_list, seed_max); |
256 | } |
257 | } |
257 | |
258 | |
258 | #if 0 |
259 | #if 0 |
259 | static struct demo |
260 | static struct demo |
260 | { |
261 | { |
… | |
… | |
263 | Layout layout (30, 30); |
264 | Layout layout (30, 30); |
264 | rmg_rndm.seed (time (0)); |
265 | rmg_rndm.seed (time (0)); |
265 | |
266 | |
266 | for(int i=1;i<10;++i) |
267 | for(int i=1;i<10;++i) |
267 | { |
268 | { |
268 | maze_gen (layout, 1); |
269 | maze_gen (layout, 3); |
269 | layout.print (); |
270 | layout.print (); |
270 | } |
271 | } |
271 | exit (1); |
272 | exit (1); |
272 | } |
273 | } |
273 | } demo; |
274 | } demo; |