ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.30
Committed: Sun Jul 1 05:00:19 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.29: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 #include <time.h>
25 #include <stdio.h>
26 #include <global.h>
27 #include <maze_gen.h>
28 #include <room_gen.h>
29 #include <random_map.h>
30 #include <rproto.h>
31 #include <sproto.h>
32
33 #define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__);
34
35 void
36 dump_layout (char **layout, random_map_params *RP)
37 {
38 {
39 int i, j;
40
41 for (i = 0; i < RP->Xsize; i++)
42 {
43 for (j = 0; j < RP->Ysize; j++)
44 {
45 if (layout[i][j] == 0)
46 layout[i][j] = ' ';
47 printf ("%c", layout[i][j]);
48 if (layout[i][j] == ' ')
49 layout[i][j] = 0;
50 }
51 printf ("\n");
52 }
53 }
54 printf ("\n");
55 }
56
57 bool
58 maptile::generate_random_map (random_map_params *RP)
59 {
60 char **layout, buf[16384];
61 int i;
62
63 RP->Xsize = RP->xsize;
64 RP->Ysize = RP->ysize;
65
66 /* pick a random seed, or use the one from the input file */
67 RP->random_seed = RP->random_seed
68 ? RP->random_seed + RP->dungeon_level
69 : time (0);
70 CEDE;
71
72 write_map_parameters_to_string (buf, RP);
73
74 if (RP->difficulty == 0)
75 {
76 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
77
78 if (RP->difficulty_increase > 0.001)
79 RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
80
81 if (RP->difficulty < 1)
82 RP->difficulty = 1;
83 }
84 else
85 RP->difficulty_given = 1;
86
87 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
88 RP->Xsize = MIN_RANDOM_MAP_SIZE + rndm (25) + 5;
89
90 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
91 RP->Ysize = MIN_RANDOM_MAP_SIZE + rndm (25) + 5;
92
93 if (RP->symmetry == SYMMETRY_RANDOM)
94 RP->symmetry_used = rndm (SYMMETRY_XY) + 1;
95 else
96 RP->symmetry_used = RP->symmetry;
97
98 if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
99 RP->Ysize = RP->Ysize / 2 + 1;
100
101 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
102 RP->Xsize = RP->Xsize / 2 + 1;
103
104 if (RP->expand2x > 0)
105 {
106 RP->Xsize /= 2;
107 RP->Ysize /= 2;
108 }
109
110 RP->map_layout_style = LAYOUT_NONE;
111
112 /* Redo this - there was a lot of redundant code of checking for preset
113 * layout style and then random layout style. Instead, figure out
114 * the numeric layoutstyle, so there is only one area that actually
115 * calls the code to make the maps.
116 */
117 if (strstr (RP->layoutstyle, "onion"))
118 RP->map_layout_style = LAYOUT_ONION;
119
120 if (strstr (RP->layoutstyle, "maze"))
121 RP->map_layout_style = LAYOUT_MAZE;
122
123 if (strstr (RP->layoutstyle, "spiral"))
124 RP->map_layout_style = LAYOUT_SPIRAL;
125
126 if (strstr (RP->layoutstyle, "rogue"))
127 RP->map_layout_style = LAYOUT_ROGUELIKE;
128
129 if (strstr (RP->layoutstyle, "snake"))
130 RP->map_layout_style = LAYOUT_SNAKE;
131
132 if (strstr (RP->layoutstyle, "squarespiral"))
133 RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
134
135 /* No style found - choose one randomly */
136 if (RP->map_layout_style == LAYOUT_NONE)
137 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1;
138
139 layout = layoutgen (RP);
140
141 #ifdef RMAP_DEBUG
142 dump_layout (layout, RP);
143 #endif
144
145 /* increment these for the current map */
146 RP->dungeon_level += 1;
147 /* allow constant-difficulty maps. */
148 /* difficulty+=1; */
149
150 /* rotate the layout randomly */
151 layout = rotate_layout (layout, rndm (4), RP);
152 #ifdef RMAP_DEBUG
153 dump_layout (layout, RP);
154 #endif
155
156 /* allocate the map and set the floor */
157 make_map_floor (layout, RP->floorstyle, RP);
158
159 /* set region */
160 default_region = RP->region;
161
162 CEDE;
163
164 /* create walls unless the wallstyle is "none" */
165 if (strcmp (RP->wallstyle, "none"))
166 {
167 make_map_walls (this, layout, RP->wallstyle, RP);
168
169 /* place doors unless doorstyle or wallstyle is "none" */
170 if (strcmp (RP->doorstyle, "none"))
171 put_doors (this, layout, RP->doorstyle, RP);
172 }
173
174 CEDE;
175
176 /* create exits unless the exitstyle is "none" */
177 if (strcmp (RP->exitstyle, "none"))
178 place_exits (this, layout, RP->exitstyle, RP->orientation, RP);
179
180 CEDE;
181
182 place_specials_in_map (this, layout, RP);
183
184 CEDE;
185
186 /* create monsters unless the monsterstyle is "none" */
187 if (strcmp (RP->monsterstyle, "none"))
188 place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
189
190 CEDE;
191
192 /* treasures needs to have a proper difficulty set for the map. */
193 difficulty = estimate_difficulty ();
194
195 CEDE;
196
197 /* create treasure unless the treasurestyle is "none" */
198 if (strcmp (RP->treasurestyle, "none"))
199 place_treasure (this, layout, RP->treasurestyle, RP->treasureoptions, RP);
200
201 CEDE;
202
203 /* create decor unless the decorstyle is "none" */
204 if (strcmp (RP->decorstyle, "none"))
205 put_decor (this, layout, RP->decorstyle, RP->decoroptions, RP);
206
207 CEDE;
208
209 /* generate treasures, etc. */
210 fix_auto_apply ();
211
212 CEDE;
213
214 unblock_exits (this, layout, RP);
215
216 /* free the layout */
217 for (i = 0; i < RP->Xsize; i++)
218 free (layout[i]);
219
220 free (layout);
221
222 msg = strdup (buf);
223 in_memory = MAP_IN_MEMORY;
224
225 CEDE;
226
227 return 1;
228 }
229
230 /* function selects the layout function and gives it whatever
231 arguments it needs. */
232 char **
233 layoutgen (random_map_params *RP)
234 {
235 char **maze = 0;
236 int oxsize = RP->Xsize, oysize = RP->Ysize;
237
238 switch (RP->map_layout_style)
239 {
240 case LAYOUT_ONION:
241 maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
242 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY))
243 roomify_layout (maze, RP);
244 break;
245
246 case LAYOUT_MAZE:
247 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2));
248 if (!(rndm (2)))
249 doorify_layout (maze, RP);
250 break;
251
252 case LAYOUT_SPIRAL:
253 maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1);
254 if (!(rndm (2)))
255 doorify_layout (maze, RP);
256 break;
257
258 case LAYOUT_ROGUELIKE:
259 /* 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 * but more importantly, the symmetry code presumes we are symmetrizing
262 * spirals, or maps with lots of passages - making a symmetric rogue
263 * map fails because its likely that the passages the symmetry process
264 * creates may not connect the rooms.
265 */
266 RP->symmetry_used = SYMMETRY_NONE;
267 RP->Ysize = oysize;
268 RP->Xsize = oxsize;
269 maze = roguelike_layout_gen (RP->Xsize, RP->Ysize, RP->layoutoptions1);
270 /* no doorifying... done already */
271 break;
272
273 case LAYOUT_SNAKE:
274 maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
275 if (rndm (2))
276 roomify_layout (maze, RP);
277 break;
278
279 case LAYOUT_SQUARE_SPIRAL:
280 maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
281 if (rndm (2))
282 roomify_layout (maze, RP);
283 break;
284 }
285
286 maze = symmetrize_layout (maze, RP->symmetry_used, RP);
287
288 #ifdef RMAP_DEBUG
289 dump_layout (maze, RP);
290 #endif
291
292 if (RP->expand2x)
293 {
294 maze = expand2x (maze, RP->Xsize, RP->Ysize);
295 RP->Xsize = RP->Xsize * 2 - 1;
296 RP->Ysize = RP->Ysize * 2 - 1;
297 }
298
299 return maze;
300 }
301
302 /* takes a map and makes it symmetric: adjusts Xsize and
303 Ysize to produce a symmetric map. */
304 char **
305 symmetrize_layout (char **maze, int sym, random_map_params *RP)
306 {
307 int i, j;
308 char **sym_maze;
309 int Xsize_orig, Ysize_orig;
310
311 Xsize_orig = RP->Xsize;
312 Ysize_orig = RP->Ysize;
313 RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */
314 if (sym == SYMMETRY_NONE)
315 {
316 RP->Xsize = Xsize_orig;
317 RP->Ysize = Ysize_orig;
318 return maze;
319 }
320 /* pick new sizes */
321 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);
323
324 sym_maze = (char **) calloc (sizeof (char *), RP->Xsize);
325 for (i = 0; i < RP->Xsize; i++)
326 sym_maze[i] = (char *) calloc (sizeof (char), RP->Ysize);
327
328 if (sym == SYMMETRY_X)
329 for (i = 0; i < RP->Xsize / 2 + 1; i++)
330 for (j = 0; j < RP->Ysize; j++)
331 {
332 sym_maze[i][j] = maze[i][j];
333 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
334 };
335 if (sym == SYMMETRY_Y)
336 for (i = 0; i < RP->Xsize; i++)
337 for (j = 0; j < RP->Ysize / 2 + 1; j++)
338 {
339 sym_maze[i][j] = maze[i][j];
340 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
341 }
342 if (sym == SYMMETRY_XY)
343 for (i = 0; i < RP->Xsize / 2 + 1; i++)
344 for (j = 0; j < RP->Ysize / 2 + 1; j++)
345 {
346 sym_maze[i][j] = maze[i][j];
347 sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
348 sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
349 sym_maze[RP->Xsize - i - 1][RP->Ysize - j - 1] = maze[i][j];
350 }
351 /* delete the old maze */
352 for (i = 0; i < Xsize_orig; i++)
353 free (maze[i]);
354 free (maze);
355 /* reconnect disjointed spirals */
356 if (RP->map_layout_style == LAYOUT_SPIRAL)
357 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
358 /* reconnect disjointed nethackmazes: the routine for
359 spirals will do the trick? */
360 if (RP->map_layout_style == LAYOUT_ROGUELIKE)
361 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
362
363 return sym_maze;
364 }
365
366
367 /* takes a map and rotates it. This completes the
368 onion layouts, making them possibly centered on any wall.
369 It'll modify Xsize and Ysize if they're swapped.
370 */
371
372 char **
373 rotate_layout (char **maze, int rotation, random_map_params *RP)
374 {
375 char **new_maze;
376 int i, j;
377
378 switch (rotation)
379 {
380 case 0:
381 return maze;
382 break;
383 case 2: /* a reflection */
384 {
385 char *newmaze = (char *) malloc (sizeof (char) * RP->Xsize * RP->Ysize);
386
387 for (i = 0; i < RP->Xsize; i++)
388 { /* make a copy */
389 for (j = 0; j < RP->Ysize; j++)
390 {
391 newmaze[i * RP->Ysize + j] = maze[i][j];
392 }
393 }
394 for (i = 0; i < RP->Xsize; i++)
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:
406 case 3:
407 {
408 int swap;
409 new_maze = (char **) calloc (sizeof (char *), RP->Ysize);
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 */
415 for (i = 0; i < RP->Xsize; i++)
416 for (j = 0; j < RP->Ysize; j++)
417 new_maze[j][i] = maze[i][j];
418
419 if (rotation == 3)
420 { /* swap x and y */
421 for (i = 0; i < RP->Xsize; i++)
422 for (j = 0; j < RP->Ysize; j++)
423 new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
424 }
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 }
438 return NULL;
439 }
440
441 /* take a layout and make some rooms in it.
442 --works best on onions.*/
443 void
444 roomify_layout (char **maze, random_map_params *RP)
445 {
446 int tries = RP->Xsize * RP->Ysize / 30;
447 int ti;
448
449 for (ti = 0; ti < tries; ti++)
450 {
451 int dx, dy; /* starting location for looking at creating a door */
452 int cx, cy; /* results of checking on creating walls. */
453
454 dx = rndm (RP->Xsize);
455 dy = rndm (RP->Ysize);
456
457 cx = can_make_wall (maze, dx, dy, 0, RP); /* horizontal */
458 cy = can_make_wall (maze, dx, dy, 1, RP); /* vertical */
459 if (cx == -1)
460 {
461 if (cy != -1)
462 make_wall (maze, dx, dy, 1);
463
464 continue;
465 }
466
467 if (cy == -1)
468 {
469 make_wall (maze, dx, dy, 0);
470 continue;
471 }
472
473 if (cx < cy)
474 make_wall (maze, dx, dy, 0);
475 else
476 make_wall (maze, dx, dy, 1);
477 }
478 }
479
480 /* checks the layout to see if I can stick a horizontal(dir = 0) wall
481 (or vertical, dir == 1)
482 here which ends up on other walls sensibly. */
483
484 int
485 can_make_wall (char **maze, int dx, int dy, int dir, random_map_params *RP)
486 {
487 int i1;
488 int length = 0;
489
490 /* dont make walls if we're on the edge. */
491 if (dx == 0 || dx == (RP->Xsize - 1) || dy == 0 || dy == (RP->Ysize - 1))
492 return -1;
493
494 /* don't make walls if we're ON a wall. */
495 if (maze[dx][dy] != 0)
496 return -1;
497
498 if (dir == 0) /* horizontal */
499 {
500 int y = dy;
501
502 for (i1 = dx - 1; i1 > 0; i1--)
503 {
504 int sindex = surround_flag2 (maze, i1, y, RP);
505
506 if (sindex == 1)
507 break;
508 if (sindex != 0)
509 return -1; /* can't make horiz. wall here */
510 if (maze[i1][y] != 0)
511 return -1; /* can't make horiz. wall here */
512 length++;
513 }
514
515 for (i1 = dx + 1; i1 < RP->Xsize - 1; i1++)
516 {
517 int sindex = surround_flag2 (maze, i1, y, RP);
518
519 if (sindex == 2)
520 break;
521 if (sindex != 0)
522 return -1; /* can't make horiz. wall here */
523 if (maze[i1][y] != 0)
524 return -1; /* can't make horiz. wall here */
525 length++;
526 }
527 return length;
528 }
529 else
530 { /* vertical */
531 int x = dx;
532
533 for (i1 = dy - 1; i1 > 0; i1--)
534 {
535 int sindex = surround_flag2 (maze, x, i1, RP);
536
537 if (sindex == 4)
538 break;
539 if (sindex != 0)
540 return -1; /* can't make vert. wall here */
541 if (maze[x][i1] != 0)
542 return -1; /* can't make horiz. wall here */
543 length++;
544 }
545
546 for (i1 = dy + 1; i1 < RP->Ysize - 1; i1++)
547 {
548 int sindex = surround_flag2 (maze, x, i1, RP);
549
550 if (sindex == 8)
551 break;
552 if (sindex != 0)
553 return -1; /* can't make verti. wall here */
554 if (maze[x][i1] != 0)
555 return -1; /* can't make horiz. wall here */
556 length++;
557 }
558 return length;
559 }
560 return -1;
561 }
562
563
564 int
565 make_wall (char **maze, int x, int y, int dir)
566 {
567 maze[x][y] = 'D'; /* mark a door */
568 switch (dir)
569 {
570 case 0: /* horizontal */
571 {
572 int i1;
573
574 for (i1 = x - 1; maze[i1][y] == 0; i1--)
575 maze[i1][y] = '#';
576 for (i1 = x + 1; maze[i1][y] == 0; i1++)
577 maze[i1][y] = '#';
578 break;
579 }
580 case 1: /* vertical */
581 {
582 int i1;
583
584 for (i1 = y - 1; maze[x][i1] == 0; i1--)
585 maze[x][i1] = '#';
586 for (i1 = y + 1; maze[x][i1] == 0; i1++)
587 maze[x][i1] = '#';
588 break;
589 }
590 }
591
592 return 0;
593 }
594
595 /* puts doors at appropriate locations in a layout. */
596 void
597 doorify_layout (char **maze, random_map_params *RP)
598 {
599 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 */
603 int i, j;
604
605 doorlist_x = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize);
606 doorlist_y = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize);
607
608
609 /* make a list of possible door locations */
610 for (i = 1; i < RP->Xsize - 1; i++)
611 for (j = 1; j < RP->Ysize - 1; j++)
612 {
613 int sindex = surround_flag (maze, i, j, RP);
614
615 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
616 {
617 doorlist_x[doorlocs] = i;
618 doorlist_y[doorlocs] = j;
619 doorlocs++;
620 }
621 }
622
623 while (ndoors > 0 && doorlocs > 0)
624 {
625 int di;
626 int sindex;
627
628 di = rndm (doorlocs);
629 i = doorlist_x[di];
630 j = doorlist_y[di];
631 sindex = surround_flag (maze, i, j, RP);
632
633 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
634 {
635 maze[i][j] = 'D';
636 ndoors--;
637 }
638
639 /* reduce the size of the list */
640 doorlocs--;
641 doorlist_x[di] = doorlist_x[doorlocs];
642 doorlist_y[di] = doorlist_y[doorlocs];
643 }
644
645 free (doorlist_x);
646 free (doorlist_y);
647 }
648
649 void
650 write_map_parameters_to_string (char *buf, random_map_params *RP)
651 {
652 char small_buf[16384];
653
654 sprintf (buf, "xsize %d\nysize %d\n", RP->xsize, RP->ysize);
655
656 if (RP->wallstyle[0])
657 {
658 sprintf (small_buf, "wallstyle %s\n", RP->wallstyle);
659 strcat (buf, small_buf);
660 }
661
662 if (RP->floorstyle[0])
663 {
664 sprintf (small_buf, "floorstyle %s\n", RP->floorstyle);
665 strcat (buf, small_buf);
666 }
667
668 if (RP->monsterstyle[0])
669 {
670 sprintf (small_buf, "monsterstyle %s\n", RP->monsterstyle);
671 strcat (buf, small_buf);
672 }
673
674 if (RP->treasurestyle[0])
675 {
676 sprintf (small_buf, "treasurestyle %s\n", RP->treasurestyle);
677 strcat (buf, small_buf);
678 }
679
680 if (RP->layoutstyle[0])
681 {
682 sprintf (small_buf, "layoutstyle %s\n", RP->layoutstyle);
683 strcat (buf, small_buf);
684 }
685
686 if (RP->decorstyle[0])
687 {
688 sprintf (small_buf, "decorstyle %s\n", RP->decorstyle);
689 strcat (buf, small_buf);
690 }
691
692 if (RP->doorstyle[0])
693 {
694 sprintf (small_buf, "doorstyle %s\n", RP->doorstyle);
695 strcat (buf, small_buf);
696 }
697
698 if (RP->exitstyle[0])
699 {
700 sprintf (small_buf, "exitstyle %s\n", RP->exitstyle);
701 strcat (buf, small_buf);
702 }
703
704 if (RP->final_map.length ())
705 {
706 sprintf (small_buf, "final_map %s\n", &RP->final_map);
707 strcat (buf, small_buf);
708 }
709
710 if (RP->exit_on_final_map[0])
711 {
712 sprintf (small_buf, "exit_on_final_map %s\n", RP->exit_on_final_map);
713 strcat (buf, small_buf);
714 }
715
716 if (RP->this_map.length ())
717 {
718 sprintf (small_buf, "origin_map %s\n", &RP->this_map);
719 strcat (buf, small_buf);
720 }
721
722 if (RP->expand2x)
723 {
724 sprintf (small_buf, "expand2x %d\n", RP->expand2x);
725 strcat (buf, small_buf);
726 }
727
728 if (RP->layoutoptions1)
729 {
730 sprintf (small_buf, "layoutoptions1 %d\n", RP->layoutoptions1);
731 strcat (buf, small_buf);
732 }
733
734 if (RP->layoutoptions2)
735 {
736 sprintf (small_buf, "layoutoptions2 %d\n", RP->layoutoptions2);
737 strcat (buf, small_buf);
738 }
739
740 if (RP->layoutoptions3)
741 {
742 sprintf (small_buf, "layoutoptions3 %d\n", RP->layoutoptions3);
743 strcat (buf, small_buf);
744 }
745
746 if (RP->symmetry)
747 {
748 sprintf (small_buf, "symmetry %d\n", RP->symmetry);
749 strcat (buf, small_buf);
750 }
751
752 if (RP->difficulty && RP->difficulty_given)
753 {
754 sprintf (small_buf, "difficulty %d\n", RP->difficulty);
755 strcat (buf, small_buf);
756 }
757
758 if (RP->difficulty_increase != 1.0)
759 {
760 sprintf (small_buf, "difficulty_increase %f\n", RP->difficulty_increase);
761 strcat (buf, small_buf);
762 }
763
764 sprintf (small_buf, "dungeon_level %d\n", RP->dungeon_level);
765 strcat (buf, small_buf);
766
767 if (RP->dungeon_depth)
768 {
769 sprintf (small_buf, "dungeon_depth %d\n", RP->dungeon_depth);
770 strcat (buf, small_buf);
771 }
772
773 if (RP->decoroptions)
774 {
775 sprintf (small_buf, "decoroptions %d\n", RP->decoroptions);
776 strcat (buf, small_buf);
777 }
778
779 if (RP->orientation)
780 {
781 sprintf (small_buf, "orientation %d\n", RP->orientation);
782 strcat (buf, small_buf);
783 }
784
785 if (RP->origin_x)
786 {
787 sprintf (small_buf, "origin_x %d\n", RP->origin_x);
788 strcat (buf, small_buf);
789 }
790
791 if (RP->origin_y)
792 {
793 sprintf (small_buf, "origin_y %d\n", RP->origin_y);
794 strcat (buf, small_buf);
795 }
796
797 if (RP->treasureoptions)
798 {
799 sprintf (small_buf, "treasureoptions %d\n", RP->treasureoptions);
800 strcat (buf, small_buf);
801 }
802
803 if (RP->random_seed)
804 {
805 sprintf (small_buf, "random_seed %u\n", RP->random_seed);
806 strcat (buf, small_buf);
807 }
808
809 if (RP->custom)
810 {
811 sprintf (small_buf, "custom %s\n", RP->custom);
812 strcat (buf, small_buf);
813 }
814 }
815
816 void
817 write_parameters_to_string (char *buf,
818 int xsize_n,
819 int ysize_n,
820 const char *wallstyle_n,
821 const char *floorstyle_n,
822 const char *monsterstyle_n,
823 const char *treasurestyle_n,
824 const char *layoutstyle_n,
825 const char *decorstyle_n,
826 const char *doorstyle_n,
827 const char *exitstyle_n,
828 const char *final_map_n,
829 const char *exit_on_final_map_n,
830 const char *this_map_n,
831 int layoutoptions1_n,
832 int layoutoptions2_n,
833 int layoutoptions3_n,
834 int symmetry_n,
835 int dungeon_depth_n,
836 int dungeon_level_n,
837 int difficulty_n,
838 int difficulty_given_n,
839 int decoroptions_n,
840 int orientation_n,
841 int origin_x_n,
842 int origin_y_n,
843 uint32_t random_seed_n,
844 int treasureoptions_n,
845 float difficulty_increase)
846 {
847 char small_buf[16384];
848
849 sprintf (buf, "xsize %d\nysize %d\n", xsize_n, ysize_n);
850
851 if (wallstyle_n && wallstyle_n[0])
852 {
853 sprintf (small_buf, "wallstyle %s\n", wallstyle_n);
854 strcat (buf, small_buf);
855 }
856
857 if (floorstyle_n && floorstyle_n[0])
858 {
859 sprintf (small_buf, "floorstyle %s\n", floorstyle_n);
860 strcat (buf, small_buf);
861 }
862
863 if (monsterstyle_n && monsterstyle_n[0])
864 {
865 sprintf (small_buf, "monsterstyle %s\n", monsterstyle_n);
866 strcat (buf, small_buf);
867 }
868
869 if (treasurestyle_n && treasurestyle_n[0])
870 {
871 sprintf (small_buf, "treasurestyle %s\n", treasurestyle_n);
872 strcat (buf, small_buf);
873 }
874
875 if (layoutstyle_n && layoutstyle_n[0])
876 {
877 sprintf (small_buf, "layoutstyle %s\n", layoutstyle_n);
878 strcat (buf, small_buf);
879 }
880
881 if (decorstyle_n && decorstyle_n[0])
882 {
883 sprintf (small_buf, "decorstyle %s\n", decorstyle_n);
884 strcat (buf, small_buf);
885 }
886
887 if (doorstyle_n && doorstyle_n[0])
888 {
889 sprintf (small_buf, "doorstyle %s\n", doorstyle_n);
890 strcat (buf, small_buf);
891 }
892
893 if (exitstyle_n && exitstyle_n[0])
894 {
895 sprintf (small_buf, "exitstyle %s\n", exitstyle_n);
896 strcat (buf, small_buf);
897 }
898
899 if (final_map_n && final_map_n[0])
900 {
901 sprintf (small_buf, "final_map %s\n", final_map_n);
902 strcat (buf, small_buf);
903 }
904
905 if (exit_on_final_map_n && exit_on_final_map_n[0])
906 {
907 sprintf (small_buf, "exit_on_final_map %s\n", exit_on_final_map_n);
908 strcat (buf, small_buf);
909 }
910
911 if (this_map_n && this_map_n[0])
912 {
913 sprintf (small_buf, "origin_map %s\n", this_map_n);
914 strcat (buf, small_buf);
915 }
916
917 if (layoutoptions1_n)
918 {
919 sprintf (small_buf, "layoutoptions1 %d\n", layoutoptions1_n);
920 strcat (buf, small_buf);
921 }
922
923 if (layoutoptions2_n)
924 {
925 sprintf (small_buf, "layoutoptions2 %d\n", layoutoptions2_n);
926 strcat (buf, small_buf);
927 }
928
929
930 if (layoutoptions3_n)
931 {
932 sprintf (small_buf, "layoutoptions3 %d\n", layoutoptions3_n);
933 strcat (buf, small_buf);
934 }
935
936 if (symmetry_n)
937 {
938 sprintf (small_buf, "symmetry %d\n", symmetry_n);
939 strcat (buf, small_buf);
940 }
941
942
943 if (difficulty_n && difficulty_given_n)
944 {
945 sprintf (small_buf, "difficulty %d\n", difficulty_n);
946 strcat (buf, small_buf);
947 }
948
949 if (difficulty_increase > 0.001)
950 {
951 sprintf (small_buf, "difficulty_increase %f\n", difficulty_increase);
952 strcat (buf, small_buf);
953 }
954
955 sprintf (small_buf, "dungeon_level %d\n", dungeon_level_n);
956 strcat (buf, small_buf);
957
958 if (dungeon_depth_n)
959 {
960 sprintf (small_buf, "dungeon_depth %d\n", dungeon_depth_n);
961 strcat (buf, small_buf);
962 }
963
964 if (decoroptions_n)
965 {
966 sprintf (small_buf, "decoroptions %d\n", decoroptions_n);
967 strcat (buf, small_buf);
968 }
969
970 if (orientation_n)
971 {
972 sprintf (small_buf, "orientation %d\n", orientation_n);
973 strcat (buf, small_buf);
974 }
975
976 if (origin_x_n)
977 {
978 sprintf (small_buf, "origin_x %d\n", origin_x_n);
979 strcat (buf, small_buf);
980 }
981
982 if (origin_y_n)
983 {
984 sprintf (small_buf, "origin_y %d\n", origin_y_n);
985 strcat (buf, small_buf);
986 }
987
988 if (random_seed_n)
989 {
990 /* Add one so that the next map is a bit different */
991 sprintf (small_buf, "random_seed %u\n", random_seed_n + 1);
992 strcat (buf, small_buf);
993 }
994
995 if (treasureoptions_n)
996 {
997 sprintf (small_buf, "treasureoptions %d\n", treasureoptions_n);
998 strcat (buf, small_buf);
999 }
1000 }
1001
1002 /* copy an object with an inventory... i.e., duplicate the inv too. */
1003 void
1004 copy_object_with_inv (object *src_ob, object *dest_ob)
1005 {
1006 object *walk, *tmp;
1007
1008 src_ob->copy_to (dest_ob);
1009
1010 for (walk = src_ob->inv; walk; walk = walk->below)
1011 {
1012 tmp = object::create ();
1013
1014 walk->copy_to (tmp);
1015 insert_ob_in_ob (tmp, dest_ob);
1016 }
1017 }