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.16 by root, Sat Nov 7 18:32:45 2009 UTC vs.
Revision 1.20 by root, Sun Jun 27 20:40:54 2010 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines