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.2 by root, Tue Aug 29 08:01:36 2006 UTC vs.
Revision 1.3 by root, Sun Sep 10 16:06:37 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines