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.29 by root, Tue Apr 17 10:06:34 2007 UTC vs.
Revision 1.32 by root, Fri Apr 11 21:09:53 2008 UTC

1/* 1/*
2 * CrossFire, A Multiplayer game for X-windows 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (C) 2001 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * This program 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
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * 20 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de> 21 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 22 */
24 23
25#include <time.h> 24#include <time.h>
26#include <stdio.h> 25#include <stdio.h>
27#include <global.h> 26#include <global.h>
28#include <maze_gen.h>
29#include <room_gen.h>
30#include <random_map.h> 27#include <random_map.h>
31#include <rproto.h> 28#include <rproto.h>
32#include <sproto.h> 29#include <sproto.h>
33 30
34#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__);
56} 53}
57 54
58bool 55bool
59maptile::generate_random_map (random_map_params *RP) 56maptile::generate_random_map (random_map_params *RP)
60{ 57{
61 char **layout, buf[16384]; 58 char buf[16384];
62 int i; 59 int i;
63 60
64 RP->Xsize = RP->xsize; 61 RP->Xsize = RP->xsize;
65 RP->Ysize = RP->ysize; 62 RP->Ysize = RP->ysize;
66 63
135 132
136 /* No style found - choose one randomly */ 133 /* No style found - choose one randomly */
137 if (RP->map_layout_style == LAYOUT_NONE) 134 if (RP->map_layout_style == LAYOUT_NONE)
138 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1; 135 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1;
139 136
140 layout = layoutgen (RP); 137 Maze layout = layoutgen (RP);
141 138
142#ifdef RMAP_DEBUG 139#ifdef RMAP_DEBUG
143 dump_layout (layout, RP); 140 dump_layout (layout, RP);
144#endif 141#endif
145 142
212 209
213 CEDE; 210 CEDE;
214 211
215 unblock_exits (this, layout, RP); 212 unblock_exits (this, layout, RP);
216 213
217 /* free the layout */ 214 layout.free ();
218 for (i = 0; i < RP->Xsize; i++)
219 free (layout[i]);
220
221 free (layout);
222 215
223 msg = strdup (buf); 216 msg = strdup (buf);
224 in_memory = MAP_IN_MEMORY; 217 in_memory = MAP_IN_MEMORY;
225 218
226 CEDE; 219 CEDE;
228 return 1; 221 return 1;
229} 222}
230 223
231/* function selects the layout function and gives it whatever 224/* function selects the layout function and gives it whatever
232 arguments it needs. */ 225 arguments it needs. */
233char ** 226Maze
234layoutgen (random_map_params *RP) 227layoutgen (random_map_params *RP)
235{ 228{
236 char **maze = 0; 229 Maze maze;
230
237 int oxsize = RP->Xsize, oysize = RP->Ysize; 231 int oxsize = RP->Xsize, oysize = RP->Ysize;
238 232
239 switch (RP->map_layout_style) 233 switch (RP->map_layout_style)
240 { 234 {
241 case LAYOUT_ONION: 235 case LAYOUT_ONION:
242 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
243 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY)) 238 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY))
244 roomify_layout (maze, RP); 239 roomify_layout (maze, RP);
240
245 break; 241 break;
246 242
247 case LAYOUT_MAZE: 243 case LAYOUT_MAZE:
248 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2)); 244 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2));
245
249 if (!(rndm (2))) 246 if (!(rndm (2)))
250 doorify_layout (maze, RP); 247 doorify_layout (maze, RP);
248
251 break; 249 break;
252 250
253 case LAYOUT_SPIRAL: 251 case LAYOUT_SPIRAL:
254 maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1); 252 maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1);
253
255 if (!(rndm (2))) 254 if (!(rndm (2)))
256 doorify_layout (maze, RP); 255 doorify_layout (maze, RP);
256
257 break; 257 break;
258 258
259 case LAYOUT_ROGUELIKE: 259 case LAYOUT_ROGUELIKE:
260 /* 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
261 * 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),
271 /* no doorifying... done already */ 271 /* no doorifying... done already */
272 break; 272 break;
273 273
274 case LAYOUT_SNAKE: 274 case LAYOUT_SNAKE:
275 maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); 275 maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
276
276 if (rndm (2)) 277 if (rndm (2))
277 roomify_layout (maze, RP); 278 roomify_layout (maze, RP);
279
278 break; 280 break;
279 281
280 case LAYOUT_SQUARE_SPIRAL: 282 case LAYOUT_SQUARE_SPIRAL:
281 maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1); 283 maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
284
282 if (rndm (2)) 285 if (rndm (2))
283 roomify_layout (maze, RP); 286 roomify_layout (maze, RP);
287
284 break; 288 break;
289
290 default:
291 abort ();
285 } 292 }
286 293
287 maze = symmetrize_layout (maze, RP->symmetry_used, RP); 294 maze = symmetrize_layout (maze, RP->symmetry_used, RP);
288 295
289#ifdef RMAP_DEBUG 296#ifdef RMAP_DEBUG
300 return maze; 307 return maze;
301} 308}
302 309
303/* takes a map and makes it symmetric: adjusts Xsize and 310/* takes a map and makes it symmetric: adjusts Xsize and
304Ysize to produce a symmetric map. */ 311Ysize to produce a symmetric map. */
305char ** 312Maze
306symmetrize_layout (char **maze, int sym, random_map_params *RP) 313symmetrize_layout (Maze maze, int sym, random_map_params *RP)
307{ 314{
308 int i, j; 315 int i, j;
309 char **sym_maze;
310 int Xsize_orig, Ysize_orig; 316 int Xsize_orig, Ysize_orig;
311 317
312 Xsize_orig = RP->Xsize; 318 Xsize_orig = RP->Xsize;
313 Ysize_orig = RP->Ysize; 319 Ysize_orig = RP->Ysize;
320
314 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
315 if (sym == SYMMETRY_NONE) 323 if (sym == SYMMETRY_NONE)
316 { 324 {
317 RP->Xsize = Xsize_orig; 325 RP->Xsize = Xsize_orig;
318 RP->Ysize = Ysize_orig; 326 RP->Ysize = Ysize_orig;
327
319 return maze; 328 return maze;
320 } 329 }
330
321 /* pick new sizes */ 331 /* pick new sizes */
322 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);
323 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);
324 334
325 sym_maze = (char **) calloc (sizeof (char *), RP->Xsize); 335 Maze sym_maze (RP);
326 for (i = 0; i < RP->Xsize; i++)
327 sym_maze[i] = (char *) calloc (sizeof (char), RP->Ysize);
328 336
329 if (sym == SYMMETRY_X) 337 if (sym == SYMMETRY_X)
330 for (i = 0; i < RP->Xsize / 2 + 1; i++) 338 for (i = 0; i < RP->Xsize / 2 + 1; i++)
331 for (j = 0; j < RP->Ysize; j++) 339 for (j = 0; j < RP->Ysize; j++)
332 { 340 {
333 sym_maze[i][j] = maze[i][j]; 341 sym_maze[i][j] = maze[i][j];
334 sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; 342 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
335 }; 343 }
344
336 if (sym == SYMMETRY_Y) 345 if (sym == SYMMETRY_Y)
337 for (i = 0; i < RP->Xsize; i++) 346 for (i = 0; i < RP->Xsize; i++)
338 for (j = 0; j < RP->Ysize / 2 + 1; j++) 347 for (j = 0; j < RP->Ysize / 2 + 1; j++)
339 { 348 {
340 sym_maze[i][j] = maze[i][j]; 349 sym_maze[i][j] = maze[i][j];
341 sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; 350 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
342 } 351 }
352
343 if (sym == SYMMETRY_XY) 353 if (sym == SYMMETRY_XY)
344 for (i = 0; i < RP->Xsize / 2 + 1; i++) 354 for (i = 0; i < RP->Xsize / 2 + 1; i++)
345 for (j = 0; j < RP->Ysize / 2 + 1; j++) 355 for (j = 0; j < RP->Ysize / 2 + 1; j++)
346 { 356 {
347 sym_maze[i][j] = maze[i][j]; 357 sym_maze[i][j] = maze[i][j];
348 sym_maze[i][RP->Ysize - j - 1] = maze[i][j]; 358 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
349 sym_maze[RP->Xsize - i - 1][j] = maze[i][j]; 359 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
350 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];
351 } 361 }
352 /* delete the old maze */ 362
353 for (i = 0; i < Xsize_orig; i++) 363 maze.free ();
354 free (maze[i]); 364
355 free (maze);
356 /* reconnect disjointed spirals */ 365 /* reconnect disjointed spirals */
357 if (RP->map_layout_style == LAYOUT_SPIRAL) 366 if (RP->map_layout_style == LAYOUT_SPIRAL)
358 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); 367 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
368
359 /* reconnect disjointed nethackmazes: the routine for 369 /* reconnect disjointed nethackmazes: the routine for
360 spirals will do the trick? */ 370 spirals will do the trick? */
361 if (RP->map_layout_style == LAYOUT_ROGUELIKE) 371 if (RP->map_layout_style == LAYOUT_ROGUELIKE)
362 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze); 372 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
363 373
364 return sym_maze; 374 return sym_maze;
365} 375}
366 376
367
368/* takes a map and rotates it. This completes the 377/* takes a map and rotates it. This completes the
369 onion layouts, making them possibly centered on any wall. 378 onion layouts, making them possibly centered on any wall.
370 It'll modify Xsize and Ysize if they're swapped. 379 It'll modify Xsize and Ysize if they're swapped.
371*/ 380*/
372 381Maze
373char **
374rotate_layout (char **maze, int rotation, random_map_params *RP) 382rotate_layout (Maze maze, int rotation, random_map_params *RP)
375{ 383{
376 char **new_maze;
377 int i, j;
378
379 switch (rotation) 384 switch (rotation)
380 { 385 {
381 case 0:
382 return maze;
383 break;
384 case 2: /* a reflection */ 386 case 2: /* a reflection */
385 { 387 {
386 char *newmaze = (char *) malloc (sizeof (char) * RP->Xsize * RP->Ysize); 388 Maze new_maze (RP);
387 389
388 for (i = 0; i < RP->Xsize; i++) 390 for (int i = 0; i < RP->Xsize; i++) /* copy a reflection back */
389 { /* make a copy */
390 for (j = 0; j < RP->Ysize; j++) 391 for (int j = 0; j < RP->Ysize; j++)
391 { 392 new_maze[i][j] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
392 newmaze[i * RP->Ysize + j] = maze[i][j]; 393
393 } 394 maze.free ();
395 maze = new_maze;
394 } 396 }
395 for (i = 0; i < RP->Xsize; i++) 397
396 { /* copy a reflection back */
397 for (j = 0; j < RP->Ysize; j++)
398 {
399 maze[i][j] = newmaze[(RP->Xsize - i - 1) * RP->Ysize + RP->Ysize - j - 1];
400 }
401 }
402 free (newmaze);
403 return maze;
404 break;
405 }
406 case 1: 398 case 1:
407 case 3: 399 case 3:
408 { 400 {
409 int swap; 401 Maze new_maze (RP->Ysize, RP->Xsize);
410 new_maze = (char **) calloc (sizeof (char *), RP->Ysize); 402
411 for (i = 0; i < RP->Ysize; i++)
412 {
413 new_maze[i] = (char *) calloc (sizeof (char), RP->Xsize);
414 }
415 if (rotation == 1) /* swap x and y */ 403 if (rotation == 1) /* swap x and y */
416 for (i = 0; i < RP->Xsize; i++) 404 for (int i = 0; i < RP->Xsize; i++)
417 for (j = 0; j < RP->Ysize; j++) 405 for (int j = 0; j < RP->Ysize; j++)
418 new_maze[j][i] = maze[i][j]; 406 new_maze[j][i] = maze[i][j];
419 407
420 if (rotation == 3) 408 if (rotation == 3) /* swap x and y */
421 { /* swap x and y */
422 for (i = 0; i < RP->Xsize; i++) 409 for (int i = 0; i < RP->Xsize; i++)
423 for (j = 0; j < RP->Ysize; j++) 410 for (int j = 0; j < RP->Ysize; j++)
424 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);
425 } 416 }
426
427 /* delete the old layout */
428 for (i = 0; i < RP->Xsize; i++)
429 free (maze[i]);
430 free (maze);
431
432 swap = RP->Ysize;
433 RP->Ysize = RP->Xsize;
434 RP->Xsize = swap;
435 return new_maze;
436 break;
437 }
438 } 417 }
439 return NULL; 418
419 return maze;
440} 420}
441 421
442/* take a layout and make some rooms in it. 422/* take a layout and make some rooms in it.
443 --works best on onions.*/ 423 --works best on onions.*/
444void 424void
596/* puts doors at appropriate locations in a layout. */ 576/* puts doors at appropriate locations in a layout. */
597void 577void
598doorify_layout (char **maze, random_map_params *RP) 578doorify_layout (char **maze, random_map_params *RP)
599{ 579{
600 int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */ 580 int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */
601 char *doorlist_x;
602 char *doorlist_y;
603 int doorlocs = 0; /* # of available doorlocations */ 581 int doorlocs = 0; /* # of available doorlocations */
604 int i, j; 582 int i, j;
605 583
606 doorlist_x = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize); 584 char *doorlist_x = salloc<char> (RP->Xsize * RP->Ysize);
607 doorlist_y = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize); 585 char *doorlist_y = salloc<char> (RP->Xsize * RP->Ysize);
608
609 586
610 /* make a list of possible door locations */ 587 /* make a list of possible door locations */
611 for (i = 1; i < RP->Xsize - 1; i++) 588 for (i = 1; i < RP->Xsize - 1; i++)
612 for (j = 1; j < RP->Ysize - 1; j++) 589 for (j = 1; j < RP->Ysize - 1; j++)
613 { 590 {
641 doorlocs--; 618 doorlocs--;
642 doorlist_x[di] = doorlist_x[doorlocs]; 619 doorlist_x[di] = doorlist_x[doorlocs];
643 doorlist_y[di] = doorlist_y[doorlocs]; 620 doorlist_y[di] = doorlist_y[doorlocs];
644 } 621 }
645 622
646 free (doorlist_x); 623 sfree (doorlist_x, RP->Xsize * RP->Ysize);
647 free (doorlist_y); 624 sfree (doorlist_y, RP->Xsize * RP->Ysize);
648} 625}
649 626
650void 627void
651write_map_parameters_to_string (char *buf, random_map_params *RP) 628write_map_parameters_to_string (char *buf, random_map_params *RP)
652{ 629{
1014 991
1015 walk->copy_to (tmp); 992 walk->copy_to (tmp);
1016 insert_ob_in_ob (tmp, dest_ob); 993 insert_ob_in_ob (tmp, dest_ob);
1017 } 994 }
1018} 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