ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/random_map.C
Revision: 1.80
Committed: Wed May 4 19:04:45 2011 UTC (13 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.79: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 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>
23 */
24
25 #include <time.h>
26 #include <stdio.h>
27 #include <global.h>
28 #include <rmg.h>
29 #include <rproto.h>
30 #include <sproto.h>
31
32 #define CEDE coroapi::cede_to_tick ()
33
34 random_map_params::random_map_params ()
35 {
36 hv = newHV ();
37 }
38
39 random_map_params::random_map_params (random_map_params *RP)
40 {
41 *this = *RP;
42
43 HV *copy = newHV ();
44
45 hv_iterinit (hv);
46
47 // does not work for utf-8 keys
48 while (HE *he = hv_iternext (hv))
49 {
50 STRLEN klen; const char *key = HePV (he, klen);
51 hv_store (copy, key, klen, newSVsv (HeVAL (he)), HeHASH (he));
52 }
53
54 hv = copy;
55 }
56
57 random_map_params::random_map_params (HV *hv)
58 {
59 this->hv = (HV *)SvREFCNT_inc_NN ((SV *)hv);
60
61 assign (wall_name, get_str ("wall_name"));
62
63 xsize = get_iv ("xsize");
64 ysize = get_iv ("ysize");
65 layoutoptions1 = get_iv ("layoutoptions1");
66 layoutoptions2 = get_iv ("layoutoptions2");
67 layoutoptions3 = get_iv ("layoutoptions3");
68 difficulty = get_iv ("difficulty");
69 difficulty_given = get_iv ("difficulty_given");
70 difficulty_increase = get_nv ("difficulty_increase");
71 dungeon_level = get_iv ("dungeon_level");
72 dungeon_depth = get_iv ("dungeon_depth");
73 total_map_hp = get_nv ("total_map_hp"); // actually val64, but I am too lazy
74 symmetry_used = get_iv ("symmetry_used");
75 }
76
77 random_map_params::~random_map_params ()
78 {
79 SvREFCNT_dec (hv);
80 }
81
82 shstr_tmp
83 random_map_params::as_shstr () const
84 {
85 set ("xsize" , xsize);
86 set ("ysize" , ysize);
87 set ("layoutoptions1" , layoutoptions1);
88 set ("layoutoptions2" , layoutoptions2);
89 set ("layoutoptions3" , layoutoptions3);
90 set ("dungeon_depth" , dungeon_depth);
91 set ("difficulty" , difficulty && difficulty_given ? difficulty : 0);
92 set ("difficulty_increase", difficulty_increase);
93 set ("dungeon_level" , dungeon_level);
94
95 dynbuf_text buf;
96 hv_iterinit (hv);
97
98 // does not work for utf-8 keys
99 while (HE *he = hv_iternext (hv))
100 {
101 STRLEN klen; const char *key = HePV (he, klen);
102 STRLEN vlen; const char *value = SvPVutf8 (HeVAL (he), vlen);
103
104 buf.fadd (key, klen);
105 buf << ' ';
106 buf.fadd (value, vlen);
107 buf << '\n';
108 }
109
110 return shstr (buf);
111 }
112
113 noinline SV *
114 random_map_params::opt_sv (const char *option) const
115 {
116 SV **he = hv_fetch (hv, option, strlen (option), 0);
117
118 return he ? *he : 0;
119 }
120
121 noinline const_utf8_string
122 random_map_params::get_str (const char *option, const_utf8_string fallback) const
123 {
124 SV *sv = opt_sv (option);
125 return sv ? cfSvPVutf8_nolen (sv) : fallback;
126 }
127
128 noinline IV
129 random_map_params::get_iv (const char *option, IV fallback) const
130 {
131 SV *sv = opt_sv (option);
132 return sv ? SvIV (sv) : fallback;
133 }
134
135 noinline UV
136 random_map_params::get_uv (const char *option, UV fallback) const
137 {
138 SV *sv = opt_sv (option);
139 return sv ? SvUV (sv) : fallback;
140 }
141
142 noinline NV
143 random_map_params::get_nv (const char *option, NV fallback) const
144 {
145 SV *sv = opt_sv (option);
146 return sv ? SvNV (sv) : fallback;
147 }
148
149 noinline void
150 random_map_params::set (const char *option, SV *value) const
151 {
152 int len = strlen (option);
153
154 if (value)
155 hv_store (hv, option, len, value, 0);
156 else
157 hv_delete (hv, option, len, G_DISCARD);
158 }
159
160 noinline void
161 random_map_params::set (const char *option, const_utf8_string value) const
162 {
163 set (option, value && *value ? newSVpvn_utf8 (value, strlen (value), 1) : 0);
164 }
165
166 void
167 random_map_params::set (const char *option, IV value) const
168 {
169 set (option, newSViv (value));
170 }
171
172 void
173 random_map_params::set (const char *option, UV value) const
174 {
175 set (option, newSVuv (value));
176 }
177
178 void
179 random_map_params::set (const char *option, NV value) const
180 {
181 set (option, newSVnv (value));
182 }
183
184 bool
185 maptile::generate_random_map (random_map_params *RP)
186 {
187 RP->Xsize = RP->xsize;
188 RP->Ysize = RP->ysize;
189
190 max_it (RP->dungeon_level, 1);
191
192 IV expand2x = RP->get_iv ("expand2x");
193 UV random_seed = RP->get_uv ("random_seed");
194
195 /* pick a random seed, or use the one from the input file */
196 random_seed = random_seed
197 ? random_seed + RP->dungeon_level
198 : server_tick;
199
200 // we run "single-threaded"
201 rmg_rndm.seed (random_seed);
202
203 shstr buf = RP->as_shstr ();
204
205 if (RP->difficulty == 0)
206 {
207 RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
208
209 if (RP->difficulty_increase > 0.001f)
210 RP->difficulty = RP->dungeon_level * RP->difficulty_increase;
211
212 if (RP->difficulty < 1)
213 RP->difficulty = 1;
214 }
215 else
216 RP->difficulty_given = 1;
217
218 if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
219 RP->Xsize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
220
221 if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
222 RP->Ysize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
223
224 min_it (RP->Xsize, MAX_RANDOM_MAP_SIZE);
225 min_it (RP->Ysize, MAX_RANDOM_MAP_SIZE);
226
227 int symmetry = RP->get_iv ("symmetry", SYMMETRY_NONE);
228
229 if (symmetry == SYMMETRY_RANDOM)
230 RP->symmetry_used = rmg_rndm (SYMMETRY_XY) + 1;
231 else
232 RP->symmetry_used = symmetry;
233
234 if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
235 RP->Ysize = RP->Ysize / 2 + 1;
236
237 if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
238 RP->Xsize = RP->Xsize / 2 + 1;
239
240 if (expand2x)
241 {
242 RP->Xsize /= 2;
243 RP->Ysize /= 2;
244 }
245
246 const char *layoutstyle = RP->get_str ("layoutstyle", "");
247
248 if (strstr (layoutstyle, "onion"))
249 RP->map_layout_style = LAYOUT_ONION;
250 else if (strstr (layoutstyle, "maze"))
251 RP->map_layout_style = LAYOUT_MAZE;
252 else if (strstr (layoutstyle, "spiral"))
253 RP->map_layout_style = LAYOUT_SPIRAL;
254 else if (strstr (layoutstyle, "rogue"))
255 RP->map_layout_style = LAYOUT_ROGUELIKE;
256 else if (strstr (layoutstyle, "snake"))
257 RP->map_layout_style = LAYOUT_SNAKE;
258 else if (strstr (layoutstyle, "squarespiral"))
259 RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
260 else if (strstr (layoutstyle, "cave"))
261 RP->map_layout_style = LAYOUT_CAVE;
262 else if (strstr (layoutstyle, "castle"))
263 RP->map_layout_style = LAYOUT_CASTLE;
264 else if (strstr (layoutstyle, "multiple"))
265 RP->map_layout_style = LAYOUT_MULTIPLE;
266 else
267 RP->map_layout_style = rmg_rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */
268
269 layout maze (RP->Xsize, RP->Ysize);
270 maze.generate (RP);
271
272 if (RP->get_iv ("rotate", 1))
273 maze.rotate (rmg_rndm (4));
274
275 maze.symmetrize (RP->symmetry_used);
276
277 if (expand2x)
278 maze.expand2x ();
279
280 #if 0
281 maze.print ();//D
282 #endif
283
284 /* increment these for the current map */
285 ++RP->dungeon_level;
286
287 // need to patch RP becasue following code doesn't use the layout object
288 RP->Xsize = maze.w;
289 RP->Ysize = maze.h;
290
291 /* allocate the map and set the floor */
292 make_map_floor (maze, RP->get_str ("floorstyle", ""), RP);
293
294 /* set region */
295 default_region = region::find (RP->get_str ("region", 0));
296
297 CEDE;
298
299 place_specials_in_map (this, maze, RP);
300
301 CEDE;
302
303 const char *wallstyle = RP->get_str ("wallstyle", "");
304
305 /* create walls unless the wallstyle is "none" */
306 if (strcmp (wallstyle, "none"))
307 {
308 make_map_walls (this, maze, wallstyle, RP->get_str ("miningstyle", ""), RP);
309
310 const char *doorstyle = RP->get_str ("doorstyle", "");
311
312 /* place doors unless doorstyle or wallstyle is "none" */
313 if (strcmp (doorstyle, "none"))
314 put_doors (this, maze, doorstyle, RP);
315 }
316
317 CEDE;
318
319 const char *exitstyle = RP->get_str ("exitstyle", "");
320
321 /* create exits unless the exitstyle is "none" */
322 if (strcmp (exitstyle, "none"))
323 place_exits (this, maze, exitstyle, RP->get_iv ("orientation", 0), RP);
324
325 CEDE;
326
327 const char *monsterstyle = RP->get_str ("monsterstyle", "");
328
329 /* create monsters unless the monsterstyle is "none" */
330 if (strcmp (monsterstyle, "none"))
331 place_monsters (this, monsterstyle, RP->difficulty, RP);
332
333 CEDE;
334
335 /* treasures needs to have a proper difficulty set for the map. */
336 difficulty = estimate_difficulty ();
337
338 CEDE;
339
340 const char *treasurestyle = RP->get_str ("treasurestyle", "");
341
342 /* create treasure unless the treasurestyle is "none" */
343 place_treasure (this, maze, treasurestyle, RP->get_iv ("treasureoptions"), RP);
344
345 CEDE;
346
347 const char *decorstyle = RP->get_str ("decorstyle", "");
348
349 /* create decor unless the decorstyle is "none" */
350 if (strcmp (decorstyle, "none"))
351 put_decor (this, maze, decorstyle, RP->get_iv ("decoroptions"), RP);
352
353 CEDE;
354
355 /* generate treasures, etc. */
356 fix_auto_apply ();
357
358 CEDE;
359
360 unblock_exits (this, maze);
361
362 msg = buf;
363 state = MAP_INACTIVE; // this is probably a lie, but currently works with ext/map-random.ext
364
365 CEDE;
366
367 return 1;
368 }
369