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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines