ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.33
Committed: Mon Apr 14 22:41:17 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.32: +82 -95 lines
Log Message:
refactor random map gen more

File Contents

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