ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.3
Committed: Sun Sep 10 16:06:37 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +791 -634 lines
Log Message:
indent

File Contents

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