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.4 by root, Thu Sep 14 22:34:02 2006 UTC vs.
Revision 1.8 by root, Fri Apr 11 21:09:53 2008 UTC

1
1/* peterm@langmuir.eecs.berkeley.edu: this function generates a random 2/* peterm@langmuir.eecs.berkeley.edu: this function generates a random
2blocked 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
3to 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.
4 5
5input: xsize, ysize; 6input: xsize, ysize;
12 13
13/* we need to maintain a list of wall points to generate 14/* we need to maintain a list of wall points to generate
14 reasonable mazes: a straightforward recursive random walk maze 15 reasonable mazes: a straightforward recursive random walk maze
15 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 */
16 17
17#include <stdio.h>
18#include <global.h> 18#include <global.h>
19 19
20/*#include <random_map.h>*/ 20#include "random_map.h"
21#include <maze_gen.h> 21#include "rproto.h"
22#include <time.h>
23
24
25/* this include solely, and only, is needed for the definition of RANDOM */
26
27
28 22
29/* 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
30 as parameters every time. */ 24 as parameters every time. */
31int *wall_x_list = 0; 25int *wall_x_list = 0;
32int *wall_y_list = 0; 26int *wall_y_list = 0;
39 33
40/* the outsize interface routine: accepts sizes, returns a char 34/* the outsize interface routine: accepts sizes, returns a char
41** 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
42mazes have sizable rooms. option = 1, full, 0, sparse.*/ 36mazes have sizable rooms. option = 1, full, 0, sparse.*/
43 37
44char ** 38Maze
45maze_gen (int xsize, int ysize, int option) 39maze_gen (int xsize, int ysize, int option)
46{ 40{
47 int i, j; 41 int i, j;
48 42
49 /* allocate that array, set it up */ 43 Maze maze (xsize, ysize);
50 char **maze = (char **) calloc (sizeof (char *), xsize);
51
52 for (i = 0; i < xsize; i++)
53 {
54 maze[i] = (char *) calloc (sizeof (char), ysize);
55 }
56 44
57 /* write the outer walls */ 45 /* write the outer walls */
58 for (i = 0; i < xsize; i++) 46 for (i = 0; i < xsize; i++) maze[i][0] = maze[i][ysize - 1] = '#';
59 maze[i][0] = maze[i][ysize - 1] = '#'; 47 for (j = 0; j < ysize; j++) maze[0][j] = maze[xsize - 1][j] = '#';
60 for (j = 0; j < ysize; j++)
61 maze[0][j] = maze[xsize - 1][j] = '#';
62
63 48
64 /* find how many free wall spots there are */ 49 /* find how many free wall spots there are */
65 wall_free_size = 2 * (xsize - 4) + 2 * (ysize - 4); 50 wall_free_size = 2 * (xsize - 4) + 2 * (ysize - 4);
66 51
67 make_wall_free_list (xsize, ysize); 52 make_wall_free_list (xsize, ysize);
73 /* recursively generate the walls of the maze */ 58 /* recursively generate the walls of the maze */
74 /* first pop a random starting point */ 59 /* first pop a random starting point */
75 while (wall_free_size > 0) 60 while (wall_free_size > 0)
76 { 61 {
77 pop_wall_point (&i, &j); 62 pop_wall_point (&i, &j);
63
78 if (option) 64 if (option)
79 fill_maze_full (maze, i, j, xsize, ysize); 65 fill_maze_full (maze, i, j, xsize, ysize);
80 else 66 else
81 fill_maze_sparse (maze, i, j, xsize, ysize); 67 fill_maze_sparse (maze, i, j, xsize, ysize);
82 } 68 }
87 free (wall_y_list); 73 free (wall_y_list);
88 74
89 return maze; 75 return maze;
90} 76}
91 77
92
93
94/* 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
95 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. */
96
97void 80void
98make_wall_free_list (int xsize, int ysize) 81make_wall_free_list (int xsize, int ysize)
99{ 82{
100 int i, j, count; 83 int i, j, count;
101 84
102 count = 0; /* entries already placed in the free list */ 85 count = 0; /* entries already placed in the free list */
103 /*allocate it */ 86 /*allocate it */
104 if (wall_free_size < 0) 87 if (wall_free_size < 0)
105 return; 88 return;
89
106 wall_x_list = (int *) calloc (sizeof (int), wall_free_size); 90 wall_x_list = (int *)calloc (sizeof (int), wall_free_size);
107 wall_y_list = (int *) calloc (sizeof (int), wall_free_size); 91 wall_y_list = (int *)calloc (sizeof (int), wall_free_size);
108
109 92
110 /* top and bottom wall */ 93 /* top and bottom wall */
111 for (i = 2; i < xsize - 2; i++) 94 for (i = 2; i < xsize - 2; i++)
112 { 95 {
113 wall_x_list[count] = i; 96 wall_x_list[count] = i;
128 wall_y_list[count] = j; 111 wall_y_list[count] = j;
129 count++; 112 count++;
130 } 113 }
131} 114}
132 115
133
134
135/* randomly returns one of the elements from the wall point list */ 116/* randomly returns one of the elements from the wall point list */
136
137void 117void
138pop_wall_point (int *x, int *y) 118pop_wall_point (int *x, int *y)
139{ 119{
140 int index = RANDOM () % wall_free_size; 120 int index = rndm (wall_free_size);
141 121
142 *x = wall_x_list[index]; 122 *x = wall_x_list[index];
143 *y = wall_y_list[index]; 123 *y = wall_y_list[index];
144 /* write the last array point here */ 124 /* write the last array point here */
145 wall_x_list[index] = wall_x_list[wall_free_size - 1]; 125 wall_x_list[index] = wall_x_list[wall_free_size - 1];
146 wall_y_list[index] = wall_y_list[wall_free_size - 1]; 126 wall_y_list[index] = wall_y_list[wall_free_size - 1];
147 wall_free_size--; 127 wall_free_size--;
148} 128}
149 129
150
151
152/* 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
153we 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
154up, down, right, or left. */ 132up, down, right, or left. */
155
156int 133int
157find_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)
158{ 135{
159 136
160/* 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 */
223 if (count == 0) 200 if (count == 0)
224 return -1; /* failed to find any clear points */ 201 return -1; /* failed to find any clear points */
225 202
226 /* choose a random direction */ 203 /* choose a random direction */
227 if (count > 1) 204 if (count > 1)
228 count = RANDOM () % count; 205 count = rndm (count);
229 else 206 else
230 count = 0; 207 count = 0;
208
231 switch (dirlist[count]) 209 switch (dirlist[count])
232 { 210 {
233 case 1: /* up */ 211 case 1: /* up */
234 { 212 {
235 *y = yc + 1; 213 *y = yc + 1;
236 *x = xc; 214 *x = xc;
237 break; 215 break;
238 }; 216 };
239 case 2: /* down */ 217 case 2: /* down */
240 { 218 {
241 *y = yc - 1; 219 *y = yc - 1;
242 *x = xc; 220 *x = xc;
243 break; 221 break;
244 }; 222 };
245 case 3: /* right */ 223 case 3: /* right */
246 { 224 {
247 *y = yc; 225 *y = yc;
248 *x = xc + 1; 226 *x = xc + 1;
249 break; 227 break;
250 } 228 }
251 case 4: /* left */ 229 case 4: /* left */
252 { 230 {
253 *x = xc - 1; 231 *x = xc - 1;
254 *y = yc; 232 *y = yc;
255 break; 233 break;
256 } 234 }
257 default: /* ??? */ 235 default: /* ??? */
258 {
259 return -1; 236 return -1;
260 } 237
261 } 238 }
262 return 1; 239 return 1;
263} 240}
264 241
265/* recursive routine which will fill every available space in the maze 242/* recursive routine which will fill every available space in the maze
272 249
273 /* write a wall here */ 250 /* write a wall here */
274 maze[x][y] = '#'; 251 maze[x][y] = '#';
275 252
276 /* 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 */
277 if (RANDOM () % 4 && wall_free_size > 0) 254 if (rndm (4) && wall_free_size > 0)
278 { 255 {
279 pop_wall_point (&xc, &yc); 256 pop_wall_point (&xc, &yc);
280 fill_maze_full (maze, xc, yc, xsize, ysize); 257 fill_maze_full (maze, xc, yc, xsize, ysize);
281 } 258 }
282 259
285 { 262 {
286 fill_maze_full (maze, xc, yc, xsize, ysize); 263 fill_maze_full (maze, xc, yc, xsize, ysize);
287 } 264 }
288} 265}
289 266
290
291/* 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
292 some free spots (possibly large) toward the center.*/ 268 some free spots (possibly large) toward the center.*/
293
294void 269void
295fill_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)
296{ 271{
297 int xc, yc; 272 int xc, yc;
298 273
299 /* write a wall here */ 274 /* write a wall here */
300 maze[x][y] = '#'; 275 maze[x][y] = '#';
301 276
302 /* 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 */
303 if (RANDOM () % 4 && wall_free_size > 0) 278 if (rndm (4) && wall_free_size > 0)
304 { 279 {
305 pop_wall_point (&xc, &yc); 280 pop_wall_point (&xc, &yc);
306 fill_maze_sparse (maze, xc, yc, xsize, ysize); 281 fill_maze_sparse (maze, xc, yc, xsize, ysize);
307 } 282 }
308 283
309 /* change the if to a while for a complete maze. */ 284 /* change the if to a while for a complete maze. */
310 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)
311 {
312 fill_maze_sparse (maze, xc, yc, xsize, ysize); 286 fill_maze_sparse (maze, xc, yc, xsize, ysize);
313 }
314} 287}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines