ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
(Generate patch)

Comparing deliantra/server/random_maps/random_map.C (file contents):
Revision 1.2 by root, Tue Aug 29 08:01:36 2006 UTC vs.
Revision 1.52 by root, Sat Jun 26 23:53:31 2010 UTC

1/* 1/*
2 * static char *rcsid_random_map_c = 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * "$Id: random_map.C,v 1.2 2006/08/29 08:01:36 root Exp $"; 3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen
7 *
8 * 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 *
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 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * 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 *
22 * The authors can be reached via e-mail to <support@deliantra.net>
4 */ 23 */
5
6/*
7 CrossFire, A Multiplayer game for X-windows
8
9 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 The authors can be reached via e-mail at crossfire-devel@real-time.com
27*/
28 24
29#include <time.h> 25#include <time.h>
30#include <stdio.h> 26#include <stdio.h>
31#include <global.h> 27#include <global.h>
32#include <maze_gen.h>
33#include <room_gen.h>
34#include <random_map.h> 28#include <random_map.h>
35#include <rproto.h> 29#include <rproto.h>
36#include <sproto.h> 30#include <sproto.h>
37 31
38void dump_layout(char **layout,RMParms *RP) { 32#define CEDE coroapi::cede_to_tick ()
39 { int i,j;
40 for(i=0;i<RP->Xsize;i++) {
41 for(j=0;j<RP->Ysize;j++) {
42 if(layout[i][j]==0) layout[i][j]=' ';
43 printf("%c",layout[i][j]);
44 if(layout[i][j]==' ') layout[i][j]=0;
45 }
46 printf("\n");
47 }}
48 printf("\n");
49}
50EXTERN FILE *logfile;
51mapstruct *generate_random_map(const char *OutFileName, RMParms *RP) {
52 char **layout, buf[HUGE_BUF];
53 mapstruct *theMap;
54 int i;
55 33
56 /* pick a random seed, or use the one from the input file */ 34static void symmetrize_layout (Layout maze, random_map_params *RP);
57 if(RP->random_seed == 0) 35static void rotate_layout (Layout maze, int rotation);
58 RP->random_seed=time(0);
59 36
60 SRANDOM(RP->random_seed); 37const_utf8_string
38random_map_params::get_str (const_utf8_string option, const_utf8_string fallback) const
39{
40 SV **he = hv_fetch (hv, option, strlen (option), 0);
61 41
62 write_map_parameters_to_string(buf, RP); 42 return he ? cfSvPVutf8_nolen (*he) : fallback;
43}
63 44
64 if(RP->difficulty==0) { 45IV
65 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */ 46random_map_params::get_iv (const char *option, IV fallback) const
66 if (RP->difficulty_increase > 0.001) { 47{
67 RP->difficulty = (int)((float)RP->dungeon_level * RP->difficulty_increase); 48 SV **he = hv_fetch (hv, option, strlen (option), 0);
68 if (RP->difficulty < 1) RP->difficulty=1;
69 }
70 }
71 else
72 RP->difficulty_given=1;
73 49
74 if(RP->Xsize<MIN_RANDOM_MAP_SIZE) RP->Xsize = MIN_RANDOM_MAP_SIZE + RANDOM()%25 + 5; 50 return he ? SvIV (*he) : fallback;
75 if(RP->Ysize<MIN_RANDOM_MAP_SIZE) RP->Ysize = MIN_RANDOM_MAP_SIZE + RANDOM()%25 + 5; 51}
76 52
77 if(RP->expand2x > 0) { 53random_map_params::~random_map_params ()
78 RP->Xsize /=2; 54{
79 RP->Ysize /=2; 55 SvREFCNT_dec (hv);
80 } 56}
81 57
82 layout = layoutgen(RP); 58void
83 59Layout::print ()
84#ifdef RMAP_DEBUG 60{
85 dump_layout(layout,RP); 61 for (int j = 0; j < ptr->h; j++)
86#endif
87
88 /* increment these for the current map */
89 RP->dungeon_level+=1;
90 /* allow constant-difficulty maps. */
91 /* difficulty+=1; */
92
93 /* rotate the layout randomly */
94 layout=rotate_layout(layout,RANDOM()%4,RP);
95#ifdef RMAP_DEBUG
96 dump_layout(layout,RP);
97#endif
98
99 /* allocate the map and set the floor */
100 theMap = make_map_floor(layout,RP->floorstyle,RP);
101
102 /* set the name of the map. */
103 strcpy(theMap->path,OutFileName);
104
105 /* set region */
106 theMap->region=RP->region;
107 62 {
108 /* create walls unless the wallstyle is "none" */ 63 for (int i = 0; i < ptr->w; i++)
109 if (strcmp (RP->wallstyle, "none")) {
110 make_map_walls(theMap,layout,RP->wallstyle,RP);
111 64 {
112 /* place doors unless doorstyle or wallstyle is "none"*/ 65 putc (ptr->col[i][j] ? ptr->col[i][j] : ' ', stdout);
113 if (strcmp (RP->doorstyle, "none")) 66 putc (ptr->col[i][j] ? ptr->col[i][j] : ' ', stdout);
114 put_doors(theMap,layout,RP->doorstyle,RP);
115 67 }
116 }
117 68
118 /* create exits unless the exitstyle is "none" */ 69 putc ('\n', stdout);
119 if (strcmp (RP->exitstyle, "none"))
120 place_exits(theMap,layout,RP->exitstyle,RP->orientation,RP);
121
122 place_specials_in_map(theMap,layout,RP);
123
124 /* create monsters unless the monsterstyle is "none" */
125 if (strcmp (RP->monsterstyle, "none"))
126 place_monsters(theMap,RP->monsterstyle,RP->difficulty,RP);
127
128 /* treasures needs to have a proper difficulty set for the map. */
129 theMap->difficulty=calculate_difficulty(theMap);
130
131 /* create treasure unless the treasurestyle is "none" */
132 if (strcmp (RP->treasurestyle, "none"))
133 place_treasure(theMap,layout,RP->treasurestyle,RP->treasureoptions,RP);
134
135 /* create decor unless the decorstyle is "none" */
136 if (strcmp (RP->decorstyle, "none"))
137 put_decor(theMap,layout,RP->decorstyle,RP->decoroptions,RP);
138
139 /* generate treasures, etc. */
140 fix_auto_apply(theMap);
141
142 unblock_exits(theMap,layout,RP);
143
144 /* free the layout */
145 for(i=0;i<RP->Xsize;i++)
146 free(layout[i]);
147 free(layout);
148
149 theMap->msg = strdup_local(buf);
150
151 return theMap;
152}
153
154
155/* function selects the layout function and gives it whatever
156 arguments it needs. */
157char **layoutgen(RMParms *RP) {
158 char **maze=0;
159 int oxsize= RP->Xsize, oysize=RP->Ysize;
160
161 if(RP->symmetry == RANDOM_SYM)
162 RP->symmetry_used = (RANDOM() % ( XY_SYM))+1;
163 else RP->symmetry_used = RP->symmetry;
164
165 if(RP->symmetry_used==Y_SYM||RP->symmetry_used==XY_SYM) RP->Ysize = RP->Ysize/2+1;
166 if(RP->symmetry_used==X_SYM||RP->symmetry_used==XY_SYM) RP->Xsize = RP->Xsize/2+1;
167
168 if(RP->Xsize<MIN_RANDOM_MAP_SIZE) RP->Xsize = MIN_RANDOM_MAP_SIZE + RANDOM()%5;
169 if(RP->Ysize<MIN_RANDOM_MAP_SIZE) RP->Ysize = MIN_RANDOM_MAP_SIZE + RANDOM()%5;
170 RP->map_layout_style = 0;
171
172 /* Redo this - there was a lot of redundant code of checking for preset
173 * layout style and then random layout style. Instead, figure out
174 * the numeric layoutstyle, so there is only one area that actually
175 * calls the code to make the maps.
176 */
177 if(strstr(RP->layoutstyle,"onion")) {
178 RP->map_layout_style = ONION_LAYOUT;
179 } 70 }
180 71
181 if(strstr(RP->layoutstyle,"maze")) { 72 putc ('\n', stdout);
182 RP->map_layout_style = MAZE_LAYOUT;
183 }
184
185 if(strstr(RP->layoutstyle,"spiral")) {
186 RP->map_layout_style = SPIRAL_LAYOUT;
187 }
188
189 if(strstr(RP->layoutstyle,"rogue")) {
190 RP->map_layout_style = ROGUELIKE_LAYOUT;
191 }
192
193 if(strstr(RP->layoutstyle,"snake")) {
194 RP->map_layout_style = SNAKE_LAYOUT;
195 }
196
197 if(strstr(RP->layoutstyle,"squarespiral")) {
198 RP->map_layout_style = SQUARE_SPIRAL_LAYOUT;
199 }
200 /* No style found - choose one ranomdly */
201 if (RP->map_layout_style == 0) {
202 RP->map_layout_style = (RANDOM() % NROFLAYOUTS) + 1;
203 }
204
205 switch(RP->map_layout_style) {
206
207 case ONION_LAYOUT:
208 maze = map_gen_onion(RP->Xsize,RP->Ysize,RP->layoutoptions1,RP->layoutoptions2);
209 if(!(RANDOM()%3)&& !(RP->layoutoptions1 & OPT_WALLS_ONLY)) roomify_layout(maze,RP);
210 break;
211
212 case MAZE_LAYOUT:
213 maze = maze_gen(RP->Xsize,RP->Ysize,RANDOM()%2);
214 if(!(RANDOM()%2)) doorify_layout(maze,RP);
215 break;
216
217 case SPIRAL_LAYOUT:
218 maze = map_gen_spiral(RP->Xsize,RP->Ysize,RP->layoutoptions1);
219 if(!(RANDOM()%2)) doorify_layout(maze,RP);
220 break;
221
222 case ROGUELIKE_LAYOUT:
223 /* Don't put symmetry in rogue maps. There isn't much reason to
224 * do so in the first place (doesn't make it any more interesting),
225 * but more importantly, the symmetry code presumes we are symmetrizing
226 * spirals, or maps with lots of passages - making a symmetric rogue
227 * map fails because its likely that the passages the symmetry process
228 * creates may not connect the rooms.
229 */
230 RP->symmetry_used = NO_SYM;
231 RP->Ysize = oysize;
232 RP->Xsize = oxsize;
233 maze = roguelike_layout_gen(RP->Xsize,RP->Ysize,RP->layoutoptions1);
234 /* no doorifying... done already */
235 break;
236
237 case SNAKE_LAYOUT:
238 maze = make_snake_layout(RP->Xsize,RP->Ysize,RP->layoutoptions1);
239 if(RANDOM()%2) roomify_layout(maze,RP);
240 break;
241
242 case SQUARE_SPIRAL_LAYOUT:
243 maze = make_square_spiral_layout(RP->Xsize,RP->Ysize,RP->layoutoptions1);
244 if(RANDOM()%2) roomify_layout(maze,RP);
245 break;
246 }
247
248 maze = symmetrize_layout(maze, RP->symmetry_used,RP);
249#ifdef RMAP_DEBUG
250 dump_layout(maze,RP);
251#endif
252 if(RP->expand2x) {
253 maze = expand2x(maze,RP->Xsize,RP->Ysize);
254 RP->Xsize = RP->Xsize * 2 -1;
255 RP->Ysize = RP->Ysize * 2 -1;
256 }
257 return maze;
258} 73}
259 74
260
261/* takes a map and makes it symmetric: adjusts Xsize and 75/* takes a map and makes it symmetric: adjusts Xsize and
262Ysize to produce a symmetric map. */ 76 * Ysize to produce a symmetric map.
263 77 */
264char **symmetrize_layout(char **maze, int sym,RMParms *RP) { 78static void
265 int i,j; 79symmetrize_layout (Layout layout, random_map_params *RP)
266 char **sym_maze; 80{
267 int Xsize_orig,Ysize_orig; 81 if (RP->symmetry_used == SYMMETRY_NONE)
268 Xsize_orig = RP->Xsize;
269 Ysize_orig = RP->Ysize;
270 RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used.*/
271 if(sym == NO_SYM) {
272 RP->Xsize = Xsize_orig;
273 RP->Ysize = Ysize_orig;
274 return maze; 82 return;
275 }
276 /* pick new sizes */
277 RP->Xsize = ((sym==X_SYM||sym==XY_SYM)?RP->Xsize*2-3:RP->Xsize);
278 RP->Ysize = ((sym==Y_SYM||sym==XY_SYM)?RP->Ysize*2-3:RP->Ysize);
279 83
280 sym_maze = (char **)calloc(sizeof(char*),RP->Xsize); 84 Layout sym_layout (
281 for(i=0;i<RP->Xsize;i++) 85 RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY ? layout->w * 2 - 3 : layout->w,
282 sym_maze[i] = (char *)calloc(sizeof(char),RP->Ysize); 86 RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY ? layout->h * 2 - 3 : layout->h
87 );
283 88
284 if(sym==X_SYM) 89 if (RP->symmetry_used == SYMMETRY_X)
285 for(i=0;i<RP->Xsize/2+1;i++) 90 for (int i = 0; i < sym_layout->w / 2 + 1; i++)
286 for(j=0;j<RP->Ysize;j++) { 91 for (int j = 0; j < sym_layout->h; j++)
287 sym_maze[i][j] = maze[i][j]; 92 {
288 sym_maze[RP->Xsize - i-1][j] = maze[i][j]; 93 sym_layout[i ][j] =
289 }; 94 sym_layout[sym_layout->w - i - 1][j] = layout[i][j];
290 if(sym==Y_SYM)
291 for(i=0;i<RP->Xsize;i++)
292 for(j=0;j<RP->Ysize/2+1;j++) {
293 sym_maze[i][j] = maze[i][j];
294 sym_maze[i][RP->Ysize-j-1] = maze[i][j];
295 } 95 }
296 if(sym==XY_SYM) 96
297 for(i=0;i<RP->Xsize/2+1;i++) 97 if (RP->symmetry_used == SYMMETRY_Y)
298 for(j=0;j<RP->Ysize/2+1;j++) { 98 for (int i = 0; i < sym_layout->w; i++)
299 sym_maze[i][j] = maze[i][j]; 99 for (int j = 0; j < sym_layout->h / 2 + 1; j++)
300 sym_maze[i][RP->Ysize-j-1] = maze[i][j]; 100 {
301 sym_maze[RP->Xsize - i-1][j] = maze[i][j]; 101 sym_layout[i][j ] =
302 sym_maze[RP->Xsize - i-1][RP->Ysize-j-1] = maze[i][j]; 102 sym_layout[i][sym_layout->h - j - 1] = layout[i][j];
303 } 103 }
304 /* delete the old maze */ 104
305 for(i=0;i<Xsize_orig;i++) 105 if (RP->symmetry_used == SYMMETRY_XY)
306 free(maze[i]); 106 for (int i = 0; i < sym_layout->w / 2 + 1; i++)
307 free(maze); 107 for (int j = 0; j < sym_layout->h / 2 + 1; j++)
108 {
109 sym_layout[i ][j ] =
110 sym_layout[i ][sym_layout->h - j - 1] =
111 sym_layout[sym_layout->w - i - 1][j ] =
112 sym_layout[sym_layout->w - i - 1][sym_layout->h - j - 1] = layout[i][j];
113 }
114
115 layout.swap (sym_layout);
116 sym_layout.free ();
117
308 /* reconnect disjointed spirals */ 118 /* reconnect disjointed spirals */
309 if(RP->map_layout_style==SPIRAL_LAYOUT)
310 connect_spirals(RP->Xsize,RP->Ysize,sym,sym_maze);
311 /* reconnect disjointed nethackmazes: the routine for 119 /* reconnect disjointed nethacklayouts: the routine for
312 spirals will do the trick?*/ 120 spirals will do the trick? */
313 if(RP->map_layout_style==ROGUELIKE_LAYOUT) 121 if (RP->map_layout_style == LAYOUT_SPIRAL
314 connect_spirals(RP->Xsize,RP->Ysize,sym,sym_maze); 122 || RP->map_layout_style == LAYOUT_ROGUELIKE)
315 123 connect_spirals (layout->w, layout->h, RP->symmetry_used, layout);
316 return sym_maze;
317} 124}
318
319 125
320/* takes a map and rotates it. This completes the 126/* takes a map and rotates it. This completes the
321 onion layouts, making them possibly centered on any wall. 127 onion layouts, making them possibly centered on any wall.
322 It'll modify Xsize and Ysize if they're swapped. 128 It'll modify Xsize and Ysize if they're swapped.
323*/ 129*/
130static void
131rotate_layout (Layout layout, int rotation)
132{
133 int w = layout->w;
134 int h = layout->h;
324 135
325char ** rotate_layout(char **maze,int rotation,RMParms *RP) {
326 char **new_maze;
327 int i,j;
328
329 switch(rotation) { 136 switch (rotation)
330 case 0:
331 return maze;
332 break;
333 case 2: /* a reflection */
334 { 137 {
335 char *newmaze= (char *) malloc(sizeof(char) * RP->Xsize*RP->Ysize); 138 case 2: /* a reflection */
336 for(i=0;i<RP->Xsize;i++) { /* make a copy */
337 for(j=0;j<RP->Ysize;j++) {
338 newmaze[i * RP->Ysize + j] = maze[i][j];
339 } 139 {
140 Layout new_layout (w, h);
141
142 for (int i = 0; i < w; i++) /* copy a reflection back */
143 for (int j = 0; j < h; j++)
144 new_layout[i][j] = layout[w - i - 1][h - j - 1];
145
146 layout.swap (new_layout);
147 new_layout.free ();
340 } 148 }
341 for(i=0;i<RP->Xsize;i++) { /* copy a reflection back */
342 for(j=0;j<RP->Ysize;j++) {
343 maze[i][j]= newmaze[(RP->Xsize-i-1)*RP->Ysize + RP->Ysize-j-1];
344 }
345 }
346 free(newmaze);
347 return maze;
348 break; 149 break;
349 } 150
350 case 1: 151 case 1:
351 case 3: 152 case 3:
352 { int swap; 153 {
353 new_maze = (char **) calloc(sizeof(char *),RP->Ysize); 154 Layout new_layout (h, w);
354 for(i=0;i<RP->Ysize;i++) { 155
355 new_maze[i] = (char *) calloc(sizeof(char),RP->Xsize);
356 }
357 if(rotation == 1) /* swap x and y */ 156 if (rotation == 1) /* swap x and y */
358 for(i=0;i<RP->Xsize;i++) 157 for (int i = 0; i < w; i++)
359 for(j=0;j<RP->Ysize;j++) 158 for (int j = 0; j < h; j++)
360 new_maze[j][i] = maze[i][j]; 159 new_layout[j][i] = layout[i][j];
361 160
362 if(rotation == 3) { /* swap x and y */ 161 if (rotation == 3) /* swap x and y */
363 for(i=0;i<RP->Xsize;i++) 162 for (int i = 0; i < w; i++)
364 for(j=0;j<RP->Ysize;j++) 163 for (int j = 0; j < h; j++)
365 new_maze[j][i] = maze[RP->Xsize -i-1][RP->Ysize - j-1]; 164 new_layout[j][i] = layout[w - i - 1][h - j - 1];
366 }
367 165
368 /* delete the old layout */ 166 layout.swap (new_layout);
369 for(i=0;i<RP->Xsize;i++) 167 new_layout.free ();
370 free(maze[i]); 168 }
371 free(maze);
372
373 swap = RP->Ysize;
374 RP->Ysize = RP->Xsize;
375 RP->Xsize = swap;
376 return new_maze;
377 break; 169 break;
378 }
379 } 170 }
380 return NULL;
381}
382
383/* take a layout and make some rooms in it.
384 --works best on onions.*/
385void roomify_layout(char **maze,RMParms *RP) {
386 int tries = RP->Xsize*RP->Ysize/30;
387 int ti;
388
389 for(ti=0;ti<tries;ti++) {
390 int dx,dy; /* starting location for looking at creating a door */
391 int cx,cy; /* results of checking on creating walls. */
392 dx = RANDOM() % RP->Xsize;
393 dy = RANDOM() % RP->Ysize;
394 cx = can_make_wall(maze,dx,dy,0,RP); /* horizontal */
395 cy = can_make_wall(maze,dx,dy,1,RP); /* vertical */
396 if(cx == -1) {
397 if(cy != -1)
398 make_wall(maze,dx,dy,1);
399 continue;
400 }
401 if(cy == -1) {
402 make_wall(maze,dx,dy,0);
403 continue;
404 }
405 if(cx < cy) make_wall(maze,dx,dy,0);
406 else make_wall(maze,dx,dy,1);
407 }
408} 171}
409 172
410/* checks the layout to see if I can stick a horizontal(dir = 0) wall 173/* checks the layout to see if I can stick a horizontal(dir = 0) wall
411 (or vertical, dir == 1) 174 (or vertical, dir == 1)
412 here which ends up on other walls sensibly. */ 175 here which ends up on other walls sensibly. */
413 176static int
414int can_make_wall(char **maze,int dx,int dy,int dir,RMParms *RP) { 177can_make_wall (char **maze, int dx, int dy, int dir, random_map_params *RP)
178{
415 int i1; 179 int i1;
416 int length=0; 180 int length = 0;
417 181
418 /* dont make walls if we're on the edge. */ 182 /* dont make walls if we're on the edge. */
419 if(dx == 0 || dx == (RP->Xsize -1) || dy == 0 || dy == (RP->Ysize-1)) return -1; 183 if (dx == 0 || dx == (RP->Xsize - 1) || dy == 0 || dy == (RP->Ysize - 1))
184 return -1;
420 185
421 /* don't make walls if we're ON a wall. */ 186 /* don't make walls if we're ON a wall. */
422 if(maze[dx][dy]!=0) return -1; 187 if (maze[dx][dy] != 0)
188 return -1;
423 189
424 if(dir==0) /* horizontal */ 190 if (dir == 0) /* horizontal */
425 { 191 {
426 int y = dy; 192 int y = dy;
193
427 for(i1=dx-1;i1>0;i1--) { 194 for (i1 = dx - 1; i1 > 0; i1--)
195 {
428 int sindex=surround_flag2(maze,i1,y,RP); 196 int sindex = surround_flag2 (maze, i1, y, RP);
197
429 if(sindex == 1) break; 198 if (sindex == 1)
199 break;
200 if (sindex != 0)
430 if(sindex != 0) return -1; /* can't make horiz. wall here */ 201 return -1; /* can't make horiz. wall here */
202 if (maze[i1][y] != 0)
431 if(maze[i1][y]!=0) return -1; /* can't make horiz. wall here */ 203 return -1; /* can't make horiz. wall here */
432 length++; 204 length++;
205 }
206
207 for (i1 = dx + 1; i1 < RP->Xsize - 1; i1++)
208 {
209 int sindex = surround_flag2 (maze, i1, y, RP);
210
211 if (sindex == 2)
212 break;
213 if (sindex != 0)
214 return -1; /* can't make horiz. wall here */
215 if (maze[i1][y] != 0)
216 return -1; /* can't make horiz. wall here */
217 length++;
218 }
219 return length;
220 }
221 else
222 { /* vertical */
223 int x = dx;
224
225 for (i1 = dy - 1; i1 > 0; i1--)
226 {
227 int sindex = surround_flag2 (maze, x, i1, RP);
228
229 if (sindex == 4)
230 break;
231 if (sindex != 0)
232 return -1; /* can't make vert. wall here */
233 if (maze[x][i1] != 0)
234 return -1; /* can't make horiz. wall here */
235 length++;
236 }
237
238 for (i1 = dy + 1; i1 < RP->Ysize - 1; i1++)
239 {
240 int sindex = surround_flag2 (maze, x, i1, RP);
241
242 if (sindex == 8)
243 break;
244 if (sindex != 0)
245 return -1; /* can't make verti. wall here */
246 if (maze[x][i1] != 0)
247 return -1; /* can't make horiz. wall here */
248 length++;
249 }
250
251 return length;
252 }
253
254 return -1;
255}
256
257/* take a layout and make some rooms in it.
258 --works best on onions.*/
259static void
260roomify_layout (char **maze, random_map_params *RP)
261{
262 int tries = RP->Xsize * RP->Ysize / 30;
263
264 for (int ti = 0; ti < tries; ti++)
265 {
266 /* starting location for looking at creating a door */
267 int dx = rmg_rndm (RP->Xsize);
268 int dy = rmg_rndm (RP->Ysize);
269
270 /* results of checking on creating walls. */
271 int cx = can_make_wall (maze, dx, dy, 0, RP); /* horizontal */
272 int cy = can_make_wall (maze, dx, dy, 1, RP); /* vertical */
273
274 if (cx == -1)
275 {
276 if (cy != -1)
277 make_wall (maze, dx, dy, 1);
278
279 continue;
280 }
281
282 if (cy == -1)
283 {
284 make_wall (maze, dx, dy, 0);
285 continue;
286 }
287
288 if (cx < cy)
289 make_wall (maze, dx, dy, 0);
290 else
291 make_wall (maze, dx, dy, 1);
292 }
293}
294
295int
296make_wall (char **maze, int x, int y, int dir)
297{
298 maze[x][y] = 'D'; /* mark a door */
299
300 switch (dir)
301 {
302 case 0: /* horizontal */
303 {
304 for (int i1 = x - 1; maze[i1][y] == 0; --i1) maze[i1][y] = '#';
305 for (int i1 = x + 1; maze[i1][y] == 0; ++i1) maze[i1][y] = '#';
306 break;
307 }
308 case 1: /* vertical */
309 {
310 for (int i1 = y - 1; maze[x][i1] == 0; --i1) maze[x][i1] = '#';
311 for (int i1 = y + 1; maze[x][i1] == 0; ++i1) maze[x][i1] = '#';
312 break;
313 }
314 }
315
316 return 0;
317}
318
319/* puts doors at appropriate locations in a layout. */
320static void
321doorify_layout (char **maze, random_map_params *RP)
322{
323 int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */
324 int doorlocs = 0; /* # of available doorlocations */
325
326 uint16 *doorlist_x = salloc<uint16> (RP->Xsize * RP->Ysize);
327 uint16 *doorlist_y = salloc<uint16> (RP->Xsize * RP->Ysize);
328
329 /* make a list of possible door locations */
330 for (int i = 1; i < RP->Xsize - 1; i++)
331 for (int j = 1; j < RP->Ysize - 1; j++)
332 {
333 int sindex = surround_flag (maze, i, j, RP);
334
335 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
336 {
337 doorlist_x[doorlocs] = i;
338 doorlist_y[doorlocs] = j;
339 doorlocs++;
340 }
433 } 341 }
434 342
435 for(i1=dx+1;i1<RP->Xsize-1;i1++) { 343 while (ndoors > 0 && doorlocs > 0)
436 int sindex=surround_flag2(maze,i1,y,RP);
437 if(sindex == 2) break;
438 if(sindex != 0) return -1; /* can't make horiz. wall here */
439 if(maze[i1][y]!=0) return -1; /* can't make horiz. wall here */
440 length++;
441 }
442 return length;
443 } 344 {
444 else { /* vertical */ 345 int di = rmg_rndm (doorlocs);
445 int x = dx; 346 int i = doorlist_x[di];
446 for(i1=dy-1;i1>0;i1--) { 347 int j = doorlist_y[di];
447 int sindex=surround_flag2(maze,x,i1,RP);
448 if(sindex == 4) break;
449 if(sindex != 0) return -1; /* can't make vert. wall here */
450 if(maze[x][i1]!=0) return -1; /* can't make horiz. wall here */
451 length++;
452 }
453
454 for(i1=dy+1;i1<RP->Ysize-1;i1++) {
455 int sindex=surround_flag2(maze,x,i1,RP);
456 if(sindex == 8) break;
457 if(sindex != 0) return -1; /* can't make verti. wall here */
458 if(maze[x][i1]!=0) return -1; /* can't make horiz. wall here */
459 length++;
460 }
461 return length;
462 }
463 return -1;
464}
465
466
467int make_wall(char **maze,int x, int y, int dir){
468 maze[x][y] = 'D'; /* mark a door */
469 switch(dir) {
470 case 0: /* horizontal */
471 {
472 int i1;
473 for(i1 = x-1;maze[i1][y]==0;i1--)
474 maze[i1][y]='#';
475 for(i1 = x+1;maze[i1][y]==0;i1++)
476 maze[i1][y]='#';
477 break;
478 }
479 case 1: /* vertical */
480 {
481 int i1;
482 for(i1 = y-1;maze[x][i1]==0;i1--)
483 maze[x][i1]='#';
484 for(i1 = y+1;maze[x][i1]==0;i1++)
485 maze[x][i1]='#';
486 break;
487 }
488 }
489
490 return 0;
491}
492
493/* puts doors at appropriate locations in a layout. */
494
495void doorify_layout(char **maze,RMParms *RP) {
496 int ndoors = RP->Xsize*RP->Ysize/60; /* reasonable number of doors. */
497 char *doorlist_x;
498 char *doorlist_y;
499 int doorlocs = 0; /* # of available doorlocations */
500 int i,j;
501
502 doorlist_x = (char *) malloc(sizeof(int) * RP->Xsize*RP->Ysize);
503 doorlist_y = (char *) malloc(sizeof(int) * RP->Xsize*RP->Ysize);
504
505
506 /* make a list of possible door locations */
507 for(i=1;i<RP->Xsize-1;i++)
508 for(j=1;j<RP->Ysize-1;j++) {
509 int sindex = surround_flag(maze,i,j,RP); 348 int sindex = surround_flag (maze, i, j, RP);
349
510 if(sindex == 3 || sindex == 12) /* these are possible door sindex*/ 350 if (sindex == 3 || sindex == 12) /* these are possible door sindex */
511 {
512 doorlist_x[doorlocs]=i;
513 doorlist_y[doorlocs]=j;
514 doorlocs++;
515 } 351 {
516 }
517 while(ndoors > 0 && doorlocs > 0) {
518 int di;
519 int sindex;
520 di = RANDOM() % doorlocs;
521 i=doorlist_x[di];
522 j=doorlist_y[di];
523 sindex= surround_flag(maze,i,j,RP);
524 if(sindex == 3 || sindex == 12) /* these are possible door sindex*/
525 {
526 maze[i][j] = 'D'; 352 maze[i][j] = 'D';
527 ndoors--; 353 ndoors--;
528 } 354 }
355
529 /* reduce the size of the list */ 356 /* reduce the size of the list */
530 doorlocs--; 357 doorlocs--;
531 doorlist_x[di]=doorlist_x[doorlocs]; 358 doorlist_x[di] = doorlist_x[doorlocs];
532 doorlist_y[di]=doorlist_y[doorlocs]; 359 doorlist_y[di] = doorlist_y[doorlocs];
533 } 360 }
534 free(doorlist_x);
535 free(doorlist_y);
536}
537 361
362 sfree (doorlist_x, RP->Xsize * RP->Ysize);
363 sfree (doorlist_y, RP->Xsize * RP->Ysize);
364}
538 365
539void write_map_parameters_to_string(char *buf,RMParms *RP) { 366void
367write_map_parameters_to_string (dynbuf_text &buf, random_map_params *RP)
368{
369 hv_iterinit (RP->hv);
540 370
541 char small_buf[256]; 371 while (HE *he = hv_iternext (RP->hv))
372 buf << HePV (he, PL_na) << ' ' << cfSvPVutf8_nolen (HeVAL (he)) << '\n';
373
542 sprintf(buf,"xsize %d\nysize %d\n",RP->Xsize,RP->Ysize); 374 buf.printf ("xsize %d\nysize %d\n", RP->xsize, RP->ysize);
543 375
544 if(RP->wallstyle[0]) { 376 if (RP->monsterstyle[0] ) buf.printf ("monsterstyle %s\n", RP->monsterstyle);
545 sprintf(small_buf,"wallstyle %s\n",RP->wallstyle); 377 if (RP->treasurestyle[0] ) buf.printf ("treasurestyle %s\n", RP->treasurestyle);
546 strcat(buf,small_buf); 378 if (RP->layoutstyle[0] ) buf.printf ("layoutstyle %s\n", RP->layoutstyle);
547 } 379 if (RP->decorstyle[0] ) buf.printf ("decorstyle %s\n", RP->decorstyle);
380 if (RP->doorstyle[0] ) buf.printf ("doorstyle %s\n", RP->doorstyle);
381 if (RP->final_map.length () ) buf.printf ("final_map %s\n", &RP->final_map);
382 if (RP->exit_on_final_map[0]) buf.printf ("exit_on_final_map %s\n", RP->exit_on_final_map);
383 if (RP->this_map.length () ) buf.printf ("origin_map %s\n", &RP->this_map);
384 if (RP->expand2x ) buf.printf ("expand2x %d\n", RP->expand2x);
385 if (RP->layoutoptions1 ) buf.printf ("layoutoptions1 %d\n", RP->layoutoptions1);
386 if (RP->layoutoptions2 ) buf.printf ("layoutoptions2 %d\n", RP->layoutoptions2);
387 if (RP->layoutoptions3 ) buf.printf ("layoutoptions3 %d\n", RP->layoutoptions3);
388 if (RP->symmetry ) buf.printf ("symmetry %d\n", RP->symmetry);
548 389
549 if(RP->floorstyle[0]) {
550 sprintf(small_buf,"floorstyle %s\n",RP->floorstyle);
551 strcat(buf,small_buf);
552 }
553
554 if(RP->monsterstyle[0]) {
555 sprintf(small_buf,"monsterstyle %s\n",RP->monsterstyle);
556 strcat(buf,small_buf);
557 }
558
559 if(RP->treasurestyle[0]) {
560 sprintf(small_buf,"treasurestyle %s\n",RP->treasurestyle);
561 strcat(buf,small_buf);
562 }
563
564 if(RP->layoutstyle[0]) {
565 sprintf(small_buf,"layoutstyle %s\n",RP->layoutstyle);
566 strcat(buf,small_buf);
567 }
568
569 if(RP->decorstyle[0]) {
570 sprintf(small_buf,"decorstyle %s\n",RP->decorstyle);
571 strcat(buf,small_buf);
572 }
573
574 if(RP->doorstyle[0]) {
575 sprintf(small_buf,"doorstyle %s\n",RP->doorstyle);
576 strcat(buf,small_buf);
577 }
578
579 if(RP->exitstyle[0]) {
580 sprintf(small_buf,"exitstyle %s\n",RP->exitstyle);
581 strcat(buf,small_buf);
582 }
583
584 if(RP->final_map[0]) {
585 sprintf(small_buf,"final_map %s\n",RP->final_map);
586 strcat(buf,small_buf);
587 }
588
589 if(RP->exit_on_final_map[0]) {
590 sprintf(small_buf,"exit_on_final_map %s\n",RP->exit_on_final_map);
591 strcat(buf,small_buf);
592 }
593
594 if(RP->this_map[0]) {
595 sprintf(small_buf,"origin_map %s\n",RP->this_map);
596 strcat(buf,small_buf);
597 }
598
599 if(RP->expand2x) {
600 sprintf(small_buf,"expand2x %d\n",RP->expand2x);
601 strcat(buf,small_buf);
602 }
603
604 if(RP->layoutoptions1) {
605 sprintf(small_buf,"layoutoptions1 %d\n",RP->layoutoptions1);
606 strcat(buf,small_buf);
607 }
608
609
610 if(RP->layoutoptions2) {
611 sprintf(small_buf,"layoutoptions2 %d\n",RP->layoutoptions2);
612 strcat(buf,small_buf);
613 }
614
615
616 if(RP->layoutoptions3) {
617 sprintf(small_buf,"layoutoptions3 %d\n",RP->layoutoptions3);
618 strcat(buf,small_buf);
619 }
620
621 if(RP->symmetry) {
622 sprintf(small_buf,"symmetry %d\n",RP->symmetry);
623 strcat(buf,small_buf);
624 }
625
626
627 if(RP->difficulty && RP->difficulty_given ) { 390 if (RP->difficulty && RP->difficulty_given)
628 sprintf(small_buf,"difficulty %d\n",RP->difficulty); 391 buf.printf ("difficulty %d\n", RP->difficulty);
629 strcat(buf,small_buf);
630 }
631 392
632 if(RP->difficulty_increase != 1.0 ) { 393 if (fabs (RP->difficulty_increase - 1.f) >= (1.f / 1024.f))
633 sprintf(small_buf,"difficulty_increase %f\n",RP->difficulty_increase); 394 buf.printf ("difficulty_increase %f\n", RP->difficulty_increase);
634 strcat(buf,small_buf);
635 }
636 395
637 sprintf(small_buf,"dungeon_level %d\n",RP->dungeon_level); 396 buf.printf ("dungeon_level %d\n", RP->dungeon_level);
638 strcat(buf,small_buf);
639 397
640 if(RP->dungeon_depth) { 398 if (RP->dungeon_depth ) buf.printf ("dungeon_depth %d\n", RP->dungeon_depth);
641 sprintf(small_buf,"dungeon_depth %d\n",RP->dungeon_depth); 399 if (RP->decoroptions ) buf.printf ("decoroptions %d\n", RP->decoroptions);
642 strcat(buf,small_buf); 400 if (RP->orientation ) buf.printf ("orientation %d\n", RP->orientation);
401 if (RP->origin_x ) buf.printf ("origin_x %d\n", RP->origin_x);
402 if (RP->origin_y ) buf.printf ("origin_y %d\n", RP->origin_y);
403 if (RP->treasureoptions ) buf.printf ("treasureoptions %d\n", RP->treasureoptions);
404 if (RP->random_seed ) buf.printf ("random_seed %u\n", RP->random_seed);
405}
406
407/////////////////////////////////////////////////////////////////////////////
408
409LayoutData::LayoutData (int w, int h)
410: w(w), h(h)
411{
412 int size = (sizeof (char *) + sizeof (char) * h) * w;
413
414 col = (char **)salloc<char> (size);
415
416 char *data = (char *)(col + w);
417
418 for (int x = w; x--; )
419 col [x] = data + x * h;
420}
421
422LayoutData::~LayoutData ()
423{
424 int size = (sizeof (char *) + sizeof (char) * h) * w;
425
426 sfree ((char *)col, size);
427}
428
429void LayoutData::clear (char fill)
430{
431 memset (col [0], fill, w * h);
432}
433
434void LayoutData::border (char fill)
435{
436 for (int i = 0; i < w; i++) col [i][0] = col [i][h - 1] = fill;
437 for (int j = 0; j < h; j++) col [0][j] = col [w - 1][j] = fill;
438}
439
440/* function selects the layout function and gives it whatever
441 arguments it needs. */
442static Layout
443layoutgen (random_map_params *RP)
444{
445 Layout layout (RP);
446
447 switch (RP->map_layout_style)
448 {
449 case LAYOUT_ONION:
450 map_gen_onion (layout, RP->layoutoptions1, RP->layoutoptions2);
451
452 if (!(rmg_rndm (3)) && !(RP->layoutoptions1 & (RMOPT_WALLS_ONLY | RMOPT_WALL_OFF)))
453 roomify_layout (layout, RP);
454
455 break;
456
457 case LAYOUT_MAZE:
458 maze_gen (layout, rmg_rndm (2));
459
460 if (!(rmg_rndm (2)))
461 doorify_layout (layout, RP);
462
463 break;
464
465 case LAYOUT_SPIRAL:
466 map_gen_spiral (layout, RP->layoutoptions1);
467
468 if (!(rmg_rndm (2)))
469 doorify_layout (layout, RP);
470
471 break;
472
473 case LAYOUT_ROGUELIKE:
474 /* Don't put symmetry in rogue maps. There isn't much reason to
475 * do so in the first place (doesn't make it any more interesting),
476 * but more importantly, the symmetry code presumes we are symmetrizing
477 * spirals, or maps with lots of passages - making a symmetric rogue
478 * map fails because its likely that the passages the symmetry process
479 * creates may not connect the rooms.
480 */
481 RP->symmetry_used = SYMMETRY_NONE;
482 roguelike_layout_gen (layout, RP->layoutoptions1);
483 /* no doorifying... done already */
484 break;
485
486 case LAYOUT_SNAKE:
487 make_snake_layout (layout, RP->layoutoptions1);
488
489 if (rmg_rndm (2))
490 roomify_layout (layout, RP);
491
492 break;
493
494 case LAYOUT_SQUARE_SPIRAL:
495 make_square_spiral_layout (layout, RP->layoutoptions1);
496
497 if (rmg_rndm (2))
498 roomify_layout (layout, RP);
499
500 break;
501
502 default:
503 abort ();
643 } 504 }
644 505
645 if(RP->decoroptions) { 506 /* rotate the layout randomly */
646 sprintf(small_buf,"decoroptions %d\n",RP->decoroptions); 507 rotate_layout (layout, rmg_rndm (4));
647 strcat(buf,small_buf);
648 }
649 508
650 if(RP->orientation) { 509 symmetrize_layout (layout, RP);
651 sprintf(small_buf,"orientation %d\n",RP->orientation);
652 strcat(buf,small_buf);
653 }
654 510
655 if(RP->origin_x) { 511#ifdef RMAP_DEBUG
656 sprintf(small_buf,"origin_x %d\n",RP->origin_x); 512 dump_layout (layout);
657 strcat(buf,small_buf); 513#endif
658 }
659 514
660 if(RP->origin_y) { 515 if (RP->expand2x)
661 sprintf(small_buf,"origin_y %d\n",RP->origin_y); 516 expand2x (layout);
662 strcat(buf,small_buf);
663 }
664 if(RP->random_seed) {
665 /* Add one so that the next map is a bit different */
666 sprintf(small_buf,"random_seed %d\n",RP->random_seed + 1);
667 strcat(buf,small_buf);
668 }
669 517
670 if(RP->treasureoptions) { 518 return layout;
671 sprintf(small_buf,"treasureoptions %d\n",RP->treasureoptions);
672 strcat(buf,small_buf);
673 }
674
675
676} 519}
677 520
521bool
522maptile::generate_random_map (random_map_params *RP)
523{
524 int i;
525
526 RP->Xsize = RP->xsize;
527 RP->Ysize = RP->ysize;
528
529 /* pick a random seed, or use the one from the input file */
530 RP->random_seed = RP->random_seed
531 ? RP->random_seed + RP->dungeon_level
532 : time (0);
533
534 // we run "single-threaded"
535 rmg_rndm.seed (RP->random_seed);
536
537 dynbuf_text buf;
678void write_parameters_to_string(char *buf, 538 write_map_parameters_to_string (buf, RP);
679 int xsize_n,
680 int ysize_n,
681 char *wallstyle_n,
682 char *floorstyle_n,
683 char *monsterstyle_n,
684 char *treasurestyle_n,
685 char *layoutstyle_n,
686 char *decorstyle_n,
687 char *doorstyle_n,
688 char *exitstyle_n,
689 char *final_map_n,
690 char *exit_on_final_map_n,
691 char *this_map_n,
692 int layoutoptions1_n,
693 int layoutoptions2_n,
694 int layoutoptions3_n,
695 int symmetry_n,
696 int dungeon_depth_n,
697 int dungeon_level_n,
698 int difficulty_n,
699 int difficulty_given_n,
700 int decoroptions_n,
701 int orientation_n,
702 int origin_x_n,
703 int origin_y_n,
704 int random_seed_n,
705 int treasureoptions_n,
706 float difficulty_increase)
707{
708 539
709 char small_buf[256]; 540 if (RP->difficulty == 0)
710 sprintf(buf,"xsize %d\nysize %d\n",xsize_n,ysize_n); 541 {
542 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
711 543
712 if(wallstyle_n && wallstyle_n[0]) {
713 sprintf(small_buf,"wallstyle %s\n",wallstyle_n);
714 strcat(buf,small_buf);
715 }
716
717 if(floorstyle_n && floorstyle_n[0]) {
718 sprintf(small_buf,"floorstyle %s\n",floorstyle_n);
719 strcat(buf,small_buf);
720 }
721
722 if(monsterstyle_n && monsterstyle_n[0]) {
723 sprintf(small_buf,"monsterstyle %s\n",monsterstyle_n);
724 strcat(buf,small_buf);
725 }
726
727 if(treasurestyle_n && treasurestyle_n[0]) {
728 sprintf(small_buf,"treasurestyle %s\n",treasurestyle_n);
729 strcat(buf,small_buf);
730 }
731
732 if(layoutstyle_n &&layoutstyle_n[0]) {
733 sprintf(small_buf,"layoutstyle %s\n",layoutstyle_n);
734 strcat(buf,small_buf);
735 }
736
737 if(decorstyle_n && decorstyle_n[0]) {
738 sprintf(small_buf,"decorstyle %s\n",decorstyle_n);
739 strcat(buf,small_buf);
740 }
741
742 if(doorstyle_n && doorstyle_n[0]) {
743 sprintf(small_buf,"doorstyle %s\n",doorstyle_n);
744 strcat(buf,small_buf);
745 }
746
747 if(exitstyle_n && exitstyle_n[0]) {
748 sprintf(small_buf,"exitstyle %s\n",exitstyle_n);
749 strcat(buf,small_buf);
750 }
751
752 if(final_map_n && final_map_n[0]) {
753 sprintf(small_buf,"final_map %s\n",final_map_n);
754 strcat(buf,small_buf);
755 }
756
757 if(exit_on_final_map_n && exit_on_final_map_n[0]) {
758 sprintf(small_buf,"exit_on_final_map %s\n",exit_on_final_map_n);
759 strcat(buf,small_buf);
760 }
761
762 if(this_map_n && this_map_n[0]) {
763 sprintf(small_buf,"origin_map %s\n",this_map_n);
764 strcat(buf,small_buf);
765 }
766
767 if(layoutoptions1_n) {
768 sprintf(small_buf,"layoutoptions1 %d\n",layoutoptions1_n);
769 strcat(buf,small_buf);
770 }
771
772
773 if(layoutoptions2_n) {
774 sprintf(small_buf,"layoutoptions2 %d\n",layoutoptions2_n);
775 strcat(buf,small_buf);
776 }
777
778
779 if(layoutoptions3_n) {
780 sprintf(small_buf,"layoutoptions3 %d\n",layoutoptions3_n);
781 strcat(buf,small_buf);
782 }
783
784 if(symmetry_n) {
785 sprintf(small_buf,"symmetry %d\n",symmetry_n);
786 strcat(buf,small_buf);
787 }
788
789
790 if(difficulty_n && difficulty_given_n ) {
791 sprintf(small_buf,"difficulty %d\n",difficulty_n);
792 strcat(buf,small_buf);
793 }
794
795 if(difficulty_increase > 0.001 ) { 544 if (RP->difficulty_increase > 0.001)
796 sprintf(small_buf,"difficulty_increase %f\n",difficulty_increase); 545 RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
797 strcat(buf,small_buf); 546
547 if (RP->difficulty < 1)
548 RP->difficulty = 1;
798 } 549 }
550 else
551 RP->difficulty_given = 1;
799 552
800 sprintf(small_buf,"dungeon_level %d\n",dungeon_level_n); 553 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
801 strcat(buf,small_buf); 554 RP->Xsize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
802 555
803 if(dungeon_depth_n) { 556 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
804 sprintf(small_buf,"dungeon_depth %d\n",dungeon_depth_n); 557 RP->Ysize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
805 strcat(buf,small_buf); 558
559 if (RP->symmetry == SYMMETRY_RANDOM)
560 RP->symmetry_used = rmg_rndm (SYMMETRY_XY) + 1;
561 else
562 RP->symmetry_used = RP->symmetry;
563
564 if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
565 RP->Ysize = RP->Ysize / 2 + 1;
566
567 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
568 RP->Xsize = RP->Xsize / 2 + 1;
569
570 if (RP->expand2x > 0)
571 {
572 RP->Xsize /= 2;
573 RP->Ysize /= 2;
806 } 574 }
807 575
808 if(decoroptions_n) { 576 RP->map_layout_style = LAYOUT_NONE;
809 sprintf(small_buf,"decoroptions %d\n",decoroptions_n); 577
810 strcat(buf,small_buf); 578 /* Redo this - there was a lot of redundant code of checking for preset
579 * layout style and then random layout style. Instead, figure out
580 * the numeric layoutstyle, so there is only one area that actually
581 * calls the code to make the maps.
582 */
583 if (strstr (RP->layoutstyle, "onion"))
584 RP->map_layout_style = LAYOUT_ONION;
585 else if (strstr (RP->layoutstyle, "maze"))
586 RP->map_layout_style = LAYOUT_MAZE;
587 else if (strstr (RP->layoutstyle, "spiral"))
588 RP->map_layout_style = LAYOUT_SPIRAL;
589 else if (strstr (RP->layoutstyle, "rogue"))
590 RP->map_layout_style = LAYOUT_ROGUELIKE;
591 else if (strstr (RP->layoutstyle, "snake"))
592 RP->map_layout_style = LAYOUT_SNAKE;
593 else if (strstr (RP->layoutstyle, "squarespiral"))
594 RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
595 else if (RP->map_layout_style == LAYOUT_NONE)
596 RP->map_layout_style = rmg_rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */
597 else
598 abort ();
599
600 Layout layout = layoutgen (RP);
601
602#ifdef RMAP_DEBUG
603 dump_layout (layout);
604#endif
605
606 /* increment these for the current map */
607 ++RP->dungeon_level;
608
609 // need to patch RP becasue following code doesn't use the Layout object
610 RP->Xsize = layout->w;
611 RP->Ysize = layout->h;
612
613 /* allocate the map and set the floor */
614 make_map_floor (layout, RP->get_str ("floorstyle", ""), RP);
615
616 /* set region */
617 default_region = RP->region;
618
619 CEDE;
620
621 place_specials_in_map (this, layout, RP);
622
623 CEDE;
624
625 const char *wallstyle = RP->get_str ("wallstyle", 0);
626
627 /* create walls unless the wallstyle is "none" */
628 if (strcmp (wallstyle, "none"))
629 {
630 make_map_walls (this, layout, wallstyle, RP->get_str ("miningstyle", ""), RP);
631
632 /* place doors unless doorstyle or wallstyle is "none" */
633 if (strcmp (RP->doorstyle, "none"))
634 put_doors (this, layout, RP->doorstyle, RP);
811 } 635 }
812 636
813 if(orientation_n) { 637 CEDE;
814 sprintf(small_buf,"orientation %d\n",orientation_n);
815 strcat(buf,small_buf);
816 }
817 638
818 if(origin_x_n) { 639 const char *exitstyle = RP->get_str ("exitstyle", "");
819 sprintf(small_buf,"origin_x %d\n",origin_x_n);
820 strcat(buf,small_buf);
821 }
822 640
823 if(origin_y_n) { 641 /* create exits unless the exitstyle is "none" */
824 sprintf(small_buf,"origin_y %d\n",origin_y_n); 642 if (strcmp (exitstyle, "none"))
825 strcat(buf,small_buf); 643 place_exits (this, layout, exitstyle, RP->orientation, RP);
826 }
827 if(random_seed_n) {
828 /* Add one so that the next map is a bit different */
829 sprintf(small_buf,"random_seed %d\n",random_seed_n + 1);
830 strcat(buf,small_buf);
831 }
832 644
833 if(treasureoptions_n) { 645 CEDE;
834 sprintf(small_buf,"treasureoptions %d\n",treasureoptions_n);
835 strcat(buf,small_buf);
836 }
837 646
647 /* create monsters unless the monsterstyle is "none" */
648 if (strcmp (RP->monsterstyle, "none"))
649 place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
838 650
839} 651 CEDE;
840 652
841/* copy an object with an inventory... i.e., duplicate the inv too. */ 653 /* treasures needs to have a proper difficulty set for the map. */
842void copy_object_with_inv(object *src_ob, object *dest_ob) { 654 difficulty = estimate_difficulty ();
843 object *walk,*tmp;
844 655
845 copy_object(src_ob,dest_ob); 656 CEDE;
846 657
847 for(walk=src_ob->inv;walk!=NULL;walk=walk->below) { 658 /* create treasure unless the treasurestyle is "none" */
848 tmp=get_object(); 659 place_treasure (this, layout, RP->treasurestyle, RP->treasureoptions, RP);
849 copy_object(walk,tmp); 660
850 insert_ob_in_ob(tmp,dest_ob); 661 CEDE;
851 } 662
663 /* create decor unless the decorstyle is "none" */
664 if (strcmp (RP->decorstyle, "none"))
665 put_decor (this, layout, RP->decorstyle, RP->decoroptions, RP);
666
667 CEDE;
668
669 /* generate treasures, etc. */
670 fix_auto_apply ();
671
672 CEDE;
673
674 unblock_exits (this, layout, RP);
675
676 msg = buf;
677 in_memory = MAP_ACTIVE;
678
679 CEDE;
680
681 return 1;
852} 682}
683

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines