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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines