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.7 by root, Sat Jan 27 02:19:37 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines