ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/maze_gen.c
Revision: 1.2
Committed: Sun Aug 13 17:16:03 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

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