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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines