ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.36
Committed: Tue Apr 15 18:43:11 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_5, rel-2_52
Changes since 1.35: +4 -6 lines
Log Message:
fix.bug.

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