ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.20
Committed: Mon Jan 15 21:06:19 2007 UTC (17 years, 4 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.19: +22 -22 lines
Log Message:
comments

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