ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.22
Committed: Fri Jan 19 15:29:52 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.21: +57 -53 lines
Log Message:
- make random map generation more deterministic again.
- expose cf::rndm to perl.
- preset most random map parameters from perl to ensure determinism.

File Contents

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