ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/maze_gen.C
(Generate patch)

Comparing deliantra/server/random_maps/maze_gen.C (file contents):
Revision 1.4 by root, Thu Sep 14 22:34:02 2006 UTC vs.
Revision 1.11 by root, Sun May 4 14:12:37 2008 UTC

1
1/* peterm@langmuir.eecs.berkeley.edu: this function generates a random 2/* peterm@langmuir.eecs.berkeley.edu: this function generates a random
2blocked maze with the property that there is only one path from one spot 3blocked maze with the property that there is only one path from one spot
3to any other, and there is always a path from one spot to any other. 4to any other, and there is always a path from one spot to any other.
4 5
5input: xsize, ysize; 6input: xsize, ysize;
12 13
13/* we need to maintain a list of wall points to generate 14/* we need to maintain a list of wall points to generate
14 reasonable mazes: a straightforward recursive random walk maze 15 reasonable mazes: a straightforward recursive random walk maze
15 generator would generate a map with a trivial circle-the-outer-wall solution */ 16 generator would generate a map with a trivial circle-the-outer-wall solution */
16 17
17#include <stdio.h>
18#include <global.h> 18#include <global.h>
19 19
20/*#include <random_map.h>*/ 20#include "random_map.h"
21#include <maze_gen.h> 21#include "rproto.h"
22#include <time.h>
23
24
25/* this include solely, and only, is needed for the definition of RANDOM */
26
27
28 22
29/* global variables that everyone needs: don't want to pass them in 23/* global variables that everyone needs: don't want to pass them in
30 as parameters every time. */ 24 as parameters every time. */
31int *wall_x_list = 0; 25int *wall_x_list = 0;
32int *wall_y_list = 0; 26int *wall_y_list = 0;
38int wall_chance; 32int wall_chance;
39 33
40/* the outsize interface routine: accepts sizes, returns a char 34/* the outsize interface routine: accepts sizes, returns a char
41** maze. option is a flag for either a sparse or a full maze. Sparse 35** maze. option is a flag for either a sparse or a full maze. Sparse
42mazes have sizable rooms. option = 1, full, 0, sparse.*/ 36mazes have sizable rooms. option = 1, full, 0, sparse.*/
43 37void
44char ** 38maze_gen (Layout maze, int option)
45maze_gen (int xsize, int ysize, int option)
46{ 39{
47 int i, j; 40 maze->clear ();
48 41 maze->border ();
49 /* allocate that array, set it up */
50 char **maze = (char **) calloc (sizeof (char *), xsize);
51
52 for (i = 0; i < xsize; i++)
53 {
54 maze[i] = (char *) calloc (sizeof (char), ysize);
55 }
56
57 /* write the outer walls */
58 for (i = 0; i < xsize; i++)
59 maze[i][0] = maze[i][ysize - 1] = '#';
60 for (j = 0; j < ysize; j++)
61 maze[0][j] = maze[xsize - 1][j] = '#';
62
63 42
64 /* find how many free wall spots there are */ 43 /* find how many free wall spots there are */
65 wall_free_size = 2 * (xsize - 4) + 2 * (ysize - 4); 44 wall_free_size = 2 * (maze->w - 4) + 2 * (maze->h - 4);
66 45
67 make_wall_free_list (xsize, ysize); 46 make_wall_free_list (maze->w, maze->h);
68 47
69 /* return the empty maze */ 48 /* return the empty maze */
70 if (wall_free_size <= 0) 49 if (wall_free_size <= 0)
71 return maze; 50 return;
72 51
73 /* recursively generate the walls of the maze */ 52 /* recursively generate the walls of the maze */
74 /* first pop a random starting point */ 53 /* first pop a random starting point */
75 while (wall_free_size > 0) 54 while (wall_free_size > 0)
76 { 55 {
56 int i, j;
57
77 pop_wall_point (&i, &j); 58 pop_wall_point (&i, &j);
59
78 if (option) 60 if (option)
79 fill_maze_full (maze, i, j, xsize, ysize); 61 fill_maze_full (maze, i, j, maze->w, maze->h);
80 else 62 else
81 fill_maze_sparse (maze, i, j, xsize, ysize); 63 fill_maze_sparse (maze, i, j, maze->w, maze->h);
82 } 64 }
83 65
84 /* clean up our intermediate data structures. */ 66 /* clean up our intermediate data structures. */
85 67
86 free (wall_x_list); 68 free (wall_x_list);
87 free (wall_y_list); 69 free (wall_y_list);
88
89 return maze;
90} 70}
91
92
93 71
94/* the free wall points are those outer points which aren't corners or 72/* the free wall points are those outer points which aren't corners or
95 near corners, and don't have a maze wall growing out of them already. */ 73 near corners, and don't have a maze wall growing out of them already. */
96
97void 74void
98make_wall_free_list (int xsize, int ysize) 75make_wall_free_list (int xsize, int ysize)
99{ 76{
100 int i, j, count; 77 int i, j, count;
101 78
102 count = 0; /* entries already placed in the free list */ 79 count = 0; /* entries already placed in the free list */
103 /*allocate it */ 80 /*allocate it */
104 if (wall_free_size < 0) 81 if (wall_free_size < 0)
105 return; 82 return;
83
106 wall_x_list = (int *) calloc (sizeof (int), wall_free_size); 84 wall_x_list = (int *)calloc (sizeof (int), wall_free_size);
107 wall_y_list = (int *) calloc (sizeof (int), wall_free_size); 85 wall_y_list = (int *)calloc (sizeof (int), wall_free_size);
108
109 86
110 /* top and bottom wall */ 87 /* top and bottom wall */
111 for (i = 2; i < xsize - 2; i++) 88 for (i = 2; i < xsize - 2; i++)
112 { 89 {
113 wall_x_list[count] = i; 90 wall_x_list[count] = i;
128 wall_y_list[count] = j; 105 wall_y_list[count] = j;
129 count++; 106 count++;
130 } 107 }
131} 108}
132 109
133
134
135/* randomly returns one of the elements from the wall point list */ 110/* randomly returns one of the elements from the wall point list */
136
137void 111void
138pop_wall_point (int *x, int *y) 112pop_wall_point (int *x, int *y)
139{ 113{
140 int index = RANDOM () % wall_free_size; 114 int index = rmg_rndm (wall_free_size);
141 115
142 *x = wall_x_list[index]; 116 *x = wall_x_list[index];
143 *y = wall_y_list[index]; 117 *y = wall_y_list[index];
144 /* write the last array point here */ 118 /* write the last array point here */
145 wall_x_list[index] = wall_x_list[wall_free_size - 1]; 119 wall_x_list[index] = wall_x_list[wall_free_size - 1];
146 wall_y_list[index] = wall_y_list[wall_free_size - 1]; 120 wall_y_list[index] = wall_y_list[wall_free_size - 1];
147 wall_free_size--; 121 wall_free_size--;
148} 122}
149 123
150
151
152/* find free point: randomly look for a square adjacent to this one where 124/* find free point: randomly look for a square adjacent to this one where
153we can place a new block without closing a path. We may only look 125we can place a new block without closing a path. We may only look
154up, down, right, or left. */ 126up, down, right, or left. */
155
156int 127int
157find_free_point (char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize) 128find_free_point (char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize)
158{ 129{
159 130
160/* we will randomly pick from this list, 1=up,2=down,3=right,4=left */ 131/* we will randomly pick from this list, 1=up,2=down,3=right,4=left */
173 dirlist[count] = 1; 144 dirlist[count] = 1;
174 count++; 145 count++;
175 } 146 }
176 } 147 }
177 148
178
179 /* look down */ 149 /* look down */
180 if (yc > 2 && xc > 2 && xc < xsize - 2) /* it is valid to look down */ 150 if (yc > 2 && xc > 2 && xc < xsize - 2) /* it is valid to look down */
181 { 151 {
182 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1]; 152 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1];
183 153
188 dirlist[count] = 2; 158 dirlist[count] = 2;
189 count++; 159 count++;
190 } 160 }
191 } 161 }
192 162
193
194 /* look right */ 163 /* look right */
195 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) /* it is valid to look left */ 164 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) /* it is valid to look left */
196 { 165 {
197 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1]; 166 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1];
198 167
203 dirlist[count] = 3; 172 dirlist[count] = 3;
204 count++; 173 count++;
205 } 174 }
206 } 175 }
207 176
208
209 /* look left */ 177 /* look left */
210 if (xc > 2 && yc > 2 && yc < ysize - 2) /* it is valid to look down */ 178 if (xc > 2 && yc > 2 && yc < ysize - 2) /* it is valid to look down */
211 { 179 {
212 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1]; 180 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1];
213 181
223 if (count == 0) 191 if (count == 0)
224 return -1; /* failed to find any clear points */ 192 return -1; /* failed to find any clear points */
225 193
226 /* choose a random direction */ 194 /* choose a random direction */
227 if (count > 1) 195 if (count > 1)
228 count = RANDOM () % count; 196 count = rmg_rndm (count);
229 else 197 else
230 count = 0; 198 count = 0;
199
231 switch (dirlist[count]) 200 switch (dirlist[count])
232 { 201 {
233 case 1: /* up */ 202 case 1: /* up */
234 { 203 {
235 *y = yc + 1; 204 *y = yc + 1;
236 *x = xc; 205 *x = xc;
237 break; 206 break;
238 }; 207 };
239 case 2: /* down */ 208 case 2: /* down */
240 { 209 {
241 *y = yc - 1; 210 *y = yc - 1;
242 *x = xc; 211 *x = xc;
243 break; 212 break;
244 }; 213 };
245 case 3: /* right */ 214 case 3: /* right */
246 { 215 {
247 *y = yc; 216 *y = yc;
248 *x = xc + 1; 217 *x = xc + 1;
249 break; 218 break;
250 } 219 }
251 case 4: /* left */ 220 case 4: /* left */
252 { 221 {
253 *x = xc - 1; 222 *x = xc - 1;
254 *y = yc; 223 *y = yc;
255 break; 224 break;
256 } 225 }
257 default: /* ??? */ 226 default: /* ??? */
258 {
259 return -1; 227 return -1;
260 } 228
261 } 229 }
262 return 1; 230 return 1;
263} 231}
264 232
265/* recursive routine which will fill every available space in the maze 233/* recursive routine which will fill every available space in the maze
266 with walls*/ 234 with walls*/
267
268void 235void
269fill_maze_full (char **maze, int x, int y, int xsize, int ysize) 236fill_maze_full (char **maze, int x, int y, int xsize, int ysize)
270{ 237{
271 int xc, yc; 238 int xc, yc;
272 239
273 /* write a wall here */ 240 /* write a wall here */
274 maze[x][y] = '#'; 241 maze[x][y] = '#';
275 242
276 /* decide if we're going to pick from the wall_free_list */ 243 /* decide if we're going to pick from the wall_free_list */
277 if (RANDOM () % 4 && wall_free_size > 0) 244 if (rmg_rndm (4) && wall_free_size > 0)
278 { 245 {
279 pop_wall_point (&xc, &yc); 246 pop_wall_point (&xc, &yc);
280 fill_maze_full (maze, xc, yc, xsize, ysize); 247 fill_maze_full (maze, xc, yc, xsize, ysize);
281 } 248 }
282 249
285 { 252 {
286 fill_maze_full (maze, xc, yc, xsize, ysize); 253 fill_maze_full (maze, xc, yc, xsize, ysize);
287 } 254 }
288} 255}
289 256
290
291/* recursive routine which will fill much of the maze, but will leave 257/* recursive routine which will fill much of the maze, but will leave
292 some free spots (possibly large) toward the center.*/ 258 some free spots (possibly large) toward the center.*/
293
294void 259void
295fill_maze_sparse (char **maze, int x, int y, int xsize, int ysize) 260fill_maze_sparse (char **maze, int x, int y, int xsize, int ysize)
296{ 261{
297 int xc, yc; 262 int xc, yc;
298 263
299 /* write a wall here */ 264 /* write a wall here */
300 maze[x][y] = '#'; 265 maze[x][y] = '#';
301 266
302 /* decide if we're going to pick from the wall_free_list */ 267 /* decide if we're going to pick from the wall_free_list */
303 if (RANDOM () % 4 && wall_free_size > 0) 268 if (rmg_rndm (4) && wall_free_size > 0)
304 { 269 {
305 pop_wall_point (&xc, &yc); 270 pop_wall_point (&xc, &yc);
306 fill_maze_sparse (maze, xc, yc, xsize, ysize); 271 fill_maze_sparse (maze, xc, yc, xsize, ysize);
307 } 272 }
308 273
309 /* change the if to a while for a complete maze. */ 274 /* change the if to a while for a complete maze. */
310 if (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1) 275 if (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1)
311 {
312 fill_maze_sparse (maze, xc, yc, xsize, ysize); 276 fill_maze_sparse (maze, xc, yc, xsize, ysize);
313 }
314} 277}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines