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.6 by root, Thu Jan 18 19:42:10 2007 UTC vs.
Revision 1.12 by root, Thu May 8 14:20:19 2008 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines