ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/maze_gen.C
Revision: 1.15
Committed: Fri Nov 6 13:31:47 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_90
Changes since 1.14: +0 -5 lines
Log Message:
remove or document dead code

File Contents

# Content
1
2 /* peterm@langmuir.eecs.berkeley.edu: this function generates a random
3 blocked maze with the property that there is only one path from one spot
4 to any other, and there is always a path from one spot to any other.
5
6 input: xsize, ysize;
7 output: a char** array with # and . for closed and open respectively.
8
9 a char value of 0 represents a blank space: a '#' is
10 a wall.
11
12 */
13
14 /* we need to maintain a list of wall points to generate
15 reasonable mazes: a straightforward recursive random walk maze
16 generator would generate a map with a trivial circle-the-outer-wall solution */
17
18 #include <global.h>
19
20 #include "random_map.h"
21 #include "rproto.h"
22
23 /* global variables that everyone needs: don't want to pass them in
24 as parameters every time. */
25 static int *wall_x_list = 0;
26 static int *wall_y_list = 0;
27 static int wall_free_size = 0;
28
29 /* the free wall points are those outer points which aren't corners or
30 near corners, and don't have a maze wall growing out of them already. */
31 static void
32 make_wall_free_list (int xsize, int ysize)
33 {
34 int i, j, count;
35
36 count = 0; /* entries already placed in the free list */
37 /*allocate it */
38 if (wall_free_size < 0)
39 return;
40
41 wall_x_list = (int *)calloc (sizeof (int), wall_free_size);
42 wall_y_list = (int *)calloc (sizeof (int), wall_free_size);
43
44 /* top and bottom wall */
45 for (i = 2; i < xsize - 2; i++)
46 {
47 wall_x_list[count] = i;
48 wall_y_list[count] = 0;
49 count++;
50 wall_x_list[count] = i;
51 wall_y_list[count] = ysize - 1;
52 count++;
53 }
54
55 /* left and right wall */
56 for (j = 2; j < ysize - 2; j++)
57 {
58 wall_x_list[count] = 0;
59 wall_y_list[count] = j;
60 count++;
61 wall_x_list[count] = xsize - 1;
62 wall_y_list[count] = j;
63 count++;
64 }
65 }
66
67 /* randomly returns one of the elements from the wall point list */
68 static void
69 pop_wall_point (int *x, int *y)
70 {
71 int index = rmg_rndm (wall_free_size);
72
73 *x = wall_x_list[index];
74 *y = wall_y_list[index];
75 /* write the last array point here */
76 wall_x_list[index] = wall_x_list[wall_free_size - 1];
77 wall_y_list[index] = wall_y_list[wall_free_size - 1];
78 wall_free_size--;
79 }
80
81 /* find free point: randomly look for a square adjacent to this one where
82 we can place a new block without closing a path. We may only look
83 up, down, right, or left. */
84 static int
85 find_free_point (char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize)
86 {
87 /* we will randomly pick from this list, 1=up,2=down,3=right,4=left */
88 int dirlist[4];
89 int count = 0; /* # elements in dirlist */
90
91 /* look up */
92 if (yc < ysize - 2 && xc > 2 && xc < xsize - 2) /* it is valid to look up */
93 {
94 int cleartest = (int) maze[xc][yc + 1] + (int) maze[xc - 1][yc + 1] + (int) maze[xc + 1][yc + 1];
95
96 cleartest += (int) maze[xc][yc + 2] + (int) maze[xc - 1][yc + 2] + (int) maze[xc + 1][yc + 2];
97
98 if (cleartest == 0)
99 dirlist[count++] = 1;
100 }
101
102 /* look down */
103 if (yc > 2 && xc > 2 && xc < xsize - 2) /* it is valid to look down */
104 {
105 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1];
106
107 cleartest += (int) maze[xc][yc - 2] + (int) maze[xc - 1][yc - 2] + (int) maze[xc + 1][yc - 2];
108
109 if (cleartest == 0)
110 dirlist[count++] = 2;
111 }
112
113 /* look right */
114 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) /* it is valid to look left */
115 {
116 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1];
117
118 cleartest += (int) maze[xc + 2][yc] + (int) maze[xc + 2][yc - 1] + (int) maze[xc + 2][yc + 1];
119
120 if (cleartest == 0)
121 dirlist[count++] = 3;
122 }
123
124 /* look left */
125 if (xc > 2 && yc > 2 && yc < ysize - 2) /* it is valid to look down */
126 {
127 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1];
128
129 cleartest += (int) maze[xc - 2][yc] + (int) maze[xc - 2][yc - 1] + (int) maze[xc - 2][yc + 1];
130
131 if (cleartest == 0)
132 dirlist[count++] = 4;
133 }
134
135 if (count == 0)
136 return -1; /* failed to find any clear points */
137
138 /* choose a random direction */
139 switch (dirlist [rmg_rndm (count)])
140 {
141 case 1: /* up */
142 *y = yc + 1;
143 *x = xc;
144 break;
145
146 case 2: /* down */
147 *y = yc - 1;
148 *x = xc;
149 break;
150
151 case 3: /* right */
152 *y = yc;
153 *x = xc + 1;
154 break;
155
156 case 4: /* left */
157 *x = xc - 1;
158 *y = yc;
159 break;
160
161 default: /* ??? */
162 return -1;
163
164 }
165
166 return 1;
167 }
168
169 /* recursive routine which will fill every available space in the maze
170 with walls*/
171 static void
172 fill_maze_full (char **maze, int x, int y, int xsize, int ysize)
173 {
174 int xc, yc;
175
176 /* write a wall here */
177 maze[x][y] = '#';
178
179 /* decide if we're going to pick from the wall_free_list */
180 if (rmg_rndm (4) && wall_free_size > 0)
181 {
182 pop_wall_point (&xc, &yc);
183 fill_maze_full (maze, xc, yc, xsize, ysize);
184 }
185
186 /* change the if to a while for a complete maze. */
187 while (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1)
188 fill_maze_full (maze, xc, yc, xsize, ysize);
189 }
190
191 /* recursive routine which will fill much of the maze, but will leave
192 some free spots (possibly large) toward the center.*/
193 static void
194 fill_maze_sparse (char **maze, int x, int y, int xsize, int ysize)
195 {
196 int xc, yc;
197
198 /* write a wall here */
199 maze[x][y] = '#';
200
201 /* decide if we're going to pick from the wall_free_list */
202 if (rmg_rndm (4) && wall_free_size > 0)
203 {
204 pop_wall_point (&xc, &yc);
205 fill_maze_sparse (maze, xc, yc, xsize, ysize);
206 }
207
208 /* change the if to a while for a complete maze. */
209 if (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1)
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
215 mazes have sizable rooms. option = 1, full, 0, sparse.*/
216 void
217 maze_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)
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);
249 }
250