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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines