ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.35
Committed: Tue Apr 15 14:21:04 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.34: +1 -1 lines
Log Message:
*** empty log message ***

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