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.60 by root, Fri Jul 2 03:40:14 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; 33
40 for(i=0;i<RP->Xsize;i++) { 34noinline SV *
41 for(j=0;j<RP->Ysize;j++) { 35random_map_params::get_sv (const char *option) const
42 if(layout[i][j]==0) layout[i][j]=' '; 36{
43 printf("%c",layout[i][j]); 37 SV **he = hv_fetch (hv, option, strlen (option), 0);
44 if(layout[i][j]==' ') layout[i][j]=0; 38
39 return he ? *he : 0;
40}
41
42noinline const_utf8_string
43random_map_params::get_str (const char *option, const_utf8_string fallback) const
44{
45 SV *sv = get_sv (option);
46 return sv ? cfSvPVutf8_nolen (sv) : fallback;
47}
48
49noinline IV
50random_map_params::get_iv (const char *option, IV fallback) const
51{
52 SV *sv = get_sv (option);
53 return sv ? SvIV (sv) : fallback;
54}
55
56noinline UV
57random_map_params::get_uv (const char *option, UV fallback) const
58{
59 SV *sv = get_sv (option);
60 return sv ? SvUV (sv) : fallback;
61}
62
63noinline NV
64random_map_params::get_nv (const char *option, NV fallback) const
65{
66 SV *sv = get_sv (option);
67 return sv ? SvNV (sv) : fallback;
68}
69
70noinline void
71random_map_params::set (const char *option, SV *value) const
72{
73 int len = strlen (option);
74
75 if (value)
76 hv_store (hv, option, len, value, 0);
77 else
78 hv_delete (hv, option, len, G_DISCARD);
79}
80
81noinline void
82random_map_params::set (const char *option, const_utf8_string value) const
83{
84 set (option, value && *value ? newSVpvn_utf8 (value, strlen (value), 1) : 0);
85}
86
87void
88random_map_params::set (const char *option, IV value) const
89{
90 set (option, newSViv (value));
91}
92
93void
94random_map_params::set (const char *option, UV value) const
95{
96 set (option, newSVuv (value));
97}
98
99void
100random_map_params::set (const char *option, NV value) const
101{
102 set (option, newSVnv (value));
103}
104
105void
106random_map_params::hv_clone ()
107{
108 HV *copy = newHV ();
109
110 hv_iterinit (hv);
111
112 // does not work for utf-8 keys
113 while (HE *he = hv_iternext (hv))
45 } 114 {
46 printf("\n"); 115 STRLEN klen; const char *key = HePV (he, klen);
116 hv_store (copy, key, klen, newSVsv (HeVAL (he)), HeHASH (he));
47 }} 117 }
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 118
119 SvREFCNT_dec (hv);
120 hv = copy;
121}
122
123shstr_tmp
124random_map_params::as_shstr () const
125{
126 set ("xsize" , xsize);
127 set ("ysize" , ysize);
128 set ("monsterstyle" , monsterstyle);
129 set ("exit_on_final_map" , exit_on_final_map);
130 set ("layoutstyle" , layoutstyle);
131 set ("doorstyle" , doorstyle);
132 set ("final_map" , final_map);
133 set ("this_map" , this_map);
134 set ("expand2x" , expand2x);
135 set ("layoutoptions1" , layoutoptions1);
136 set ("layoutoptions2" , layoutoptions2);
137 set ("layoutoptions3" , layoutoptions3);
138 set ("symmetry" , symmetry);
139 set ("dungeon_depth" , dungeon_depth);
140 set ("orientation" , orientation);
141 set ("origin_x" , origin_x);
142 set ("origin_y" , origin_y);
143 set ("random_seed" , (UV)random_seed);
144 set ("difficulty" , difficulty && difficulty_given ? difficulty : 0);
145 set ("difficulty_increase", difficulty_increase);
146 set ("dungeon_level" , dungeon_level);
147
148 dynbuf_text buf;
149 hv_iterinit (hv);
150
151 // does not work for utf-8 keys
152 while (HE *he = hv_iternext (hv))
153 {
154 STRLEN klen; const char *key = HePV (he, klen);
155 STRLEN vlen; const char *value = SvPVutf8 (HeVAL (he), vlen);
156
157 buf.fadd (key, klen);
158 buf << ' ';
159 buf.fadd (value, vlen);
160 buf << '\n';
161 }
162
163 return shstr (buf);
164}
165
166random_map_params::~random_map_params ()
167{
168 SvREFCNT_dec (hv);
169}
170
171bool
172maptile::generate_random_map (random_map_params *RP)
173{
174 RP->Xsize = RP->xsize;
175 RP->Ysize = RP->ysize;
176
56 /* pick a random seed, or use the one from the input file */ 177 /* pick a random seed, or use the one from the input file */
57 if(RP->random_seed == 0) 178 RP->random_seed = RP->random_seed
58 RP->random_seed=time(0); 179 ? RP->random_seed + RP->dungeon_level
180 : time (0);
59 181
60 SRANDOM(RP->random_seed); 182 // we run "single-threaded"
183 rmg_rndm.seed (RP->random_seed);
61 184
62 write_map_parameters_to_string(buf, RP); 185 shstr buf = RP->as_shstr ();
63 186
64 if(RP->difficulty==0) { 187 if (RP->difficulty == 0)
188 {
65 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */ 189 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
190
66 if (RP->difficulty_increase > 0.001) { 191 if (RP->difficulty_increase > 0.001)
67 RP->difficulty = (int)((float)RP->dungeon_level * RP->difficulty_increase); 192 RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
68 if (RP->difficulty < 1) RP->difficulty=1; 193
69 } 194 if (RP->difficulty < 1)
195 RP->difficulty = 1;
70 } 196 }
71 else 197 else
72 RP->difficulty_given=1; 198 RP->difficulty_given = 1;
73 199
74 if(RP->Xsize<MIN_RANDOM_MAP_SIZE) RP->Xsize = MIN_RANDOM_MAP_SIZE + RANDOM()%25 + 5; 200 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
75 if(RP->Ysize<MIN_RANDOM_MAP_SIZE) RP->Ysize = MIN_RANDOM_MAP_SIZE + RANDOM()%25 + 5; 201 RP->Xsize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
76 202
203 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
204 RP->Ysize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
205
206 min_it (RP->Xsize, MAX_RANDOM_MAP_SIZE);
207 min_it (RP->Ysize, MAX_RANDOM_MAP_SIZE);
208
209 if (RP->symmetry == SYMMETRY_RANDOM)
210 RP->symmetry_used = rmg_rndm (SYMMETRY_XY) + 1;
211 else
212 RP->symmetry_used = RP->symmetry;
213
214 if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
215 RP->Ysize = RP->Ysize / 2 + 1;
216
217 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
218 RP->Xsize = RP->Xsize / 2 + 1;
219
77 if(RP->expand2x > 0) { 220 if (RP->expand2x > 0)
221 {
78 RP->Xsize /=2; 222 RP->Xsize /= 2;
79 RP->Ysize /=2; 223 RP->Ysize /= 2;
80 } 224 }
81 225
82 layout = layoutgen(RP); 226 if (strstr (RP->layoutstyle, "onion"))
227 RP->map_layout_style = LAYOUT_ONION;
228 else if (strstr (RP->layoutstyle, "maze"))
229 RP->map_layout_style = LAYOUT_MAZE;
230 else if (strstr (RP->layoutstyle, "spiral"))
231 RP->map_layout_style = LAYOUT_SPIRAL;
232 else if (strstr (RP->layoutstyle, "rogue"))
233 RP->map_layout_style = LAYOUT_ROGUELIKE;
234 else if (strstr (RP->layoutstyle, "snake"))
235 RP->map_layout_style = LAYOUT_SNAKE;
236 else if (strstr (RP->layoutstyle, "squarespiral"))
237 RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
238 else if (strstr (RP->layoutstyle, "cave"))
239 RP->map_layout_style = LAYOUT_CAVE;
240 else
241 RP->map_layout_style = rmg_rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */
83 242
84#ifdef RMAP_DEBUG 243 Layout layout (RP->Xsize, RP->Ysize);
85 dump_layout(layout,RP); 244 layout.generate (RP);
86#endif
87 245
88 /* increment these for the current map */ 246 /* increment these for the current map */
89 RP->dungeon_level+=1; 247 ++RP->dungeon_level;
90 /* allow constant-difficulty maps. */
91 /* difficulty+=1; */
92 248
93 /* rotate the layout randomly */ 249 // need to patch RP becasue following code doesn't use the Layout object
94 layout=rotate_layout(layout,RANDOM()%4,RP); 250 RP->Xsize = layout.w;
95#ifdef RMAP_DEBUG 251 RP->Ysize = layout.h;
96 dump_layout(layout,RP);
97#endif
98 252
99 /* allocate the map and set the floor */ 253 /* allocate the map and set the floor */
100 theMap = make_map_floor(layout,RP->floorstyle,RP); 254 make_map_floor (layout, RP->get_str ("floorstyle", ""), RP);
101 255
102 /* set the name of the map. */
103 strcpy(theMap->path,OutFileName);
104
105 /* set region */ 256 /* set region */
106 theMap->region=RP->region; 257 default_region = RP->region;
107 258
259 CEDE;
260
261 place_specials_in_map (this, layout, RP);
262
263 CEDE;
264
265 const char *wallstyle = RP->get_str ("wallstyle", 0);
266
108 /* create walls unless the wallstyle is "none" */ 267 /* create walls unless the wallstyle is "none" */
109 if (strcmp (RP->wallstyle, "none")) { 268 if (strcmp (wallstyle, "none"))
110 make_map_walls(theMap,layout,RP->wallstyle,RP); 269 {
111 270 make_map_walls (this, layout, wallstyle, RP->get_str ("miningstyle", ""), RP);
271
112 /* place doors unless doorstyle or wallstyle is "none"*/ 272 /* place doors unless doorstyle or wallstyle is "none" */
113 if (strcmp (RP->doorstyle, "none")) 273 if (strcmp (RP->doorstyle, "none"))
114 put_doors(theMap,layout,RP->doorstyle,RP); 274 put_doors (this, layout, RP->doorstyle, RP);
115
116 } 275 }
117 276
277 CEDE;
278
279 const char *exitstyle = RP->get_str ("exitstyle", "");
280
118 /* create exits unless the exitstyle is "none" */ 281 /* create exits unless the exitstyle is "none" */
119 if (strcmp (RP->exitstyle, "none")) 282 if (strcmp (exitstyle, "none"))
120 place_exits(theMap,layout,RP->exitstyle,RP->orientation,RP); 283 place_exits (this, layout, exitstyle, RP->orientation, RP);
121 284
122 place_specials_in_map(theMap,layout,RP); 285 CEDE;
123 286
124 /* create monsters unless the monsterstyle is "none" */ 287 /* create monsters unless the monsterstyle is "none" */
125 if (strcmp (RP->monsterstyle, "none")) 288 if (strcmp (RP->monsterstyle, "none"))
126 place_monsters(theMap,RP->monsterstyle,RP->difficulty,RP); 289 place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
127 290
291 CEDE;
292
128 /* treasures needs to have a proper difficulty set for the map. */ 293 /* treasures needs to have a proper difficulty set for the map. */
129 theMap->difficulty=calculate_difficulty(theMap); 294 difficulty = estimate_difficulty ();
130 295
296 CEDE;
297
298 const char *treasurestyle = RP->get_str ("treasurestyle", "");
299
131 /* create treasure unless the treasurestyle is "none" */ 300 /* create treasure unless the treasurestyle is "none" */
132 if (strcmp (RP->treasurestyle, "none"))
133 place_treasure(theMap,layout,RP->treasurestyle,RP->treasureoptions,RP); 301 place_treasure (this, layout, treasurestyle, RP->get_iv ("treasureoptions"), RP);
134 302
303 CEDE;
304
305 const char *decorstyle = RP->get_str ("treasurestyle", "");
306
135 /* create decor unless the decorstyle is "none" */ 307 /* create decor unless the decorstyle is "none" */
136 if (strcmp (RP->decorstyle, "none")) 308 if (strcmp (decorstyle, "none"))
137 put_decor(theMap,layout,RP->decorstyle,RP->decoroptions,RP); 309 put_decor (this, layout, decorstyle, RP->get_iv ("decoroptions"), RP);
138 310
311 CEDE;
312
139 /* generate treasures, etc. */ 313 /* generate treasures, etc. */
140 fix_auto_apply(theMap); 314 fix_auto_apply ();
141 315
316 CEDE;
317
142 unblock_exits(theMap,layout,RP); 318 unblock_exits (this, layout, RP);
143 319
144 /* free the layout */ 320 msg = buf;
145 for(i=0;i<RP->Xsize;i++) 321 in_memory = MAP_ACTIVE;
146 free(layout[i]);
147 free(layout);
148 322
149 theMap->msg = strdup_local(buf); 323 CEDE;
150
151 return theMap;
152}
153 324
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
262Ysize to produce a symmetric map. */
263
264char **symmetrize_layout(char **maze, int sym,RMParms *RP) {
265 int i,j;
266 char **sym_maze;
267 int Xsize_orig,Ysize_orig;
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;
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
280 sym_maze = (char **)calloc(sizeof(char*),RP->Xsize);
281 for(i=0;i<RP->Xsize;i++)
282 sym_maze[i] = (char *)calloc(sizeof(char),RP->Ysize);
283
284 if(sym==X_SYM)
285 for(i=0;i<RP->Xsize/2+1;i++)
286 for(j=0;j<RP->Ysize;j++) {
287 sym_maze[i][j] = maze[i][j];
288 sym_maze[RP->Xsize - i-1][j] = maze[i][j];
289 };
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 }
296 if(sym==XY_SYM)
297 for(i=0;i<RP->Xsize/2+1;i++)
298 for(j=0;j<RP->Ysize/2+1;j++) {
299 sym_maze[i][j] = maze[i][j];
300 sym_maze[i][RP->Ysize-j-1] = maze[i][j];
301 sym_maze[RP->Xsize - i-1][j] = maze[i][j];
302 sym_maze[RP->Xsize - i-1][RP->Ysize-j-1] = maze[i][j];
303 }
304 /* delete the old maze */
305 for(i=0;i<Xsize_orig;i++)
306 free(maze[i]);
307 free(maze);
308 /* 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
312 spirals will do the trick?*/
313 if(RP->map_layout_style==ROGUELIKE_LAYOUT)
314 connect_spirals(RP->Xsize,RP->Ysize,sym,sym_maze);
315
316 return sym_maze;
317}
318
319
320/* takes a map and rotates it. This completes the
321 onion layouts, making them possibly centered on any wall.
322 It'll modify Xsize and Ysize if they're swapped.
323*/
324
325char ** rotate_layout(char **maze,int rotation,RMParms *RP) {
326 char **new_maze;
327 int i,j;
328
329 switch(rotation) {
330 case 0:
331 return maze;
332 break;
333 case 2: /* a reflection */
334 {
335 char *newmaze= (char *) malloc(sizeof(char) * RP->Xsize*RP->Ysize);
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 }
340 }
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;
349 }
350 case 1:
351 case 3:
352 { int swap;
353 new_maze = (char **) calloc(sizeof(char *),RP->Ysize);
354 for(i=0;i<RP->Ysize;i++) {
355 new_maze[i] = (char *) calloc(sizeof(char),RP->Xsize);
356 }
357 if(rotation == 1) /* swap x and y */
358 for(i=0;i<RP->Xsize;i++)
359 for(j=0;j<RP->Ysize;j++)
360 new_maze[j][i] = maze[i][j];
361
362 if(rotation == 3) { /* swap x and y */
363 for(i=0;i<RP->Xsize;i++)
364 for(j=0;j<RP->Ysize;j++)
365 new_maze[j][i] = maze[RP->Xsize -i-1][RP->Ysize - j-1];
366 }
367
368 /* delete the old layout */
369 for(i=0;i<RP->Xsize;i++)
370 free(maze[i]);
371 free(maze);
372
373 swap = RP->Ysize;
374 RP->Ysize = RP->Xsize;
375 RP->Xsize = swap;
376 return new_maze;
377 break;
378 }
379 }
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}
409
410/* checks the layout to see if I can stick a horizontal(dir = 0) wall
411 (or vertical, dir == 1)
412 here which ends up on other walls sensibly. */
413
414int can_make_wall(char **maze,int dx,int dy,int dir,RMParms *RP) {
415 int i1;
416 int length=0;
417
418 /* 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;
420
421 /* don't make walls if we're ON a wall. */
422 if(maze[dx][dy]!=0) return -1;
423
424 if(dir==0) /* horizontal */
425 {
426 int y = dy;
427 for(i1=dx-1;i1>0;i1--) {
428 int sindex=surround_flag2(maze,i1,y,RP);
429 if(sindex == 1) break;
430 if(sindex != 0) return -1; /* can't make horiz. wall here */
431 if(maze[i1][y]!=0) return -1; /* can't make horiz. wall here */
432 length++;
433 }
434
435 for(i1=dx+1;i1<RP->Xsize-1;i1++) {
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 }
444 else { /* vertical */
445 int x = dx;
446 for(i1=dy-1;i1>0;i1--) {
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; 325 return 1;
491} 326}
492 327
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);
510 if(sindex == 3 || sindex == 12) /* these are possible door sindex*/
511 {
512 doorlist_x[doorlocs]=i;
513 doorlist_y[doorlocs]=j;
514 doorlocs++;
515 }
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';
527 ndoors--;
528 }
529 /* reduce the size of the list */
530 doorlocs--;
531 doorlist_x[di]=doorlist_x[doorlocs];
532 doorlist_y[di]=doorlist_y[doorlocs];
533 }
534 free(doorlist_x);
535 free(doorlist_y);
536}
537
538
539void write_map_parameters_to_string(char *buf,RMParms *RP) {
540
541 char small_buf[256];
542 sprintf(buf,"xsize %d\nysize %d\n",RP->Xsize,RP->Ysize);
543
544 if(RP->wallstyle[0]) {
545 sprintf(small_buf,"wallstyle %s\n",RP->wallstyle);
546 strcat(buf,small_buf);
547 }
548
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 ) {
628 sprintf(small_buf,"difficulty %d\n",RP->difficulty);
629 strcat(buf,small_buf);
630 }
631
632 if(RP->difficulty_increase != 1.0 ) {
633 sprintf(small_buf,"difficulty_increase %f\n",RP->difficulty_increase);
634 strcat(buf,small_buf);
635 }
636
637 sprintf(small_buf,"dungeon_level %d\n",RP->dungeon_level);
638 strcat(buf,small_buf);
639
640 if(RP->dungeon_depth) {
641 sprintf(small_buf,"dungeon_depth %d\n",RP->dungeon_depth);
642 strcat(buf,small_buf);
643 }
644
645 if(RP->decoroptions) {
646 sprintf(small_buf,"decoroptions %d\n",RP->decoroptions);
647 strcat(buf,small_buf);
648 }
649
650 if(RP->orientation) {
651 sprintf(small_buf,"orientation %d\n",RP->orientation);
652 strcat(buf,small_buf);
653 }
654
655 if(RP->origin_x) {
656 sprintf(small_buf,"origin_x %d\n",RP->origin_x);
657 strcat(buf,small_buf);
658 }
659
660 if(RP->origin_y) {
661 sprintf(small_buf,"origin_y %d\n",RP->origin_y);
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
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);
830 strcat(buf,small_buf);
831 }
832
833 if(treasureoptions_n) {
834 sprintf(small_buf,"treasureoptions %d\n",treasureoptions_n);
835 strcat(buf,small_buf);
836 }
837
838
839}
840
841/* copy an object with an inventory... i.e., duplicate the inv too. */
842void copy_object_with_inv(object *src_ob, object *dest_ob) {
843 object *walk,*tmp;
844
845 copy_object(src_ob,dest_ob);
846
847 for(walk=src_ob->inv;walk!=NULL;walk=walk->below) {
848 tmp=get_object();
849 copy_object(walk,tmp);
850 insert_ob_in_ob(tmp,dest_ob);
851 }
852}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines