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.1 by elmex, Sun Aug 13 17:16:03 2006 UTC vs.
Revision 1.4 by root, Thu Sep 14 22:34:02 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines