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

Comparing deliantra/server/random_maps/random_map.C (file contents):
Revision 1.31 by root, Thu Nov 8 19:43:25 2007 UTC vs.
Revision 1.32 by root, Fri Apr 11 21:09:53 2008 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
22 */ 22 */
23 23
24#include <time.h> 24#include <time.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <global.h> 26#include <global.h>
27#include <maze_gen.h>
28#include <room_gen.h>
29#include <random_map.h> 27#include <random_map.h>
30#include <rproto.h> 28#include <rproto.h>
31#include <sproto.h> 29#include <sproto.h>
32 30
33#define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__); 31#define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__);
55} 53}
56 54
57bool 55bool
58maptile::generate_random_map (random_map_params *RP) 56maptile::generate_random_map (random_map_params *RP)
59{ 57{
60 char **layout, buf[16384]; 58 char buf[16384];
61 int i; 59 int i;
62 60
63 RP->Xsize = RP->xsize; 61 RP->Xsize = RP->xsize;
64 RP->Ysize = RP->ysize; 62 RP->Ysize = RP->ysize;
65 63
134 132
135 /* No style found - choose one randomly */ 133 /* No style found - choose one randomly */
136 if (RP->map_layout_style == LAYOUT_NONE) 134 if (RP->map_layout_style == LAYOUT_NONE)
137 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1; 135 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1;
138 136
139 layout = layoutgen (RP); 137 Maze layout = layoutgen (RP);
140 138
141#ifdef RMAP_DEBUG 139#ifdef RMAP_DEBUG
142 dump_layout (layout, RP); 140 dump_layout (layout, RP);
143#endif 141#endif
144 142
211 209
212 CEDE; 210 CEDE;
213 211
214 unblock_exits (this, layout, RP); 212 unblock_exits (this, layout, RP);
215 213
216 /* free the layout */ 214 layout.free ();
217 for (i = 0; i < RP->Xsize; i++)
218 free (layout[i]);
219
220 free (layout);
221 215
222 msg = strdup (buf); 216 msg = strdup (buf);
223 in_memory = MAP_IN_MEMORY; 217 in_memory = MAP_IN_MEMORY;
224 218
225 CEDE; 219 CEDE;
227 return 1; 221 return 1;
228} 222}
229 223
230/* function selects the layout function and gives it whatever 224/* function selects the layout function and gives it whatever
231 arguments it needs. */ 225 arguments it needs. */
232char ** 226Maze
233layoutgen (random_map_params *RP) 227layoutgen (random_map_params *RP)
234{ 228{
235 char **maze = 0; 229 Maze maze;
230
236 int oxsize = RP->Xsize, oysize = RP->Ysize; 231 int oxsize = RP->Xsize, oysize = RP->Ysize;
237 232
238 switch (RP->map_layout_style) 233 switch (RP->map_layout_style)
239 { 234 {
240 case LAYOUT_ONION: 235 case LAYOUT_ONION:
241 maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2); 236 maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
237
242 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) 238 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY))
243 roomify_layout (maze, RP); 239 roomify_layout (maze, RP);
240
244 break; 241 break;
245 242
246 case LAYOUT_MAZE: 243 case LAYOUT_MAZE:
247 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2)); 244 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2));
245
248 if (!(rndm (2))) 246 if (!(rndm (2)))
249 doorify_layout (maze, RP); 247 doorify_layout (maze, RP);
248
250 break; 249 break;
251 250
252 case LAYOUT_SPIRAL: 251 case LAYOUT_SPIRAL:
253 maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1); 252 maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1);
253
254 if (!(rndm (2))) 254 if (!(rndm (2)))
255 doorify_layout (maze, RP); 255 doorify_layout (maze, RP);
256
256 break; 257 break;
257 258
258 case LAYOUT_ROGUELIKE: 259 case LAYOUT_ROGUELIKE:
259 /* Don't put symmetry in rogue maps. There isn't much reason to 260 /* Don't put symmetry in rogue maps. There isn't much reason to
260 * do so in the first place (doesn't make it any more interesting), 261 * do so in the first place (doesn't make it any more interesting),
270 /* no doorifying... done already */ 271 /* no doorifying... done already */
271 break; 272 break;
272 273
273 case LAYOUT_SNAKE: 274 case LAYOUT_SNAKE:
274 maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); 275 maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
276
275 if (rndm (2)) 277 if (rndm (2))
276 roomify_layout (maze, RP); 278 roomify_layout (maze, RP);
279
277 break; 280 break;
278 281
279 case LAYOUT_SQUARE_SPIRAL: 282 case LAYOUT_SQUARE_SPIRAL:
280 maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); 283 maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
284
281 if (rndm (2)) 285 if (rndm (2))
282 roomify_layout (maze, RP); 286 roomify_layout (maze, RP);
287
283 break; 288 break;
289
290 default:
291 abort ();
284 } 292 }
285 293
286 maze = symmetrize_layout (maze, RP->symmetry_used, RP); 294 maze = symmetrize_layout (maze, RP->symmetry_used, RP);
287 295
288#ifdef RMAP_DEBUG 296#ifdef RMAP_DEBUG
299 return maze; 307 return maze;
300} 308}
301 309
302/* takes a map and makes it symmetric: adjusts Xsize and 310/* takes a map and makes it symmetric: adjusts Xsize and
303Ysize to produce a symmetric map. */ 311Ysize to produce a symmetric map. */
304char ** 312Maze
305symmetrize_layout (char **maze, int sym, random_map_params *RP) 313symmetrize_layout (Maze maze, int sym, random_map_params *RP)
306{ 314{
307 int i, j; 315 int i, j;
308 char **sym_maze;
309 int Xsize_orig, Ysize_orig; 316 int Xsize_orig, Ysize_orig;
310 317
311 Xsize_orig = RP->Xsize; 318 Xsize_orig = RP->Xsize;
312 Ysize_orig = RP->Ysize; 319 Ysize_orig = RP->Ysize;
320
313 RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */ 321 RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */
322
314 if (sym == SYMMETRY_NONE) 323 if (sym == SYMMETRY_NONE)
315 { 324 {
316 RP->Xsize = Xsize_orig; 325 RP->Xsize = Xsize_orig;
317 RP->Ysize = Ysize_orig; 326 RP->Ysize = Ysize_orig;
327
318 return maze; 328 return maze;
319 } 329 }
330
320 /* pick new sizes */ 331 /* pick new sizes */
321 RP->Xsize = ((sym == SYMMETRY_X || sym == SYMMETRY_XY) ? RP->Xsize * 2 - 3 : RP->Xsize); 332 RP->Xsize = ((sym == SYMMETRY_X || sym == SYMMETRY_XY) ? RP->Xsize * 2 - 3 : RP->Xsize);
322 RP->Ysize = ((sym == SYMMETRY_Y || sym == SYMMETRY_XY) ? RP->Ysize * 2 - 3 : RP->Ysize); 333 RP->Ysize = ((sym == SYMMETRY_Y || sym == SYMMETRY_XY) ? RP->Ysize * 2 - 3 : RP->Ysize);
323 334
324 sym_maze = (char **) calloc (sizeof (char *), RP->Xsize); 335 Maze sym_maze (RP);
325 for (i = 0; i < RP->Xsize; i++)
326 sym_maze[i] = (char *) calloc (sizeof (char), RP->Ysize);
327 336
328 if (sym == SYMMETRY_X) 337 if (sym == SYMMETRY_X)
329 for (i = 0; i < RP->Xsize / 2 + 1; i++) 338 for (i = 0; i < RP->Xsize / 2 + 1; i++)
330 for (j = 0; j < RP->Ysize; j++) 339 for (j = 0; j < RP->Ysize; j++)
331 { 340 {
332 sym_maze[i][j] = maze[i][j]; 341 sym_maze[i][j] = maze[i][j];
333 sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; 342 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
334 }; 343 }
344
335 if (sym == SYMMETRY_Y) 345 if (sym == SYMMETRY_Y)
336 for (i = 0; i < RP->Xsize; i++) 346 for (i = 0; i < RP->Xsize; i++)
337 for (j = 0; j < RP->Ysize / 2 + 1; j++) 347 for (j = 0; j < RP->Ysize / 2 + 1; j++)
338 { 348 {
339 sym_maze[i][j] = maze[i][j]; 349 sym_maze[i][j] = maze[i][j];
340 sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; 350 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
341 } 351 }
352
342 if (sym == SYMMETRY_XY) 353 if (sym == SYMMETRY_XY)
343 for (i = 0; i < RP->Xsize / 2 + 1; i++) 354 for (i = 0; i < RP->Xsize / 2 + 1; i++)
344 for (j = 0; j < RP->Ysize / 2 + 1; j++) 355 for (j = 0; j < RP->Ysize / 2 + 1; j++)
345 { 356 {
346 sym_maze[i][j] = maze[i][j]; 357 sym_maze[i][j] = maze[i][j];
347 sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; 358 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
348 sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; 359 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
349 sym_maze[RP->Xsize - i - 1][RP->Ysize - j - 1] = maze[i][j]; 360 sym_maze[RP->Xsize - i - 1][RP->Ysize - j - 1] = maze[i][j];
350 } 361 }
351 /* delete the old maze */ 362
352 for (i = 0; i < Xsize_orig; i++) 363 maze.free ();
353 free (maze[i]); 364
354 free (maze);
355 /* reconnect disjointed spirals */ 365 /* reconnect disjointed spirals */
356 if (RP->map_layout_style == LAYOUT_SPIRAL) 366 if (RP->map_layout_style == LAYOUT_SPIRAL)
357 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); 367 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
368
358 /* reconnect disjointed nethackmazes: the routine for 369 /* reconnect disjointed nethackmazes: the routine for
359 spirals will do the trick? */ 370 spirals will do the trick? */
360 if (RP->map_layout_style == LAYOUT_ROGUELIKE) 371 if (RP->map_layout_style == LAYOUT_ROGUELIKE)
361 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); 372 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
362 373
363 return sym_maze; 374 return sym_maze;
364} 375}
365 376
366
367/* takes a map and rotates it. This completes the 377/* takes a map and rotates it. This completes the
368 onion layouts, making them possibly centered on any wall. 378 onion layouts, making them possibly centered on any wall.
369 It'll modify Xsize and Ysize if they're swapped. 379 It'll modify Xsize and Ysize if they're swapped.
370*/ 380*/
371 381Maze
372char **
373rotate_layout (char **maze, int rotation, random_map_params *RP) 382rotate_layout (Maze maze, int rotation, random_map_params *RP)
374{ 383{
375 char **new_maze;
376 int i, j;
377
378 switch (rotation) 384 switch (rotation)
379 { 385 {
380 case 0:
381 return maze;
382 break;
383 case 2: /* a reflection */ 386 case 2: /* a reflection */
384 { 387 {
385 char *newmaze = (char *) malloc (sizeof (char) * RP->Xsize * RP->Ysize); 388 Maze new_maze (RP);
386 389
387 for (i = 0; i < RP->Xsize; i++) 390 for (int i = 0; i < RP->Xsize; i++) /* copy a reflection back */
388 { /* make a copy */
389 for (j = 0; j < RP->Ysize; j++) 391 for (int j = 0; j < RP->Ysize; j++)
390 { 392 new_maze[i][j] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
391 newmaze[i * RP->Ysize + j] = maze[i][j]; 393
392 } 394 maze.free ();
395 maze = new_maze;
393 } 396 }
394 for (i = 0; i < RP->Xsize; i++) 397
395 { /* copy a reflection back */
396 for (j = 0; j < RP->Ysize; j++)
397 {
398 maze[i][j] = newmaze[(RP->Xsize - i - 1) * RP->Ysize + RP->Ysize - j - 1];
399 }
400 }
401 free (newmaze);
402 return maze;
403 break;
404 }
405 case 1: 398 case 1:
406 case 3: 399 case 3:
407 { 400 {
408 int swap; 401 Maze new_maze (RP->Ysize, RP->Xsize);
409 new_maze = (char **) calloc (sizeof (char *), RP->Ysize); 402
410 for (i = 0; i < RP->Ysize; i++)
411 {
412 new_maze[i] = (char *) calloc (sizeof (char), RP->Xsize);
413 }
414 if (rotation == 1) /* swap x and y */ 403 if (rotation == 1) /* swap x and y */
415 for (i = 0; i < RP->Xsize; i++) 404 for (int i = 0; i < RP->Xsize; i++)
416 for (j = 0; j < RP->Ysize; j++) 405 for (int j = 0; j < RP->Ysize; j++)
417 new_maze[j][i] = maze[i][j]; 406 new_maze[j][i] = maze[i][j];
418 407
419 if (rotation == 3) 408 if (rotation == 3) /* swap x and y */
420 { /* swap x and y */
421 for (i = 0; i < RP->Xsize; i++) 409 for (int i = 0; i < RP->Xsize; i++)
422 for (j = 0; j < RP->Ysize; j++) 410 for (int j = 0; j < RP->Ysize; j++)
423 new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1]; 411 new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
412
413 maze.free ();
414 maze = new_maze;
415 swap (RP->Xsize, RP->Ysize);
424 } 416 }
425
426 /* delete the old layout */
427 for (i = 0; i < RP->Xsize; i++)
428 free (maze[i]);
429 free (maze);
430
431 swap = RP->Ysize;
432 RP->Ysize = RP->Xsize;
433 RP->Xsize = swap;
434 return new_maze;
435 break;
436 }
437 } 417 }
438 return NULL; 418
419 return maze;
439} 420}
440 421
441/* take a layout and make some rooms in it. 422/* take a layout and make some rooms in it.
442 --works best on onions.*/ 423 --works best on onions.*/
443void 424void
595/* puts doors at appropriate locations in a layout. */ 576/* puts doors at appropriate locations in a layout. */
596void 577void
597doorify_layout (char **maze, random_map_params *RP) 578doorify_layout (char **maze, random_map_params *RP)
598{ 579{
599 int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */ 580 int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */
600 char *doorlist_x;
601 char *doorlist_y;
602 int doorlocs = 0; /* # of available doorlocations */ 581 int doorlocs = 0; /* # of available doorlocations */
603 int i, j; 582 int i, j;
604 583
605 doorlist_x = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize); 584 char *doorlist_x = salloc<char> (RP->Xsize * RP->Ysize);
606 doorlist_y = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize); 585 char *doorlist_y = salloc<char> (RP->Xsize * RP->Ysize);
607
608 586
609 /* make a list of possible door locations */ 587 /* make a list of possible door locations */
610 for (i = 1; i < RP->Xsize - 1; i++) 588 for (i = 1; i < RP->Xsize - 1; i++)
611 for (j = 1; j < RP->Ysize - 1; j++) 589 for (j = 1; j < RP->Ysize - 1; j++)
612 { 590 {
640 doorlocs--; 618 doorlocs--;
641 doorlist_x[di] = doorlist_x[doorlocs]; 619 doorlist_x[di] = doorlist_x[doorlocs];
642 doorlist_y[di] = doorlist_y[doorlocs]; 620 doorlist_y[di] = doorlist_y[doorlocs];
643 } 621 }
644 622
645 free (doorlist_x); 623 sfree (doorlist_x, RP->Xsize * RP->Ysize);
646 free (doorlist_y); 624 sfree (doorlist_y, RP->Xsize * RP->Ysize);
647} 625}
648 626
649void 627void
650write_map_parameters_to_string (char *buf, random_map_params *RP) 628write_map_parameters_to_string (char *buf, random_map_params *RP)
651{ 629{
1013 991
1014 walk->copy_to (tmp); 992 walk->copy_to (tmp);
1015 insert_ob_in_ob (tmp, dest_ob); 993 insert_ob_in_ob (tmp, dest_ob);
1016 } 994 }
1017} 995}
996
997MazeData::MazeData (int xsize, int ysize)
998{
999 int size = xsize * ysize
1000 + sizeof (char *) * xsize
1001 + sizeof (char *);
1002
1003 col = (char **)salloc0<char> (size);
1004 *col++ = (char *)size;
1005
1006 char *data = (char *)(col + xsize);
1007
1008 for (int x = xsize; x--; )
1009 col [x] = data + x * ysize;
1010}
1011
1012MazeData::~MazeData ()
1013{
1014 int size = (long)*--col;
1015 sfree ((char *)col, size);
1016}
1017

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines