ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.42
Committed: Mon Oct 12 14:00:58 2009 UTC (14 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_82, rel-2_81
Changes since 1.41: +7 -6 lines
Log Message:
clarify license

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.42 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.20 *
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 root 1.42 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.30 *
22 root 1.31 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.20 */
24 elmex 1.1
25     #include <time.h>
26     #include <stdio.h>
27     #include <global.h>
28     #include <random_map.h>
29     #include <rproto.h>
30     #include <sproto.h>
31    
32 root 1.39 #define CEDE coroapi::cede_to_tick ()
33 root 1.22
34 root 1.34 static void symmetrize_layout (Layout maze, random_map_params *RP);
35     static void rotate_layout (Layout maze, int rotation);
36 root 1.33
37 root 1.3 void
38 root 1.34 dump_layout (Layout layout)
39 root 1.3 {
40 root 1.36 for (int j = 0; j < layout->h; j++)
41 root 1.34 {
42 root 1.36 for (int i = 0; i < layout->w; i++)
43 root 1.34 putc (layout[i][j] ? layout[i][j] : ' ', stdout);
44    
45     putc ('\n', stdout);
46     }
47 root 1.3
48 root 1.34 putc ('\n', stdout);
49 elmex 1.1 }
50 root 1.8
51 root 1.19 bool
52     maptile::generate_random_map (random_map_params *RP)
53 root 1.3 {
54 root 1.32 char buf[16384];
55 root 1.3 int i;
56    
57 root 1.24 RP->Xsize = RP->xsize;
58     RP->Ysize = RP->ysize;
59    
60 root 1.3 /* pick a random seed, or use the one from the input file */
61 root 1.22 RP->random_seed = RP->random_seed
62     ? RP->random_seed + RP->dungeon_level
63     : time (0);
64 root 1.39
65     // we run "single-threaded"
66     rmg_rndm.seed (RP->random_seed);
67 root 1.3
68     write_map_parameters_to_string (buf, RP);
69    
70     if (RP->difficulty == 0)
71     {
72     RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
73 root 1.6
74 root 1.3 if (RP->difficulty_increase > 0.001)
75 root 1.6 RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
76    
77     if (RP->difficulty < 1)
78     RP->difficulty = 1;
79 elmex 1.1 }
80 root 1.3 else
81     RP->difficulty_given = 1;
82 elmex 1.1
83 root 1.3 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
84 root 1.39 RP->Xsize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
85 root 1.6
86 root 1.3 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
87 root 1.39 RP->Ysize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
88 elmex 1.1
89 root 1.22 if (RP->symmetry == SYMMETRY_RANDOM)
90 root 1.39 RP->symmetry_used = rmg_rndm (SYMMETRY_XY) + 1;
91 root 1.22 else
92     RP->symmetry_used = RP->symmetry;
93    
94     if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
95     RP->Ysize = RP->Ysize / 2 + 1;
96 root 1.24
97 root 1.22 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
98     RP->Xsize = RP->Xsize / 2 + 1;
99    
100 root 1.3 if (RP->expand2x > 0)
101     {
102     RP->Xsize /= 2;
103     RP->Ysize /= 2;
104 elmex 1.1 }
105    
106 root 1.22 RP->map_layout_style = LAYOUT_NONE;
107    
108     /* Redo this - there was a lot of redundant code of checking for preset
109     * layout style and then random layout style. Instead, figure out
110     * the numeric layoutstyle, so there is only one area that actually
111     * calls the code to make the maps.
112     */
113     if (strstr (RP->layoutstyle, "onion"))
114     RP->map_layout_style = LAYOUT_ONION;
115 root 1.34 else if (strstr (RP->layoutstyle, "maze"))
116 root 1.22 RP->map_layout_style = LAYOUT_MAZE;
117 root 1.34 else if (strstr (RP->layoutstyle, "spiral"))
118 root 1.22 RP->map_layout_style = LAYOUT_SPIRAL;
119 root 1.34 else if (strstr (RP->layoutstyle, "rogue"))
120 root 1.22 RP->map_layout_style = LAYOUT_ROGUELIKE;
121 root 1.34 else if (strstr (RP->layoutstyle, "snake"))
122 root 1.22 RP->map_layout_style = LAYOUT_SNAKE;
123 root 1.34 else if (strstr (RP->layoutstyle, "squarespiral"))
124 root 1.22 RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
125 root 1.34 else if (RP->map_layout_style == LAYOUT_NONE)
126 root 1.39 RP->map_layout_style = rmg_rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */
127 root 1.34 else
128     abort ();
129 root 1.22
130 root 1.34 Layout layout = layoutgen (RP);
131 elmex 1.1
132     #ifdef RMAP_DEBUG
133 root 1.36 dump_layout (layout);
134 elmex 1.1 #endif
135    
136 root 1.3 /* increment these for the current map */
137 root 1.36 ++RP->dungeon_level;
138 elmex 1.1
139 root 1.34 // need to patch RP becasue following code doesn't use the Layout object
140 root 1.33 RP->Xsize = layout->w;
141     RP->Ysize = layout->h;
142    
143 root 1.3 /* allocate the map and set the floor */
144 root 1.19 make_map_floor (layout, RP->floorstyle, RP);
145 root 1.3
146     /* set region */
147 root 1.26 default_region = RP->region;
148 root 1.3
149 root 1.22 CEDE;
150 root 1.19
151 root 1.39 place_specials_in_map (this, layout, RP);
152    
153     CEDE;
154    
155 root 1.3 /* create walls unless the wallstyle is "none" */
156     if (strcmp (RP->wallstyle, "none"))
157     {
158 root 1.19 make_map_walls (this, layout, RP->wallstyle, RP);
159 elmex 1.1
160 root 1.3 /* place doors unless doorstyle or wallstyle is "none" */
161     if (strcmp (RP->doorstyle, "none"))
162 root 1.19 put_doors (this, layout, RP->doorstyle, RP);
163 root 1.3 }
164    
165 root 1.22 CEDE;
166 root 1.19
167 root 1.3 /* create exits unless the exitstyle is "none" */
168     if (strcmp (RP->exitstyle, "none"))
169 root 1.19 place_exits (this, layout, RP->exitstyle, RP->orientation, RP);
170 root 1.3
171 root 1.22 CEDE;
172 root 1.19
173 root 1.3 /* create monsters unless the monsterstyle is "none" */
174     if (strcmp (RP->monsterstyle, "none"))
175 root 1.19 place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
176 root 1.3
177 root 1.22 CEDE;
178 root 1.19
179 root 1.3 /* treasures needs to have a proper difficulty set for the map. */
180 root 1.19 difficulty = estimate_difficulty ();
181 root 1.3
182 root 1.22 CEDE;
183 root 1.19
184 root 1.3 /* create treasure unless the treasurestyle is "none" */
185 root 1.40 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.39 if (!(rmg_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.39 maze_gen (layout, rmg_rndm (2));
229 root 1.32
230 root 1.39 if (!(rmg_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.39 if (!(rmg_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.39 if (rmg_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.39 if (rmg_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 root 1.39 rotate_layout (layout, rmg_rndm (4));
278 root 1.34
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.39 dx = rmg_rndm (RP->Xsize);
403     dy = rmg_rndm (RP->Ysize);
404 root 1.27
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    
550 root 1.41 uint16 *doorlist_x = salloc<uint16> (RP->Xsize * RP->Ysize);
551     uint16 *doorlist_y = salloc<uint16> (RP->Xsize * RP->Ysize);
552 elmex 1.1
553     /* make a list of possible door locations */
554 root 1.41 for (int i = 1; i < RP->Xsize - 1; i++)
555     for (int j = 1; j < RP->Ysize - 1; j++)
556 root 1.3 {
557     int sindex = surround_flag (maze, i, j, RP);
558    
559     if (sindex == 3 || sindex == 12) /* these are possible door sindex */
560     {
561     doorlist_x[doorlocs] = i;
562     doorlist_y[doorlocs] = j;
563     doorlocs++;
564     }
565     }
566 root 1.12
567 root 1.3 while (ndoors > 0 && doorlocs > 0)
568     {
569 root 1.41 int di = rmg_rndm (doorlocs);
570     int i = doorlist_x[di];
571     int j = doorlist_y[di];
572     int sindex = surround_flag (maze, i, j, RP);
573 root 1.27
574 root 1.3 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
575     {
576     maze[i][j] = 'D';
577     ndoors--;
578 elmex 1.1 }
579 root 1.27
580 root 1.3 /* reduce the size of the list */
581     doorlocs--;
582     doorlist_x[di] = doorlist_x[doorlocs];
583     doorlist_y[di] = doorlist_y[doorlocs];
584 elmex 1.1 }
585 root 1.12
586 root 1.32 sfree (doorlist_x, RP->Xsize * RP->Ysize);
587     sfree (doorlist_y, RP->Xsize * RP->Ysize);
588 elmex 1.1 }
589    
590 root 1.3 void
591 root 1.13 write_map_parameters_to_string (char *buf, random_map_params *RP)
592 root 1.3 {
593 root 1.18 char small_buf[16384];
594 elmex 1.1
595 root 1.24 sprintf (buf, "xsize %d\nysize %d\n", RP->xsize, RP->ysize);
596 root 1.3
597     if (RP->wallstyle[0])
598     {
599     sprintf (small_buf, "wallstyle %s\n", RP->wallstyle);
600     strcat (buf, small_buf);
601     }
602    
603     if (RP->floorstyle[0])
604     {
605     sprintf (small_buf, "floorstyle %s\n", RP->floorstyle);
606     strcat (buf, small_buf);
607     }
608    
609     if (RP->monsterstyle[0])
610     {
611     sprintf (small_buf, "monsterstyle %s\n", RP->monsterstyle);
612     strcat (buf, small_buf);
613     }
614 elmex 1.1
615 root 1.3 if (RP->treasurestyle[0])
616     {
617     sprintf (small_buf, "treasurestyle %s\n", RP->treasurestyle);
618     strcat (buf, small_buf);
619     }
620 elmex 1.1
621 root 1.3 if (RP->layoutstyle[0])
622     {
623     sprintf (small_buf, "layoutstyle %s\n", RP->layoutstyle);
624     strcat (buf, small_buf);
625     }
626 elmex 1.1
627 root 1.3 if (RP->decorstyle[0])
628     {
629     sprintf (small_buf, "decorstyle %s\n", RP->decorstyle);
630     strcat (buf, small_buf);
631     }
632 elmex 1.1
633 root 1.3 if (RP->doorstyle[0])
634     {
635     sprintf (small_buf, "doorstyle %s\n", RP->doorstyle);
636     strcat (buf, small_buf);
637     }
638 elmex 1.1
639 root 1.3 if (RP->exitstyle[0])
640     {
641     sprintf (small_buf, "exitstyle %s\n", RP->exitstyle);
642     strcat (buf, small_buf);
643     }
644 elmex 1.1
645 root 1.14 if (RP->final_map.length ())
646 root 1.3 {
647 root 1.14 sprintf (small_buf, "final_map %s\n", &RP->final_map);
648 root 1.3 strcat (buf, small_buf);
649     }
650 elmex 1.1
651 root 1.3 if (RP->exit_on_final_map[0])
652     {
653     sprintf (small_buf, "exit_on_final_map %s\n", RP->exit_on_final_map);
654     strcat (buf, small_buf);
655     }
656 elmex 1.1
657 root 1.14 if (RP->this_map.length ())
658 root 1.3 {
659 root 1.14 sprintf (small_buf, "origin_map %s\n", &RP->this_map);
660 root 1.3 strcat (buf, small_buf);
661     }
662 elmex 1.1
663 root 1.3 if (RP->expand2x)
664     {
665     sprintf (small_buf, "expand2x %d\n", RP->expand2x);
666     strcat (buf, small_buf);
667     }
668 elmex 1.1
669 root 1.3 if (RP->layoutoptions1)
670     {
671     sprintf (small_buf, "layoutoptions1 %d\n", RP->layoutoptions1);
672     strcat (buf, small_buf);
673     }
674 elmex 1.1
675 root 1.3 if (RP->layoutoptions2)
676     {
677     sprintf (small_buf, "layoutoptions2 %d\n", RP->layoutoptions2);
678     strcat (buf, small_buf);
679     }
680 elmex 1.1
681 root 1.3 if (RP->layoutoptions3)
682     {
683     sprintf (small_buf, "layoutoptions3 %d\n", RP->layoutoptions3);
684     strcat (buf, small_buf);
685     }
686 elmex 1.1
687 root 1.3 if (RP->symmetry)
688     {
689     sprintf (small_buf, "symmetry %d\n", RP->symmetry);
690     strcat (buf, small_buf);
691     }
692 elmex 1.1
693 root 1.3 if (RP->difficulty && RP->difficulty_given)
694     {
695     sprintf (small_buf, "difficulty %d\n", RP->difficulty);
696     strcat (buf, small_buf);
697     }
698 elmex 1.1
699 root 1.3 if (RP->difficulty_increase != 1.0)
700     {
701     sprintf (small_buf, "difficulty_increase %f\n", RP->difficulty_increase);
702     strcat (buf, small_buf);
703     }
704 elmex 1.1
705 root 1.3 sprintf (small_buf, "dungeon_level %d\n", RP->dungeon_level);
706     strcat (buf, small_buf);
707 elmex 1.1
708 root 1.3 if (RP->dungeon_depth)
709     {
710     sprintf (small_buf, "dungeon_depth %d\n", RP->dungeon_depth);
711     strcat (buf, small_buf);
712     }
713 elmex 1.1
714 root 1.3 if (RP->decoroptions)
715     {
716     sprintf (small_buf, "decoroptions %d\n", RP->decoroptions);
717     strcat (buf, small_buf);
718     }
719 elmex 1.1
720 root 1.3 if (RP->orientation)
721     {
722     sprintf (small_buf, "orientation %d\n", RP->orientation);
723     strcat (buf, small_buf);
724     }
725 elmex 1.1
726 root 1.3 if (RP->origin_x)
727     {
728     sprintf (small_buf, "origin_x %d\n", RP->origin_x);
729     strcat (buf, small_buf);
730     }
731 elmex 1.1
732 root 1.3 if (RP->origin_y)
733     {
734     sprintf (small_buf, "origin_y %d\n", RP->origin_y);
735     strcat (buf, small_buf);
736     }
737 root 1.11
738 root 1.3 if (RP->treasureoptions)
739     {
740     sprintf (small_buf, "treasureoptions %d\n", RP->treasureoptions);
741     strcat (buf, small_buf);
742     }
743 root 1.14
744     if (RP->random_seed)
745     {
746 root 1.25 sprintf (small_buf, "random_seed %u\n", RP->random_seed);
747 root 1.14 strcat (buf, small_buf);
748     }
749 root 1.18
750     if (RP->custom)
751     {
752     sprintf (small_buf, "custom %s\n", RP->custom);
753     strcat (buf, small_buf);
754     }
755 elmex 1.1 }
756    
757 root 1.3 void
758     write_parameters_to_string (char *buf,
759     int xsize_n,
760     int ysize_n,
761 root 1.28 const char *wallstyle_n,
762     const char *floorstyle_n,
763     const char *monsterstyle_n,
764     const char *treasurestyle_n,
765     const char *layoutstyle_n,
766     const char *decorstyle_n,
767     const char *doorstyle_n,
768     const char *exitstyle_n,
769     const char *final_map_n,
770     const char *exit_on_final_map_n,
771     const char *this_map_n,
772 root 1.3 int layoutoptions1_n,
773     int layoutoptions2_n,
774     int layoutoptions3_n,
775     int symmetry_n,
776     int dungeon_depth_n,
777     int dungeon_level_n,
778     int difficulty_n,
779     int difficulty_given_n,
780     int decoroptions_n,
781     int orientation_n,
782 root 1.28 int origin_x_n,
783     int origin_y_n,
784     uint32_t random_seed_n,
785     int treasureoptions_n,
786     float difficulty_increase)
787 elmex 1.1 {
788 root 1.18 char small_buf[16384];
789 elmex 1.1
790 root 1.3 sprintf (buf, "xsize %d\nysize %d\n", xsize_n, ysize_n);
791    
792     if (wallstyle_n && wallstyle_n[0])
793     {
794     sprintf (small_buf, "wallstyle %s\n", wallstyle_n);
795     strcat (buf, small_buf);
796     }
797    
798     if (floorstyle_n && floorstyle_n[0])
799     {
800     sprintf (small_buf, "floorstyle %s\n", floorstyle_n);
801     strcat (buf, small_buf);
802     }
803 elmex 1.1
804 root 1.3 if (monsterstyle_n && monsterstyle_n[0])
805     {
806     sprintf (small_buf, "monsterstyle %s\n", monsterstyle_n);
807     strcat (buf, small_buf);
808     }
809 elmex 1.1
810 root 1.3 if (treasurestyle_n && treasurestyle_n[0])
811     {
812     sprintf (small_buf, "treasurestyle %s\n", treasurestyle_n);
813     strcat (buf, small_buf);
814     }
815 elmex 1.1
816 root 1.3 if (layoutstyle_n && layoutstyle_n[0])
817     {
818     sprintf (small_buf, "layoutstyle %s\n", layoutstyle_n);
819     strcat (buf, small_buf);
820     }
821 elmex 1.1
822 root 1.3 if (decorstyle_n && decorstyle_n[0])
823     {
824     sprintf (small_buf, "decorstyle %s\n", decorstyle_n);
825     strcat (buf, small_buf);
826     }
827 elmex 1.1
828 root 1.3 if (doorstyle_n && doorstyle_n[0])
829     {
830     sprintf (small_buf, "doorstyle %s\n", doorstyle_n);
831     strcat (buf, small_buf);
832     }
833 elmex 1.1
834 root 1.3 if (exitstyle_n && exitstyle_n[0])
835     {
836     sprintf (small_buf, "exitstyle %s\n", exitstyle_n);
837     strcat (buf, small_buf);
838     }
839 elmex 1.1
840 root 1.3 if (final_map_n && final_map_n[0])
841     {
842     sprintf (small_buf, "final_map %s\n", final_map_n);
843     strcat (buf, small_buf);
844     }
845 elmex 1.1
846 root 1.3 if (exit_on_final_map_n && exit_on_final_map_n[0])
847     {
848     sprintf (small_buf, "exit_on_final_map %s\n", exit_on_final_map_n);
849     strcat (buf, small_buf);
850     }
851 elmex 1.1
852 root 1.3 if (this_map_n && this_map_n[0])
853     {
854     sprintf (small_buf, "origin_map %s\n", this_map_n);
855     strcat (buf, small_buf);
856     }
857 elmex 1.1
858 root 1.3 if (layoutoptions1_n)
859     {
860     sprintf (small_buf, "layoutoptions1 %d\n", layoutoptions1_n);
861     strcat (buf, small_buf);
862     }
863 elmex 1.1
864 root 1.3 if (layoutoptions2_n)
865     {
866     sprintf (small_buf, "layoutoptions2 %d\n", layoutoptions2_n);
867     strcat (buf, small_buf);
868     }
869 elmex 1.1
870    
871 root 1.3 if (layoutoptions3_n)
872     {
873     sprintf (small_buf, "layoutoptions3 %d\n", layoutoptions3_n);
874     strcat (buf, small_buf);
875     }
876 elmex 1.1
877 root 1.3 if (symmetry_n)
878     {
879     sprintf (small_buf, "symmetry %d\n", symmetry_n);
880     strcat (buf, small_buf);
881     }
882 elmex 1.1
883    
884 root 1.3 if (difficulty_n && difficulty_given_n)
885     {
886     sprintf (small_buf, "difficulty %d\n", difficulty_n);
887     strcat (buf, small_buf);
888     }
889 elmex 1.1
890 root 1.3 if (difficulty_increase > 0.001)
891     {
892     sprintf (small_buf, "difficulty_increase %f\n", difficulty_increase);
893     strcat (buf, small_buf);
894     }
895 elmex 1.1
896 root 1.3 sprintf (small_buf, "dungeon_level %d\n", dungeon_level_n);
897     strcat (buf, small_buf);
898 elmex 1.1
899 root 1.3 if (dungeon_depth_n)
900     {
901     sprintf (small_buf, "dungeon_depth %d\n", dungeon_depth_n);
902     strcat (buf, small_buf);
903     }
904 elmex 1.1
905 root 1.3 if (decoroptions_n)
906     {
907     sprintf (small_buf, "decoroptions %d\n", decoroptions_n);
908     strcat (buf, small_buf);
909     }
910 elmex 1.1
911 root 1.3 if (orientation_n)
912     {
913     sprintf (small_buf, "orientation %d\n", orientation_n);
914     strcat (buf, small_buf);
915     }
916 elmex 1.1
917 root 1.3 if (origin_x_n)
918     {
919     sprintf (small_buf, "origin_x %d\n", origin_x_n);
920     strcat (buf, small_buf);
921     }
922 elmex 1.1
923 root 1.3 if (origin_y_n)
924     {
925     sprintf (small_buf, "origin_y %d\n", origin_y_n);
926     strcat (buf, small_buf);
927     }
928 root 1.11
929 root 1.3 if (random_seed_n)
930     {
931     /* Add one so that the next map is a bit different */
932 root 1.25 sprintf (small_buf, "random_seed %u\n", random_seed_n + 1);
933 root 1.3 strcat (buf, small_buf);
934     }
935 elmex 1.1
936 root 1.3 if (treasureoptions_n)
937     {
938     sprintf (small_buf, "treasureoptions %d\n", treasureoptions_n);
939     strcat (buf, small_buf);
940     }
941 elmex 1.1 }
942    
943 root 1.34 /////////////////////////////////////////////////////////////////////////////
944    
945     LayoutData::LayoutData (int w, int h)
946 root 1.33 : w(w), h(h)
947 root 1.32 {
948 root 1.33 int size = (sizeof (char *) + sizeof (char) * h) * w;
949 root 1.32
950 root 1.33 col = (char **)salloc<char> (size);
951 root 1.32
952 root 1.33 char *data = (char *)(col + w);
953 root 1.32
954 root 1.33 for (int x = w; x--; )
955     col [x] = data + x * h;
956 root 1.32 }
957    
958 root 1.34 LayoutData::~LayoutData ()
959 root 1.32 {
960 root 1.33 int size = (sizeof (char *) + sizeof (char) * h) * w;
961    
962 root 1.32 sfree ((char *)col, size);
963     }
964    
965 root 1.34 void LayoutData::clear (char fill)
966 root 1.33 {
967     memset (col [0], fill, w * h);
968     }
969    
970 root 1.34 void LayoutData::border (char fill)
971 root 1.33 {
972     for (int i = 0; i < w; i++) col [i][0] = col [i][h - 1] = fill;
973     for (int j = 0; j < h; j++) col [0][j] = col [w - 1][j] = fill;
974     }
975