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.9 by root, Mon Apr 14 22:41:17 2008 UTC vs.
Revision 1.16 by root, Sat Nov 7 18:32:45 2009 UTC

1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) Crossfire Development Team (restored, original file without copyright notice)
6 *
7 * Deliantra is free software: you can redistribute it and/or modify it under
8 * the terms of the Affero GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the Affero GNU General Public License
18 * and the GNU General Public License along with this program. If not, see
19 * <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <support@deliantra.net>
22 */
1 23
2/* peterm@langmuir.eecs.berkeley.edu: this function generates a random 24/* peterm@langmuir.eecs.berkeley.edu: this function generates a random
3blocked maze with the property that there is only one path from one spot 25blocked maze with the property that there is only one path from one spot
4to any other, and there is always a path from one spot to any other. 26to any other, and there is always a path from one spot to any other.
5 27
20#include "random_map.h" 42#include "random_map.h"
21#include "rproto.h" 43#include "rproto.h"
22 44
23/* global variables that everyone needs: don't want to pass them in 45/* global variables that everyone needs: don't want to pass them in
24 as parameters every time. */ 46 as parameters every time. */
25int *wall_x_list = 0; 47static int *wall_x_list = 0;
26int *wall_y_list = 0; 48static int *wall_y_list = 0;
27int wall_free_size = 0; 49static int wall_free_size = 0;
28
29/* heuristically, we need to change wall_chance based on the size of
30 the maze. */
31
32int wall_chance;
33
34/* the outsize interface routine: accepts sizes, returns a char
35** maze. option is a flag for either a sparse or a full maze. Sparse
36mazes have sizable rooms. option = 1, full, 0, sparse.*/
37void
38maze_gen (Maze maze, int option)
39{
40 maze->clear ();
41 maze->border ();
42
43 /* find how many free wall spots there are */
44 wall_free_size = 2 * (maze->w - 4) + 2 * (maze->h - 4);
45
46 make_wall_free_list (maze->w, maze->h);
47
48 /* return the empty maze */
49 if (wall_free_size <= 0)
50 return;
51
52 /* recursively generate the walls of the maze */
53 /* first pop a random starting point */
54 while (wall_free_size > 0)
55 {
56 int i, j;
57
58 pop_wall_point (&i, &j);
59
60 if (option)
61 fill_maze_full (maze, i, j, maze->w, maze->h);
62 else
63 fill_maze_sparse (maze, i, j, maze->w, maze->h);
64 }
65
66 /* clean up our intermediate data structures. */
67
68 free (wall_x_list);
69 free (wall_y_list);
70}
71 50
72/* the free wall points are those outer points which aren't corners or 51/* the free wall points are those outer points which aren't corners or
73 near corners, and don't have a maze wall growing out of them already. */ 52 near corners, and don't have a maze wall growing out of them already. */
74void 53static void
75make_wall_free_list (int xsize, int ysize) 54make_wall_free_list (int xsize, int ysize)
76{ 55{
77 int i, j, count; 56 int i, j, count;
78 57
79 count = 0; /* entries already placed in the free list */ 58 count = 0; /* entries already placed in the free list */
106 count++; 85 count++;
107 } 86 }
108} 87}
109 88
110/* randomly returns one of the elements from the wall point list */ 89/* randomly returns one of the elements from the wall point list */
111void 90static void
112pop_wall_point (int *x, int *y) 91pop_wall_point (int *x, int *y)
113{ 92{
114 int index = rndm (wall_free_size); 93 int index = rmg_rndm (wall_free_size);
115 94
116 *x = wall_x_list[index]; 95 *x = wall_x_list[index];
117 *y = wall_y_list[index]; 96 *y = wall_y_list[index];
118 /* write the last array point here */ 97 /* write the last array point here */
119 wall_x_list[index] = wall_x_list[wall_free_size - 1]; 98 wall_x_list[index] = wall_x_list[wall_free_size - 1];
122} 101}
123 102
124/* find free point: randomly look for a square adjacent to this one where 103/* find free point: randomly look for a square adjacent to this one where
125we can place a new block without closing a path. We may only look 104we can place a new block without closing a path. We may only look
126up, down, right, or left. */ 105up, down, right, or left. */
127int 106static int
128find_free_point (char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize) 107find_free_point (char **maze, int *x, int *y, int xc, int yc, int xsize, int ysize)
129{ 108{
130
131/* we will randomly pick from this list, 1=up,2=down,3=right,4=left */ 109 /* we will randomly pick from this list, 1=up,2=down,3=right,4=left */
132 int dirlist[4]; 110 int dirlist[4];
133 int count = 0; /* # elements in dirlist */ 111 int count = 0; /* # elements in dirlist */
134 112
135 /* look up */ 113 /* look up */
136 if (yc < ysize - 2 && xc > 2 && xc < xsize - 2) /* it is valid to look up */ 114 if (yc < ysize - 2 && xc > 2 && xc < xsize - 2) /* it is valid to look up */
138 int cleartest = (int) maze[xc][yc + 1] + (int) maze[xc - 1][yc + 1] + (int) maze[xc + 1][yc + 1]; 116 int cleartest = (int) maze[xc][yc + 1] + (int) maze[xc - 1][yc + 1] + (int) maze[xc + 1][yc + 1];
139 117
140 cleartest += (int) maze[xc][yc + 2] + (int) maze[xc - 1][yc + 2] + (int) maze[xc + 1][yc + 2]; 118 cleartest += (int) maze[xc][yc + 2] + (int) maze[xc - 1][yc + 2] + (int) maze[xc + 1][yc + 2];
141 119
142 if (cleartest == 0) 120 if (cleartest == 0)
143 {
144 dirlist[count] = 1; 121 dirlist[count++] = 1;
145 count++;
146 }
147 } 122 }
148 123
149 /* look down */ 124 /* look down */
150 if (yc > 2 && xc > 2 && xc < xsize - 2) /* it is valid to look down */ 125 if (yc > 2 && xc > 2 && xc < xsize - 2) /* it is valid to look down */
151 { 126 {
152 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1]; 127 int cleartest = (int) maze[xc][yc - 1] + (int) maze[xc - 1][yc - 1] + (int) maze[xc + 1][yc - 1];
153 128
154 cleartest += (int) maze[xc][yc - 2] + (int) maze[xc - 1][yc - 2] + (int) maze[xc + 1][yc - 2]; 129 cleartest += (int) maze[xc][yc - 2] + (int) maze[xc - 1][yc - 2] + (int) maze[xc + 1][yc - 2];
155 130
156 if (cleartest == 0) 131 if (cleartest == 0)
157 {
158 dirlist[count] = 2; 132 dirlist[count++] = 2;
159 count++;
160 }
161 } 133 }
162 134
163 /* look right */ 135 /* look right */
164 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) /* it is valid to look left */ 136 if (xc < xsize - 2 && yc > 2 && yc < ysize - 2) /* it is valid to look left */
165 { 137 {
166 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1]; 138 int cleartest = (int) maze[xc + 1][yc] + (int) maze[xc + 1][yc - 1] + (int) maze[xc + 1][yc + 1];
167 139
168 cleartest += (int) maze[xc + 2][yc] + (int) maze[xc + 2][yc - 1] + (int) maze[xc + 2][yc + 1]; 140 cleartest += (int) maze[xc + 2][yc] + (int) maze[xc + 2][yc - 1] + (int) maze[xc + 2][yc + 1];
169 141
170 if (cleartest == 0) 142 if (cleartest == 0)
171 {
172 dirlist[count] = 3; 143 dirlist[count++] = 3;
173 count++;
174 }
175 } 144 }
176 145
177 /* look left */ 146 /* look left */
178 if (xc > 2 && yc > 2 && yc < ysize - 2) /* it is valid to look down */ 147 if (xc > 2 && yc > 2 && yc < ysize - 2) /* it is valid to look down */
179 { 148 {
180 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1]; 149 int cleartest = (int) maze[xc - 1][yc] + (int) maze[xc - 1][yc - 1] + (int) maze[xc - 1][yc + 1];
181 150
182 cleartest += (int) maze[xc - 2][yc] + (int) maze[xc - 2][yc - 1] + (int) maze[xc - 2][yc + 1]; 151 cleartest += (int) maze[xc - 2][yc] + (int) maze[xc - 2][yc - 1] + (int) maze[xc - 2][yc + 1];
183 152
184 if (cleartest == 0) 153 if (cleartest == 0)
185 {
186 dirlist[count] = 4; 154 dirlist[count++] = 4;
187 count++;
188 }
189 } 155 }
190 156
191 if (count == 0) 157 if (count == 0)
192 return -1; /* failed to find any clear points */ 158 return -1; /* failed to find any clear points */
193 159
194 /* choose a random direction */ 160 /* choose a random direction */
195 if (count > 1)
196 count = rndm (count);
197 else
198 count = 0;
199
200 switch (dirlist[count]) 161 switch (dirlist [rmg_rndm (count)])
201 { 162 {
202 case 1: /* up */ 163 case 1: /* up */
203 {
204 *y = yc + 1; 164 *y = yc + 1;
205 *x = xc; 165 *x = xc;
206 break; 166 break;
207 }; 167
208 case 2: /* down */ 168 case 2: /* down */
209 {
210 *y = yc - 1; 169 *y = yc - 1;
211 *x = xc; 170 *x = xc;
212 break; 171 break;
213 }; 172
214 case 3: /* right */ 173 case 3: /* right */
215 {
216 *y = yc; 174 *y = yc;
217 *x = xc + 1; 175 *x = xc + 1;
218 break; 176 break;
219 } 177
220 case 4: /* left */ 178 case 4: /* left */
221 {
222 *x = xc - 1; 179 *x = xc - 1;
223 *y = yc; 180 *y = yc;
224 break; 181 break;
225 } 182
226 default: /* ??? */ 183 default: /* ??? */
227 return -1; 184 return -1;
228 185
229 } 186 }
187
230 return 1; 188 return 1;
231} 189}
232 190
233/* recursive routine which will fill every available space in the maze 191/* recursive routine which will fill every available space in the maze
234 with walls*/ 192 with walls*/
235void 193static void
236fill_maze_full (char **maze, int x, int y, int xsize, int ysize) 194fill_maze_full (char **maze, int x, int y, int xsize, int ysize)
237{ 195{
238 int xc, yc; 196 int xc, yc;
239 197
240 /* write a wall here */ 198 /* write a wall here */
241 maze[x][y] = '#'; 199 maze[x][y] = '#';
242 200
243 /* 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 */
244 if (rndm (4) && wall_free_size > 0) 202 if (rmg_rndm (4) && wall_free_size > 0)
245 { 203 {
246 pop_wall_point (&xc, &yc); 204 pop_wall_point (&xc, &yc);
247 fill_maze_full (maze, xc, yc, xsize, ysize); 205 fill_maze_full (maze, xc, yc, xsize, ysize);
248 } 206 }
249 207
250 /* change the if to a while for a complete maze. */ 208 /* change the if to a while for a complete maze. */
251 while (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1) 209 while (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1)
252 {
253 fill_maze_full (maze, xc, yc, xsize, ysize); 210 fill_maze_full (maze, xc, yc, xsize, ysize);
254 }
255} 211}
256 212
257/* recursive routine which will fill much of the maze, but will leave 213/* recursive routine which will fill much of the maze, but will leave
258 some free spots (possibly large) toward the center.*/ 214 some free spots (possibly large) toward the center.*/
259void 215static void
260fill_maze_sparse (char **maze, int x, int y, int xsize, int ysize) 216fill_maze_sparse (char **maze, int x, int y, int xsize, int ysize)
261{ 217{
262 int xc, yc; 218 int xc, yc;
263 219
264 /* write a wall here */ 220 /* write a wall here */
265 maze[x][y] = '#'; 221 maze[x][y] = '#';
266 222
267 /* decide if we're going to pick from the wall_free_list */ 223 /* decide if we're going to pick from the wall_free_list */
268 if (rndm (4) && wall_free_size > 0) 224 if (rmg_rndm (4) && wall_free_size > 0)
269 { 225 {
270 pop_wall_point (&xc, &yc); 226 pop_wall_point (&xc, &yc);
271 fill_maze_sparse (maze, xc, yc, xsize, ysize); 227 fill_maze_sparse (maze, xc, yc, xsize, ysize);
272 } 228 }
273 229
274 /* change the if to a while for a complete maze. */ 230 /* change the if to a while for a complete maze. */
275 if (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1) 231 if (find_free_point (maze, &xc, &yc, x, y, xsize, ysize) != -1)
276 fill_maze_sparse (maze, xc, yc, xsize, ysize); 232 fill_maze_sparse (maze, xc, yc, xsize, ysize);
277} 233}
234
235/* the outsize interface routine: accepts sizes, returns a char
236** maze. option is a flag for either a sparse or a full maze. Sparse
237mazes have sizable rooms. option = 1, full, 0, sparse.*/
238void
239maze_gen (Layout maze, int option)
240{
241 maze->clear ();
242 maze->border ();
243
244 /* find how many free wall spots there are */
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;
252
253 /* recursively generate the walls of the maze */
254 /* first pop a random starting point */
255 while (wall_free_size > 0)
256 {
257 int i, j;
258
259 pop_wall_point (&i, &j);
260
261 if (option)
262 fill_maze_full (maze, i, j, maze->w, maze->h);
263 else
264 fill_maze_sparse (maze, i, j, maze->w, maze->h);
265 }
266
267 /* clean up our intermediate data structures. */
268
269 free (wall_x_list);
270 free (wall_y_list);
271}
272

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines