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, 10 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

# User Rev Content
1 elmex 1.1 /*
2 root 1.30 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.20 *
4 root 1.30 * 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 pippijn 1.20 *
8 root 1.30 * Crossfire TRT is free software: you can redistribute it and/or modify
9 pippijn 1.20 * it under the terms of the GNU General Public License as published by
10 root 1.30 * the Free Software Foundation, either version 3 of the License, or
11 pippijn 1.20 * (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 root 1.30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 pippijn 1.20 * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19 root 1.30 * 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 pippijn 1.20 */
23 elmex 1.1
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 root 1.29 #define CEDE coroapi::cede_to_tick (); rndm.seed (RP->random_seed + __LINE__);
34 root 1.22
35 root 1.3 void
36 root 1.13 dump_layout (char **layout, random_map_params *RP)
37 root 1.3 {
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 elmex 1.1 }
56 root 1.8
57 root 1.19 bool
58     maptile::generate_random_map (random_map_params *RP)
59 root 1.3 {
60 root 1.18 char **layout, buf[16384];
61 root 1.3 int i;
62    
63 root 1.24 RP->Xsize = RP->xsize;
64     RP->Ysize = RP->ysize;
65    
66 root 1.3 /* pick a random seed, or use the one from the input file */
67 root 1.22 RP->random_seed = RP->random_seed
68     ? RP->random_seed + RP->dungeon_level
69     : time (0);
70     CEDE;
71 root 1.3
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 root 1.6
78 root 1.3 if (RP->difficulty_increase > 0.001)
79 root 1.6 RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
80    
81     if (RP->difficulty < 1)
82     RP->difficulty = 1;
83 elmex 1.1 }
84 root 1.3 else
85     RP->difficulty_given = 1;
86 elmex 1.1
87 root 1.3 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
88 root 1.21 RP->Xsize = MIN_RANDOM_MAP_SIZE + rndm (25) + 5;
89 root 1.6
90 root 1.3 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
91 root 1.21 RP->Ysize = MIN_RANDOM_MAP_SIZE + rndm (25) + 5;
92 elmex 1.1
93 root 1.22 if (RP->symmetry == SYMMETRY_RANDOM)
94 root 1.27 RP->symmetry_used = rndm (SYMMETRY_XY) + 1;
95 root 1.22 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 root 1.24
101 root 1.22 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
102     RP->Xsize = RP->Xsize / 2 + 1;
103    
104 root 1.3 if (RP->expand2x > 0)
105     {
106     RP->Xsize /= 2;
107     RP->Ysize /= 2;
108 elmex 1.1 }
109    
110 root 1.22 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 root 1.27 RP->map_layout_style = rndm (NROFLAYOUTS - 1) + 1;
138 root 1.22
139 root 1.3 layout = layoutgen (RP);
140 elmex 1.1
141     #ifdef RMAP_DEBUG
142 root 1.3 dump_layout (layout, RP);
143 elmex 1.1 #endif
144    
145 root 1.3 /* increment these for the current map */
146     RP->dungeon_level += 1;
147     /* allow constant-difficulty maps. */
148     /* difficulty+=1; */
149 elmex 1.1
150 root 1.3 /* rotate the layout randomly */
151 root 1.21 layout = rotate_layout (layout, rndm (4), RP);
152 elmex 1.1 #ifdef RMAP_DEBUG
153 root 1.3 dump_layout (layout, RP);
154 elmex 1.1 #endif
155    
156 root 1.3 /* allocate the map and set the floor */
157 root 1.19 make_map_floor (layout, RP->floorstyle, RP);
158 root 1.3
159     /* set region */
160 root 1.26 default_region = RP->region;
161 root 1.3
162 root 1.22 CEDE;
163 root 1.19
164 root 1.3 /* create walls unless the wallstyle is "none" */
165     if (strcmp (RP->wallstyle, "none"))
166     {
167 root 1.19 make_map_walls (this, layout, RP->wallstyle, RP);
168 elmex 1.1
169 root 1.3 /* place doors unless doorstyle or wallstyle is "none" */
170     if (strcmp (RP->doorstyle, "none"))
171 root 1.19 put_doors (this, layout, RP->doorstyle, RP);
172 root 1.3 }
173    
174 root 1.22 CEDE;
175 root 1.19
176 root 1.3 /* create exits unless the exitstyle is "none" */
177     if (strcmp (RP->exitstyle, "none"))
178 root 1.19 place_exits (this, layout, RP->exitstyle, RP->orientation, RP);
179 root 1.3
180 root 1.22 CEDE;
181 root 1.19
182     place_specials_in_map (this, layout, RP);
183 root 1.3
184 root 1.22 CEDE;
185 root 1.19
186 root 1.3 /* create monsters unless the monsterstyle is "none" */
187     if (strcmp (RP->monsterstyle, "none"))
188 root 1.19 place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
189 root 1.3
190 root 1.22 CEDE;
191 root 1.19
192 root 1.3 /* treasures needs to have a proper difficulty set for the map. */
193 root 1.19 difficulty = estimate_difficulty ();
194 root 1.3
195 root 1.22 CEDE;
196 root 1.19
197 root 1.3 /* create treasure unless the treasurestyle is "none" */
198     if (strcmp (RP->treasurestyle, "none"))
199 root 1.19 place_treasure (this, layout, RP->treasurestyle, RP->treasureoptions, RP);
200 root 1.3
201 root 1.22 CEDE;
202 root 1.19
203 root 1.3 /* create decor unless the decorstyle is "none" */
204     if (strcmp (RP->decorstyle, "none"))
205 root 1.19 put_decor (this, layout, RP->decorstyle, RP->decoroptions, RP);
206 root 1.3
207 root 1.22 CEDE;
208 root 1.19
209 root 1.3 /* generate treasures, etc. */
210 root 1.19 fix_auto_apply ();
211 root 1.3
212 root 1.22 CEDE;
213    
214 root 1.19 unblock_exits (this, layout, RP);
215 root 1.3
216     /* free the layout */
217     for (i = 0; i < RP->Xsize; i++)
218     free (layout[i]);
219 root 1.12
220 root 1.3 free (layout);
221    
222 root 1.19 msg = strdup (buf);
223     in_memory = MAP_IN_MEMORY;
224 root 1.3
225 root 1.22 CEDE;
226    
227 root 1.19 return 1;
228 elmex 1.1 }
229    
230     /* function selects the layout function and gives it whatever
231     arguments it needs. */
232 root 1.3 char **
233 root 1.13 layoutgen (random_map_params *RP)
234 root 1.3 {
235     char **maze = 0;
236     int oxsize = RP->Xsize, oysize = RP->Ysize;
237 elmex 1.1
238 root 1.3 switch (RP->map_layout_style)
239     {
240 root 1.11 case LAYOUT_ONION:
241     maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
242 root 1.21 if (!(rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY))
243 root 1.11 roomify_layout (maze, RP);
244     break;
245    
246     case LAYOUT_MAZE:
247 root 1.21 maze = maze_gen (RP->Xsize, RP->Ysize, rndm (2));
248     if (!(rndm (2)))
249 root 1.11 doorify_layout (maze, RP);
250     break;
251    
252     case LAYOUT_SPIRAL:
253     maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1);
254 root 1.21 if (!(rndm (2)))
255 root 1.11 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 root 1.21 if (rndm (2))
276 root 1.11 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 root 1.21 if (rndm (2))
282 root 1.11 roomify_layout (maze, RP);
283     break;
284 root 1.3 }
285 root 1.2
286 root 1.3 maze = symmetrize_layout (maze, RP->symmetry_used, RP);
287 root 1.11
288 elmex 1.1 #ifdef RMAP_DEBUG
289 root 1.3 dump_layout (maze, RP);
290 elmex 1.1 #endif
291 root 1.11
292 root 1.3 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 elmex 1.1 }
298 root 1.11
299 root 1.3 return maze;
300 elmex 1.1 }
301    
302     /* takes a map and makes it symmetric: adjusts Xsize and
303     Ysize to produce a symmetric map. */
304 root 1.3 char **
305 root 1.13 symmetrize_layout (char **maze, int sym, random_map_params *RP)
306 root 1.3 {
307     int i, j;
308 elmex 1.1 char **sym_maze;
309 root 1.3 int Xsize_orig, Ysize_orig;
310    
311 elmex 1.1 Xsize_orig = RP->Xsize;
312     Ysize_orig = RP->Ysize;
313 root 1.3 RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */
314 root 1.11 if (sym == SYMMETRY_NONE)
315 root 1.3 {
316     RP->Xsize = Xsize_orig;
317     RP->Ysize = Ysize_orig;
318     return maze;
319     }
320 elmex 1.1 /* pick new sizes */
321 root 1.11 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 elmex 1.1
324 root 1.3 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 root 1.11 if (sym == SYMMETRY_X)
329 root 1.3 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 root 1.11 if (sym == SYMMETRY_Y)
336 root 1.3 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 root 1.11 if (sym == SYMMETRY_XY)
343 root 1.3 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 elmex 1.1 /* delete the old maze */
352 root 1.3 for (i = 0; i < Xsize_orig; i++)
353     free (maze[i]);
354     free (maze);
355 elmex 1.1 /* reconnect disjointed spirals */
356 root 1.11 if (RP->map_layout_style == LAYOUT_SPIRAL)
357 root 1.3 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
358 elmex 1.1 /* reconnect disjointed nethackmazes: the routine for
359 root 1.3 spirals will do the trick? */
360 root 1.11 if (RP->map_layout_style == LAYOUT_ROGUELIKE)
361 root 1.3 connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
362    
363 elmex 1.1 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 root 1.3 char **
373 root 1.13 rotate_layout (char **maze, int rotation, random_map_params *RP)
374 root 1.3 {
375 elmex 1.1 char **new_maze;
376 root 1.3 int i, j;
377 elmex 1.1
378 root 1.3 switch (rotation)
379     {
380 root 1.11 case 0:
381     return maze;
382     break;
383 root 1.13 case 2: /* a reflection */
384 root 1.11 {
385     char *newmaze = (char *) malloc (sizeof (char) * RP->Xsize * RP->Ysize);
386    
387     for (i = 0; i < RP->Xsize; i++)
388 root 1.13 { /* make a copy */
389 root 1.11 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 root 1.13 { /* copy a reflection back */
396 root 1.11 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 root 1.3 return maze;
403     break;
404 root 1.11 }
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 root 1.13 if (rotation == 1) /* swap x and y */
415 root 1.11 for (i = 0; i < RP->Xsize; i++)
416     for (j = 0; j < RP->Ysize; j++)
417     new_maze[j][i] = maze[i][j];
418 root 1.3
419 root 1.11 if (rotation == 3)
420 root 1.13 { /* swap x and y */
421 root 1.3 for (i = 0; i < RP->Xsize; i++)
422     for (j = 0; j < RP->Ysize; j++)
423 root 1.11 new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
424     }
425 root 1.3
426 root 1.11 /* 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 elmex 1.1 }
438     return NULL;
439     }
440    
441     /* take a layout and make some rooms in it.
442     --works best on onions.*/
443 root 1.3 void
444 root 1.13 roomify_layout (char **maze, random_map_params *RP)
445 root 1.3 {
446     int tries = RP->Xsize * RP->Ysize / 30;
447 elmex 1.1 int ti;
448    
449 root 1.3 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 root 1.27 dx = rndm (RP->Xsize);
455     dy = rndm (RP->Ysize);
456    
457 root 1.3 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 root 1.27
464 root 1.3 continue;
465     }
466 root 1.27
467 root 1.3 if (cy == -1)
468     {
469     make_wall (maze, dx, dy, 0);
470     continue;
471     }
472 root 1.27
473 root 1.3 if (cx < cy)
474     make_wall (maze, dx, dy, 0);
475     else
476     make_wall (maze, dx, dy, 1);
477 elmex 1.1 }
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 root 1.3
484     int
485 root 1.13 can_make_wall (char **maze, int dx, int dy, int dir, random_map_params *RP)
486 root 1.3 {
487 elmex 1.1 int i1;
488 root 1.3 int length = 0;
489 elmex 1.1
490     /* dont make walls if we're on the edge. */
491 root 1.3 if (dx == 0 || dx == (RP->Xsize - 1) || dy == 0 || dy == (RP->Ysize - 1))
492     return -1;
493 elmex 1.1
494     /* don't make walls if we're ON a wall. */
495 root 1.3 if (maze[dx][dy] != 0)
496     return -1;
497 elmex 1.1
498 root 1.3 if (dir == 0) /* horizontal */
499 elmex 1.1 {
500     int y = dy;
501 root 1.3
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 elmex 1.1 return length;
528     }
529 root 1.3 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 elmex 1.1 }
560 root 1.3 return -1;
561 elmex 1.1 }
562    
563    
564 root 1.3 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 elmex 1.1 {
570 root 1.13 case 0: /* horizontal */
571     {
572     int i1;
573 root 1.3
574 root 1.13 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 root 1.3
584 root 1.13 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 elmex 1.1 }
591    
592     return 0;
593     }
594    
595     /* puts doors at appropriate locations in a layout. */
596 root 1.3 void
597 root 1.13 doorify_layout (char **maze, random_map_params *RP)
598 root 1.3 {
599     int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */
600 elmex 1.1 char *doorlist_x;
601     char *doorlist_y;
602 root 1.3 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 elmex 1.1
608    
609     /* make a list of possible door locations */
610 root 1.3 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 root 1.12
623 root 1.3 while (ndoors > 0 && doorlocs > 0)
624     {
625     int di;
626     int sindex;
627    
628 root 1.27 di = rndm (doorlocs);
629 root 1.3 i = doorlist_x[di];
630     j = doorlist_y[di];
631     sindex = surround_flag (maze, i, j, RP);
632 root 1.27
633 root 1.3 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
634     {
635     maze[i][j] = 'D';
636     ndoors--;
637 elmex 1.1 }
638 root 1.27
639 root 1.3 /* reduce the size of the list */
640     doorlocs--;
641     doorlist_x[di] = doorlist_x[doorlocs];
642     doorlist_y[di] = doorlist_y[doorlocs];
643 elmex 1.1 }
644 root 1.12
645 root 1.3 free (doorlist_x);
646     free (doorlist_y);
647 elmex 1.1 }
648    
649 root 1.3 void
650 root 1.13 write_map_parameters_to_string (char *buf, random_map_params *RP)
651 root 1.3 {
652 root 1.18 char small_buf[16384];
653 elmex 1.1
654 root 1.24 sprintf (buf, "xsize %d\nysize %d\n", RP->xsize, RP->ysize);
655 root 1.3
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 elmex 1.1
674 root 1.3 if (RP->treasurestyle[0])
675     {
676     sprintf (small_buf, "treasurestyle %s\n", RP->treasurestyle);
677     strcat (buf, small_buf);
678     }
679 elmex 1.1
680 root 1.3 if (RP->layoutstyle[0])
681     {
682     sprintf (small_buf, "layoutstyle %s\n", RP->layoutstyle);
683     strcat (buf, small_buf);
684     }
685 elmex 1.1
686 root 1.3 if (RP->decorstyle[0])
687     {
688     sprintf (small_buf, "decorstyle %s\n", RP->decorstyle);
689     strcat (buf, small_buf);
690     }
691 elmex 1.1
692 root 1.3 if (RP->doorstyle[0])
693     {
694     sprintf (small_buf, "doorstyle %s\n", RP->doorstyle);
695     strcat (buf, small_buf);
696     }
697 elmex 1.1
698 root 1.3 if (RP->exitstyle[0])
699     {
700     sprintf (small_buf, "exitstyle %s\n", RP->exitstyle);
701     strcat (buf, small_buf);
702     }
703 elmex 1.1
704 root 1.14 if (RP->final_map.length ())
705 root 1.3 {
706 root 1.14 sprintf (small_buf, "final_map %s\n", &RP->final_map);
707 root 1.3 strcat (buf, small_buf);
708     }
709 elmex 1.1
710 root 1.3 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 elmex 1.1
716 root 1.14 if (RP->this_map.length ())
717 root 1.3 {
718 root 1.14 sprintf (small_buf, "origin_map %s\n", &RP->this_map);
719 root 1.3 strcat (buf, small_buf);
720     }
721 elmex 1.1
722 root 1.3 if (RP->expand2x)
723     {
724     sprintf (small_buf, "expand2x %d\n", RP->expand2x);
725     strcat (buf, small_buf);
726     }
727 elmex 1.1
728 root 1.3 if (RP->layoutoptions1)
729     {
730     sprintf (small_buf, "layoutoptions1 %d\n", RP->layoutoptions1);
731     strcat (buf, small_buf);
732     }
733 elmex 1.1
734 root 1.3 if (RP->layoutoptions2)
735     {
736     sprintf (small_buf, "layoutoptions2 %d\n", RP->layoutoptions2);
737     strcat (buf, small_buf);
738     }
739 elmex 1.1
740 root 1.3 if (RP->layoutoptions3)
741     {
742     sprintf (small_buf, "layoutoptions3 %d\n", RP->layoutoptions3);
743     strcat (buf, small_buf);
744     }
745 elmex 1.1
746 root 1.3 if (RP->symmetry)
747     {
748     sprintf (small_buf, "symmetry %d\n", RP->symmetry);
749     strcat (buf, small_buf);
750     }
751 elmex 1.1
752 root 1.3 if (RP->difficulty && RP->difficulty_given)
753     {
754     sprintf (small_buf, "difficulty %d\n", RP->difficulty);
755     strcat (buf, small_buf);
756     }
757 elmex 1.1
758 root 1.3 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 elmex 1.1
764 root 1.3 sprintf (small_buf, "dungeon_level %d\n", RP->dungeon_level);
765     strcat (buf, small_buf);
766 elmex 1.1
767 root 1.3 if (RP->dungeon_depth)
768     {
769     sprintf (small_buf, "dungeon_depth %d\n", RP->dungeon_depth);
770     strcat (buf, small_buf);
771     }
772 elmex 1.1
773 root 1.3 if (RP->decoroptions)
774     {
775     sprintf (small_buf, "decoroptions %d\n", RP->decoroptions);
776     strcat (buf, small_buf);
777     }
778 elmex 1.1
779 root 1.3 if (RP->orientation)
780     {
781     sprintf (small_buf, "orientation %d\n", RP->orientation);
782     strcat (buf, small_buf);
783     }
784 elmex 1.1
785 root 1.3 if (RP->origin_x)
786     {
787     sprintf (small_buf, "origin_x %d\n", RP->origin_x);
788     strcat (buf, small_buf);
789     }
790 elmex 1.1
791 root 1.3 if (RP->origin_y)
792     {
793     sprintf (small_buf, "origin_y %d\n", RP->origin_y);
794     strcat (buf, small_buf);
795     }
796 root 1.11
797 root 1.3 if (RP->treasureoptions)
798     {
799     sprintf (small_buf, "treasureoptions %d\n", RP->treasureoptions);
800     strcat (buf, small_buf);
801     }
802 root 1.14
803     if (RP->random_seed)
804     {
805 root 1.25 sprintf (small_buf, "random_seed %u\n", RP->random_seed);
806 root 1.14 strcat (buf, small_buf);
807     }
808 root 1.18
809     if (RP->custom)
810     {
811     sprintf (small_buf, "custom %s\n", RP->custom);
812     strcat (buf, small_buf);
813     }
814 elmex 1.1 }
815    
816 root 1.3 void
817     write_parameters_to_string (char *buf,
818     int xsize_n,
819     int ysize_n,
820 root 1.28 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 root 1.3 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 root 1.28 int origin_x_n,
842     int origin_y_n,
843     uint32_t random_seed_n,
844     int treasureoptions_n,
845     float difficulty_increase)
846 elmex 1.1 {
847 root 1.18 char small_buf[16384];
848 elmex 1.1
849 root 1.3 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 elmex 1.1
863 root 1.3 if (monsterstyle_n && monsterstyle_n[0])
864     {
865     sprintf (small_buf, "monsterstyle %s\n", monsterstyle_n);
866     strcat (buf, small_buf);
867     }
868 elmex 1.1
869 root 1.3 if (treasurestyle_n && treasurestyle_n[0])
870     {
871     sprintf (small_buf, "treasurestyle %s\n", treasurestyle_n);
872     strcat (buf, small_buf);
873     }
874 elmex 1.1
875 root 1.3 if (layoutstyle_n && layoutstyle_n[0])
876     {
877     sprintf (small_buf, "layoutstyle %s\n", layoutstyle_n);
878     strcat (buf, small_buf);
879     }
880 elmex 1.1
881 root 1.3 if (decorstyle_n && decorstyle_n[0])
882     {
883     sprintf (small_buf, "decorstyle %s\n", decorstyle_n);
884     strcat (buf, small_buf);
885     }
886 elmex 1.1
887 root 1.3 if (doorstyle_n && doorstyle_n[0])
888     {
889     sprintf (small_buf, "doorstyle %s\n", doorstyle_n);
890     strcat (buf, small_buf);
891     }
892 elmex 1.1
893 root 1.3 if (exitstyle_n && exitstyle_n[0])
894     {
895     sprintf (small_buf, "exitstyle %s\n", exitstyle_n);
896     strcat (buf, small_buf);
897     }
898 elmex 1.1
899 root 1.3 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 elmex 1.1
905 root 1.3 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 elmex 1.1
911 root 1.3 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 elmex 1.1
917 root 1.3 if (layoutoptions1_n)
918     {
919     sprintf (small_buf, "layoutoptions1 %d\n", layoutoptions1_n);
920     strcat (buf, small_buf);
921     }
922 elmex 1.1
923 root 1.3 if (layoutoptions2_n)
924     {
925     sprintf (small_buf, "layoutoptions2 %d\n", layoutoptions2_n);
926     strcat (buf, small_buf);
927     }
928 elmex 1.1
929    
930 root 1.3 if (layoutoptions3_n)
931     {
932     sprintf (small_buf, "layoutoptions3 %d\n", layoutoptions3_n);
933     strcat (buf, small_buf);
934     }
935 elmex 1.1
936 root 1.3 if (symmetry_n)
937     {
938     sprintf (small_buf, "symmetry %d\n", symmetry_n);
939     strcat (buf, small_buf);
940     }
941 elmex 1.1
942    
943 root 1.3 if (difficulty_n && difficulty_given_n)
944     {
945     sprintf (small_buf, "difficulty %d\n", difficulty_n);
946     strcat (buf, small_buf);
947     }
948 elmex 1.1
949 root 1.3 if (difficulty_increase > 0.001)
950     {
951     sprintf (small_buf, "difficulty_increase %f\n", difficulty_increase);
952     strcat (buf, small_buf);
953     }
954 elmex 1.1
955 root 1.3 sprintf (small_buf, "dungeon_level %d\n", dungeon_level_n);
956     strcat (buf, small_buf);
957 elmex 1.1
958 root 1.3 if (dungeon_depth_n)
959     {
960     sprintf (small_buf, "dungeon_depth %d\n", dungeon_depth_n);
961     strcat (buf, small_buf);
962     }
963 elmex 1.1
964 root 1.3 if (decoroptions_n)
965     {
966     sprintf (small_buf, "decoroptions %d\n", decoroptions_n);
967     strcat (buf, small_buf);
968     }
969 elmex 1.1
970 root 1.3 if (orientation_n)
971     {
972     sprintf (small_buf, "orientation %d\n", orientation_n);
973     strcat (buf, small_buf);
974     }
975 elmex 1.1
976 root 1.3 if (origin_x_n)
977     {
978     sprintf (small_buf, "origin_x %d\n", origin_x_n);
979     strcat (buf, small_buf);
980     }
981 elmex 1.1
982 root 1.3 if (origin_y_n)
983     {
984     sprintf (small_buf, "origin_y %d\n", origin_y_n);
985     strcat (buf, small_buf);
986     }
987 root 1.11
988 root 1.3 if (random_seed_n)
989     {
990     /* Add one so that the next map is a bit different */
991 root 1.25 sprintf (small_buf, "random_seed %u\n", random_seed_n + 1);
992 root 1.3 strcat (buf, small_buf);
993     }
994 elmex 1.1
995 root 1.3 if (treasureoptions_n)
996     {
997     sprintf (small_buf, "treasureoptions %d\n", treasureoptions_n);
998     strcat (buf, small_buf);
999     }
1000 elmex 1.1 }
1001    
1002     /* copy an object with an inventory... i.e., duplicate the inv too. */
1003 root 1.3 void
1004     copy_object_with_inv (object *src_ob, object *dest_ob)
1005     {
1006     object *walk, *tmp;
1007 elmex 1.1
1008 root 1.7 src_ob->copy_to (dest_ob);
1009 elmex 1.1
1010 root 1.14 for (walk = src_ob->inv; walk; walk = walk->below)
1011 root 1.3 {
1012 root 1.7 tmp = object::create ();
1013 root 1.13
1014 root 1.7 walk->copy_to (tmp);
1015 root 1.3 insert_ob_in_ob (tmp, dest_ob);
1016     }
1017 elmex 1.1 }