ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/layout.C
(Generate patch)

Comparing deliantra/server/random_maps/layout.C (file contents):
Revision 1.9 by root, Fri Jul 2 17:18:04 2010 UTC vs.
Revision 1.13 by root, Sat Jul 3 01:52:52 2010 UTC

72} 72}
73 73
74void 74void
75layout::rect (int x1, int y1, int x2, int y2, char fill) 75layout::rect (int x1, int y1, int x2, int y2, char fill)
76{ 76{
77 --x2;
78
79 memset (data [x1] + y1, fill, y2 - y1);
80 memset (data [x2] + y1, fill, y2 - y1);
81
82 while (++x1 < x2)
83 data [x1][y1] = data [x1][y2 - 1] = fill;
84}
85
86void
87layout::fill_rect (int x1, int y1, int x2, int y2, char fill)
88{
77 for (; x1 < x2; ++x1) 89 for (; x1 < x2; ++x1)
78 memset (data [x1] + y1, fill, y2 - y1); 90 memset (data [x1] + y1, fill, y2 - y1);
79} 91}
80 92
81void layout::border (char fill) 93void layout::border (char fill)
82{ 94{
83 for (int i = 0; i < w; i++) data [i][0] = data [i][h - 1] = fill; 95 rect (0, 0, w, h, fill);
84 for (int j = 0; j < h; j++) data [0][j] = data [w - 1][j] = fill;
85} 96}
86 97
87void 98void
88layout::fill_rand (int percent) 99layout::fill_rand (int percent)
89{ 100{
171///////////////////////////////////////////////////////////////////////////// 182/////////////////////////////////////////////////////////////////////////////
172// isolation remover - ensures single connected area 183// isolation remover - ensures single connected area
173 184
174typedef fixed_stack<point> pointlist; 185typedef fixed_stack<point> pointlist;
175 186
176static noinline void 187static void noinline
177push_flood_fill (layout &dist, pointlist &seeds, int x, int y) 188push_flood_fill (layout &dist, pointlist &seeds, int x, int y)
178{ 189{
179 if (dist [x][y]) 190 if (dist [x][y])
180 return; 191 return;
181 192
192 ++y; 203 ++y;
193 } 204 }
194 205
195 while (--y >= y0) 206 while (--y >= y0)
196 { 207 {
197 if (x > 0) push_flood_fill (dist, seeds, x - 1, y); 208 if (x > 0 && !dist [x - 1][y]) push_flood_fill (dist, seeds, x - 1, y);
198 if (x < dist.w - 1) push_flood_fill (dist, seeds, x + 1, y); 209 if (x < dist.w - 1 && !dist [x + 1][y]) push_flood_fill (dist, seeds, x + 1, y);
199 } 210 }
200} 211}
201 212
202static inline void 213static inline void
203make_tunnel (layout &dist, pointlist &seeds, int x, int y, U8 d) 214make_tunnel (layout &dist, pointlist &seeds, int x, int y, U8 d)
204{ 215{
205 for (;;) 216 for (;;)
206 { 217 {
218 point neigh[4];
219 int ncnt = 0;
220
207 if (x > 1 && U8 (dist [x - 1][y]) < d && dist [x - 1][y] > 1) 221 if (x > 0 && U8 (dist [x - 1][y]) <= d && dist [x - 1][y] > 1) neigh [ncnt++] = point (x - 1, y);
208 --x;
209 else if (x < dist.w - 2 && U8 (dist [x + 1][y]) < d && dist [x + 1][y] > 1) 222 if (x < dist.w - 1 && U8 (dist [x + 1][y]) <= d && dist [x + 1][y] > 1) neigh [ncnt++] = point (x + 1, y);
210 ++x;
211 else if (y > 1 && U8 (dist [x][y - 1]) < d && dist [x][y - 1] > 1) 223 if (y > 0 && U8 (dist [x][y - 1]) <= d && dist [x][y - 1] > 1) neigh [ncnt++] = point (x, y - 1);
212 --y;
213 else if (y < dist.h - 2 && U8 (dist [x][y + 1]) < d && dist [x][y + 1] > 1) 224 if (y < dist.h - 1 && U8 (dist [x][y + 1]) <= d && dist [x][y + 1] > 1) neigh [ncnt++] = point (x, y + 1);
214 ++y; 225
215 else 226 if (!ncnt)
216 break; 227 return;
228
229 point &p = neigh [rmg_rndm (ncnt)];
230
231 seeds.push (p);
232
233 x = p.x;
234 y = p.y;
217 235
218 d = dist [x][y]; 236 d = dist [x][y];
219 dist [x][y] = 1; 237 dist [x][y] = 1;
220 seeds.push (point (x, y));
221 } 238 }
222} 239}
223 240
224static void inline 241static void inline
225maybe_push (layout &dist, pointlist &seeds, int x, int y, U8 d) 242maybe_push (layout &dist, pointlist &seeds, int x, int y, U8 d)
232 return; 249 return;
233 250
234 seeds.push (point (x, y)); 251 seeds.push (point (x, y));
235} 252}
236 253
237void 254// isolation remover, works on a "distance" map
238layout::isolation_remover (bool dirty) 255// the map must be initialised with 0 == rooms, 255 = walls
256static void noinline
257isolation_remover (layout &dist)
239{ 258{
240 layout dist (w, h);
241
242 // dist contains 259 // dist contains
243 // 0 == invisited rooms 260 // 0 == invisited rooms
244 // 1 == visited rooms 261 // 1 == visited rooms
245 // 2+ shortest distance to random near room 262 // 2+ shortest distance to random near room
246 263
247 // phase 1, initialise dist array, find seed 264 // phase 1, find seed
248 int cnt = 0; 265 int cnt = 0;
249 int x, y; 266 int x, y;
250 267
251 for (int i = 0; i < w; ++i) 268 for (int i = 0; i < dist.w; ++i)
252 for (int j = 0; j < h; ++j) 269 for (int j = 0; j < dist.h; ++j)
253 { 270 if (!dist [i][j] && !rmg_rndm (++cnt))
254 if (data [i][j] == '#')
255 dist [i][j] = U8 (255);
256 else
257 {
258 dist [i][j] = 0;
259 if (!rmg_rndm (++cnt))
260 x = i, y = j; 271 x = i, y = j;
261 }
262 }
263 272
264 if (!cnt) 273 if (!cnt)
265 { 274 {
266 // map is completely massive, this is not good, 275 // map is completely massive, this is not good,
267 // so make it empty instead. 276 // so make it empty instead.
268 clear (); 277 dist.fill (1);
269 border ();
270 return; 278 return;
271 } 279 }
272 280
273 fixed_stack<point> seeds (w * h * 5); 281 fixed_stack<point> seeds (dist.w * dist.h * 5);
274 282
275 // found first free space - picking the first one gives 283 // found first free space - picking the first one gives
276 // us a slight bias for tunnels, but usually you won't 284 // us a slight bias for tunnels, but usually you won't
277 // notice that in-game 285 // notice that in-game
278 seeds.push (point (x, y)); 286 seeds.push (point (x, y));
290 y = p.y; 298 y = p.y;
291 299
292 if (!dist [x][y]) 300 if (!dist [x][y])
293 { 301 {
294 // found new isolated area, make tunnel 302 // found new isolated area, make tunnel
295 if (!dirty)
296 push_flood_fill (dist, seeds, x, y); 303 push_flood_fill (dist, seeds, x, y);
297
298 make_tunnel (dist, seeds, x, y, 255); 304 make_tunnel (dist, seeds, x, y, 255);
299
300 if (dirty)
301 push_flood_fill (dist, seeds, x, y);
302 } 305 }
303 else 306 else
304 { 307 {
305 // nothing here, continue to expand 308 // nothing here, continue to expand
306 U8 d = U8 (dist [x][y]) + 1; 309 U8 d = U8 (dist [x][y]) + 1;
309 if (x > 0) maybe_push (dist, seeds, x - 1, y, d); 312 if (x > 0) maybe_push (dist, seeds, x - 1, y, d);
310 if (y < dist.h - 1) maybe_push (dist, seeds, x, y + 1, d); 313 if (y < dist.h - 1) maybe_push (dist, seeds, x, y + 1, d);
311 if (y > 0) maybe_push (dist, seeds, x, y - 1, d); 314 if (y > 0) maybe_push (dist, seeds, x, y - 1, d);
312 } 315 }
313 } 316 }
317}
318
319void
320layout::isolation_remover ()
321{
322 layout dist (w - 2, h - 2); // map without border
323
324 for (int x = 1; x < w - 1; ++x)
325 for (int y = 1; y < h - 1; ++y)
326 dist [x - 1][y - 1] = data [x][y] == '#' ? U8 (255) : 0;
327
328 ::isolation_remover (dist);
314 329
315 // now copy the tunnels over 330 // now copy the tunnels over
316 for (int x = 0; x < w; ++x) 331 for (int x = 1; x < w - 1; ++x)
317 for (int y = 0; y < h; ++y) 332 for (int y = 1; y < h - 1; ++y)
318 if (data [x][y] == '#' && dist [x][y] == 1) 333 if (data [x][y] == '#' && dist [x - 1][y - 1] == 1)
319 data [x][y] = 0; 334 data [x][y] = 0;
320} 335}
321 336
322///////////////////////////////////////////////////////////////////////////// 337/////////////////////////////////////////////////////////////////////////////
323 338
327{ 342{
328 switch (subtype) 343 switch (subtype)
329 { 344 {
330 // a rough cave 345 // a rough cave
331 case 0: 346 case 0:
332 fill_rand (rmg_rndm (80, 95)); 347 fill_rand (rmg_rndm (85, 97));
333 break; 348 break;
334 349
335 // corridors 350 // corridors
336 case 1: 351 case 1:
337 fill_rand (rmg_rndm (5, 40)); 352 fill_rand (rmg_rndm (5, 40));
880{ 895{
881 demo () 896 demo ()
882 { 897 {
883 rmg_rndm.seed (time (0)); 898 rmg_rndm.seed (time (0));
884 899
885 for(int i=1;i<10;i) 900 for(int i=1;i<100;i++)
886 { 901 {
887 layout maze (10, 10); 902 layout maze (40, 25);
888 maze.fill_rand (90); 903 maze.fill_rand (85);
889 maze.border (); 904 maze.border ();
890 maze.isolation_remover (); 905 maze.isolation_remover ();
891 maze.doorify ();
892 maze.symmetrize (rmg_rndm (2, 4));
893 maze.rotate (rmg_rndm (4));
894 maze.expand2x ();
895 maze.print (); 906 maze.print ();
896 } 907 }
897 908
898 exit (1); 909 exit (1);
899 } 910 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines