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.8 by root, Fri Jul 2 15:43:37 2010 UTC vs.
Revision 1.10 by root, Sat Jul 3 00:39:57 2010 UTC

23 23
24#include <global.h> 24#include <global.h>
25#include <random_map.h> 25#include <random_map.h>
26#include <rproto.h> 26#include <rproto.h>
27 27
28void
28layout::layout (int w, int h) 29layout::alloc (int w, int h)
29: w(w), h(h)
30{ 30{
31 assert (sizeof (cell) == 1); 31 assert (sizeof (cell) == 1);
32
33 this->w = w;
34 this->h = h;
32 35
33 // we store the layout in a single contiguous memory layout 36 // we store the layout in a single contiguous memory layout
34 // first part consists of pointers to each column, followed 37 // first part consists of pointers to each column, followed
35 // by the actual columns (not rows!) 38 // by the actual columns (not rows!)
36 int size = (sizeof (cell *) + sizeof (cell) * h) * w; 39 int size = (sizeof (cell *) + sizeof (cell) * h) * w;
41 44
42 for (int x = w; x--; ) 45 for (int x = w; x--; )
43 data [x] = p + x * h; 46 data [x] = p + x * h;
44} 47}
45 48
49layout::layout (int w, int h)
50{
51 alloc (w, h);
52}
53
54layout::layout (layout &copy)
55{
56 alloc (copy.w, copy.h);
57
58 memcpy (data [0], copy.data [0], sizeof (cell) * h * w);
59}
60
46layout::~layout () 61layout::~layout ()
47{ 62{
48 int size = (sizeof (cell *) + sizeof (cell) * h) * w; 63 int size = (sizeof (cell *) + sizeof (cell) * h) * w;
49 64
50 sfree ((char *)data, size); 65 sfree ((char *)data, size);
56 memset (data [0], fill, w * h); 71 memset (data [0], fill, w * h);
57} 72}
58 73
59void 74void
60layout::rect (int x1, int y1, int x2, int y2, char fill) 75layout::rect (int x1, int y1, int x2, int y2, char fill)
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)
61{ 88{
62 for (; x1 < x2; ++x1) 89 for (; x1 < x2; ++x1)
63 memset (data [x1] + y1, fill, y2 - y1); 90 memset (data [x1] + y1, fill, y2 - y1);
64} 91}
65 92
66void layout::border (char fill) 93void layout::border (char fill)
67{ 94{
68 for (int i = 0; i < w; i++) data [i][0] = data [i][h - 1] = fill; 95 rect (0, 0, w, h, fill);
69 for (int j = 0; j < h; j++) data [0][j] = data [w - 1][j] = fill;
70} 96}
71 97
72void 98void
73layout::fill_rand (int percent) 99layout::fill_rand (int percent)
74{ 100{
156///////////////////////////////////////////////////////////////////////////// 182/////////////////////////////////////////////////////////////////////////////
157// isolation remover - ensures single connected area 183// isolation remover - ensures single connected area
158 184
159typedef fixed_stack<point> pointlist; 185typedef fixed_stack<point> pointlist;
160 186
161static noinline void 187static void noinline
162push_flood_fill (layout &dist, pointlist &seeds, int x, int y) 188push_flood_fill (layout &dist, pointlist &seeds, int x, int y)
163{ 189{
164 if (dist [x][y]) 190 if (dist [x][y])
165 return; 191 return;
166 192
187static inline void 213static inline void
188make_tunnel (layout &dist, pointlist &seeds, int x, int y, U8 d) 214make_tunnel (layout &dist, pointlist &seeds, int x, int y, U8 d)
189{ 215{
190 for (;;) 216 for (;;)
191 { 217 {
218 point neigh[4];
219 int ncnt = 0;
220
192 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);
193 --x;
194 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);
195 ++x;
196 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);
197 --y;
198 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);
199 ++y; 225
200 else 226 if (!ncnt)
201 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;
202 235
203 d = dist [x][y]; 236 d = dist [x][y];
204 dist [x][y] = 1; 237 dist [x][y] = 1;
205 seeds.push (point (x, y));
206 } 238 }
207} 239}
208 240
209static void inline 241static void inline
210maybe_push (layout &dist, pointlist &seeds, int x, int y, U8 d) 242maybe_push (layout &dist, pointlist &seeds, int x, int y, U8 d)
217 return; 249 return;
218 250
219 seeds.push (point (x, y)); 251 seeds.push (point (x, y));
220} 252}
221 253
222void 254// isolation remover, works on a "distance" map
223layout::isolation_remover (bool dirty) 255// the map must be initialised with 0 == rooms, 255 = walls
256static void noinline
257isolation_remover (layout &dist)
224{ 258{
225 layout dist (w, h);
226
227 // dist contains 259 // dist contains
228 // 0 == invisited rooms 260 // 0 == invisited rooms
229 // 1 == visited rooms 261 // 1 == visited rooms
230 // 2+ shortest distance to random near room 262 // 2+ shortest distance to random near room
231 263
232 // phase 1, initialise dist array, find seed 264 // phase 1, find seed
233 int cnt = 0; 265 int cnt = 0;
234 int x, y; 266 int x, y;
235 267
236 for (int i = 0; i < w; ++i) 268 for (int i = 0; i < dist.w; ++i)
237 for (int j = 0; j < h; ++j) 269 for (int j = 0; j < dist.h; ++j)
238 { 270 if (!dist [i][j] && !rmg_rndm (++cnt))
239 if (data [i][j] == '#')
240 dist [i][j] = U8 (255);
241 else
242 {
243 dist [i][j] = 0;
244 if (!rmg_rndm (++cnt))
245 x = i, y = j; 271 x = i, y = j;
246 }
247 }
248 272
249 if (!cnt) 273 if (!cnt)
250 { 274 {
251 // map is completely massive, this is not good, 275 // map is completely massive, this is not good,
252 // so make it empty instead. 276 // so make it empty instead.
253 clear (); 277 dist.clear ();
254 border (); 278 dist.border (255);
255 return; 279 return;
256 } 280 }
257 281
258 fixed_stack<point> seeds (w * h * 5); 282 fixed_stack<point> seeds (dist.w * dist.h * 5);
259 283
260 // found first free space - picking the first one gives 284 // found first free space - picking the first one gives
261 // us a slight bias for tunnels, but usually you won't 285 // us a slight bias for tunnels, but usually you won't
262 // notice that in-game 286 // notice that in-game
263 seeds.push (point (x, y)); 287 seeds.push (point (x, y));
275 y = p.y; 299 y = p.y;
276 300
277 if (!dist [x][y]) 301 if (!dist [x][y])
278 { 302 {
279 // found new isolated area, make tunnel 303 // found new isolated area, make tunnel
280 if (!dirty)
281 push_flood_fill (dist, seeds, x, y); 304 push_flood_fill (dist, seeds, x, y);
282
283 make_tunnel (dist, seeds, x, y, 255); 305 make_tunnel (dist, seeds, x, y, 255);
284
285 if (dirty)
286 push_flood_fill (dist, seeds, x, y);
287 } 306 }
288 else 307 else
289 { 308 {
290 // nothing here, continue to expand 309 // nothing here, continue to expand
291 U8 d = U8 (dist [x][y]) + 1; 310 U8 d = U8 (dist [x][y]) + 1;
294 if (x > 0) maybe_push (dist, seeds, x - 1, y, d); 313 if (x > 0) maybe_push (dist, seeds, x - 1, y, d);
295 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);
296 if (y > 0) maybe_push (dist, seeds, x, y - 1, d); 315 if (y > 0) maybe_push (dist, seeds, x, y - 1, d);
297 } 316 }
298 } 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);
299 330
300 // now copy the tunnels over 331 // now copy the tunnels over
301 for (int x = 0; x < w; ++x) 332 for (int x = 0; x < w; ++x)
302 for (int y = 0; y < h; ++y) 333 for (int y = 0; y < h; ++y)
303 if (data [x][y] == '#' && dist [x][y] == 1) 334 if (data [x][y] == '#' && dist [x][y] == 1)
312{ 343{
313 switch (subtype) 344 switch (subtype)
314 { 345 {
315 // a rough cave 346 // a rough cave
316 case 0: 347 case 0:
317 fill_rand (rmg_rndm (80, 95)); 348 fill_rand (rmg_rndm (85, 97));
318 break; 349 break;
319 350
320 // corridors 351 // corridors
321 case 1: 352 case 1:
322 fill_rand (rmg_rndm (5, 40)); 353 fill_rand (rmg_rndm (5, 40));
865{ 896{
866 demo () 897 demo ()
867 { 898 {
868 rmg_rndm.seed (time (0)); 899 rmg_rndm.seed (time (0));
869 900
870 for(int i=1;i<10;i) 901 for(int i=1;i<100;i++)
871 { 902 {
872 layout maze (10, 10); 903 layout maze (40, 25);
873 maze.fill_rand (90); 904 maze.fill_rand (85);
874 maze.border (); 905 maze.border ();
875 maze.isolation_remover (); 906 maze.isolation_remover ();
876 maze.doorify ();
877 maze.symmetrize (rmg_rndm (2, 4));
878 maze.rotate (rmg_rndm (4));
879 maze.expand2x ();
880 maze.print (); 907 maze.print ();
881 } 908 }
882 909
883 exit (1); 910 exit (1);
884 } 911 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines