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.10 by root, Sat Jul 3 00:39:57 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
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 > 1 && 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 - 2 && 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 > 1 && 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 - 2 && 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.clear ();
269 border (); 278 dist.border (255);
270 return; 279 return;
271 } 280 }
272 281
273 fixed_stack<point> seeds (w * h * 5); 282 fixed_stack<point> seeds (dist.w * dist.h * 5);
274 283
275 // found first free space - picking the first one gives 284 // found first free space - picking the first one gives
276 // us a slight bias for tunnels, but usually you won't 285 // us a slight bias for tunnels, but usually you won't
277 // notice that in-game 286 // notice that in-game
278 seeds.push (point (x, y)); 287 seeds.push (point (x, y));
290 y = p.y; 299 y = p.y;
291 300
292 if (!dist [x][y]) 301 if (!dist [x][y])
293 { 302 {
294 // found new isolated area, make tunnel 303 // found new isolated area, make tunnel
295 if (!dirty)
296 push_flood_fill (dist, seeds, x, y); 304 push_flood_fill (dist, seeds, x, y);
297
298 make_tunnel (dist, seeds, x, y, 255); 305 make_tunnel (dist, seeds, x, y, 255);
299
300 if (dirty)
301 push_flood_fill (dist, seeds, x, y);
302 } 306 }
303 else 307 else
304 { 308 {
305 // nothing here, continue to expand 309 // nothing here, continue to expand
306 U8 d = U8 (dist [x][y]) + 1; 310 U8 d = U8 (dist [x][y]) + 1;
309 if (x > 0) maybe_push (dist, seeds, x - 1, y, d); 313 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); 314 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); 315 if (y > 0) maybe_push (dist, seeds, x, y - 1, d);
312 } 316 }
313 } 317 }
318}
319
320void
321layout::isolation_remover ()
322{
323 layout dist (w, h);
324
325 for (int x = 0; x < w; ++x)
326 for (int y = 0; y < h; ++y)
327 dist [x][y] = data [x][y] == '#' ? U8 (255) : 0;
328
329 ::isolation_remover (dist);
314 330
315 // now copy the tunnels over 331 // now copy the tunnels over
316 for (int x = 0; x < w; ++x) 332 for (int x = 0; x < w; ++x)
317 for (int y = 0; y < h; ++y) 333 for (int y = 0; y < h; ++y)
318 if (data [x][y] == '#' && dist [x][y] == 1) 334 if (data [x][y] == '#' && dist [x][y] == 1)
327{ 343{
328 switch (subtype) 344 switch (subtype)
329 { 345 {
330 // a rough cave 346 // a rough cave
331 case 0: 347 case 0:
332 fill_rand (rmg_rndm (80, 95)); 348 fill_rand (rmg_rndm (85, 97));
333 break; 349 break;
334 350
335 // corridors 351 // corridors
336 case 1: 352 case 1:
337 fill_rand (rmg_rndm (5, 40)); 353 fill_rand (rmg_rndm (5, 40));
880{ 896{
881 demo () 897 demo ()
882 { 898 {
883 rmg_rndm.seed (time (0)); 899 rmg_rndm.seed (time (0));
884 900
885 for(int i=1;i<10;i) 901 for(int i=1;i<100;i++)
886 { 902 {
887 layout maze (10, 10); 903 layout maze (40, 25);
888 maze.fill_rand (90); 904 maze.fill_rand (85);
889 maze.border (); 905 maze.border ();
890 maze.isolation_remover (); 906 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 (); 907 maze.print ();
896 } 908 }
897 909
898 exit (1); 910 exit (1);
899 } 911 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines