1 /* $Id$ */
2 /* File: generate.c */
3
4 /* Purpose: Dungeon generation */
5
6 /*
7 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
8 *
9 * This software may be copied and distributed for educational, research, and
10 * not for profit purposes provided that this copyright and statement are
11 * included in all such copies.
12 */
13
14 #define SERVER
15
16 #include "angband.h"
17
18 /* Avoid generating doors that are standing around in weird/pointless locations (eg without walls attached) -- todo: fix/complete */
19 //#define ENABLE_DOOR_CHECK
20
21 static void vault_monsters(struct worldpos *wpos, int y1, int x1, int num);
22 static void town_gen_hack(struct worldpos *wpos);
23 #ifdef ENABLE_DOOR_CHECK
24 static bool door_makes_no_sense(cave_type **zcave, int x, int y);
25 #endif
26
27 struct stairs_list {
28 int x, y;
29 };
30
31 /*
32 * Note that Level generation is *not* an important bottleneck,
33 * though it can be annoyingly slow on older machines... Thus
34 * we emphasize "simplicity" and "correctness" over "speed".
35 *
36 * This entire file is only needed for generating levels.
37 * This may allow smart compilers to only load it when needed.
38 *
39 * Consider the "v_info.txt" file for vault generation.
40 *
41 * In this file, we use the "special" granite and perma-wall sub-types,
42 * where "basic" is normal, "inner" is inside a room, "outer" is the
43 * outer wall of a room, and "solid" is the outer wall of the dungeon
44 * or any walls that may not be pierced by corridors. Thus the only
45 * wall type that may be pierced by a corridor is the "outer granite"
46 * type. The "basic granite" type yields the "actual" corridors.
47 *
48 * Note that we use the special "solid" granite wall type to prevent
49 * multiple corridors from piercing a wall in two adjacent locations,
50 * which would be messy, and we use the special "outer" granite wall
51 * to indicate which walls "surround" rooms, and may thus be "pierced"
52 * by corridors entering or leaving the room.
53 *
54 * Note that a tunnel which attempts to leave a room near the "edge"
55 * of the dungeon in a direction toward that edge will cause "silly"
56 * wall piercings, but will have no permanently incorrect effects,
57 * as long as the tunnel can *eventually* exit from another side.
58 * And note that the wall may not come back into the room by the
59 * hole it left through, so it must bend to the left or right and
60 * then optionally re-enter the room (at least 2 grids away). This
61 * is not a problem since every room that is large enough to block
62 * the passage of tunnels is also large enough to allow the tunnel
63 * to pierce the room itself several times.
64 *
65 * Note that no two corridors may enter a room through adjacent grids,
66 * they must either share an entryway or else use entryways at least
67 * two grids apart. This prevents "large" (or "silly") doorways.
68 *
69 * To create rooms in the dungeon, we first divide the dungeon up
70 * into "blocks" of 11x11 grids each, and require that all rooms
71 * occupy a rectangular group of blocks. As long as each room type
72 * reserves a sufficient number of blocks, the room building routines
73 * will not need to check bounds. Note that most of the normal rooms
74 * actually only use 23x11 grids, and so reserve 33x11 grids.
75 *
76 * Note that the use of 11x11 blocks (instead of the old 33x11 blocks)
77 * allows more variability in the horizontal placement of rooms, and
78 * at the same time has the disadvantage that some rooms (two thirds
79 * of the normal rooms) may be "split" by panel boundaries. This can
80 * induce a situation where a player is in a room and part of the room
81 * is off the screen. It may be annoying enough to go back to 33x11
82 * blocks to prevent this visual situation.
83 *
84 * Note that the dungeon generation routines are much different (2.7.5)
85 * and perhaps "DUN_ROOMS" should be less than 50.
86 *
87 * XXX XXX XXX Note that it is possible to create a room which is only
88 * connected to itself, because the "tunnel generation" code allows a
89 * tunnel to leave a room, wander around, and then re-enter the room.
90 *
91 * XXX XXX XXX Note that it is possible to create a set of rooms which
92 * are only connected to other rooms in that set, since there is nothing
93 * explicit in the code to prevent this from happening. But this is less
94 * likely than the "isolated room" problem, because each room attempts to
95 * connect to another room, in a giant cycle, thus requiring at least two
96 * bizarre occurances to create an isolated section of the dungeon.
97 *
98 * Note that (2.7.9) monster pits have been split into monster "nests"
99 * and monster "pits". The "nests" have a collection of monsters of a
100 * given type strewn randomly around the room (jelly, animal, or undead),
101 * while the "pits" have a collection of monsters of a given type placed
102 * around the room in an organized manner (orc, troll, giant, dragon, or
103 * demon). Note that both "nests" and "pits" are now "level dependant",
104 * and both make 16 "expensive" calls to the "get_mon_num()" function.
105 *
106 * Note that the cave grid flags changed in a rather drastic manner
107 * for Angband 2.8.0 (and 2.7.9+), in particular, dungeon terrain
108 * features, such as doors and stairs and traps and rubble and walls,
109 * are all handled as a set of 64 possible "terrain features", and
110 * not as "fake" objects (440-479) as in pre-2.8.0 versions.
111 *
112 * The 64 new "dungeon features" will also be used for "visual display"
113 * but we must be careful not to allow, for example, the user to display
114 * hidden traps in a different way from floors, or secret doors in a way
115 * different from granite walls, or even permanent granite in a different
116 * way from granite. XXX XXX XXX
117 */
118
119
120 /*
121 * Dungeon generation values
122 */
123 #define DUN_ROOMS 50 /* Number of rooms to attempt */
124 #define DUN_UNUSUAL (cfg.dun_unusual) /* Level/chance of unusual room */
125 #define DUN_DEST 15 /* 1/chance of having a destroyed level */
126
127 /*
128 * Dungeon tunnel generation values
129 */
130 #define DUN_TUN_RND 10 /* Chance of random direction */
131 #define DUN_TUN_CHG 30 /* Chance of changing direction */
132 #define DUN_TUN_CON 15 /* Chance of extra tunneling */
133 #define DUN_TUN_PEN 25 /* Chance of doors at room entrances */
134 #define DUN_TUN_JCT 90 /* Chance of doors at tunnel junctions */
135
136 /*
137 * Dungeon streamer generation values
138 */
139 #define DUN_STR_DEN 5 /* Density of streamers */
140 #define DUN_STR_RNG 2 /* Width of streamers */
141 #define DUN_STR_MAG 3 /* Number of magma streamers */
142 #define DUN_STR_MC 90 /* 1/chance of treasure per magma */
143 #define DUN_STR_QUA 2 /* Number of quartz streamers */
144 #define DUN_STR_QC 40 /* 1/chance of treasure per quartz */
145 #define DUN_STR_SC 10 /* 1/chance of treasure per sandwall */
146 #define DUN_STR_WLW 1 /* Width of lava & water streamers -KMW- */
147 #define DUN_STR_DWLW 8 /* Density of water & lava streams -KMW- */
148
149 /*
150 * Dungeon treausre allocation values
151 */
152 #define DUN_AMT_ROOM 9 /* Amount of objects for rooms */
153 #define DUN_AMT_ITEM 3 /* Amount of objects for rooms/corridors */
154 #define DUN_AMT_GOLD 3 /* Amount of treasure for rooms/corridors */
155 /* #define DUN_AMT_ALTAR 1 */ /* Amount of altars */
156 #define DUN_AMT_BETWEEN 2 /* Amount of between gates */
157 #define DUN_AMT_FOUNTAIN 1 /* Amount of fountains */
158
159 /*
160 * Hack -- Dungeon allocation "places"
161 */
162 #define ALLOC_SET_CORR 1 /* Hallway */
163 #define ALLOC_SET_ROOM 2 /* Room */
164 #define ALLOC_SET_BOTH 3 /* Anywhere */
165
166 /*
167 * Hack -- Dungeon allocation "types"
168 */
169 #define ALLOC_TYP_RUBBLE 1 /* Rubble */
170 #define ALLOC_TYP_TRAP 3 /* Trap */
171 #define ALLOC_TYP_GOLD 4 /* Gold */
172 #define ALLOC_TYP_OBJECT 5 /* Object */
173 #define ALLOC_TYP_ALTAR 6 /* Altar */
174 #define ALLOC_TYP_BETWEEN 7 /* Between */
175 #define ALLOC_TYP_FOUNTAIN 8 /* Fountain */
176 #define ALLOC_TYP_FOUNTAIN_OF_BLOOD 9 /* Fountain of Blood */
177
178
179
180 /*
181 * The "size" of a "generation block" in grids
182 */
183 #define BLOCK_HGT 11
184 #define BLOCK_WID 11
185
186 /*
187 * Maximum numbers of rooms along each axis (currently 6x6)
188 */
189 #define MAX_ROOMS_ROW (MAX_HGT / BLOCK_HGT)
190 #define MAX_ROOMS_COL (MAX_WID / BLOCK_WID)
191
192
193 /*
194 * Bounds on some arrays used in the "dun_data" structure.
195 * These bounds are checked, though usually this is a formality.
196 */
197 #define CENT_MAX 100
198 #define DOOR_MAX 400
199 #define WALL_MAX 1000
200 #define TUNN_MAX 1800
201
202
203 /*
204 * Maximal number of room types
205 */
206 #define ROOM_MAX 13
207
208 /*
209 * Maxumal 'depth' that has extra stairs;
210 * also, those floors will be w/o trapped doors.
211 */
212 #define COMFORT_PASSAGE_DEPTH 5
213
214 /*
215 * ((level+TRAPPED_DOOR_BASE)/TRAPPED_DOOR_RATE) chance of generation
216 */
217 #define TRAPPED_DOOR_RATE 400
218 #define TRAPPED_DOOR_BASE 30
219
220 /*
221 * Below this are makeshift implementations of extra dungeon features;
222 * TODO: replace them by dungeon_types etc - Jir -
223 */
224 /*
225 * makeshift river for 3.3.x
226 * pfft, still alive for 4.0.0...
227 * [15,7,4,6,45,4,19,100, 1000,50]
228 *
229 * A player is supposed to cross 2 watery belts without avoiding them
230 * by scumming; the first by swimming, the second by levitation parhaps.
231 */
232 #define DUN_RIVER_CHANCE 15 /* The deeper, the less watery area. */
233 #define DUN_RIVER_REDUCE 7 /* DUN_RIVER_CHANCE / 2, maximum. */
234 #define DUN_STR_WAT 4
235 #define DUN_LAKE_TRY 6 /* how many tries to generate lake on river */
236 #define WATERY_CYCLE 45 /* defines 'watery belt' */
237 #define WATERY_RANGE 4 /* (45,4,19) = '1100-1250, 3350-3500,.. ' */
238 #define WATERY_OFFSET 19
239 #define WATERY_BELT_CHANCE 100 /* chance of river generated on watery belt */
240
241 #define DUN_MAZE_FACTOR 1000 /* depth/DUN_MAZE_FACTOR chance of maze */
242 #define DUN_MAZE_PERMAWALL 20 /* % of maze built of permawall */
243
244
245 /*
246 * Those flags are mainly for vaults, quests and non-Angband dungeons...
247 * but none of them implemented, qu'a faire?
248 */
249 #define NO_MAGIC_CHANCE 4
250 #define NO_GENO_CHANCE 4
251 #define NO_MAP_CHANCE 4
252 #define NO_MAGIC_MAP_CHANCE 4
253 #define NO_DESTROY_CHANCE 4
254
255 /*
256 * Chances of a vault creating some special effects on the level, in %.
257 * FORCE_FLAG bypasses this check. [50]
258 */
259 #define VAULT_FLAG_CHANCE 30
260
261 /*
262 * Chance of 'HIVES' type vaults reproducing themselves, in %. [60]
263 */
264 #define HIVE_CHANCE(lev) (lev > 120 ? 60 : lev / 3 + 20)
265
266 /*
267 * Borrowed stuffs from ToME
268 */
269 #define DUN_CAVERN 30 /* chance/depth of having a cavern level */
270 #define DUN_CAVERN2 20 /* 1/chance extra check for cavern level */
271 #define EMPTY_LEVEL 15 /* 1/chance of being 'empty' (15)*/
272 #define DARK_EMPTY 5 /* 1/chance of arena level NOT being lit (2)*/
273 #define SMALL_LEVEL 4 /* 1/chance of smaller size (3)*/
274 #define DUN_WAT_RNG 2 /* Width of rivers */
275 #define DUN_WAT_CHG 50 /* 1 in 50 chance of junction in river */
276
277 #define DUN_SANDWALL 10 /* percentage for Sandwall being generated [10] */
278
279 /* specify behaviour/possibility of vaults/rooms in 'maze' levels */
280 #define VAULTS_OVERRIDE_MAZE /* make vault walls override maze emptiness. otherwise, mazes can 'unwall' vaults! */
281
282 /* Prevent staircases from being generated on inner/outer ring of pits and nests? */
283 //#define NEST_PIT_NO_STAIRS_INNER
284 #define NEST_PIT_NO_STAIRS_OUTER /* implies NEST_PIT_NO_STAIRS_INNER */
285
286 /* Ironman Deep Dive Challenge levels should always be big, unless the dungeon theme dictates otherwise? */
287 #define IRONDEEPDIVE_BIG_IF_POSSIBLE
288 /* Ironman Deep Dive Challenge levels of SMALL or SMALLEST theme should actually be enlarged for better exp gain? */
289 #define IRONDEEPDIVE_EXPAND_SMALL
290 /* Ironman Deep Dive Challenge levels have less chance to generate vaults */
291 #define IDDC_FEWER_VAULTS
292 /* Final guardians are guaranteed spawns instead of rolling against their r-rarity? */
293 #define IDDC_GUARANTEED_FG
294
295 /* experimental - this might be too costly on cpu: add volcanic floor around lava rivers - C. Blue */
296 #define VOLCANIC_FLOOR
297
298
299 /*
300 * Simple structure to hold a map location
301 */
302
303 typedef struct coord coord;
304
305 struct coord
306 {
307 byte y;
308 byte x;
309 };
310
311
312 /*
313 * Room type information
314 */
315
316 typedef struct room_data room_data;
317
318 struct room_data
319 {
320 /* Required size in blocks */
321 s16b dy1, dy2, dx1, dx2;
322
323 /* Hack -- minimum level */
324 s16b level;
325 };
326
327
328 /*
329 * Structure to hold all "dungeon generation" data
330 */
331
332 typedef struct dun_data dun_data;
333
334 struct dun_data
335 {
336 /* Array of centers of rooms */
337 int cent_n;
338 coord cent[CENT_MAX];
339
340 /* Array of possible door locations */
341 int door_n;
342 coord door[DOOR_MAX];
343
344 /* Array of wall piercing locations */
345 int wall_n;
346 coord wall[WALL_MAX];
347
348 /* Array of tunnel grids */
349 int tunn_n;
350 coord tunn[TUNN_MAX];
351
352 /* Number of blocks along each axis */
353 int row_rooms;
354 int col_rooms;
355
356 /* Array of which blocks are used */
357 bool room_map[MAX_ROOMS_ROW][MAX_ROOMS_COL];
358
359 /* Hack -- there is a pit/nest on this level */
360 bool crowded;
361
362 bool watery; /* this should be included in dun_level struct. */
363 bool no_penetr;
364
365 dun_level *l_ptr;
366 int ratio;
367 #if 0
368 byte max_hgt; /* Vault height */
369 byte max_wid; /* Vault width */
370 #endif /*0 */
371 };
372
373
374 /*
375 * Dungeon generation data -- see "cave_gen()"
376 */
377 static dun_data *dun;
378
379 /*
380 * Dungeon graphics info
381 * Why the first two are byte and the rest s16b???
382 */
383 /* ToME variables -- not implemented, but needed to have it work */
384 static byte feat_wall_outer = FEAT_WALL_OUTER; /* Outer wall of rooms */
385 static byte feat_wall_inner = FEAT_WALL_INNER; /* Inner wall of rooms */
386 s16b floor_type[1000]; /* Dungeon floor */
387 s16b fill_type[1000]; /* Dungeon filler */
388
389 static bool good_item_flag; /* True if "Artifact" on this level */
390
391 /*
392 * Array of room types (assumes 11x11 blocks)
393 */
394 static room_data room[ROOM_MAX] =
395 {
396 { 0, 0, 0, 0, 0 }, /* 0 = Nothing */
397 { 0, 0, -1, 1, 1 }, /* 1 = Simple (33x11) */
398 { 0, 0, -1, 1, 1 }, /* 2 = Overlapping (33x11) */
399 { 0, 0, -1, 1, 3 }, /* 3 = Crossed (33x11) */
400 { 0, 0, -1, 1, 3 }, /* 4 = Large (33x11) */
401 { 0, 0, -1, 1, 5 }, /* 5 = Monster nest (33x11) */
402 { 0, 0, -1, 1, 5 }, /* 6 = Monster pit (33x11) */
403 { 0, 1, -1, 1, 5 }, /* 7 = Lesser vault (33x22) */
404 { -1, 2, -2, 3, 10 }, /* 8 = Greater vault (66x44) */
405
406 { 0, 1, 0, 1, 1 }, /* 9 = Circular rooms (22x22) */
407 { 0, 1, -1, 1, 3 }, /* 10 = Fractal cave (42x24) */
408 { 0, 1, -1, 1, 10 }, /* 11 = Random vault (44x22) */
409 { 0, 1, 0, 1, 10 }, /* 12 = Crypts (22x22) */
410 };
411
412
413 /*
414 * Always picks a correct direction
415 */
correct_dir(int * rdir,int * cdir,int y1,int x1,int y2,int x2)416 static void correct_dir(int *rdir, int *cdir, int y1, int x1, int y2, int x2)
417 {
418 /* Extract vertical and horizontal directions */
419 *rdir = (y1 == y2) ? 0 : (y1 < y2) ? 1 : -1;
420 *cdir = (x1 == x2) ? 0 : (x1 < x2) ? 1 : -1;
421
422 /* Never move diagonally */
423 if (*rdir && *cdir)
424 {
425 if (rand_int(100) < 50)
426 {
427 *rdir = 0;
428 }
429 else
430 {
431 *cdir = 0;
432 }
433 }
434 }
435
436 #ifdef ARCADE_SERVER
arcade_wipe(worldpos * wpos)437 extern void arcade_wipe(worldpos *wpos)
438 {
439 cave_type **zcave;
440 // cave_type *c_ptr;
441 if (!(zcave = getcave(wpos))) return;
442 int my, mx;
443 for (mx = 1; mx < 131; mx++) {
444 for (my = 1; my < 43; my++) {
445 cave_set_feat(wpos, my, mx, 1);
446 }
447 }
448 return;
449 }
450 #endif
451
452 /*
453 * Pick a random direction
454 */
rand_dir(int * rdir,int * cdir)455 static void rand_dir(int *rdir, int *cdir)
456 {
457 /* Pick a random direction */
458 int i = rand_int(4);
459
460 /* Extract the dy/dx components */
461 *rdir = ddy_ddd[i];
462 *cdir = ddx_ddd[i];
463 }
464
465
466 /*
467 * Returns random co-ordinates for player starts
468 */
new_player_spot(struct worldpos * wpos)469 static void new_player_spot(struct worldpos *wpos)
470 {
471 int y, x, tries = 5000;
472
473 cave_type **zcave;
474 if (!(zcave = getcave(wpos))) return;
475
476 /* Place the player */
477 while (TRUE)
478 {
479 /* Pick a legal spot */
480 y = rand_range(1, dun->l_ptr->hgt - 2);
481 x = rand_range(1, dun->l_ptr->wid - 2);
482
483 /* prevent infinite loop (not sure about exact circumstances yet) */
484 if (!--tries) break;
485
486 /* Must be a "naked" floor grid */
487 if (!cave_naked_bold(zcave, y, x)) continue;
488
489 /* Refuse to start on anti-teleport grids */
490 if (zcave[y][x].info & CAVE_ICKY) continue;
491
492 /* Done */
493 break;
494 }
495
496 /* emergency procedure: avoid no-tele vaults */
497 if ((!tries) && (zcave[y][x].info & CAVE_STCK)) {
498 for (x = 1; x < dun->l_ptr->wid - 2; x++)
499 for (y = 1; y < dun->l_ptr->hgt - 2; y++) {
500 if (!(zcave[y][x].info & CAVE_STCK)) break;
501 }
502 /* This shouldn't happen: Whole level is filled with CAVE_STCK spots, exclusively! */
503 y = rand_range(1, dun->l_ptr->hgt - 2);
504 x = rand_range(1, dun->l_ptr->wid - 2);
505 }
506
507 /* Save the new grid */
508 new_level_rand_y(wpos, y);
509 new_level_rand_x(wpos, x);
510 }
511
512
513
514 /*
515 * Count the number of walls adjacent to the given grid.
516 *
517 * Note -- Assumes "in_bounds(y, x)"
518 *
519 * We count only granite walls and permanent walls.
520 */
next_to_walls(struct worldpos * wpos,int y,int x)521 static int next_to_walls(struct worldpos *wpos, int y, int x)
522 {
523 int k = 0;
524 cave_type **zcave;
525 if (!(zcave = getcave(wpos))) return(FALSE);
526
527 if (f_info[zcave[y+1][x].feat].flags1 & FF1_WALL) k++;
528 if (f_info[zcave[y-1][x].feat].flags1 & FF1_WALL) k++;
529 if (f_info[zcave[y][x+1].feat].flags1 & FF1_WALL) k++;
530 if (f_info[zcave[y][x-1].feat].flags1 & FF1_WALL) k++;
531 return (k);
532 }
533
534
535 /* For new place_rubble() that can place a double-rubble - C. Blue
536 Returns: dir of hallway wall or 0 if not in hallway or if in
537 a corner of a hallway (ie in any spot that doesn't
538 feature exactly 3 wall grids in a row, rest floor grids. */
along_hallway(cave_type ** zcave,int x,int y)539 static int along_hallway(cave_type **zcave, int x, int y) {
540 int pos, d, x1, y1, walls;
541
542 /* Assume 4 possible directions of hallway walls:
543 horizontally below us, vertically right of us, horizontally above us, vertically left of us. */
544 for (pos = 0; pos <= 7; pos += 2) {
545 /* test for 3 wall grids + 5 floor grids */
546 walls = 0;
547
548 /* begin with 3 walls */
549 for (d = 0; d <= 2; d++) {
550 /* Extract the location */
551 x1 = x + ddx_cyc[(pos + d) % 8];
552 y1 = y + ddy_cyc[(pos + d) % 8];
553
554 /* Require non-floor */
555 if (cave_floor_bold(zcave, y1, x1)) continue;
556 if (zcave[y1][x1].feat == FEAT_RUBBLE) continue; /* exempt actual rubble */
557 walls++;
558 }
559 /* test for '3 walls grids' already failed? */
560 if (walls != 3) continue;
561
562 /* test for 5 floor grids now */
563 for (d = 3; d <= 7; d++) {
564 /* Extract the location */
565 x1 = x + ddx_cyc[(pos + d) % 8];
566 y1 = y + ddy_cyc[(pos + d) % 8];
567
568 /* Require floor */
569 if (cave_floor_bold(zcave, y1, x1)) continue;
570 if (zcave[y1][x1].feat == FEAT_RUBBLE) continue; /* exempt actual rubble */
571 walls++;
572 }
573 /* failed to find 5 floor grids? */
574 if (walls != 3) continue;
575
576 /* success */
577 return (pos + 1);
578 }
579 return 0;
580 }
581
582 /*
583 * Convert existing terrain type to rubble
584 */
place_rubble(struct worldpos * wpos,int y,int x)585 static void place_rubble(struct worldpos *wpos, int y, int x)
586 {
587 cave_type **zcave;
588 cave_type *c_ptr;
589 int dir;
590 if(!(zcave = getcave(wpos))) return;
591 c_ptr = &zcave[y][x];
592
593 /* Create rubble */
594 c_ptr->feat = FEAT_RUBBLE;
595
596 /* new: if it's inside a hallway, have a chance for a second rubble
597 to be generated to completely block the way.
598 Note: currently does not affect dungeon-specific rubble tiles (Mines of Moria). */
599 if (!rand_int(4)) return;
600 if (!(c_ptr->info & (CAVE_ROOM | CAVE_ICKY))
601 && (dir = along_hallway(zcave, x, y))) {
602 /* place another rubble in the opposite dir */
603 x = x + ddx_cyc[ddi_cyc[dir]];
604 y = y + ddy_cyc[ddi_cyc[dir]];
605 /* check that potential new rubble grid also passes the hallway test,
606 and therefore is located at the opposite wall of our hallway */
607 if (ddi_cyc[dir] == along_hallway(zcave, x, y)) {
608 /* double check that it's *clean* floor */
609 if (cave_naked_bold(zcave, y, x)) {
610 /* place a second rubble pile */
611 zcave[y][x].feat = FEAT_RUBBLE;
612 }
613 }
614 }
615 }
616
617 /*
618 * Create a fountain here.
619 */
place_fountain(struct worldpos * wpos,int y,int x)620 void place_fountain(struct worldpos *wpos, int y, int x) {
621 cave_type **zcave;
622 cave_type *c_ptr;
623 int dun_lev;
624 c_special *cs_ptr;
625 int svals[SV_POTION_LAST + SV_POTION2_LAST + 1], maxsval = 0, k;
626
627 if(!(zcave = getcave(wpos))) return;
628 dun_lev = getlevel(wpos);
629 c_ptr = &zcave[y][x];
630
631
632 /* No fountains over traps/house doors etc */
633 if (c_ptr->special) return;
634
635 /* Place the fountain */
636 if (randint(100) < 20) { /* 30 */
637 /* XXX Empty fountain doesn't need 'type', does it? */
638 cave_set_feat(wpos, y, x, FEAT_EMPTY_FOUNTAIN);
639 /* c_ptr->special2 = 0; */
640 return;
641 }
642
643 /* List of usable svals */
644 for (k = 1; k < max_k_idx; k++) {
645 object_kind *k_ptr = &k_info[k];
646
647 if (((k_ptr->tval == TV_POTION) || (k_ptr->tval == TV_POTION2)) &&
648 (k_ptr->level <= dun_lev) && (k_ptr->flags4 & TR4_FOUNTAIN)) {
649 /* C. Blue -- reduce amount of stat-draining fountains before sustain rings become available */
650 if (!((k_ptr->tval == TV_POTION) && (
651 ((dun_lev < 8) && /* no stat-draining fountains above -400ft (finding sustain-rings there) */
652 (k_ptr->sval == SV_POTION_DEC_STR || k_ptr->sval == SV_POTION_DEC_INT ||
653 k_ptr->sval == SV_POTION_DEC_WIS || k_ptr->sval == SV_POTION_DEC_DEX ||
654 k_ptr->sval == SV_POTION_DEC_CON)) || /* allow CHR drain */
655 ((dun_lev < 20) && /* no exp-draining fountains before stat-fountains appear */
656 ((k_ptr->sval == SV_POTION_LOSE_MEMORIES) ||
657 ((!k_ptr->cost) && magik(50)))) /* bad fountains 50% less probable before stat-fountains appear */
658 )) &&
659 #ifndef EXPAND_TV_POTION
660 !((k_ptr->tval == TV_POTION2) && (dun_lev < 20) &&
661 (k_ptr->sval == SV_POTION2_CHAUVE_SOURIS))
662 #else
663 !((k_ptr->tval == TV_POTION) && (dun_lev < 20) &&
664 (k_ptr->sval == SV_POTION_CHAUVE_SOURIS))
665 #endif
666 )
667 {
668 if (k_ptr->tval == TV_POTION2) svals[maxsval] = k_ptr->sval + SV_POTION_LAST;
669 else svals[maxsval] = k_ptr->sval;
670 maxsval++;
671 }
672 }
673 }
674
675 if (maxsval == 0) return;
676 else {
677 /* TODO: rarity should be counted in? */
678 cave_set_feat(wpos, y, x, FEAT_FOUNTAIN);
679 if (!(cs_ptr = AddCS(c_ptr, CS_FOUNTAIN))) return;
680
681 if (!maxsval || magik(20)) /* often water */
682 cs_ptr->sc.fountain.type = SV_POTION_WATER;
683 else cs_ptr->sc.fountain.type = svals[rand_int(maxsval)];
684
685 cs_ptr->sc.fountain.rest = damroll(1, 5);
686
687 /* Some hacks: */
688 if (cs_ptr->sc.fountain.type <= SV_POTION_LAST)
689 switch (cs_ptr->sc.fountain.type) {
690 /* case SV_POTION_NEW_LIFE:
691 cs_ptr->sc.fountain.rest = 1;
692 break;
693 */ case SV_POTION_INC_STR: case SV_POTION_INC_INT:
694 case SV_POTION_INC_WIS: case SV_POTION_INC_DEX:
695 case SV_POTION_INC_CON: case SV_POTION_INC_CHR:
696 case SV_POTION_STAR_ENLIGHTENMENT:
697 case SV_POTION_STAR_RESTORE_MANA:
698 case SV_POTION_STAR_HEALING:
699 case SV_POTION_LIFE:
700 case SV_POTION_SELF_KNOWLEDGE:
701 cs_ptr->sc.fountain.rest = damroll(1, 3);
702 break;
703 case SV_POTION_AUGMENTATION:
704 case SV_POTION_EXPERIENCE:
705 case SV_POTION_INVULNERABILITY:
706 cs_ptr->sc.fountain.rest = 1;
707 break;
708 #ifdef EXPAND_TV_POTION
709 case SV_POTION2_CHAUVE_SOURIS:
710 case SV_POTION2_CURE_SANITY:
711 case SV_POTION_LEARNING:
712 cs_ptr->sc.fountain.rest = damroll(1, 2);
713 break;
714 #endif
715 }
716 else
717 switch (cs_ptr->sc.fountain.type - SV_POTION_LAST) {
718 /* make it hard to polymorph back at a bat fountain by sipping again */
719 case SV_POTION2_CHAUVE_SOURIS:
720 case SV_POTION2_CURE_SANITY:
721 case SV_POTION2_LEARNING:
722 cs_ptr->sc.fountain.rest = damroll(1, 2);
723 break;
724 }
725
726 cs_ptr->sc.fountain.known = FALSE;
727 #if 0
728 cs_ptr->type = CS_TRAPS;
729 c_ptr->special2 = damroll(3, 4);
730 #endif /* 0 */
731 }
732
733 /* c_ptr->special = svals[rand_int(maxsval)]; */
734 }
735
736 /* Place a fountain of blood, for Vampires, as suggested by Mark - C. Blue */
place_fountain_of_blood(struct worldpos * wpos,int y,int x)737 void place_fountain_of_blood(struct worldpos *wpos, int y, int x) {
738 cave_type **zcave;
739 cave_type *c_ptr;
740 c_special *cs_ptr;
741
742 if(!(zcave = getcave(wpos))) return;
743 c_ptr = &zcave[y][x];
744
745 /* No fountains over traps/house doors etc */
746 if (c_ptr->special) return;
747
748 /* TODO: rarity should be counted in? */
749 cave_set_feat(wpos, y, x, FEAT_FOUNTAIN_BLOOD);
750 if (!(cs_ptr = AddCS(c_ptr, CS_FOUNTAIN))) return;
751 cs_ptr->sc.fountain.type = SV_POTION_BLOOD;
752 cs_ptr->sc.fountain.rest = damroll(1, 5);
753 cs_ptr->sc.fountain.known = TRUE;
754 }
755
756 #if 0
757 /*
758 * Place an altar at the given location
759 */
760 static void place_altar(int y, int x)
761 {
762 if (magik(10))
763 cave_set_feat(y, x, 164);
764 }
765 #endif /* 0 */
766
767
768 /*
769 * Place a between gate at the two specified locations
770 */
place_between_targetted(struct worldpos * wpos,int y,int x,int ty,int tx)771 bool place_between_targetted(struct worldpos *wpos, int y, int x, int ty, int tx) {
772 cave_type **zcave;
773 cave_type *c_ptr, *c1_ptr;
774 c_special *cs_ptr;
775
776 if (!(zcave = getcave(wpos))) return FALSE;
777
778 /* Require "naked" floor grid */
779 if (!cave_clean_bold(zcave, y, x)) return FALSE;
780 if (!cave_naked_bold(zcave, ty, tx)) return FALSE;
781
782 /* No between-gate over traps/house doors etc */
783 c_ptr = &zcave[y][x];
784 if (c_ptr->special) return FALSE;
785
786 /* Access the target grid */
787 c1_ptr = &zcave[ty][tx];
788 if (c1_ptr->special) return FALSE;
789
790 if (!(cs_ptr = AddCS(c_ptr, CS_BETWEEN))) return FALSE;
791 cave_set_feat(wpos, y, x, FEAT_BETWEEN);
792 cs_ptr->sc.between.fy = ty;
793 cs_ptr->sc.between.fx = tx;
794
795 /* XXX not 'between' gate can be generated */
796 if (!(cs_ptr = AddCS(c1_ptr, CS_BETWEEN))) return FALSE;
797 cave_set_feat(wpos, ty, tx, FEAT_BETWEEN);
798 cs_ptr->sc.between.fy = y;
799 cs_ptr->sc.between.fx = x;
800
801 return TRUE;
802 }
803
804 /*
805 * Place a between gate at the given location
806 */
place_between(struct worldpos * wpos,int y,int x)807 static void place_between(struct worldpos *wpos, int y, int x) {
808 int gx, gy, tries = 1000;
809 while (TRUE) {
810 gy = rand_int(dun->l_ptr->hgt);
811 gx = rand_int(dun->l_ptr->wid);
812 if (place_between_targetted(wpos, y, x, gy, gx)) break;
813
814 if (tries-- == 0) return;
815 }
816 }
817 /* external variant for use from elsewhere */
place_between_ext(struct worldpos * wpos,int y,int x,int hgt,int wid)818 void place_between_ext(struct worldpos *wpos, int y, int x, int hgt, int wid) {
819 int gx, gy, tries = 1000;
820 while (TRUE) {
821 gy = rand_int(hgt);
822 gx = rand_int(wid);
823 if (place_between_targetted(wpos, y, x, gy, gx)) break;
824
825 if (tries-- == 0) return;
826 }
827 }
828
829 /* For divine_gateway() - cool visuals only */
place_between_dummy(struct worldpos * wpos,int y,int x)830 bool place_between_dummy(struct worldpos *wpos, int y, int x) {
831 cave_type **zcave;
832 cave_type *c_ptr;
833
834 if (!(zcave = getcave(wpos))) return FALSE;
835
836 /* Require "naked" floor grid */
837 if (!cave_clean_bold(zcave, y, x)) return FALSE;
838
839 /* No between-gate over traps/house doors etc */
840 c_ptr = &zcave[y][x];
841 if (c_ptr->special) return FALSE;
842
843 cave_set_feat(wpos, y, x, FEAT_BETWEEN_TEMP);
844
845 return TRUE;
846 }
847
848 /*
849 * Convert existing terrain type to "up stairs"
850 */
place_up_stairs(struct worldpos * wpos,int y,int x)851 extern void place_up_stairs(struct worldpos *wpos, int y, int x) {
852 cave_type **zcave;
853 cave_type *c_ptr;
854 if (!(zcave = getcave(wpos))) return;
855 c_ptr = &zcave[y][x];
856
857 /* Create up stairs */
858 if (can_go_up(wpos, 0x1)) {
859 c_ptr->feat = FEAT_LESS;
860 aquatic_terrain_hack(zcave, x, y);
861 }
862 }
863
864
865 /*
866 * Convert existing terrain type to "down stairs"
867 */
place_down_stairs(worldpos * wpos,int y,int x)868 static void place_down_stairs(worldpos *wpos, int y, int x) {
869 cave_type **zcave;
870 cave_type *c_ptr;
871 if (!(zcave = getcave(wpos))) return;
872 c_ptr = &zcave[y][x];
873
874 /* Create down stairs */
875 if (can_go_down(wpos, 0x1)) {
876 c_ptr->feat = FEAT_MORE;
877 aquatic_terrain_hack(zcave, x, y);
878 }
879 }
880
881
882 /*
883 * Place an up/down staircase at given location
884 */
place_random_stairs(struct worldpos * wpos,int y,int x)885 static void place_random_stairs(struct worldpos *wpos, int y, int x) {
886 cave_type **zcave;
887
888 /* no staircase spam anyway, one is sufficient */
889 //#ifdef NETHERREALM_BOTTOM_RESTRICT
890 if (netherrealm_bottom(wpos)) return;
891 //#endif
892
893 if (!(zcave = getcave(wpos))) return;
894
895 if (!cave_clean_bold(zcave, y, x)) return;
896
897 if (!can_go_down(wpos, 0x1) && !can_go_up(wpos, 0x1)){
898 /* special or what? */
899 } else if(!can_go_down(wpos, 0x1) && can_go_up(wpos, 0x1)){
900 place_up_stairs(wpos, y, x);
901 } else if(!can_go_up(wpos, 0x1) && can_go_down(wpos, 0x1)){
902 place_down_stairs(wpos, y, x);
903 } else if (rand_int(100) < 50) {
904 place_down_stairs(wpos, y, x);
905 } else {
906 place_up_stairs(wpos, y, x);
907 }
908 }
909
910
911 /*
912 * Place a locked door at the given location
913 */
place_locked_door(struct worldpos * wpos,int y,int x)914 static void place_locked_door(struct worldpos *wpos, int y, int x) {
915 int tmp;
916 cave_type **zcave;
917 cave_type *c_ptr;
918 if (!(zcave = getcave(wpos))) return;
919 c_ptr = &zcave[y][x];
920
921 #ifdef ENABLE_DOOR_CHECK
922 if (door_makes_no_sense(zcave, x, y)) return;
923 #endif
924
925 /* Create locked door */
926 c_ptr->feat = FEAT_DOOR_HEAD + randint(7);
927 aquatic_terrain_hack(zcave, x, y);
928
929 /* let's trap this ;) */
930 if ((tmp = getlevel(wpos)) <= COMFORT_PASSAGE_DEPTH ||
931 rand_int(TRAPPED_DOOR_RATE) > tmp + TRAPPED_DOOR_BASE) return;
932 place_trap(wpos, y, x, 0);
933 }
934
935
936 /*
937 * Place a secret door at the given location
938 */
place_secret_door(struct worldpos * wpos,int y,int x)939 static void place_secret_door(struct worldpos *wpos, int y, int x) {
940 int tmp;
941 cave_type **zcave;
942 cave_type *c_ptr;
943 struct c_special *cs_ptr;
944 if (!(zcave = getcave(wpos))) return;
945 c_ptr = &zcave[y][x];
946
947 #ifdef ENABLE_DOOR_CHECK
948 if (door_makes_no_sense(zcave, x, y)) return;
949 #endif
950
951 if ((cs_ptr = AddCS(c_ptr, CS_MIMIC))) {
952 /* Vaults */
953 if (c_ptr->info & CAVE_ICKY)
954 cs_ptr->sc.omni = FEAT_WALL_INNER;
955
956 /* Ordinary room -- use current outer or inner wall */
957 else if (c_ptr->info & CAVE_ROOM) {
958 /* Determine if it's inner or outer XXX XXX XXX */
959 if ((zcave[y - 1][x].info & CAVE_ROOM) &&
960 (zcave[y + 1][x].info & CAVE_ROOM) &&
961 (zcave[y][x - 1].info & CAVE_ROOM) &&
962 (zcave[y][x + 1].info & CAVE_ROOM))
963 {
964 cs_ptr->sc.omni = feat_wall_inner;
965 } else {
966 cs_ptr->sc.omni = feat_wall_outer;
967 }
968 } else {
969 cs_ptr->sc.omni = fill_type[rand_int(1000)];
970 }
971 }
972
973 /* Create secret door */
974 c_ptr->feat = FEAT_SECRET;
975 aquatic_terrain_hack(zcave, x, y);
976
977 /* let's trap this ;) */
978 if ((tmp = getlevel(wpos)) <= COMFORT_PASSAGE_DEPTH ||
979 rand_int(TRAPPED_DOOR_RATE) > tmp + TRAPPED_DOOR_BASE) return;
980 place_trap(wpos, y, x, 0);
981 }
982
983
984 /*
985 * Place a random type of door at the given location
986 */
place_random_door(struct worldpos * wpos,int y,int x)987 static void place_random_door(struct worldpos *wpos, int y, int x) {
988 int tmp;
989 cave_type **zcave;
990 cave_type *c_ptr;
991 if (!(zcave = getcave(wpos))) return;
992 c_ptr = &zcave[y][x];
993
994 #ifdef ENABLE_DOOR_CHECK
995 if (door_makes_no_sense(zcave, x, y)) return;
996 #endif
997
998 #if 0 /* fixed the build_tunnel() code, should make this hack obsolete */
999 /* hack: after adding dungeon-custom boundary feats, we had a panic in
1000 Mordor, where the 2nd door of a pair of doors was created inside the
1001 upper level side high mountain boundary.
1002 TODO instead of this: look for perm wall checks (eg FEAT_PERM_SOLID)
1003 that don't recognize the new boundary feats. */
1004 if ((f_info[zcave[y][x].feat].flags2 & FF2_BOUNDARY)) return;
1005 #endif
1006
1007 /* Choose an object */
1008 tmp = rand_int(1000);
1009
1010 /* Open doors (300/1000) */
1011 if (tmp < 300) {
1012 /* Create open door */
1013 c_ptr->feat = FEAT_OPEN;
1014 }
1015
1016 /* Broken doors (100/1000) */
1017 else if (tmp < 400) {
1018 /* Create broken door */
1019 c_ptr->feat = FEAT_BROKEN;
1020 }
1021
1022 /* Secret doors (200/1000) */
1023 else if (tmp < 600) {
1024 /* Create secret door */
1025 c_ptr->feat = FEAT_SECRET;
1026 }
1027
1028 /* Closed doors (300/1000) */
1029 else if (tmp < 900) {
1030 /* Create closed door */
1031 c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
1032 }
1033
1034 /* Locked doors (99/1000) */
1035 else if (tmp < 999) {
1036 /* Create locked door */
1037 c_ptr->feat = FEAT_DOOR_HEAD + randint(7);
1038 }
1039
1040 /* Stuck doors (1/1000) */
1041 else {
1042 /* Create jammed door */
1043 c_ptr->feat = FEAT_DOOR_HEAD + 0x08 + rand_int(8);
1044 }
1045
1046 aquatic_terrain_hack(zcave, x, y);
1047
1048 /* let's trap this ;) */
1049 if ((tmp = getlevel(wpos)) <= COMFORT_PASSAGE_DEPTH ||
1050 rand_int(TRAPPED_DOOR_RATE) > tmp + TRAPPED_DOOR_BASE) return;
1051 place_trap(wpos, y, x, 0);
1052 }
1053
1054
1055
1056 /*
1057 * Places some staircases near walls
1058 */
alloc_stairs(struct worldpos * wpos,int feat,int num,int walls,struct stairs_list * stairs)1059 static void alloc_stairs(struct worldpos *wpos, int feat, int num, int walls, struct stairs_list *stairs) {
1060 int y = 5, x = 5, i, j, flag, tries = 0; /* initialise x,y to kill compiler warnings */
1061 int emergency_flag = TRUE, new_feat = -1, nlev_down = FALSE, nlev_up = FALSE;
1062 int starty, startx;
1063 cave_type *c_ptr;
1064 cave_type **zcave;
1065 struct stairs_list *sptr = stairs;
1066 bool stairs_store = FALSE, stairs_check = FALSE;
1067
1068 #ifdef NETHERREALM_BOTTOM_RESTRICT
1069 if (netherrealm_bottom(wpos)) return;
1070 #endif
1071
1072 if (!(zcave = getcave(wpos))) return;
1073
1074 /* for Nether Realm: store stairs to 'stairs' array, or check them against it? */
1075 if (stairs) {
1076 if (wpos->wz < 1) {
1077 if (feat == FEAT_MORE || feat == FEAT_WAY_MORE) stairs_store = TRUE;
1078 else stairs_check = TRUE;
1079 } else if (feat == FEAT_LESS || feat == FEAT_WAY_LESS) stairs_store = TRUE;
1080 else stairs_check = TRUE;
1081
1082 /* advance to first free element */
1083 if (stairs_store) {
1084 while (sptr->x != -1 && sptr->y != -1) sptr++;
1085 /* out of available array entries? */
1086 if (sptr->y == -1) {
1087 //s_printf("-no more stairs-\n");
1088 stairs_store = FALSE;
1089 }
1090 }
1091 #if 0 //DEBUG CODE
1092 if (stairs_store) s_printf("stairs_store\n");
1093 if (stairs_check) {
1094 sptr = stairs;
1095 s_printf("stairs_check\n");
1096 while (sptr->x != -1 && sptr->y != -1) {
1097 s_printf(" stairs x,y = %d,%d\n", sptr->x, sptr->y);
1098 sptr++;
1099 }
1100 }
1101 #endif
1102 }
1103
1104 /* Town -- must go down */
1105 if (!can_go_up_simple(wpos)) {
1106 /* Clear previous contents, add down stairs */
1107 if (can_go_down(wpos, 0x1)) new_feat = FEAT_MORE;
1108 if (!istown(wpos)) nlev_up = TRUE;
1109 }
1110 /* Quest -- must go up */
1111 else if (is_xorder(wpos) || !can_go_down_simple(wpos)) {
1112 /* Clear previous contents, add up stairs */
1113 if (can_go_up(wpos, 0x1)) new_feat = FEAT_LESS;
1114 /* Set this to be the starting location for people going down */
1115 nlev_down = TRUE;
1116 }
1117 /* Requested type */
1118 else {
1119 /* Clear previous contents, add stairs */
1120 if ((can_go_up(wpos, 0x1) && (feat == FEAT_LESS || feat == FEAT_WAY_LESS)) ||
1121 (can_go_down(wpos, 0x1) && (feat == FEAT_MORE || feat == FEAT_WAY_MORE)))
1122 new_feat = feat;
1123
1124 if (feat == FEAT_LESS || feat == FEAT_WAY_LESS) {
1125 /* Set this to be the starting location for people going down */
1126 nlev_down = TRUE;
1127 }
1128 if (feat == FEAT_MORE || feat == FEAT_WAY_MORE) {
1129 /* Set this to be the starting location for people going up */
1130 nlev_up = TRUE;
1131 }
1132 }
1133
1134 /* Place "num" stairs */
1135 for (i = 0; i < num; i++) {
1136 tries = 1000; /* don't hang again. extremely rare though. wonder what the situation was like. */
1137
1138 /* Place some stairs */
1139 for (flag = FALSE; !flag && tries; tries--) {
1140 /* Try several times, then decrease "walls" */
1141 for (j = 0; !flag && j <= 3000; j++) {
1142 /* Pick a random grid */
1143 y = 1 + rand_int(dun->l_ptr->hgt - 2);
1144 x = 1 + rand_int(dun->l_ptr->wid - 2);
1145
1146 /* Require "naked" floor grid */
1147 if (!cave_naked_bold(zcave, y, x)) continue;
1148
1149 /* No stairs that lead into nests/pits */
1150 if (zcave[y][x].info & CAVE_NEST_PIT) continue;
1151
1152 /* Require a certain number of adjacent walls */
1153 if (next_to_walls(wpos, y, x) < walls) continue;
1154
1155 if (stairs_check) {
1156 bool bad = FALSE;
1157
1158 sptr = stairs;
1159 while (sptr->x != -1 && sptr->y != -1 && j < 3000) {
1160 if (distance(sptr->y, sptr->x, y, x) < 100 - j / 75) { /* assume max-sized map (Nether Realm) */
1161 bad = TRUE;
1162 break;
1163 }
1164 sptr++;
1165 }
1166 if (bad) continue;
1167 //if (j == 3000) s_printf(" sptr full fail\n");
1168 //else s_printf(" sptr OK %d,%d\n", x,y);
1169 }
1170
1171 /* Access the grid */
1172 c_ptr = &zcave[y][x];
1173
1174 if (new_feat != -1) {
1175 c_ptr->feat = new_feat;
1176 aquatic_terrain_hack(zcave, x, y);
1177
1178 if (stairs_store) {
1179 sptr->x = x;
1180 sptr->y = y;
1181 sptr++;
1182 /* no more array space? */
1183 if (sptr->y == -1) stairs_store = FALSE;
1184 }
1185 }
1186 if (nlev_up) {
1187 new_level_up_y(wpos, y);
1188 new_level_up_x(wpos, x);
1189 }
1190 if (nlev_down) {
1191 new_level_down_y(wpos, y);
1192 new_level_down_x(wpos, x);
1193 }
1194
1195 /* All done */
1196 flag = TRUE;
1197 emergency_flag = FALSE;
1198 }
1199
1200 /* Require fewer walls */
1201 if (walls) walls--;
1202 }
1203 #if 0 /* taken are of in cave_gen(), calling this function */
1204 /* no staircase spam in general, one per alloc_stairs() is enough */
1205 if (flag && netherrealm_bottom(wpos)) return;
1206 #endif
1207 }
1208
1209 if (!emergency_flag) return;
1210 s_printf("Staircase-generation emergency at (%d, %d, %d)\n", wpos->wx, wpos->wy, wpos->wz);
1211 /* Emergency! We were unable to place a staircase.
1212 This can happen if a huge vault nearly completely fills out a level */
1213 /* note: tries == 0 here, actually, from above code */
1214
1215 /* note: if we reach 10000 tries now, we just accept the grid anyway! */
1216 do {
1217 starty = rand_int(dun->l_ptr->hgt - 2) + 1;
1218 startx = rand_int(dun->l_ptr->wid - 2) + 1;
1219 } while (!cave_floor_bold(zcave, starty, startx) && (++tries < 10000));
1220
1221 c_ptr = &zcave[starty][startx];
1222 if (new_feat != -1) {
1223 c_ptr->feat = new_feat;
1224
1225 if (stairs_store) {
1226 sptr->x = x;
1227 sptr->y = y;
1228 sptr++;
1229 /* no more array space? */
1230 if (sptr->y == -1) stairs_store = FALSE;
1231 }
1232 }
1233 if (nlev_up) {
1234 new_level_up_y(wpos, starty);
1235 new_level_up_x(wpos, startx);
1236 }
1237 if (nlev_down) {
1238 new_level_down_y(wpos, starty);
1239 new_level_down_x(wpos, startx);
1240 }
1241 }
1242
1243
1244
1245
1246 /*
1247 * Allocates some objects (using "place" and "type")
1248 */
alloc_object(struct worldpos * wpos,int set,int typ,int num,player_type * p_ptr)1249 static void alloc_object(struct worldpos *wpos, int set, int typ, int num, player_type *p_ptr)
1250 {
1251 int y, x, k;
1252 int try = 1000;
1253 cave_type **zcave;
1254 if(!(zcave = getcave(wpos))) return;
1255
1256 #ifdef RPG_SERVER /* no objects are generated in Training Tower */
1257 if (in_trainingtower(wpos) && level_generation_time) return;
1258 #endif
1259
1260 /* Place some objects */
1261 for (k = 0; k < num; k++) {
1262 /* Pick a "legal" spot */
1263 while (TRUE) {
1264 bool room;
1265
1266 if (!--try) {
1267 #if DEBUG_LEVEL > 1
1268 s_printf("alloc_object failed!\n");
1269 #endif /* DEBUG_LEVEL */
1270 return;
1271 }
1272
1273 /* Location */
1274 y = rand_int(dun->l_ptr->hgt);
1275 x = rand_int(dun->l_ptr->wid);
1276
1277 /* Require "naked" floor grid */
1278 if (!cave_naked_bold(zcave, y, x)) continue;
1279
1280 /* Hack -- avoid doors */
1281 if (typ != ALLOC_TYP_TRAP &&
1282 f_info[zcave[y][x].feat].flags1 & FF1_DOOR)
1283 continue;
1284
1285 /* Check for "room" */
1286 room = (zcave[y][x].info & CAVE_ROOM) ? TRUE : FALSE;
1287
1288 /* Require corridor? */
1289 if ((set == ALLOC_SET_CORR) && room) continue;
1290
1291 /* Require room? */
1292 if ((set == ALLOC_SET_ROOM) && !room) continue;
1293
1294 /* Accept it */
1295 break;
1296 }
1297
1298 /* Place something */
1299 switch (typ) {
1300 case ALLOC_TYP_RUBBLE:
1301 place_rubble(wpos, y, x);
1302 break;
1303
1304 case ALLOC_TYP_TRAP:
1305 place_trap(wpos, y, x, 0);
1306 break;
1307
1308 case ALLOC_TYP_GOLD:
1309 place_gold(wpos, y, x, 0);
1310 /* hack -- trap can be hidden under gold */
1311 if (rand_int(100) < 3) place_trap(wpos, y, x, 0);
1312 break;
1313
1314 case ALLOC_TYP_OBJECT:
1315 place_object(wpos, y, x, FALSE, FALSE, FALSE, make_resf(p_ptr), default_obj_theme, 0, ITEM_REMOVAL_NEVER);
1316 /* hack -- trap can be hidden under an item */
1317 if (rand_int(100) < 2) place_trap(wpos, y, x, 0);
1318 break;
1319
1320 #if 0
1321 case ALLOC_TYP_ALTAR:
1322 place_altar(wpos, y, x);
1323 break;
1324 #endif /* 0 */
1325
1326 case ALLOC_TYP_BETWEEN:
1327 place_between(wpos, y, x);
1328 break;
1329
1330 case ALLOC_TYP_FOUNTAIN:
1331 place_fountain(wpos, y, x);
1332 break;
1333
1334 case ALLOC_TYP_FOUNTAIN_OF_BLOOD:
1335 /* this actually means "allocate SOME fountains of blood,
1336 while keeping most of them normal ones" ;) - C. Blue */
1337 if (!rand_int(3)) place_fountain_of_blood(wpos, y, x);
1338 else place_fountain(wpos, y, x);
1339 break;
1340 }
1341 }
1342 }
1343
1344 /*
1345 * Helper function for "monster nest (undead)"
1346 */
vault_aux_aquatic(int r_idx)1347 static bool vault_aux_aquatic(int r_idx)
1348 {
1349 monster_race *r_ptr = &r_info[r_idx];
1350
1351 /* Decline unique monsters */
1352 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1353
1354 /* Require Aquatique */
1355 if (!(r_ptr->flags7 & RF7_AQUATIC)) return (FALSE);
1356
1357 /* Okay */
1358 return (TRUE);
1359 }
1360
1361 /*
1362 * Places "streamers" of rock through dungeon
1363 *
1364 * Note that their are actually six different terrain features used
1365 * to represent streamers. Three each of magma and quartz, one for
1366 * basic vein, one with hidden gold, and one with known gold. The
1367 * hidden gold types are currently unused.
1368 */
build_streamer(struct worldpos * wpos,int feat,int chance,bool pierce)1369 static void build_streamer(struct worldpos *wpos, int feat, int chance, bool pierce) {
1370 int i, tx, ty, tries = 1000;
1371 int y, x, dir;
1372 cave_type *c_ptr;
1373
1374 dungeon_type *dt_ptr = getdungeon(wpos);
1375 struct c_special *cs_ptr;
1376 cave_type **zcave;
1377 int dun_type;
1378
1379 #ifdef IRONDEEPDIVE_MIXED_TYPES
1380 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
1381 else
1382 #endif
1383 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
1384
1385 if (!(zcave = getcave(wpos))) return;
1386
1387 #if 1
1388 /* hard-coded hack: Training Tower has no streamers, only built granite walls */
1389 if (in_trainingtower(wpos))
1390 return;
1391 #else
1392 /* hard-coded hack: Training Tower streamers have no treasure */
1393 if (in_trainingtower(wpos))
1394 chance = 0;
1395 #endif
1396
1397 /* Hack -- Choose starting point */
1398 while (TRUE) {
1399 y = rand_spread(dun->l_ptr->hgt / 2, 10);
1400 x = rand_spread(dun->l_ptr->wid / 2, 15);
1401
1402 if (in_bounds4(dun->l_ptr, y, x)) break;
1403
1404 if (tries-- == 0) return;
1405 }
1406
1407 /* Choose a random compass direction */
1408 dir = ddd[rand_int(8)];
1409
1410 /* Place streamer into dungeon */
1411 while (TRUE) {
1412 /* One grid per density */
1413 for (i = 0; i < DUN_STR_DEN; i++) {
1414
1415 int d = DUN_STR_RNG;
1416
1417 /* Pick a nearby grid */
1418 tries = 1000;
1419 while (TRUE) {
1420 ty = rand_spread(y, d);
1421 tx = rand_spread(x, d);
1422 if (in_bounds4(dun->l_ptr, ty, tx)) break;
1423 if (tries-- == 0) return;
1424 }
1425
1426 /* Access the grid */
1427 c_ptr = &zcave[ty][tx];
1428
1429 /* Only convert "granite" walls */
1430 if (pierce) {
1431 if (cave_perma_bold(zcave, ty, tx)) continue;
1432 } else {
1433 /* Only convert "granite" walls */
1434 if (!(c_ptr->feat == feat_wall_inner) &&
1435 !(c_ptr->feat == feat_wall_outer) &&
1436 !(c_ptr->feat == d_info[dun_type].fill_type[0]) &&
1437 !(c_ptr->feat == d_info[dun_type].fill_type[1]) &&
1438 !(c_ptr->feat == d_info[dun_type].fill_type[2]) &&
1439 #ifdef IRONDEEPDIVE_MIXED_TYPES
1440 !(c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 0) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[3]) &&
1441 !(c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 1) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[4]))
1442 #else
1443 !(c_ptr->feat == d_info[dun_type].fill_type[3]) &&
1444 !(c_ptr->feat == d_info[dun_type].fill_type[4]))
1445 #endif
1446 continue;
1447
1448 #if 0
1449 if (c_ptr->feat < FEAT_WALL_EXTRA) continue;
1450 if (c_ptr->feat > FEAT_WALL_SOLID) continue;
1451 #endif /* 0 */
1452 }
1453
1454 if (dun->no_penetr && c_ptr->info & CAVE_ICKY) continue;
1455
1456 /* Clear mimic feature to avoid nasty consequences */
1457 if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
1458 cs_erase(c_ptr, cs_ptr);
1459
1460 /* Clear previous contents, add proper vein type */
1461 c_ptr->feat = feat;
1462
1463 /* Hack -- Add some (known) treasure */
1464 /* XXX seemingly it was ToME bug */
1465 if (chance && rand_int(chance) == 0)
1466 /* turn into FEAT_SANDWALL_K / FEAT_MAGMA_K / FEAT_QUARTZ_K: */
1467 c_ptr->feat += (c_ptr->feat == FEAT_SANDWALL ? 0x2 : 0x4);
1468 }
1469
1470 #if 0
1471 /* Hack^2 - place watery monsters */
1472 if (feat == FEAT_DEEP_WATER && magik(2)) vault_monsters(wpos, y, x, 1);
1473 #endif
1474
1475 /* Advance the streamer */
1476 y += ddy[dir];
1477 x += ddx[dir];
1478
1479
1480 /* Quit before leaving the dungeon */
1481 if (!in_bounds4(dun->l_ptr, y, x)) break;
1482 }
1483 }
1484
1485
1486 /*
1487 * Place streams of water, lava, & trees -KMW-
1488 * This routine varies the placement based on dungeon level
1489 * otherwise is similar to build_streamer
1490 */
build_streamer2(worldpos * wpos,int feat,int killwall)1491 static void build_streamer2(worldpos *wpos, int feat, int killwall) {
1492 int i, j, mid, tx, ty, tries = 1000;
1493 int y, x, dir;
1494 int poolchance;
1495 int poolsize;
1496 cave_type *c_ptr;
1497 struct c_special *cs_ptr;
1498 cave_type **zcave;
1499
1500 #if 0
1501 dungeon_type *dt_ptr = getdungeon(wpos);
1502 int dun_type;
1503
1504 #ifdef IRONDEEPDIVE_MIXED_TYPES
1505 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
1506 else
1507 #endif
1508 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
1509 #endif /* 0 */
1510
1511 if (!(zcave = getcave(wpos))) return;
1512
1513 poolchance = randint(10);
1514
1515 /* Hack -- Choose starting point */
1516 while (TRUE) {
1517 y = rand_spread(dun->l_ptr->hgt / 2, 10);
1518 x = rand_spread(dun->l_ptr->wid / 2, 15);
1519
1520 if (in_bounds4(dun->l_ptr, y, x)) break;
1521 if (!tries--) return;
1522 }
1523
1524 /* Choose a random compass direction */
1525 dir = ddd[rand_int(8)];
1526
1527 /* Place streamer into dungeon */
1528 if (poolchance > 2) {
1529 while (TRUE) {
1530 /* One grid per density */
1531 for (i = 0; i < (DUN_STR_DWLW + 1); i++) {
1532
1533 int d = DUN_STR_WLW;
1534
1535 /* Pick a nearby grid */
1536 tries = 1000;
1537 while (TRUE) {
1538 ty = rand_spread(y, d);
1539 tx = rand_spread(x, d);
1540 if (in_bounds4(dun->l_ptr, ty, tx)) break;
1541 if (!tries--) return;
1542 }
1543
1544 /* Access grid */
1545 c_ptr = &zcave[ty][tx];
1546
1547 /* Never convert vaults */
1548 if (c_ptr->info & (CAVE_ICKY)) continue;
1549
1550 /* Reject permanent features */
1551 if ((f_info[c_ptr->feat].flags1 & (FF1_PERMANENT)) &&
1552 (f_info[c_ptr->feat].flags1 & (FF1_FLOOR))) continue;
1553
1554 /* Avoid converting walls when told so */
1555 if (killwall == 0)
1556 if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
1557
1558 /* Clear mimic feature to avoid nasty consequences */
1559 if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
1560 cs_erase(c_ptr, cs_ptr);
1561
1562 /* Clear previous contents, add proper vein type */
1563 cave_set_feat(wpos, ty, tx, feat);
1564 }
1565
1566 /* Advance the streamer */
1567 y += ddy[dir];
1568 x += ddx[dir];
1569
1570 /* Change direction */
1571 if (rand_int(20) == 0) dir = ddd[rand_int(8)];
1572
1573 /* Stop at dungeon edge */
1574 if (!in_bounds4(dun->l_ptr, y, x)) break;
1575 }
1576 }
1577
1578 /* Create pool */
1579 else if ((feat == FEAT_DEEP_WATER) || (feat == FEAT_DEEP_LAVA)) {
1580 poolsize = 5 + randint(10);
1581 mid = poolsize / 2;
1582
1583 /* One grid per density */
1584 for (i = 0; i < poolsize; i++) {
1585 for (j = 0; j < poolsize; j++) {
1586 tx = x + j;
1587 ty = y + i;
1588
1589 if (!in_bounds4(dun->l_ptr, ty, tx)) continue;
1590
1591 if (i < mid) {
1592 if (j < mid) {
1593 if ((i + j + 1) < mid) continue;
1594 }
1595 else if (j > (mid+ i)) continue;
1596 }
1597 else if (j < mid)
1598 {
1599 if (i > (mid + j))
1600 continue;
1601 }
1602 else if ((i + j) > ((mid * 3)-1))
1603 continue;
1604
1605 c_ptr = &zcave[ty][tx];
1606
1607 /* Only convert non-permanent features */
1608 if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) continue;
1609
1610
1611 /* Clear mimic feature to avoid nasty consequences */
1612 if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
1613 cs_erase(c_ptr, cs_ptr);
1614
1615 /* Clear previous contents, add proper vein type */
1616 cave_set_feat(wpos, ty, tx, feat);
1617 }
1618 }
1619 }
1620 }
1621
1622
1623 #if 0
1624 int dist2(int x1, int y1, int x2, int y2, int h1, int h2, int h3, int h4)
1625 /*
1626 * Build an underground lake
1627 */
1628 static void lake_level(struct worldpos *wpos)
1629 {
1630 int y1, x1, y, x, k, t, n, rad;
1631 int h1, h2, h3, h4;
1632 bool distort = FALSE;
1633 cave_type *c_ptr;
1634
1635 cave_type **zcave;
1636 if (!(zcave = getcave(wpos))) return;
1637
1638 /* Drop a few epi-centers (usually about two) */
1639 for (n = 0; n < DUN_LAKE_TRY; n++)
1640 {
1641 /* Pick an epi-center */
1642 y1 = rand_range(5, dun->l_ptr->hgt - 6);
1643 x1 = rand_range(5, dun->l_ptr->wid - 6);
1644
1645 /* Access the grid */
1646 c_ptr = &zcave[y1][x1];
1647
1648 if (c_ptr->feat != FEAT_DEEP_WATER) continue;
1649
1650 rad = rand_range(8, 18);
1651 distort = magik(50 - rad * 2);
1652
1653 /* (Warning killer) */
1654 h1 = h2 = h3 = h4 = 0;
1655
1656 if (distort)
1657 {
1658 /* Make a random metric */
1659 h1 = randint(32) - 16;
1660 h2 = randint(16);
1661 h3 = randint(32);
1662 h4 = randint(32) - 16;
1663 }
1664
1665 /* Big area of affect */
1666 for (y = (y1 - rad); y <= (y1 + rad); y++)
1667 {
1668 for (x = (x1 - rad); x <= (x1 + rad); x++)
1669 {
1670 /* Skip illegal grids */
1671 if (!in_bounds(y, x)) continue;
1672
1673 /* Extract the distance */
1674 k = distort ? dist2(y1, x1, y, x, h1, h2, h3, h4) :
1675 distance(y1, x1, y, x);
1676
1677 /* Stay in the circle of death */
1678 if (k > rad) continue;
1679
1680 #if 0
1681 /* Delete the monster (if any) */
1682 delete_monster(wpos, y, x, TRUE);
1683 #endif
1684
1685 /* Destroy valid grids */
1686 if (cave_valid_bold(zcave, y, x))
1687 {
1688 #if 0
1689 /* Delete the object (if any) */
1690 delete_object(wpos, y, x, TRUE);
1691 #endif
1692
1693 /* Access the grid */
1694 c_ptr = &zcave[y][x];
1695
1696 /* Wall (or floor) type */
1697 t = rand_int(200);
1698
1699 /* Water */
1700 if (t < 174)
1701 {
1702 /* Create granite wall */
1703 c_ptr->feat = FEAT_DEEP_WATER;
1704 }
1705 else if (t < 180)
1706 {
1707 /* Create dirt */
1708 c_ptr->feat = FEAT_DIRT;
1709 }
1710 else if (t < 182)
1711 {
1712 /* Create dirt */
1713 c_ptr->feat = FEAT_MUD;
1714 }
1715
1716 /* No longer part of a room or vault */
1717 c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
1718
1719 /* No longer illuminated or known */
1720 c_ptr->info &= ~CAVE_GLOW;
1721 }
1722 }
1723 }
1724 break;
1725 }
1726 }
1727 #endif /* 0 */
1728
1729
1730 /*
1731 * Build a destroyed level
1732 */
destroy_level(struct worldpos * wpos)1733 static void destroy_level(struct worldpos *wpos) {
1734 int y1, x1, y, x, k, t, n;
1735 cave_type *c_ptr;
1736
1737 cave_type **zcave;
1738 if (!(zcave = getcave(wpos))) return;
1739
1740 /* Drop a few epi-centers (usually about two) */
1741 for (n = 0; n < randint(5); n++) {
1742 /* Pick an epi-center */
1743 y1 = rand_range(5, dun->l_ptr->hgt - 6);
1744 x1 = rand_range(5, dun->l_ptr->wid - 6);
1745
1746 /* Big area of affect */
1747 for (y = (y1 - 15); y <= (y1 + 15); y++) {
1748 for (x = (x1 - 15); x <= (x1 + 15); x++) {
1749 /* Skip illegal grids */
1750 if (!in_bounds(y, x)) continue;
1751
1752 /* Extract the distance */
1753 k = distance(y1, x1, y, x);
1754
1755 /* Stay in the circle of death */
1756 if (k >= 16) continue;
1757
1758 /* Delete the monster (if any) */
1759 delete_monster(wpos, y, x, TRUE);
1760
1761 /* Destroy valid grids */
1762 if (cave_valid_bold(zcave, y, x)) {
1763 /* Delete the object (if any) */
1764 delete_object(wpos, y, x, TRUE);
1765
1766 /* Access the grid */
1767 c_ptr = &zcave[y][x];
1768
1769 /* Wall (or floor) type */
1770 t = rand_int(200);
1771
1772 /* Granite */
1773 if (t < 20)
1774 /* Create granite wall */
1775 c_ptr->feat = FEAT_WALL_EXTRA;
1776
1777 /* Quartz */
1778 else if (t < 70)
1779 /* Create quartz vein */
1780 c_ptr->feat = FEAT_QUARTZ;
1781
1782 /* Magma */
1783 else if (t < 100)
1784 /* Create magma vein */
1785 c_ptr->feat = FEAT_MAGMA;
1786
1787 /* Floor */
1788 else
1789 /* Create floor */
1790 place_floor(wpos, y, x);
1791
1792 /* No longer part of a room or vault */
1793 c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
1794
1795 /* No longer illuminated or known */
1796 c_ptr->info &= ~CAVE_GLOW;
1797 }
1798 }
1799 }
1800 }
1801 }
1802
1803
1804
1805 /*
1806 * Create up to "num" objects near the given coordinates
1807 * Only really called by some of the "vault" routines.
1808 */
vault_objects(struct worldpos * wpos,int y,int x,int num,player_type * p_ptr)1809 static void vault_objects(struct worldpos *wpos, int y, int x, int num, player_type *p_ptr) {
1810 int i, j, k, tries = 1000;
1811 cave_type **zcave;
1812 u32b resf = make_resf(p_ptr);
1813 if (!(zcave = getcave(wpos))) return;
1814
1815 /* Attempt to place 'num' objects */
1816 for (; num > 0; --num) {
1817 /* Try up to 11 spots looking for empty space */
1818 for (i = 0; i < 11; ++i) {
1819 /* Pick a random location */
1820 while (TRUE) {
1821 j = rand_spread(y, 2);
1822 k = rand_spread(x, 3);
1823 if (!in_bounds(j, k)) continue;
1824 if (!tries--) return;
1825 break;
1826 }
1827
1828 /* Require "clean" floor space */
1829 if (!cave_clean_bold(zcave, j, k)) continue;
1830
1831 /* Place an item */
1832 if (rand_int(100) < 75)
1833 place_object(wpos, j, k, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
1834
1835 /* Place gold */
1836 else
1837 place_gold(wpos, j, k, 0);
1838
1839 /* Placement accomplished */
1840 break;
1841 }
1842 }
1843 }
1844
1845
1846 /*
1847 * Place a trap with a given displacement of point
1848 */
vault_trap_aux(struct worldpos * wpos,int y,int x,int yd,int xd)1849 static void vault_trap_aux(struct worldpos *wpos, int y, int x, int yd, int xd) {
1850 int count, y1, x1, tries = 1000;
1851 cave_type **zcave;
1852 if (!(zcave = getcave(wpos))) return;
1853
1854 /* Place traps */
1855 for (count = 0; count <= 5; count++) {
1856 /* Get a location */
1857 while (TRUE) {
1858 y1 = rand_spread(y, yd);
1859 x1 = rand_spread(x, xd);
1860 if (!in_bounds(y1, x1)) continue;
1861 if (!tries--) return;
1862 break;
1863 }
1864
1865 /* Place the trap */
1866 place_trap(wpos, y1, x1, 0);
1867
1868 /* Done */
1869 break;
1870 }
1871 }
1872
1873
1874 /*
1875 * Place some traps with a given displacement of given location
1876 */
vault_traps(struct worldpos * wpos,int y,int x,int yd,int xd,int num)1877 static void vault_traps(struct worldpos *wpos, int y, int x, int yd, int xd, int num) {
1878 int i;
1879
1880 for (i = 0; i < num; i++)
1881 vault_trap_aux(wpos, y, x, yd, xd);
1882 }
1883
1884
1885 /*
1886 * Hack -- Place some sleeping monsters near the given location
1887 */
vault_monsters(struct worldpos * wpos,int y1,int x1,int num)1888 static void vault_monsters(struct worldpos *wpos, int y1, int x1, int num) {
1889 int k, i, y, x;
1890 cave_type **zcave;
1891 int dun_lev;
1892
1893 if (!(zcave = getcave(wpos))) return;
1894 dun_lev = getlevel(wpos);
1895
1896 #ifdef ARCADE_SERVER
1897 if (in_trainingtower(wpos)) return;
1898 #endif
1899
1900 /* Try to summon "num" monsters "near" the given location */
1901 for (k = 0; k < num; k++) {
1902 /* Try nine locations */
1903 for (i = 0; i < 9; i++) {
1904 int d = 1;
1905
1906 /* Pick a nearby location */
1907 scatter(wpos, &y, &x, y1, x1, d, 0);
1908
1909 /* Require "empty" floor grids */
1910 if (!cave_empty_bold(zcave, y, x)) continue;
1911
1912 /* Place the monster (allow groups) */
1913 monster_level = dun_lev + 2;
1914 (void)place_monster(wpos, y, x, TRUE, TRUE);
1915 monster_level = dun_lev;
1916 }
1917 }
1918 }
1919
1920
1921 /* XXX XXX Here begins a big lump of ToME cake - Jir - */
1922 /* XXX part I -- generic functions */
1923
1924
1925 /*
1926 * Place a cave filler at (y, x)
1927 */
place_filler(worldpos * wpos,int y,int x)1928 static void place_filler(worldpos *wpos, int y, int x) {
1929 cave_set_feat(wpos, y, x, fill_type[rand_int(1000)]);
1930 }
1931
1932 /*
1933 * Place floor terrain at (y, x) according to dungeon info
1934 */
1935 /* XXX this function can produce strange results when called
1936 * outside of generate.c */
place_floor(worldpos * wpos,int y,int x)1937 void place_floor(worldpos *wpos, int y, int x) {
1938 cave_set_feat(wpos, y, x, floor_type[rand_int(1000)]);
1939 }
place_floor_live(worldpos * wpos,int y,int x)1940 void place_floor_live(worldpos *wpos, int y, int x) {
1941 cave_set_feat_live(wpos, y, x, floor_type[rand_int(1000)]);
1942 }
1943
1944 /*
1945 * Place floor terrain at (y, x) according to dungeon info
1946 * NOTE: Currently ONLY used for 'maze' levels!
1947 For that reason, it contains a hack preventing un-walling
1948 any vaults, to keep them sane. - C. Blue
1949 */
place_floor_respectedly(worldpos * wpos,int y,int x)1950 static void place_floor_respectedly(worldpos *wpos, int y, int x) {
1951 cave_type **zcave;
1952 if (!(zcave = getcave(wpos))) return;
1953
1954 #ifndef VAULTS_OVERRIDE_MAZE /* this is actually 'normal', but we need a hack since we allow room/vault generation in mazes currently */
1955 if (dun->no_penetr && zcave[y][x].info & CAVE_ICKY) return;
1956 #else /* ..and here it is: no harming of vault walls at all */
1957 if (zcave[y][x].info & CAVE_ICKY) return; /* works fine */
1958 // if (zcave[y][x].info & CAVE_NEST_PIT) return; /* no effect, because the limiting walls don't have the flag actually. Also, accessibility unclear? */
1959 // if (zcave[y][x].info & CAVE_ROOM) return; /* lacks door generation! Rooms won't be accessible (although otherwise fine) */
1960 #endif
1961 cave_set_feat(wpos, y, x, floor_type[rand_int(1000)]);
1962 }
1963
1964 /*
1965 * Function that sees if a square is a floor (Includes range checking)
1966 */
get_is_floor(worldpos * wpos,int x,int y)1967 static bool get_is_floor(worldpos *wpos, int x, int y)
1968 {
1969 cave_type **zcave;
1970 if (!(zcave = getcave(wpos))) return(FALSE);
1971
1972 /* Out of bounds */
1973 if (!in_bounds(y, x)) return (FALSE); /* XXX */
1974
1975 /* Do the real check: */
1976 if (f_info[zcave[y][x].feat].flags1 & FF1_FLOOR) return (TRUE);
1977 #if 0
1978 if (zcave[y][x].feat == FEAT_FLOOR ||
1979 zcave[y][x].feat == FEAT_DEEP_WATER) return (TRUE);
1980 #endif /* 0 */
1981
1982 return (FALSE);
1983 }
1984
1985 /*
1986 * Tunnel around a room if it will cut off part of a cave system
1987 */
check_room_boundary(worldpos * wpos,int x1,int y1,int x2,int y2)1988 static void check_room_boundary(worldpos *wpos, int x1, int y1, int x2, int y2)
1989 {
1990 int count, x, y;
1991 bool old_is_floor, new_is_floor;
1992
1993 cave_type **zcave;
1994 if (!(zcave = getcave(wpos))) return;
1995
1996 #if 0
1997 /* Avoid doing this in irrelevant places -- pelpel */
1998 if (!(d_info[dungeon_type].flags1 & DF1_CAVERN)) return;
1999 #endif
2000
2001 /* Initialize */
2002 count = 0;
2003
2004 old_is_floor = get_is_floor(wpos, x1 - 1, y1);
2005
2006 /*
2007 * Count the number of floor-wall boundaries around the room
2008 * Note: diagonal squares are ignored since the player can move diagonally
2009 * to bypass these if needed.
2010 */
2011
2012 /* Above the top boundary */
2013 for (x = x1; x <= x2; x++)
2014 {
2015 new_is_floor = get_is_floor(wpos, x, y1 - 1);
2016
2017 /* increment counter if they are different */
2018 if (new_is_floor != old_is_floor) count++;
2019
2020 old_is_floor = new_is_floor;
2021 }
2022
2023 /* Right boundary */
2024 for (y = y1; y <= y2; y++)
2025 {
2026 new_is_floor = get_is_floor(wpos, x2 + 1, y);
2027
2028 /* increment counter if they are different */
2029 if (new_is_floor != old_is_floor) count++;
2030
2031 old_is_floor = new_is_floor;
2032 }
2033
2034 /* Bottom boundary*/
2035 for (x = x2; x >= x1; x--)
2036 {
2037 new_is_floor = get_is_floor(wpos, x, y2 + 1);
2038
2039 /* Increment counter if they are different */
2040 if (new_is_floor != old_is_floor) count++;
2041
2042 old_is_floor = new_is_floor;
2043 }
2044
2045 /* Left boundary */
2046 for (y = y2; y >= y1; y--)
2047 {
2048 new_is_floor = get_is_floor(wpos, x1 - 1, y);
2049
2050 /* Increment counter if they are different */
2051 if (new_is_floor != old_is_floor) count++;
2052
2053 old_is_floor = new_is_floor;
2054 }
2055
2056
2057 /* If all the same, or only one connection exit */
2058 if ((count == 0) || (count == 2)) return;
2059
2060
2061 /* Tunnel around the room so to prevent problems with caves */
2062 for (y = y1; y <= y2; y++)
2063 {
2064 for (x = x1; x <= x2; x++)
2065 {
2066 if (in_bounds(y, x)) place_floor(wpos, y, x);
2067 }
2068 }
2069 }
2070
2071
2072 /*
2073 * Allocate the space needed by a room in the room_map array.
2074 *
2075 * x, y represent the size of the room (0...x-1) by (0...y-1).
2076 * crowded is used to denote a monset nest.
2077 * by0, bx0 are the positions in the room_map array given to the build_type'x'
2078 * function.
2079 * xx, yy are the returned center of the allocated room in coordinates for
2080 * cave.feat and cave.info etc.
2081 */
room_alloc(worldpos * wpos,int x,int y,bool crowded,int by0,int bx0,int * xx,int * yy)2082 bool room_alloc(worldpos *wpos, int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
2083 {
2084 int temp, bx1, bx2, by1, by2, by, bx;
2085
2086
2087 /* Calculate number of room_map squares to allocate */
2088
2089 /* Total number along width */
2090 temp = ((x - 1) / BLOCK_WID) + 1;
2091
2092 /* Ending block */
2093 bx2 = temp / 2 + bx0;
2094
2095 /* Starting block (Note: rounding taken care of here) */
2096 bx1 = bx2 + 1 - temp;
2097
2098
2099 /* Total number along height */
2100 temp = ((y - 1) / BLOCK_HGT) + 1;
2101
2102 /* Ending block */
2103 by2 = temp / 2 + by0;
2104
2105 /* Starting block */
2106 by1 = by2 + 1 - temp;
2107
2108
2109 /* Never run off the screen */
2110 if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
2111 if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
2112
2113 /* Verify open space */
2114 for (by = by1; by <= by2; by++)
2115 {
2116 for (bx = bx1; bx <= bx2; bx++)
2117 {
2118 if (dun->room_map[by][bx]) return (FALSE);
2119 }
2120 }
2121
2122 /*
2123 * It is *extremely* important that the following calculation
2124 * be *exactly* correct to prevent memory errors XXX XXX XXX
2125 */
2126
2127 /* Acquire the location of the room */
2128 *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
2129 *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
2130
2131 /* Save the room location */
2132 if (dun->cent_n < CENT_MAX)
2133 {
2134 dun->cent[dun->cent_n].y = *yy;
2135 dun->cent[dun->cent_n].x = *xx;
2136 dun->cent_n++;
2137 }
2138
2139 /* Reserve some blocks */
2140 for (by = by1; by <= by2; by++)
2141 {
2142 for (bx = bx1; bx <= bx2; bx++)
2143 {
2144 dun->room_map[by][bx] = TRUE;
2145 }
2146 }
2147
2148 /* Count "crowded" rooms */
2149 if (crowded) dun->crowded = TRUE;
2150
2151 /*
2152 * Hack -- See if room will cut off a cavern.
2153 * If so, fix by tunneling outside the room in such a way as
2154 * to conect the caves.
2155 */
2156 check_room_boundary(wpos, *xx - x / 2 - 1, *yy - y / 2 - 1,
2157 *xx + x / 2 + 1, *yy + y / 2 + 1);
2158
2159 /* Success */
2160 return (TRUE);
2161 }
2162
2163
2164 /*
2165 * The following functions create a rectangle (e.g. outer wall of rooms)
2166 */
build_rectangle(worldpos * wpos,int y1,int x1,int y2,int x2,int feat,int info)2167 static void build_rectangle(worldpos *wpos, int y1, int x1, int y2, int x2, int feat, int info)
2168 {
2169 int y, x;
2170
2171 cave_type **zcave;
2172 if (!(zcave = getcave(wpos))) return;
2173
2174 /* Top and bottom boundaries */
2175 for (x = x1; x <= x2; x++)
2176 {
2177 cave_set_feat(wpos, y1, x, feat);
2178 zcave[y1][x].info |= (info);
2179
2180 cave_set_feat(wpos, y2, x, feat);
2181 zcave[y2][x].info |= (info);
2182 }
2183
2184 /* Top and bottom boundaries */
2185 for (y = y1; y <= y2; y++)
2186 {
2187 cave_set_feat(wpos, y, x1, feat);
2188 zcave[y][x1].info |= (info);
2189
2190 cave_set_feat(wpos, y, x2, feat);
2191 zcave[y][x2].info |= (info);
2192 }
2193 }
2194
2195
2196 /*
2197 * Place water through the dungeon using recursive fractal algorithm
2198 *
2199 * Why do those good at math and/or algorithms tend *not* to
2200 * place any spaces around binary operators? I've been always
2201 * wondering. This seems almost a unversal phenomenon...
2202 * Tried to make those conform to the rule, but there may still
2203 * some left untouched...
2204 */
recursive_river(worldpos * wpos,int x1,int y1,int x2,int y2,int feat1,int feat2,int width)2205 static void recursive_river(worldpos *wpos, int x1,int y1, int x2, int y2,
2206 int feat1, int feat2,int width)
2207 {
2208 int dx, dy, length, l, x, y;
2209 int changex, changey;
2210 int ty, tx;
2211
2212 cave_type **zcave;
2213 if (!(zcave = getcave(wpos))) return;
2214
2215
2216 length = distance(x1, y1, x2, y2);
2217
2218 if (length > 4)
2219 {
2220 /*
2221 * Divide path in half and call routine twice.
2222 * There is a small chance of splitting the river
2223 */
2224 dx = (x2 - x1) / 2;
2225 dy = (y2 - y1) / 2;
2226
2227 if (dy != 0)
2228 {
2229 /* perturbation perpendicular to path */
2230 changex = randint(abs(dy)) * 2 - abs(dy);
2231 }
2232 else
2233 {
2234 changex = 0;
2235 }
2236
2237 if (dx != 0)
2238 {
2239 /* perturbation perpendicular to path */
2240 changey = randint(abs(dx)) * 2 - abs(dx);
2241 }
2242 else
2243 {
2244 changey = 0;
2245 }
2246
2247
2248
2249 /* construct river out of two smaller ones */
2250 recursive_river(wpos, x1, y1, x1 + dx + changex, y1 + dy + changey,
2251 feat1, feat2, width);
2252 recursive_river(wpos, x1 + dx + changex, y1 + dy + changey, x2, y2,
2253 feat1, feat2, width);
2254
2255 /* Split the river some of the time -junctions look cool */
2256 if ((width > 0) && (rand_int(DUN_WAT_CHG) == 0))
2257 {
2258 recursive_river(wpos, x1 + dx + changex, y1 + dy + changey,
2259 x1 + 8 * (dx + changex), y1 + 8 * (dy + changey),
2260 feat1, feat2, width - 1);
2261 }
2262 }
2263
2264 /* Actually build the river */
2265 else
2266 {
2267 for (l = 0; l < length; l++)
2268 {
2269 x = x1 + l * (x2 - x1) / length;
2270 y = y1 + l * (y2 - y1) / length;
2271
2272 for (ty = y - width - 1; ty <= y + width + 1; ty++)
2273 {
2274 for (tx = x - width - 1; tx <= x + width + 1; tx++)
2275 {
2276 if (!in_bounds(ty, tx)) continue;
2277
2278 if (zcave[ty][tx].feat == feat1) continue;
2279 if (zcave[ty][tx].feat == feat2) continue;
2280
2281 if (distance(ty, tx, y, x) > rand_spread(width, 1)) continue;
2282
2283 /* Do not convert permanent features */
2284 if (cave_perma_bold(zcave, ty, tx)) continue;
2285
2286 /*
2287 * Clear previous contents, add feature
2288 * The border mainly gets feat2, while the center
2289 * gets feat1
2290 */
2291 if (distance(ty, tx, y, x) > width)
2292 {
2293 cave_set_feat(wpos, ty, tx, feat2);
2294 }
2295 else
2296 {
2297 cave_set_feat(wpos, ty, tx, feat1);
2298 }
2299
2300 /* Lava terrain glows */
2301 if ((feat1 == FEAT_DEEP_LAVA) ||
2302 (feat1 == FEAT_SHAL_LAVA))
2303 {
2304 zcave[ty][tx].info |= CAVE_GLOW;
2305 }
2306
2307 /* Hack -- don't teleport here */
2308 zcave[ty][tx].info |= CAVE_ICKY;
2309 }
2310 }
2311 }
2312 }
2313 }
2314
2315
2316 /*
2317 * Places water through dungeon.
2318 */
add_river(worldpos * wpos,int feat1,int feat2)2319 static void add_river(worldpos *wpos, int feat1, int feat2)
2320 {
2321 struct dun_level *l_ptr = getfloor(wpos);
2322
2323 int y2, x2;
2324 int y1 = 0, x1 = 0, wid;
2325
2326 int cur_hgt = dun->l_ptr->hgt;
2327 int cur_wid = dun->l_ptr->wid;
2328
2329 cave_type **zcave;
2330 if(!(zcave = getcave(wpos))) return;
2331
2332 /* hacks - don't build rivers that are shallower than the actual dungeon floor.. - C. Blue */
2333 if ((l_ptr->flags1 & LF1_DEEP_WATER)) {
2334 if (feat1 == FEAT_SHAL_WATER) feat1 = FEAT_DEEP_WATER;
2335 if (feat2 == FEAT_SHAL_WATER) feat2 = FEAT_DEEP_WATER;
2336 }
2337 if ((l_ptr->flags1 & LF1_DEEP_LAVA)) {
2338 if (feat1 == FEAT_SHAL_LAVA) feat1 = FEAT_DEEP_LAVA;
2339 if (feat2 == FEAT_SHAL_LAVA) feat2 = FEAT_DEEP_LAVA;
2340 }
2341
2342 /* for DIGGING */
2343 if (feat1 == FEAT_SHAL_WATER || feat1 == FEAT_DEEP_WATER ||
2344 feat2 == FEAT_SHAL_WATER || feat2 == FEAT_DEEP_WATER)
2345 l_ptr->flags1 |= LF1_WATER;
2346 if (feat1 == FEAT_SHAL_LAVA || feat1 == FEAT_DEEP_LAVA ||
2347 feat2 == FEAT_SHAL_LAVA || feat2 == FEAT_DEEP_LAVA) {
2348 l_ptr->flags1 |= LF1_LAVA;
2349 s_printf("adding river (%d) %d,%d\n", (l_ptr->flags1 & LF1_DEEP_LAVA) ? 1 : 0, feat1, feat2);
2350 // feat1 = feat2 = FEAT_DEEP_LAVA;
2351 }
2352
2353 /* Hack -- Choose starting point */
2354 y2 = randint(cur_hgt / 2 - 2) + cur_hgt / 2;
2355 x2 = randint(cur_wid / 2 - 2) + cur_wid / 2;
2356
2357 /* Hack -- Choose ending point somewhere on boundary */
2358 switch(randint(4))
2359 {
2360 case 1:
2361 {
2362 /* top boundary */
2363 x1 = randint(cur_wid - 2) + 1;
2364 y1 = 1;
2365 break;
2366 }
2367 case 2:
2368 {
2369 /* left boundary */
2370 x1 = 1;
2371 y1 = randint(cur_hgt - 2) + 1;
2372 break;
2373 }
2374 case 3:
2375 {
2376 /* right boundary */
2377 x1 = cur_wid - 1;
2378 y1 = randint(cur_hgt - 2) + 1;
2379 break;
2380 }
2381 case 4:
2382 {
2383 /* bottom boundary */
2384 x1 = randint(cur_wid - 2) + 1;
2385 y1 = cur_hgt - 1;
2386 break;
2387 }
2388 }
2389 wid = randint(DUN_WAT_RNG);
2390 recursive_river(wpos, x1, y1, x2, y2, feat1, feat2, wid);
2391 }
2392
2393
2394
2395
2396 /*
2397 * Room building routines.
2398 *
2399 * Six basic room types:
2400 * 1 -- normal
2401 * 2 -- overlapping
2402 * 3 -- cross shaped
2403 * 4 -- large room with features
2404 * 5 -- monster nests
2405 * 6 -- monster pits
2406 * 7 -- simple vaults
2407 * 8 -- greater vaults
2408
2409 * 9 -- vertical oval room
2410 * 10 -- fractal cave
2411 * 11 -- random vaults
2412 * 12 -- crypt room
2413 */
2414
2415
2416 /*
2417 * Type 1 -- normal rectangular rooms
2418 */
build_type1(struct worldpos * wpos,int by0,int bx0,player_type * p_ptr)2419 static void build_type1(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
2420 {
2421 int y, x = 1, y2, x2, yval, xval;
2422 int y1, x1, xsize, ysize;
2423
2424 bool light;
2425 cave_type *c_ptr;
2426
2427 cave_type **zcave;
2428 if (!(zcave = getcave(wpos))) return;
2429
2430 /* Choose lite or dark */
2431 light = (getlevel(wpos) <= randint(25)) || magik(2);
2432
2433 #if 0
2434 /* Pick a room size */
2435 y1 = yval - randint(4);
2436 y2 = yval + randint(3);
2437 x1 = xval - randint(11);
2438 x2 = xval + randint(11);
2439 #endif /* 0 */
2440
2441 /* Pick a room size */
2442 y1 = randint(4);
2443 x1 = randint(11);
2444 y2 = randint(3);
2445 x2 = randint(11);
2446
2447 xsize = x1 + x2 + 1;
2448 ysize = y1 + y2 + 1;
2449
2450 /* Try to allocate space for room. If fails, exit */
2451 if (!room_alloc(wpos, xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
2452
2453 /* Get corner values */
2454 y1 = yval - ysize / 2;
2455 x1 = xval - xsize / 2;
2456 y2 = yval + (ysize + 1) / 2;
2457 x2 = xval + (xsize + 1) / 2;
2458
2459 /* evileye - exceeds MAX_WID... causes efence crash */
2460 if ((x2 + 1) >= MAX_WID)
2461 x2 = MAX_WID - 2;
2462 if ((y2 + 1) >= MAX_HGT)
2463 y2 = MAX_HGT - 2;
2464
2465
2466 /* Place a full floor under the room */
2467 for (y = y1 - 1; y <= y2 + 1; y++) {
2468 for (x = x1 - 1; x <= x2 + 1; x++) {
2469 c_ptr = &zcave[y][x];
2470 place_floor(wpos, y, x);
2471 c_ptr->info |= CAVE_ROOM;
2472 if (light) c_ptr->info |= CAVE_GLOW;
2473 }
2474 }
2475
2476 /* Walls around the room */
2477 for (y = y1 - 1; y <= y2 + 1; y++) {
2478 c_ptr = &zcave[y][x1-1];
2479 c_ptr->feat = feat_wall_outer;
2480 c_ptr = &zcave[y][x2+1];
2481 c_ptr->feat = feat_wall_outer;
2482 }
2483 for (x = x1 - 1; x <= x2 + 1; x++) {
2484 c_ptr = &zcave[y1-1][x];
2485 c_ptr->feat = feat_wall_outer;
2486 c_ptr = &zcave[y2+1][x];
2487 c_ptr->feat = feat_wall_outer;
2488 }
2489
2490
2491 /* Hack -- Occasional pillar room */
2492 if (rand_int(20) == 0) {
2493 for (y = y1; y <= y2; y += 2) {
2494 for (x = x1; x <= x2; x += 2) {
2495 c_ptr = &zcave[y][x];
2496 c_ptr->feat = feat_wall_inner;
2497 }
2498 }
2499 }
2500
2501 /* Hack -- Occasional ragged-edge room */
2502 else if (rand_int(50) == 0) {
2503 for (y = y1 + 2; y <= y2 - 2; y += 2) {
2504 c_ptr = &zcave[y][x1];
2505 c_ptr->feat = feat_wall_inner;
2506 c_ptr = &zcave[y][x2];
2507 c_ptr->feat = feat_wall_inner;
2508 }
2509 for (x = x1 + 2; x <= x2 - 2; x += 2) {
2510 c_ptr = &zcave[y1][x];
2511 c_ptr->feat = feat_wall_inner;
2512 c_ptr = &zcave[y2][x];
2513 c_ptr->feat = feat_wall_inner;
2514 }
2515 }
2516 }
2517
2518
2519 /*
2520 * Type 2 -- Overlapping rectangular rooms
2521 */
build_type2(struct worldpos * wpos,int by0,int bx0,player_type * p_ptr)2522 static void build_type2(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
2523 {
2524 int y, x, yval, xval;
2525 int y1a, x1a, y2a, x2a;
2526 int y1b, x1b, y2b, x2b;
2527
2528 bool light;
2529 cave_type *c_ptr;
2530
2531 cave_type **zcave;
2532 if (!(zcave = getcave(wpos))) return;
2533
2534 /* Choose lite or dark */
2535 light = (getlevel(wpos) <= randint(25));
2536
2537 /* Try to allocate space for room. If fails, exit */
2538 if (!room_alloc(wpos, 25, 11, FALSE, by0, bx0, &xval, &yval))return;
2539
2540
2541 /* Determine extents of the first room */
2542 y1a = yval - randint(4);
2543 y2a = yval + randint(3);
2544 x1a = xval - randint(11);
2545 x2a = xval + randint(10);
2546
2547 /* Determine extents of the second room */
2548 y1b = yval - randint(3);
2549 y2b = yval + randint(4);
2550 x1b = xval - randint(10);
2551 x2b = xval + randint(11);
2552
2553 /* Place a full floor for room "a" */
2554 for (y = y1a - 1; y <= y2a + 1; y++)
2555 {
2556 for (x = x1a - 1; x <= x2a + 1; x++)
2557 {
2558 c_ptr = &zcave[y][x];
2559 place_floor(wpos, y, x);
2560 c_ptr->info |= CAVE_ROOM;
2561 if (light) c_ptr->info |= CAVE_GLOW;
2562 }
2563 }
2564
2565 /* Place a full floor for room "b" */
2566 for (y = y1b - 1; y <= y2b + 1; y++)
2567 {
2568 for (x = x1b - 1; x <= x2b + 1; x++)
2569 {
2570 c_ptr = &zcave[y][x];
2571 place_floor(wpos, y, x);
2572 c_ptr->info |= CAVE_ROOM;
2573 if (light) c_ptr->info |= CAVE_GLOW;
2574 }
2575 }
2576
2577
2578 /* Place the walls around room "a" */
2579 for (y = y1a - 1; y <= y2a + 1; y++)
2580 {
2581 c_ptr = &zcave[y][x1a-1];
2582 c_ptr->feat = feat_wall_outer;
2583 c_ptr = &zcave[y][x2a+1];
2584 c_ptr->feat = feat_wall_outer;
2585 }
2586 for (x = x1a - 1; x <= x2a + 1; x++)
2587 {
2588 c_ptr = &zcave[y1a-1][x];
2589 c_ptr->feat = feat_wall_outer;
2590 c_ptr = &zcave[y2a+1][x];
2591 c_ptr->feat = feat_wall_outer;
2592 }
2593
2594 /* Place the walls around room "b" */
2595 for (y = y1b - 1; y <= y2b + 1; y++)
2596 {
2597 c_ptr = &zcave[y][x1b-1];
2598 c_ptr->feat = feat_wall_outer;
2599 c_ptr = &zcave[y][x2b+1];
2600 c_ptr->feat = feat_wall_outer;
2601 }
2602 for (x = x1b - 1; x <= x2b + 1; x++)
2603 {
2604 c_ptr = &zcave[y1b-1][x];
2605 c_ptr->feat = feat_wall_outer;
2606 c_ptr = &zcave[y2b+1][x];
2607 c_ptr->feat = feat_wall_outer;
2608 }
2609
2610
2611
2612 /* Replace the floor for room "a" */
2613 for (y = y1a; y <= y2a; y++)
2614 {
2615 for (x = x1a; x <= x2a; x++)
2616 {
2617 c_ptr = &zcave[y][x];
2618 place_floor(wpos, y, x);
2619 }
2620 }
2621
2622 /* Replace the floor for room "b" */
2623 for (y = y1b; y <= y2b; y++)
2624 {
2625 for (x = x1b; x <= x2b; x++)
2626 {
2627 c_ptr = &zcave[y][x];
2628 place_floor(wpos, y, x);
2629 }
2630 }
2631 }
2632
2633
2634
2635 /*
2636 * Type 3 -- Cross shaped rooms
2637 *
2638 * Builds a room at a row, column coordinate
2639 *
2640 * Room "a" runs north/south, and Room "b" runs east/east
2641 * So the "central pillar" runs from x1a,y1b to x2a,y2b.
2642 *
2643 * Note that currently, the "center" is always 3x3, but I think that
2644 * the code below will work (with "bounds checking") for 5x5, or even
2645 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
2646 */
build_type3(struct worldpos * wpos,int by0,int bx0,player_type * p_ptr)2647 static void build_type3(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
2648 {
2649 int y, x, dy, dx, wy, wx;
2650 int y1a, x1a, y2a, x2a;
2651 int y1b, x1b, y2b, x2b;
2652 int yval, xval;
2653 u32b resf = make_resf(p_ptr);
2654
2655 bool light;
2656 cave_type *c_ptr;
2657
2658 cave_type **zcave;
2659 if (!(zcave = getcave(wpos))) return;
2660
2661 /* Try to allocate space for room. If fails, exit */
2662 if (!room_alloc(wpos, 25, 11, FALSE, by0, bx0, &xval, &yval)) return;
2663
2664 /* Choose lite or dark */
2665 light = (getlevel(wpos) <= randint(25));
2666
2667
2668 /* For now, always 3x3 */
2669 wx = wy = 1;
2670
2671 /* Pick max vertical size (at most 4) */
2672 dy = rand_range(3, 4);
2673
2674 /* Pick max horizontal size (at most 15) */
2675 dx = rand_range(3, 11);
2676
2677
2678 /* Determine extents of the north/south room */
2679 y1a = yval - dy;
2680 y2a = yval + dy;
2681 x1a = xval - wx;
2682 x2a = xval + wx;
2683
2684 /* Determine extents of the east/west room */
2685 y1b = yval - wy;
2686 y2b = yval + wy;
2687 x1b = xval - dx;
2688 x2b = xval + dx;
2689
2690
2691 /* Place a full floor for room "a" */
2692 for (y = y1a - 1; y <= y2a + 1; y++)
2693 {
2694 for (x = x1a - 1; x <= x2a + 1; x++)
2695 {
2696 c_ptr = &zcave[y][x];
2697 place_floor(wpos, y, x);
2698 c_ptr->info |= CAVE_ROOM;
2699 if (light) c_ptr->info |= CAVE_GLOW;
2700 }
2701 }
2702
2703 /* Place a full floor for room "b" */
2704 for (y = y1b - 1; y <= y2b + 1; y++)
2705 {
2706 for (x = x1b - 1; x <= x2b + 1; x++)
2707 {
2708 c_ptr = &zcave[y][x];
2709 place_floor(wpos, y, x);
2710 c_ptr->info |= CAVE_ROOM;
2711 if (light) c_ptr->info |= CAVE_GLOW;
2712 }
2713 }
2714
2715
2716 /* Place the walls around room "a" */
2717 for (y = y1a - 1; y <= y2a + 1; y++)
2718 {
2719 c_ptr = &zcave[y][x1a-1];
2720 c_ptr->feat = feat_wall_outer;
2721 c_ptr = &zcave[y][x2a+1];
2722 c_ptr->feat = feat_wall_outer;
2723 }
2724 for (x = x1a - 1; x <= x2a + 1; x++)
2725 {
2726 c_ptr = &zcave[y1a-1][x];
2727 c_ptr->feat = feat_wall_outer;
2728 c_ptr = &zcave[y2a+1][x];
2729 c_ptr->feat = feat_wall_outer;
2730 }
2731
2732 /* Place the walls around room "b" */
2733 for (y = y1b - 1; y <= y2b + 1; y++)
2734 {
2735 c_ptr = &zcave[y][x1b-1];
2736 c_ptr->feat = feat_wall_outer;
2737 c_ptr = &zcave[y][x2b+1];
2738 c_ptr->feat = feat_wall_outer;
2739 }
2740 for (x = x1b - 1; x <= x2b + 1; x++)
2741 {
2742 c_ptr = &zcave[y1b-1][x];
2743 c_ptr->feat = feat_wall_outer;
2744 c_ptr = &zcave[y2b+1][x];
2745 c_ptr->feat = feat_wall_outer;
2746 }
2747
2748
2749 /* Replace the floor for room "a" */
2750 for (y = y1a; y <= y2a; y++)
2751 {
2752 for (x = x1a; x <= x2a; x++)
2753 {
2754 c_ptr = &zcave[y][x];
2755 place_floor(wpos, y, x);
2756 }
2757 }
2758
2759 /* Replace the floor for room "b" */
2760 for (y = y1b; y <= y2b; y++)
2761 {
2762 for (x = x1b; x <= x2b; x++)
2763 {
2764 c_ptr = &zcave[y][x];
2765 place_floor(wpos, y, x);
2766 }
2767 }
2768
2769
2770
2771 /* Special features (3/4) */
2772 switch (rand_int(4))
2773 {
2774 /* Large solid middle pillar */
2775 case 1:
2776 for (y = y1b; y <= y2b; y++)
2777 {
2778 for (x = x1a; x <= x2a; x++)
2779 {
2780 c_ptr = &zcave[y][x];
2781 c_ptr->feat = feat_wall_inner;
2782 }
2783 }
2784 break;
2785
2786 /* Inner treasure vault */
2787 case 2:
2788
2789 /* Build the vault */
2790 for (y = y1b; y <= y2b; y++)
2791 {
2792 c_ptr = &zcave[y][x1a];
2793 c_ptr->feat = feat_wall_inner;
2794 c_ptr = &zcave[y][x2a];
2795 c_ptr->feat = feat_wall_inner;
2796 }
2797 for (x = x1a; x <= x2a; x++)
2798 {
2799 c_ptr = &zcave[y1b][x];
2800 c_ptr->feat = feat_wall_inner;
2801 c_ptr = &zcave[y2b][x];
2802 c_ptr->feat = feat_wall_inner;
2803 }
2804
2805 /* Place a secret door on the inner room */
2806 switch (rand_int(4))
2807 {
2808 case 0: place_secret_door(wpos, y1b, xval); break;
2809 case 1: place_secret_door(wpos, y2b, xval); break;
2810 case 2: place_secret_door(wpos, yval, x1a); break;
2811 case 3: place_secret_door(wpos, yval, x2a); break;
2812 }
2813
2814 /* Place a treasure in the vault */
2815 place_object(wpos, yval, xval, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
2816
2817 /* Let's guard the treasure well */
2818 vault_monsters(wpos, yval, xval, rand_int(2) + 3);
2819
2820 /* Place the trap */
2821 if (magik(50)) place_trap(wpos, yval, xval, 0);
2822
2823 /* Traps naturally */
2824 vault_traps(wpos, yval, xval, 4, 4, rand_int(3) + 2);
2825
2826 break;
2827
2828
2829 /* Something else */
2830 case 3:
2831
2832 /* Occasionally pinch the center shut */
2833 if (rand_int(3) == 0)
2834 {
2835 /* Pinch the east/west sides */
2836 for (y = y1b; y <= y2b; y++)
2837 {
2838 if (y == yval) continue;
2839 c_ptr = &zcave[y][x1a - 1];
2840 c_ptr->feat = feat_wall_inner;
2841 c_ptr = &zcave[y][x2a + 1];
2842 c_ptr->feat = feat_wall_inner;
2843 }
2844
2845 /* Pinch the north/south sides */
2846 for (x = x1a; x <= x2a; x++)
2847 {
2848 if (x == xval) continue;
2849 c_ptr = &zcave[y1b - 1][x];
2850 c_ptr->feat = feat_wall_inner;
2851 c_ptr = &zcave[y2b + 1][x];
2852 c_ptr->feat = feat_wall_inner;
2853 }
2854
2855 /* Sometimes shut using secret doors */
2856 if (rand_int(3) == 0)
2857 {
2858 place_secret_door(wpos, yval, x1a - 1);
2859 place_secret_door(wpos, yval, x2a + 1);
2860 place_secret_door(wpos, y1b - 1, xval);
2861 place_secret_door(wpos, y2b + 1, xval);
2862 }
2863 }
2864
2865 /* Occasionally put a "plus" in the center */
2866 else if (rand_int(3) == 0)
2867 {
2868 c_ptr = &zcave[yval][xval];
2869 c_ptr->feat = feat_wall_inner;
2870 c_ptr = &zcave[y1b][xval];
2871 c_ptr->feat = feat_wall_inner;
2872 c_ptr = &zcave[y2b][xval];
2873 c_ptr->feat = feat_wall_inner;
2874 c_ptr = &zcave[yval][x1a];
2875 c_ptr->feat = feat_wall_inner;
2876 c_ptr = &zcave[yval][x2a];
2877 c_ptr->feat = feat_wall_inner;
2878 }
2879
2880 /* Occasionally put a pillar in the center */
2881 else if (rand_int(3) == 0)
2882 {
2883 c_ptr = &zcave[yval][xval];
2884 c_ptr->feat = feat_wall_inner;
2885 }
2886
2887 break;
2888 }
2889 }
2890
2891
2892 /*
2893 * Type 4 -- Large room with inner features (pit-shaped room (with pillar(s)) or gorth)
2894 *
2895 * Possible sub-types:
2896 * 1 - Just an inner room with one door
2897 * 2 - An inner room within an inner room
2898 * 3 - An inner room with pillar(s)
2899 * 4 - Inner room has a maze
2900 * 5 - A set of four inner rooms (a "Gorth")
2901 * I'm adding the following sub-types: - C. Blue
2902 * 6 - Inner room has a lot of bones and skulls, possibly low-brain+ferocious guardian
2903 * 7 - Treasure chamber (inner room has money lying around), possibly non-human guardian
2904 */
build_type4(struct worldpos * wpos,int by0,int bx0,player_type * p_ptr)2905 static void build_type4(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
2906 {
2907 int y, x, y1, x1;
2908 int y2, x2, tmp, yval, xval;
2909 u32b resf = make_resf(p_ptr);
2910
2911 bool light;
2912 cave_type *c_ptr;
2913
2914 cave_type **zcave;
2915 if (!(zcave = getcave(wpos))) return;
2916
2917 /* Try to allocate space for room. If fails, exit */
2918 if (!room_alloc(wpos, 25, 11, FALSE, by0, bx0, &xval, &yval)) return;
2919
2920 /* Choose lite or dark */
2921 light = (getlevel(wpos) <= randint(25));
2922
2923 /* Large room */
2924 y1 = yval - 4;
2925 y2 = yval + 4;
2926 x1 = xval - 11;
2927 x2 = xval + 11;
2928
2929
2930 /* Place a full floor under the room */
2931 for (y = y1 - 1; y <= y2 + 1; y++) {
2932 for (x = x1 - 1; x <= x2 + 1; x++) {
2933 c_ptr = &zcave[y][x];
2934 place_floor(wpos, y, x);
2935 c_ptr->info |= CAVE_ROOM;
2936 if (light) c_ptr->info |= CAVE_GLOW;
2937 }
2938 }
2939
2940 /* Outer Walls */
2941 for (y = y1 - 1; y <= y2 + 1; y++) {
2942 c_ptr = &zcave[y][x1-1];
2943 c_ptr->feat = feat_wall_outer;
2944 c_ptr = &zcave[y][x2+1];
2945 c_ptr->feat = feat_wall_outer;
2946 }
2947 for (x = x1 - 1; x <= x2 + 1; x++) {
2948 c_ptr = &zcave[y1-1][x];
2949 c_ptr->feat = feat_wall_outer;
2950 c_ptr = &zcave[y2+1][x];
2951 c_ptr->feat = feat_wall_outer;
2952 }
2953
2954
2955 /* The inner room */
2956 y1 = y1 + 2;
2957 y2 = y2 - 2;
2958 x1 = x1 + 2;
2959 x2 = x2 - 2;
2960
2961 /* The inner walls */
2962 for (y = y1 - 1; y <= y2 + 1; y++) {
2963 c_ptr = &zcave[y][x1-1];
2964 c_ptr->feat = feat_wall_inner;
2965 c_ptr = &zcave[y][x2+1];
2966 c_ptr->feat = feat_wall_inner;
2967 }
2968 for (x = x1 - 1; x <= x2 + 1; x++) {
2969 c_ptr = &zcave[y1-1][x];
2970 c_ptr->feat = feat_wall_inner;
2971 c_ptr = &zcave[y2+1][x];
2972 c_ptr->feat = feat_wall_inner;
2973 }
2974
2975
2976 /* Inner room variations */
2977 #ifndef BONE_AND_TREASURE_CHAMBERS
2978 #ifndef IDDC_BONE_AND_TREASURE_CHAMBERS
2979 switch (randint(10)) {
2980 #else
2981 switch (randint(in_irondeepdive(wpos) ? 11 : 10)) {
2982 #endif
2983 #else
2984 switch (randint(11)) {
2985 #endif
2986
2987 /* Just an inner room with a monster */
2988 case 1: case 2:
2989
2990 /* Place a secret door */
2991 switch (randint(4)) {
2992 case 1: place_secret_door(wpos, y1 - 1, xval); break;
2993 case 2: place_secret_door(wpos, y2 + 1, xval); break;
2994 case 3: place_secret_door(wpos, yval, x1 - 1); break;
2995 case 4: place_secret_door(wpos, yval, x2 + 1); break;
2996 }
2997
2998 /* Place a monster in the room */
2999 vault_monsters(wpos, yval, xval, 1);
3000
3001 break;
3002
3003
3004 /* Treasure Vault (with a door) */
3005 case 3: case 4:
3006
3007 /* Place a secret door */
3008 switch (randint(4)) {
3009 case 1: place_secret_door(wpos, y1 - 1, xval); break;
3010 case 2: place_secret_door(wpos, y2 + 1, xval); break;
3011 case 3: place_secret_door(wpos, yval, x1 - 1); break;
3012 case 4: place_secret_door(wpos, yval, x2 + 1); break;
3013 }
3014
3015 /* Place another inner room */
3016 for (y = yval - 1; y <= yval + 1; y++) {
3017 for (x = xval - 1; x <= xval + 1; x++) {
3018 if ((x == xval) && (y == yval)) continue;
3019 c_ptr = &zcave[y][x];
3020 c_ptr->feat = feat_wall_inner;
3021 }
3022 }
3023
3024 /* Place a locked door on the inner room */
3025 switch (randint(4)) {
3026 case 1: place_locked_door(wpos, yval - 1, xval); break;
3027 case 2: place_locked_door(wpos, yval + 1, xval); break;
3028 case 3: place_locked_door(wpos, yval, xval - 1); break;
3029 case 4: place_locked_door(wpos, yval, xval + 1); break;
3030 }
3031
3032 /* Monsters to guard the "treasure" */
3033 vault_monsters(wpos, yval, xval, randint(3) + 2);
3034
3035 /* Object (80%) */
3036 if (rand_int(100) < 80)
3037 place_object(wpos, yval, xval, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
3038
3039 /* Stairs (20%) */
3040 else {
3041 #ifndef ARCADE_SERVER
3042 place_random_stairs(wpos, yval, xval);
3043 #else
3044 if (wpos->wz < 0) place_random_stairs(wpos, yval, xval);
3045 #endif
3046 }
3047
3048 /* Traps to protect the treasure */
3049 vault_traps(wpos, yval, xval, 4, 10, 2 + randint(3));
3050
3051 break;
3052
3053
3054 /* Inner pillar(s). */
3055 case 5: case 6:
3056
3057 /* Place a secret door */
3058 switch (randint(4)) {
3059 case 1: place_secret_door(wpos, y1 - 1, xval); break;
3060 case 2: place_secret_door(wpos, y2 + 1, xval); break;
3061 case 3: place_secret_door(wpos, yval, x1 - 1); break;
3062 case 4: place_secret_door(wpos, yval, x2 + 1); break;
3063 }
3064
3065 /* Large Inner Pillar */
3066 for (y = yval - 1; y <= yval + 1; y++) {
3067 for (x = xval - 1; x <= xval + 1; x++) {
3068 c_ptr = &zcave[y][x];
3069 c_ptr->feat = feat_wall_inner;
3070 }
3071 }
3072
3073 /* Occasionally, two more Large Inner Pillars */
3074 if (rand_int(2) == 0) {
3075 tmp = randint(2);
3076 for (y = yval - 1; y <= yval + 1; y++) {
3077 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++) {
3078 c_ptr = &zcave[y][x];
3079 c_ptr->feat = feat_wall_inner;
3080 }
3081 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++) {
3082 c_ptr = &zcave[y][x];
3083 c_ptr->feat = feat_wall_inner;
3084 }
3085 }
3086 }
3087
3088 /* Occasionally, some Inner rooms */
3089 if (rand_int(3) == 0) {
3090 /* Long horizontal walls */
3091 for (x = xval - 5; x <= xval + 5; x++) {
3092 c_ptr = &zcave[yval-1][x];
3093 c_ptr->feat = feat_wall_inner;
3094 c_ptr = &zcave[yval+1][x];
3095 c_ptr->feat = feat_wall_inner;
3096 }
3097
3098 /* Close off the left/right edges */
3099 c_ptr = &zcave[yval][xval-5];
3100 c_ptr->feat = feat_wall_inner;
3101 c_ptr = &zcave[yval][xval+5];
3102 c_ptr->feat = feat_wall_inner;
3103
3104 /* Secret doors (random top/bottom) */
3105 place_secret_door(wpos, yval - 3 + (randint(2) * 2), xval - 3);
3106 place_secret_door(wpos, yval - 3 + (randint(2) * 2), xval + 3);
3107
3108 /* Monsters */
3109 vault_monsters(wpos, yval, xval - 2, randint(2));
3110 vault_monsters(wpos, yval, xval + 2, randint(2));
3111
3112 /* Objects */
3113 if (rand_int(3) == 0) place_object(wpos, yval, xval - 2, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
3114 if (rand_int(3) == 0) place_object(wpos, yval, xval + 2, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
3115 }
3116
3117 break;
3118
3119
3120 /* Maze inside. */
3121 case 7: case 8:
3122
3123 /* Place a secret door */
3124 switch (randint(4)) {
3125 case 1: place_secret_door(wpos, y1 - 1, xval); break;
3126 case 2: place_secret_door(wpos, y2 + 1, xval); break;
3127 case 3: place_secret_door(wpos, yval, x1 - 1); break;
3128 case 4: place_secret_door(wpos, yval, x2 + 1); break;
3129 }
3130
3131 /* Maze (really a checkerboard) */
3132 for (y = y1; y <= y2; y++) {
3133 for (x = x1; x <= x2; x++) {
3134 if (0x1 & (x + y)) {
3135 c_ptr = &zcave[y][x];
3136 c_ptr->feat = feat_wall_inner;
3137 }
3138 }
3139 }
3140
3141 /* Monsters just love mazes. */
3142 vault_monsters(wpos, yval, xval - 5, randint(3));
3143 vault_monsters(wpos, yval, xval + 5, randint(3));
3144
3145 /* Traps make them entertaining. */
3146 vault_traps(wpos, yval, xval - 3, 2, 8, randint(3));
3147 vault_traps(wpos, yval, xval + 3, 2, 8, randint(3));
3148
3149 /* Mazes should have some treasure too. */
3150 vault_objects(wpos, yval, xval, 3, p_ptr);
3151
3152 break;
3153
3154
3155 /* Four small rooms. */
3156 case 9: case 10:
3157
3158 /* Inner "cross" */
3159 for (y = y1; y <= y2; y++) {
3160 c_ptr = &zcave[y][xval];
3161 c_ptr->feat = feat_wall_inner;
3162 }
3163 for (x = x1; x <= x2; x++) {
3164 c_ptr = &zcave[yval][x];
3165 c_ptr->feat = feat_wall_inner;
3166 }
3167
3168 /* Doors into the rooms */
3169 if (rand_int(100) < 50) {
3170 int i = randint(10);
3171 place_secret_door(wpos, y1 - 1, xval - i);
3172 place_secret_door(wpos, y1 - 1, xval + i);
3173 place_secret_door(wpos, y2 + 1, xval - i);
3174 place_secret_door(wpos, y2 + 1, xval + i);
3175 } else {
3176 int i = randint(3);
3177 place_secret_door(wpos, yval + i, x1 - 1);
3178 place_secret_door(wpos, yval - i, x1 - 1);
3179 place_secret_door(wpos, yval + i, x2 + 1);
3180 place_secret_door(wpos, yval - i, x2 + 1);
3181 }
3182
3183 /* Treasure, centered at the center of the cross */
3184 vault_objects(wpos, yval, xval, 2 + randint(2), p_ptr);
3185
3186 /* Gotta have some monsters. */
3187 vault_monsters(wpos, yval + 1, xval - 4, randint(4));
3188 vault_monsters(wpos, yval + 1, xval + 4, randint(4));
3189 vault_monsters(wpos, yval - 1, xval - 4, randint(4));
3190 vault_monsters(wpos, yval - 1, xval + 4, randint(4));
3191
3192 break;
3193
3194
3195 /* Room with lots of bones, possibly guardian (Butcher-style ;) or
3196 room with lots of treasure, possibly guardian - C. Blue */
3197 case 11:
3198 /* Place a secret door */
3199 switch (randint(4)) {
3200 case 1: place_secret_door(wpos, y1 - 1, xval); break;
3201 case 2: place_secret_door(wpos, y2 + 1, xval); break;
3202 case 3: place_secret_door(wpos, yval, x1 - 1); break;
3203 case 4: place_secret_door(wpos, yval, x2 + 1); break;
3204 }
3205
3206 if (rand_int(2)) {
3207 s_printf("ROOM4_BONES\n");
3208 /* Place bones, skulls and skeletons */
3209 object_type forge;
3210 // for (y = yval; y <= yval; y++)
3211 // for (x = xval; x <= xval; x++)
3212 for (y = y1; y <= y2; y++)
3213 for (x = x1; x <= x2; x++)
3214 if (!rand_int(5)) {
3215 invcopy(&forge, lookup_kind(TV_SKELETON, randint(8)));
3216 drop_near(&forge, 0, wpos, y, x);
3217 }
3218
3219 /* Place a monster in the room */
3220 // vault_monsters(wpos, yval, xval, 1);
3221 } else {
3222 s_printf("ROOM4_TREASURE\n");
3223 /* Place monetary treasure */
3224 // for (y = yval; y <= yval; y++)
3225 // for (x = xval; x <= xval; x++)
3226 for (y = y1; y <= y2; y++)
3227 for (x = x1; x <= x2; x++)
3228 if (!rand_int(5)) place_gold(wpos, y, x, 0);
3229
3230 /* Place a monster in the room */
3231 // vault_monsters(wpos, yval, xval, 1);
3232 }
3233
3234 break;
3235
3236 }
3237 }
3238
3239
3240 /*
3241 * The following functions are used to determine if the given monster
3242 * is appropriate for inclusion in a monster nest or monster pit or
3243 * the given type.
3244 *
3245 * None of the pits/nests are allowed to include "unique" monsters,
3246 * or monsters which can "multiply".
3247 *
3248 * Some of the pits/nests are asked to avoid monsters which can blink
3249 * away or which are invisible. This is probably a hack.
3250 *
3251 * The old method made direct use of monster "names", which is bad.
3252 *
3253 * Note the use of Angband 2.7.9 monster race pictures in various places.
3254 */
3255
3256 /* Some new types of nests/pits are borrowed from ToME. - Jir - */
3257
3258 /* Hack -- for clone pits */
3259 static int template_race;
3260
3261 /*
3262 * Dungeon monster filter - not null
3263 */
3264 bool dungeon_aux(int r_idx){
3265 monster_race *r_ptr = &r_info[r_idx];
3266
3267 if (r_ptr->flags8 & RF8_DUNGEON)
3268 return TRUE;
3269 else
3270 return FALSE;
3271 #if 0
3272 if (dun->watery) return(TRUE);
3273
3274 /* No aquatic life in the dungeon */
3275 if (r_ptr->flags7 & RF7_AQUATIC) return(FALSE);
3276 return TRUE;
3277 #endif /* 0 */
3278 }
3279
3280 /*
3281 * Quest monster filter
3282 */
3283 bool xorder_aux(int r_idx) {
3284 monster_race *r_ptr = &r_info[r_idx];
3285
3286 /* Reject monsters that occur in the wilderness instead of the dungeon */
3287 if (!(r_ptr->flags8 & RF8_DUNGEON))
3288 return FALSE;
3289
3290 /* Reject 'non-spawning' monsters */
3291 if (r_ptr->rarity == 255) return (FALSE);
3292
3293 return TRUE;
3294 }
3295
3296 /*
3297 * Helper function for "monster nest (jelly)"
3298 */
3299 static bool vault_aux_jelly(int r_idx)
3300 {
3301 monster_race *r_ptr = &r_info[r_idx];
3302
3303 /* Decline unique monsters */
3304 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3305
3306 /* Require icky thing, jelly, mold, or mushroom */
3307 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
3308
3309 /* Okay */
3310 return (TRUE);
3311 }
3312
3313
3314 /*
3315 * Helper function for "monster nest (animal)"
3316 */
3317 static bool vault_aux_animal(int r_idx)
3318 {
3319 monster_race *r_ptr = &r_info[r_idx];
3320
3321 /* No aquatic life in the dungeon */
3322 if (r_ptr->flags7 & RF7_AQUATIC) return(FALSE);
3323
3324 /* Decline unique monsters */
3325 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3326
3327 /* Require "animal" flag */
3328 if (!(r_ptr->flags3 & RF3_ANIMAL)) return (FALSE);
3329
3330 /* Okay */
3331 return (TRUE);
3332 }
3333
3334
3335 /*
3336 * Helper function for "monster nest (undead)"
3337 */
3338 static bool vault_aux_undead(int r_idx)
3339 {
3340 monster_race *r_ptr = &r_info[r_idx];
3341
3342 /* Decline unique monsters */
3343 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3344
3345 /* Require Undead */
3346 if (!(r_ptr->flags3 & RF3_UNDEAD)) return (FALSE);
3347
3348 /* Okay */
3349 return (TRUE);
3350 }
3351
3352
3353 /*
3354 * Helper function for "monster nest (chapel)"
3355 */
3356 static bool vault_aux_chapel(int r_idx)
3357 {
3358 monster_race *r_ptr = &r_info[r_idx];
3359
3360 /* Decline unique monsters */
3361 if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
3362
3363 /* Require "priest" or Angel */
3364 if (!((r_ptr->d_char == 'A') ||
3365 strstr((r_name + r_ptr->name),"riest") ||
3366 strstr((r_name + r_ptr->name),"aladin") ||
3367 strstr((r_name + r_ptr->name),"emplar")))
3368 {
3369 return (FALSE);
3370 }
3371
3372 /* Okay */
3373 return (TRUE);
3374 }
3375 static bool vault_aux_lesser_chapel(int r_idx)
3376 {
3377 monster_race *r_ptr = &r_info[r_idx];
3378
3379 /* Decline unique monsters */
3380 if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
3381
3382 if (r_ptr->flags0 & RF0_NO_NEST) return (FALSE);
3383
3384 /* Require "priest" or Angel */
3385 // if (!((r_ptr->d_char == 'A' && (r_ptr->level <= 70)) ||
3386 if (!((r_ptr->d_char == 'A') ||
3387 strstr((r_name + r_ptr->name),"riest") ||
3388 strstr((r_name + r_ptr->name),"aladin") ||
3389 strstr((r_name + r_ptr->name),"emplar")))
3390 {
3391 return (FALSE);
3392 }
3393
3394 /* Okay */
3395 return (TRUE);
3396 }
3397
3398
3399 /*
3400 * Helper function for "monster nest (kennel)"
3401 */
3402 static bool vault_aux_kennel(int r_idx)
3403 {
3404 monster_race *r_ptr = &r_info[r_idx];
3405
3406 /* Decline unique monsters */
3407 if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
3408
3409 /* Require a Zephyr Hound or a dog */
3410 return ((r_ptr->d_char == 'Z') || (r_ptr->d_char == 'C'));
3411
3412 }
3413 static bool vault_aux_lesser_kennel(int r_idx)
3414 {
3415 monster_race *r_ptr = &r_info[r_idx];
3416
3417 /* Decline unique monsters */
3418 if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
3419
3420 /* Not too many Black Dogs */
3421 if (r_ptr->flags0 & RF0_NO_NEST) return (FALSE);
3422
3423 /* Require a Zephyr Hound or a dog */
3424 return ((r_ptr->d_char == 'Z') || (r_ptr->d_char == 'C'));
3425
3426 }
3427
3428
3429 /*
3430 * Helper function for "monster nest (treasure)"
3431 */
3432 static bool vault_aux_treasure(int r_idx)
3433 {
3434 monster_race *r_ptr = &r_info[r_idx];
3435
3436 /* Decline unique monsters */
3437 if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
3438
3439 /* Hack -- allow mimics */
3440 if (r_ptr->flags9 & (RF9_MIMIC)) return (TRUE);
3441
3442 /* Require Object form */
3443 if (!((r_ptr->d_char == '!') || (r_ptr->d_char == '|') ||
3444 (r_ptr->d_char == '$') || (r_ptr->d_char == '?') ||
3445 (r_ptr->d_char == '=')))
3446 return (FALSE);
3447
3448 /* Okay */
3449 return (TRUE);
3450 }
3451
3452
3453 /*
3454 * Helper function for "monster nest (clone)"
3455 */
3456 static bool vault_aux_clone(int r_idx)
3457 {
3458 /* unsure - blades shouldn't happen, but should titans?
3459 if (r_info[r_idx].flags0 & RF0_NO_NEST) return (FALSE); */
3460
3461 return (r_idx == template_race);
3462 }
3463
3464
3465 /*
3466 * Helper function for "monster nest (symbol clone)"
3467 */
3468 static bool vault_aux_symbol(int r_idx)
3469 {
3470 return ((r_info[r_idx].d_char == (r_info[template_race].d_char))
3471 && !(r_info[r_idx].flags1 & RF1_UNIQUE)
3472 && !(r_info[r_idx].flags0 & RF0_NO_NEST)
3473 && !(r_info[r_idx].d_char == 'A' && r_info[r_idx].level > 70));
3474 }
3475
3476
3477
3478 /*
3479 * Helper function for "monster pit (orc)"
3480 */
3481 static bool vault_aux_orc(int r_idx)
3482 {
3483 monster_race *r_ptr = &r_info[r_idx];
3484
3485 /* Decline unique monsters */
3486 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3487
3488 /* Hack -- Require "o" monsters */
3489 if (!strchr("o", r_ptr->d_char)) return (FALSE);
3490
3491 /* Okay */
3492 return (TRUE);
3493 }
3494
3495
3496 /*
3497 * Helper function for "monster pit (orc and ogre)"
3498 */
3499 static bool vault_aux_orc_ogre(int r_idx)
3500 {
3501 monster_race *r_ptr = &r_info[r_idx];
3502
3503 /* Decline unique monsters */
3504 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3505
3506 /* Hack -- Require "o" monsters */
3507 if (!strchr("oO", r_ptr->d_char)) return (FALSE);
3508
3509 /* Okay */
3510 return (TRUE);
3511 }
3512
3513
3514 /*
3515 * Helper function for "monster pit (troll)"
3516 */
3517 static bool vault_aux_troll(int r_idx)
3518 {
3519 monster_race *r_ptr = &r_info[r_idx];
3520
3521 /* Decline unique monsters */
3522 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3523
3524 /* Hack -- Require "T" monsters */
3525 if (!strchr("T", r_ptr->d_char)) return (FALSE);
3526
3527 /* Okay */
3528 return (TRUE);
3529 }
3530
3531
3532 /*
3533 * Helper function for "monster pit (mankind)"
3534 */
3535 static bool vault_aux_man(int r_idx)
3536 {
3537 monster_race *r_ptr = &r_info[r_idx];
3538
3539 /* Decline unique monsters */
3540 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3541
3542 /* Hack -- Require "p" or "h" monsters */
3543 if (!strchr("ph", r_ptr->d_char)) return (FALSE);
3544
3545 /* Okay */
3546 return (TRUE);
3547 }
3548
3549
3550 /*
3551 * Helper function for "monster pit (giant)"
3552 */
3553 static bool vault_aux_giant(int r_idx)
3554 {
3555 monster_race *r_ptr = &r_info[r_idx];
3556
3557 /* Decline unique monsters */
3558 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3559
3560 /* Hack -- Require "P" monsters */
3561 if (!strchr("P", r_ptr->d_char)) return (FALSE);
3562
3563 /* Okay */
3564 return (TRUE);
3565 }
3566 static bool vault_aux_lesser_giant(int r_idx)
3567 {
3568 monster_race *r_ptr = &r_info[r_idx];
3569
3570 /* Decline unique monsters */
3571 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3572
3573 if (r_ptr->flags0 & RF0_NO_NEST) return (FALSE);
3574
3575 /* Hack -- Require "P" monsters */
3576 if (!strchr("P", r_ptr->d_char)) return (FALSE);
3577
3578 /* Okay */
3579 return (TRUE);
3580 }
3581
3582
3583 /*
3584 * Hack -- breath type for "vault_aux_dragon()"
3585 */
3586 static u32b vault_aux_dragon_mask4;
3587
3588
3589 /*
3590 * Helper function for "monster pit (dragon)"
3591 */
3592 static bool vault_aux_dragon(int r_idx)
3593 {
3594 monster_race *r_ptr = &r_info[r_idx];
3595
3596 /* Decline unique monsters */
3597 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3598
3599 /* Hack -- Require "d" or "D" monsters */
3600 if (!strchr("Dd", r_ptr->d_char)) return (FALSE);
3601
3602 /* Hack -- Allow 'all stars' type */
3603 if (!vault_aux_dragon_mask4) return (TRUE);
3604
3605 /* Hack -- Require correct "breath attack" */
3606 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
3607
3608 /* Okay */
3609 return (TRUE);
3610 }
3611
3612
3613 /*
3614 * Helper function for "monster pit (demon)"
3615 */
3616 static bool vault_aux_demon(int r_idx)
3617 {
3618 monster_race *r_ptr = &r_info[r_idx];
3619
3620 /* Decline unique monsters */
3621 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
3622
3623 /* Hack -- Require "U" monsters */
3624 if (!strchr("U", r_ptr->d_char)) return (FALSE);
3625
3626 /* Okay */
3627 return (TRUE);
3628 }
3629
3630
3631
3632 /*
3633 * Type 5 -- Monster nests
3634 *
3635 * A monster nest is a "big" room, with an "inner" room, containing
3636 * a "collection" of monsters of a given type strewn about the room.
3637 *
3638 * The monsters are chosen from a set of 64 randomly selected monster
3639 * races, to allow the nest creation to fail instead of having "holes".
3640 *
3641 * Note the use of the "get_mon_num_prep()" function, and the special
3642 * "get_mon_num_hook()" restriction function, to prepare the "monster
3643 * allocation table" in such a way as to optimize the selection of
3644 * "appropriate" non-unique monsters for the nest.
3645 *
3646 * Currently, a monster nest is one of
3647 * a nest of one monster symbol (Dungeon level 0 and deeper)
3648 * a nest of "jelly"/"treasure" monsters (Dungeon level 5 and deeper)
3649 * a nest of one monster index (Dungeon level 25 and deeper)
3650 * a nest of "animal"/"kennel" monsters (Dungeon level 30 and deeper)
3651 * a nest of "chapel"/"undead" monsters (Dungeon level 50 and deeper)
3652 *
3653 * Note that the "get_mon_num()" function may (rarely) fail, in which
3654 * case the nest will be empty, and will not affect the level rating.
3655 *
3656 * Note that "monster nests" will never contain "unique" monsters.
3657 */
3658 static void build_type5(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr) {
3659 int y, x, y1, x1, y2, x2, xval, yval;
3660 int tmp, i, dun_lev;
3661 s16b what[64];
3662 cave_type *c_ptr;
3663 //cptr name;
3664
3665 dungeon_type *dt_ptr = getdungeon(wpos);
3666 int dun_type;
3667 #ifdef IRONDEEPDIVE_MIXED_TYPES
3668 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
3669 else
3670 #endif
3671 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
3672
3673 dun_level *l_ptr = getfloor(wpos);
3674
3675 bool (*chosen_type)(int r_idx);
3676 bool empty = FALSE;
3677 cave_type **zcave;
3678 if (!(zcave = getcave(wpos))) return;
3679
3680 dun_lev = getlevel(wpos);
3681
3682 /* Try to allocate space for room. If fails, exit */
3683 if (!room_alloc(wpos, 25, 11, TRUE, by0, bx0, &xval, &yval)) return;
3684
3685 /* Large room */
3686 y1 = yval - 4;
3687 y2 = yval + 4;
3688 x1 = xval - 11;
3689 x2 = xval + 11;
3690
3691
3692 /* Place the floor area */
3693 for (y = y1 - 1; y <= y2 + 1; y++) {
3694 for (x = x1 - 1; x <= x2 + 1; x++) {
3695 c_ptr = &zcave[y][x];
3696 place_floor(wpos, y, x);
3697 c_ptr->info |= CAVE_ROOM;
3698 }
3699 }
3700
3701 /* Place the outer walls */
3702 for (y = y1 - 1; y <= y2 + 1; y++) {
3703 c_ptr = &zcave[y][x1-1];
3704 c_ptr->feat = feat_wall_outer;
3705 c_ptr = &zcave[y][x2+1];
3706 c_ptr->feat = feat_wall_outer;
3707 }
3708 for (x = x1 - 1; x <= x2 + 1; x++) {
3709 c_ptr = &zcave[y1-1][x];
3710 c_ptr->feat = feat_wall_outer;
3711 c_ptr = &zcave[y2+1][x];
3712 c_ptr->feat = feat_wall_outer;
3713 }
3714
3715
3716 /* Advance to the center room */
3717 y1 = y1 + 2;
3718 y2 = y2 - 2;
3719 x1 = x1 + 2;
3720 x2 = x2 - 2;
3721
3722 /* The inner walls */
3723 for (y = y1 - 1; y <= y2 + 1; y++) {
3724 c_ptr = &zcave[y][x1-1];
3725 c_ptr->feat = feat_wall_inner;
3726 c_ptr = &zcave[y][x2+1];
3727 c_ptr->feat = feat_wall_inner;
3728 }
3729 for (x = x1 - 1; x <= x2 + 1; x++) {
3730 c_ptr = &zcave[y1-1][x];
3731 c_ptr->feat = feat_wall_inner;
3732 c_ptr = &zcave[y2+1][x];
3733 c_ptr->feat = feat_wall_inner;
3734 }
3735
3736
3737 /* Place a secret door */
3738 switch (randint(4)) {
3739 case 1: place_secret_door(wpos, y1 - 1, xval); break;
3740 case 2: place_secret_door(wpos, y2 + 1, xval); break;
3741 case 3: place_secret_door(wpos, yval, x1 - 1); break;
3742 case 4: place_secret_door(wpos, yval, x2 + 1); break;
3743 }
3744
3745 /* Prevent teleportation into the nest (experimental, 2008-05-26) */
3746 #ifdef NEST_PIT_NO_STAIRS_OUTER
3747 for (y = yval - 4; y <= yval + 4; y++)
3748 for (x = xval - 11; x <= xval + 11; x++)
3749 zcave[y][x].info |= CAVE_NEST_PIT;
3750 #else
3751 #ifdef NEST_PIT_NO_STAIRS_INNER
3752 for (y = yval - 2; y <= yval + 2; y++)
3753 for (x = xval - 9; x <= xval + 92; x++)
3754 zcave[y][x].info |= CAVE_NEST_PIT;
3755 #endif
3756 #endif
3757
3758 /* Hack -- Choose a nest type */
3759 tmp = randint(dun_lev);
3760
3761 if ((tmp < 25) && (rand_int(5) != 0)) {
3762 #if 0
3763 int tries = 2000;
3764
3765 while (TRUE) {
3766 template_race = randint(MAX_R_IDX - 2);
3767
3768 /* Reject uniques */
3769 if (r_info[template_race].flags1 & RF1_UNIQUE) continue;
3770
3771 /* Reject OoD monsters in a loose fashion */
3772 if (((r_info[template_race].level) + randint(5)) >
3773 (dun_lev + randint(5))) continue;
3774
3775 if (!tries--) return;
3776
3777 /* Don't like 'break's like this, but this cannot be made better */
3778 break;
3779 }
3780 #else
3781 /* Alternate version that uses get_mon_num() - mikaelh */
3782 get_mon_num_hook = dungeon_aux;
3783 set_mon_num2_hook(floor_type[0]);
3784 get_mon_num_prep(dun_type, reject_uniques);
3785 template_race = get_mon_num(dun_lev, dun_lev);
3786 #endif
3787
3788 if ((dun_lev >= (25 + randint(15))) && (rand_int(2) != 0)) {
3789 /* monster nest (same r_info symbol) */
3790 //name = "symbol clone";
3791 get_mon_num_hook = vault_aux_symbol;
3792 } else {
3793 /* monster nest (same r_idx) */
3794 //name = "clone";
3795 get_mon_num_hook = vault_aux_clone;
3796 }
3797 }
3798 else if (tmp < 35) {
3799 /* Monster nest (jelly) */
3800 /* Describe */
3801 //name = "jelly";
3802
3803 /* Restrict to jelly */
3804 get_mon_num_hook = vault_aux_jelly;
3805 }
3806
3807 else if (tmp < 45) {
3808 //name = "treasure";
3809 get_mon_num_hook = vault_aux_treasure;
3810 }
3811
3812 /* Monster nest (animal) */
3813 else if (tmp < 65) {
3814 if (rand_int(3) == 0) {
3815 //name = "kennel";
3816 get_mon_num_hook = vault_aux_lesser_kennel;
3817 } else {
3818 /* Describe */
3819 //name = "animal";
3820
3821 /* Restrict to animal */
3822 get_mon_num_hook = vault_aux_animal;
3823 }
3824 }
3825
3826 /* Monster nest (undead) */
3827 else {
3828 if (rand_int(3) == 0) {
3829 //name = "chapel";
3830 get_mon_num_hook = vault_aux_lesser_chapel;
3831 } else {
3832 /* Describe */
3833 //name = "undead";
3834
3835 /* Restrict to undead */
3836 get_mon_num_hook = vault_aux_undead;
3837 }
3838 }
3839
3840 #if 0
3841 /* Monster nest (jelly) */
3842 if (tmp < 30) {
3843 /* Describe */
3844 //name = "jelly";
3845
3846 /* Restrict to jelly */
3847 get_mon_num_hook = vault_aux_jelly;
3848 }
3849
3850 /* Monster nest (animal) */
3851 else if (tmp < 50) {
3852 /* Describe */
3853 //name = "animal";
3854
3855 /* Restrict to animal */
3856 get_mon_num_hook = vault_aux_animal;
3857 }
3858
3859 /* Monster nest (undead) */
3860 else {
3861 /* Describe */
3862 //name = "undead";
3863
3864 /* Restrict to undead */
3865 get_mon_num_hook = vault_aux_undead;
3866 }
3867 #endif /* 0 */
3868
3869 /* Set the second hook according to the first floor type */
3870 set_mon_num2_hook(floor_type[0]);
3871
3872 /* Prepare allocation table */
3873 get_mon_num_prep(dun_type, l_ptr->uniques_killed);
3874
3875
3876 /* Pick some monster types */
3877 for (i = 0; i < 64; i++)
3878 {
3879 /* Get a (hard) monster type */
3880 what[i] = get_mon_num(dun_lev + 10, dun_lev);
3881
3882 /* Notice failure */
3883 if (!what[i]) empty = TRUE;
3884 }
3885
3886
3887 /* Remove restriction */
3888 chosen_type = get_mon_num_hook; /* preserve for later checks */
3889 get_mon_num_hook = dungeon_aux;
3890 get_mon_num2_hook = NULL;
3891
3892 /* Oops */
3893 if (empty) {
3894 s_printf("EMPTY_NEST (%d, %d, %d)\n", wpos->wx, wpos->wy, wpos->wz);
3895 return;
3896 }
3897
3898 /* Place some monsters */
3899 for (y = yval - 2; y <= yval + 2; y++)
3900 {
3901 for (x = xval - 9; x <= xval + 9; x++)
3902 {
3903 int r_idx = what[rand_int(64)];
3904
3905 /* Place that "random" monster (no groups) */
3906 (void)place_monster_aux(wpos, y, x, r_idx, FALSE, FALSE, FALSE, 0);
3907
3908 #if 0 /* not needed, monster level is in fact limited (see further above) */
3909 if (r_info[r_idx].level >= (dun_lev * 3) / 2 ||
3910 #endif
3911 if (r_info[r_idx].level >= 60)
3912 l_ptr->flags2 |= LF2_PITNEST_HI;
3913 }
3914 }
3915
3916 l_ptr->flags2 |= LF2_PITNEST;
3917 /* summoner nests are dangerous albeit not high level, graveyards too */
3918 if (chosen_type == vault_aux_chapel ||
3919 chosen_type == vault_aux_undead)
3920 l_ptr->flags2 |= LF2_PITNEST_HI;
3921 }
3922
3923
3924
3925 /*
3926 * Type 6 -- Monster pits
3927 *
3928 * A monster pit is a "big" room, with an "inner" room, containing
3929 * a "collection" of monsters of a given type organized in the room.
3930 *
3931 * Monster types in the pit
3932 * aquatic pit (Dungeon Level 0 and deeper)
3933 * orc pit (Dungeon Level 5 and deeper)
3934 * troll pit (Dungeon Level 20 and deeper)
3935 * orc/ogre pit (Dungeon Level 30 and deeper)
3936 * man pit (h/p) (Dungeon Level 20 and deeper)
3937 * giant pit (Dungeon Level 40 and deeper)
3938 * same r_info symbol pit (Dungeon Level 5 and deeper)
3939 * chapel pit (Dungeon Level 5 and deeper)
3940 * dragon pit (Dungeon Level 60 and deeper)
3941 * demon pit (Dungeon Level 80 and deeper)
3942 *
3943 * The inside room in a monster pit appears as shown below, where the
3944 * actual monsters in each location depend on the type of the pit
3945 *
3946 * #####################
3947 * #0000000000000000000#
3948 * #0112233455543322110#
3949 * #0112233467643322110#
3950 * #0112233455543322110#
3951 * #0000000000000000000#
3952 * #####################
3953 *
3954 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
3955 * to request 16 "appropriate" monsters, sorting them by level, and using
3956 * the "even" entries in this sorted list for the contents of the pit.
3957 *
3958 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
3959 * which is handled by requiring a specific "breath" attack for all of the
3960 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
3961 * be present in many of the dragon pits, if they have the proper breath.
3962 *
3963 * Note the use of the "get_mon_num_prep()" function, and the special
3964 * "get_mon_num_hook()" restriction function, to prepare the "monster
3965 * allocation table" in such a way as to optimize the selection of
3966 * "appropriate" non-unique monsters for the pit.
3967 *
3968 * Note that the "get_mon_num()" function may (rarely) fail, in which case
3969 * the pit will be empty, and will not effect the level rating.
3970 *
3971 * Note that "monster pits" will never contain "unique" monsters.
3972 */
3973 #define BUILD_6_MONSTER_TABLE 32
3974 static void build_type6(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr) {
3975 int tmp, what[BUILD_6_MONSTER_TABLE];
3976 int i, j, y, x, y1, x1, y2, x2, dun_lev, xval, yval;
3977 bool empty = FALSE;
3978 #if 0
3979 bool aqua = magik(dun->watery? 50 : 10);
3980 #else
3981 /* Disabled for now because aquatic pits are getting filled with eyes of the deep - mikaelh */
3982 bool aqua = FALSE;
3983 #endif
3984 cave_type *c_ptr;
3985 dungeon_type *dt_ptr = getdungeon(wpos);
3986 int dun_type;
3987 #ifdef IRONDEEPDIVE_MIXED_TYPES
3988 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
3989 else
3990 #endif
3991 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
3992
3993 dun_level *l_ptr = getfloor(wpos);
3994
3995 bool (*chosen_type)(int r_idx);
3996 //cptr name;
3997 cave_type **zcave;
3998 if (!(zcave = getcave(wpos))) return;
3999
4000 /* Try to allocate space for room. If fails, exit */
4001 if (!room_alloc(wpos, 25, 11, TRUE, by0, bx0, &xval, &yval)) return;
4002
4003 dun_lev = getlevel(wpos);
4004
4005 /* Large room */
4006 y1 = yval - 4;
4007 y2 = yval + 4;
4008 x1 = xval - 11;
4009 x2 = xval + 11;
4010
4011
4012 /* Place the floor area */
4013 for (y = y1 - 1; y <= y2 + 1; y++) {
4014 for (x = x1 - 1; x <= x2 + 1; x++) {
4015 c_ptr = &zcave[y][x];
4016 place_floor(wpos, y, x);
4017 c_ptr->info |= CAVE_ROOM;
4018 }
4019 }
4020
4021 /* Place the outer walls */
4022 for (y = y1 - 1; y <= y2 + 1; y++) {
4023 c_ptr = &zcave[y][x1-1];
4024 c_ptr->feat = feat_wall_outer;
4025 c_ptr = &zcave[y][x2+1];
4026 c_ptr->feat = feat_wall_outer;
4027 }
4028 for (x = x1 - 1; x <= x2 + 1; x++) {
4029 c_ptr = &zcave[y1-1][x];
4030 c_ptr->feat = feat_wall_outer;
4031 c_ptr = &zcave[y2+1][x];
4032 c_ptr->feat = feat_wall_outer;
4033 }
4034
4035
4036 /* Advance to the center room */
4037 y1 = y1 + 2;
4038 y2 = y2 - 2;
4039 x1 = x1 + 2;
4040 x2 = x2 - 2;
4041
4042
4043 #if 0
4044 /* This creates pits that are just too evil - mikaelh */
4045 if (aqua) {
4046 /* Fill aquatic pits with water */
4047 for (y = y1 - 1; y <= y2 + 1; y++)
4048 for (x = x1 - 1; x <= x2 + 1; x++)
4049 cave_set_feat(wpos, y, x, FEAT_DEEP_WATER);
4050 }
4051 #endif
4052
4053
4054 /* The inner walls */
4055 for (y = y1 - 1; y <= y2 + 1; y++) {
4056 c_ptr = &zcave[y][x1-1];
4057 c_ptr->feat = feat_wall_inner;
4058 c_ptr = &zcave[y][x2+1];
4059 c_ptr->feat = feat_wall_inner;
4060 }
4061 for (x = x1 - 1; x <= x2 + 1; x++) {
4062 c_ptr = &zcave[y1-1][x];
4063 c_ptr->feat = feat_wall_inner;
4064 c_ptr = &zcave[y2+1][x];
4065 c_ptr->feat = feat_wall_inner;
4066 }
4067
4068
4069 /* Place a secret door */
4070 switch (randint(4)) {
4071 case 1: place_secret_door(wpos, y1 - 1, xval); break;
4072 case 2: place_secret_door(wpos, y2 + 1, xval); break;
4073 case 3: place_secret_door(wpos, yval, x1 - 1); break;
4074 case 4: place_secret_door(wpos, yval, x2 + 1); break;
4075 }
4076
4077
4078 /* Prevent teleportation into the nest (experimental, 2008-05-26) */
4079 #ifdef NEST_PIT_NO_STAIRS_OUTER
4080 for (y = yval - 4; y <= yval + 4; y++)
4081 for (x = xval - 11; x <= xval + 11; x++)
4082 zcave[y][x].info |= CAVE_NEST_PIT;
4083 #else
4084 #ifdef NEST_PIT_NO_STAIRS_INNER
4085 for (y = yval - 2; y <= yval + 2; y++)
4086 for (x = xval - 9; x <= xval + 92; x++)
4087 zcave[y][x].info |= CAVE_NEST_PIT;
4088 #endif
4089 #endif
4090
4091
4092 /* Choose a pit type */
4093 tmp = randint(dun_lev);
4094
4095
4096 /* Watery pit */
4097 if (aqua) {
4098 /* Message */
4099 //name = "aquatic";
4100
4101 /* Restrict monster selection */
4102 get_mon_num_hook = vault_aux_aquatic;
4103 }
4104
4105 /* Orc pit */
4106 else if (tmp < 15) {
4107 if (dun_lev > 30 && magik(50)) {
4108 /* Message */
4109 //name = "orc and ogre";
4110
4111 /* Restrict monster selection */
4112 get_mon_num_hook = vault_aux_orc_ogre;
4113 } else {
4114 /* Message */
4115 //name = "orc";
4116
4117 /* Restrict monster selection */
4118 get_mon_num_hook = vault_aux_orc;
4119 }
4120 }
4121
4122 /* Troll pit */
4123 else if (tmp < 30) {
4124 /* Message */
4125 //name = "troll";
4126
4127 /* Restrict monster selection */
4128 get_mon_num_hook = vault_aux_troll;
4129 }
4130
4131 /* Man pit */
4132 else if (tmp < 40) {
4133 /* Message */
4134 //name = "mankind";
4135
4136 /* Restrict monster selection */
4137 get_mon_num_hook = vault_aux_man;
4138 }
4139
4140 /* Giant pit */
4141 else if (tmp < 55) {
4142 /* Message */
4143 //name = "giant";
4144
4145 /* Restrict monster selection */
4146 get_mon_num_hook = vault_aux_lesser_giant;
4147 }
4148
4149 else if (tmp < 70) {
4150 if (randint(4) != 1) {
4151 /* Message */
4152 //name = "ordered clones";
4153
4154 #if 0
4155 do { template_race = randint(MAX_R_IDX - 2); }
4156 while ((r_info[template_race].flags1 & RF1_UNIQUE)
4157 || (((r_info[template_race].level) + randint(5)) >
4158 (dun_lev + randint(5))));
4159 #else
4160 /* Alternate version that uses get_mon_num() - mikaelh */
4161 get_mon_num_hook = dungeon_aux;
4162 set_mon_num2_hook(floor_type[0]);
4163 get_mon_num_prep(dun_type, reject_uniques);
4164 template_race = get_mon_num(dun_lev, dun_lev);
4165 #endif
4166
4167 /* Restrict selection */
4168 get_mon_num_hook = vault_aux_symbol;
4169 } else {
4170
4171 //name = "ordered chapel";
4172 get_mon_num_hook = vault_aux_lesser_chapel;
4173 }
4174
4175 }
4176
4177 /* Dragon pit */
4178 else if (tmp < 80) {
4179 /* Pick dragon type */
4180 switch (rand_int(7)) {
4181 /* Black */
4182 case 0:
4183 /* Message */
4184 //name = "acid dragon";
4185
4186 /* Restrict dragon breath type */
4187 vault_aux_dragon_mask4 = RF4_BR_ACID;
4188
4189 /* Done */
4190 break;
4191
4192 /* Blue */
4193 case 1:
4194 /* Message */
4195 //name = "electric dragon";
4196
4197 /* Restrict dragon breath type */
4198 vault_aux_dragon_mask4 = RF4_BR_ELEC;
4199
4200 /* Done */
4201 break;
4202
4203 /* Red */
4204 case 2:
4205 /* Message */
4206 //name = "fire dragon";
4207
4208 /* Restrict dragon breath type */
4209 vault_aux_dragon_mask4 = RF4_BR_FIRE;
4210
4211 /* Done */
4212 break;
4213
4214 /* White */
4215 case 3:
4216 /* Message */
4217 //name = "cold dragon";
4218
4219 /* Restrict dragon breath type */
4220 vault_aux_dragon_mask4 = RF4_BR_COLD;
4221
4222 /* Done */
4223 break;
4224
4225 /* Green */
4226 case 4:
4227 /* Message */
4228 //name = "poison dragon";
4229
4230 /* Restrict dragon breath type */
4231 vault_aux_dragon_mask4 = RF4_BR_POIS;
4232
4233 /* Done */
4234 break;
4235
4236 /* All stars */
4237 case 5:
4238 /* Message */
4239 //name = "dragon";
4240
4241 /* Restrict dragon breath type */
4242 vault_aux_dragon_mask4 = 0L;
4243
4244 /* Done */
4245 break;
4246
4247 /* Multi-hued */
4248 default:
4249 /* Message */
4250 //name = "multi-hued dragon";
4251
4252 /* Restrict dragon breath type */
4253 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
4254 RF4_BR_FIRE | RF4_BR_COLD |
4255 RF4_BR_POIS);
4256
4257 /* Done */
4258 break;
4259 }
4260
4261 /* Restrict monster selection */
4262 get_mon_num_hook = vault_aux_dragon;
4263 }
4264
4265 /* Demon pit */
4266 else {
4267 /* Message */
4268 //name = "demon";
4269
4270 /* Restrict monster selection */
4271 get_mon_num_hook = vault_aux_demon;
4272 }
4273
4274 /* Set the second hook according to the first floor type */
4275 set_mon_num2_hook(floor_type[0]);
4276
4277 /* Prepare allocation table */
4278 get_mon_num_prep(dun_type, l_ptr->uniques_killed);
4279
4280
4281 /* Pick some monster types */
4282 for (i = 0; i < BUILD_6_MONSTER_TABLE; i++) {
4283 for (j = 0; j < 100; j++) {
4284 /* Get a (hard) monster type */
4285 what[i] = get_mon_num(dun_lev + 10, dun_lev);
4286 if (what[i] && !(r_info[what[i]].flags1 & RF1_UNIQUE)) break;
4287 }
4288 /* Notice failure */
4289 if (!what[i]) empty = TRUE;
4290 }
4291
4292 chosen_type = get_mon_num_hook; /* preserve */
4293
4294 /* Remove restriction */
4295 get_mon_num_hook = dungeon_aux;
4296 get_mon_num2_hook = NULL;
4297
4298 /* Oops */
4299 if (empty) {
4300 s_printf("EMPTY_PIT (%d, %d, %d)\n", wpos->wx, wpos->wy, wpos->wz);
4301 return;
4302 }
4303
4304
4305 /* XXX XXX XXX */
4306 /* Sort the entries */
4307 for (i = 0; i < BUILD_6_MONSTER_TABLE - 1; i++) {
4308 /* Sort the entries */
4309 for (j = 0; j < BUILD_6_MONSTER_TABLE - 1; j++) {
4310 int i1 = j;
4311 int i2 = j + 1;
4312
4313 int p1 = r_info[what[i1]].level;
4314 int p2 = r_info[what[i2]].level;
4315
4316 /* Bubble */
4317 if (p1 > p2) {
4318 int tmp = what[i1];
4319 what[i1] = what[i2];
4320 what[i2] = tmp;
4321 }
4322 }
4323 }
4324
4325 /* Select the entries */
4326 for (i = 0; i < 8; i++) {
4327 /* Every other entry */
4328 if (chosen_type == vault_aux_symbol || /* All dangerous nests get weakened here.. */
4329 chosen_type == vault_aux_clone ||
4330 chosen_type == vault_aux_kennel ||
4331 chosen_type == vault_aux_lesser_kennel ||
4332 chosen_type == vault_aux_animal ||
4333 chosen_type == vault_aux_undead ||
4334 chosen_type == vault_aux_dragon ||
4335 chosen_type == vault_aux_demon ||
4336 chosen_type == vault_aux_chapel ||
4337 chosen_type == vault_aux_lesser_chapel ||
4338 (chosen_type == vault_aux_troll && dun_lev < 35)) /* otherwise too much exp */
4339 what[i] = what[i * 2]; /* ..note that this takes only the weaker half
4340 of the 32 (BUILD_6_MONSTER_TABLE) sorted monsters!.. */
4341 /* else if (chosen_type == vault_aux_man ||
4342 chosen_type == vault_aux_giant ||
4343 chosen_type == vault_aux_aquatic ||*/
4344 else if (chosen_type == vault_aux_troll && dun_lev < 45) /* otherwise too much exp? but also very dangerous.. */
4345 what[i] = what[i * 3]; /* exclude the top quarter */
4346 else /* orc, ogre, troll */
4347 what[i] = what[i * 3 + 10]; /* full size & nice diversity */
4348 /* else
4349 what[i] = what[BUILD_6_MONSTER_TABLE - 15 + i * 2]; <- too powerful =) - C. Blue */
4350 }
4351
4352 #if 0
4353 /* Restrict ultra P pits */
4354 if (chosen_type == vault_aux_giant) {
4355 /* Find the first 'Hru' */
4356 for (i = 0; i < 8; i++) {
4357 if (what[i] == 709) {
4358 /* make one 'Hru' the top entry, all following entries weaker than 'Hru' */
4359 for (j = 7; j >= 7-i; j--) {
4360 what[j] = what[i+j-7];
4361 }
4362 break;
4363 }
4364 }
4365 /* Restrict Hru/Greater Titan/Lesser Titan to entry#1, entry#1/#2/#3, entry #1/#2/#3 respectively */
4366 /* Check for Hru at positions below #1 (leaving out the last entry, shouldn't occur there really) */
4367 for (i = 1; i < 7; i++) {
4368 if (what[i] == 709) {
4369 /* Copy over the following entries (duplicating the last entry effectively) */
4370 for (j = i; j >= 1; j--) {
4371 what[j] = what[j-1];
4372 }
4373 }
4374 }
4375 /* Check for Greater Titan at positions below #2 or #3 (leaving out the last entry, shouldn't occur there really) */
4376 // for (i = 1; i < (what[7] == 709 ? 6 : 5); i++) { /* allow more GTs if there's no Hru inside as well */
4377 for (i = 1; i < 6; i++) { /* up to 3 GTs allowed (at positions #1 and #2) */
4378 if (what[i] == 702) {
4379 /* Copy over the following entries (duplicating the last entry effectively) */
4380 for (j = i; j >= 1; j--) {
4381 what[j] = what[j-1];
4382 }
4383 }
4384 }
4385 /* Check for Lesser Titan at positions below #2 or #3 (leaving out the last entry, shouldn't occur there really) */
4386 // for (i = 1; i < (what[7] == 634 ? 6 : 5); i++) { /* disallow too many LTs */
4387 for (i = 1; i < ((what[6] == 634) ? 6 : 5); i++) { /* disallow too many LTs */
4388 if (what[i] == 634) {
4389 /* Copy over the following entries (duplicating the last entry effectively) */
4390 for (j = i; j >= 1; j--) {
4391 what[j] = what[j-1];
4392 }
4393 }
4394 }
4395 }
4396 #endif
4397 #if 0 /* restrict them some more: */
4398 /* Restrict ultra P pits */
4399 if (chosen_type == vault_aux_giant) {
4400 /* Find the first 'Hru' */
4401 for (i = 0; i < 8; i++) {
4402 if (what[i] == 709) {
4403 /* make one 'Hru' the top entry, all following entries weaker than 'Hru' */
4404 for (j = 7; j >= 7-i; j--) {
4405 what[j] = what[i+j-7];
4406 }
4407 break;
4408 }
4409 }
4410 /* Find the first 'Greater Titan' */
4411 for (i = 0; i < 8; i++) {
4412 if (what[i] == 702) {
4413 if (what[7] == 709) { /* Is a 'Hru' at the top? */
4414 /* make 'Greater Titan' the second to top entry, all following entries weaker than 'Greater Titan' */
4415 for (j = 6; j >= 6-i; j--) {
4416 what[j] = what[i+j-6];
4417 }
4418 break;
4419 } else {
4420 /* make one 'Greater Titan' the top entry, all following entries weaker than 'Greater Titan' */
4421 for (j = 7; j >= 7-i; j--) {
4422 what[j] = what[i+j-7];
4423 }
4424 break;
4425 }
4426 }
4427 }
4428 /* Find the first 'Lesser Titan' */
4429 for (i = 0; i < 8; i++) {
4430 if (what[i] == 634) {
4431 if (what[6] == 702) { /* Is a 'Greater Titan' already occupying the second to top position? */
4432 /* Remove either 'Lesser Titan' or 'Greater Titan' since 6 of them would be too many */
4433 if (magik(50)) what[i] = 702;
4434 for (j = 6; j >= 6-i; j--) {
4435 what[j] = what[i+j-6];
4436 }
4437 break;
4438 } else if (what[7] == 702 || what[7] == 709) {
4439 /* make one 'Lesser Titan' the second to top entry, all following entries weaker than 'Lesser Titan' */
4440 for (j = 6; j >= 6-i; j--) {
4441 what[j] = what[i+j-6];
4442 }
4443 break;
4444 } else {
4445 /* make one 'Lesser Titan' the top entry, all following entries weaker than 'Lesser Titan' */
4446 for (j = 7; j >= 7-i; j--) {
4447 what[j] = what[i+j-7];
4448 }
4449 break;
4450 }
4451 }
4452 }
4453 }
4454 #endif
4455 #if 1 /* no titans/hrus in P pits again */
4456 /* Restrict ultra P pits */
4457 if (chosen_type == vault_aux_giant) {
4458 /* Find the first 'Hru' */
4459 for (i = 0; i < 8; i++) {
4460 if (what[i] == 709) {
4461 /* make next entry the top entry, removing the 'Hru' */
4462 for (j = 7; j >= i; j--) {
4463 what[j] = what[i-1];
4464 }
4465 break;
4466 }
4467 }
4468 /* Find the first 'Greater Titan' */
4469 for (i = 0; i < 8; i++) {
4470 if (what[i] == 702) {
4471 /* make next entry the top entry, removing the 'Greater Titan' */
4472 for (j = 7; j >= i; j--) {
4473 what[j] = what[i-1];
4474 }
4475 break;
4476 }
4477 }
4478 /* Find the first 'Lesser Titan' */
4479 for (i = 0; i < 8; i++) {
4480 if (what[i] == 634) {
4481 /* make next entry the top entry, removing the 'Lesser Titan' */
4482 for (j = 7; j >= i; j--) {
4483 what[j] = what[i-1];
4484 }
4485 break;
4486 }
4487 }
4488 }
4489 #endif
4490
4491
4492 /* Debugging code for "holes" in pits :( */
4493 for (i = 0; i < 8; i++){
4494 if (!what[i]) s_printf("HOLE(%d)\n", i);
4495
4496 /* abuse the debugging code for setting extra level feelings =p */
4497 else if (r_info[what[i]].level >= 60) l_ptr->flags2 |= LF2_PITNEST_HI;
4498 }
4499 l_ptr->flags2 |= LF2_PITNEST;
4500 /* summoner pits are dangerous albeit not that high level really */
4501 if (chosen_type == vault_aux_man ||
4502 chosen_type == vault_aux_undead ||
4503 chosen_type == vault_aux_lesser_chapel)
4504 l_ptr->flags2 |= LF2_PITNEST_HI;
4505
4506
4507 /* Top and bottom rows */
4508 for (x = xval - 9; x <= xval + 9; x++) {
4509 place_monster_aux(wpos, yval - 2, x, what[0], FALSE, FALSE, FALSE, 0);
4510 place_monster_aux(wpos, yval + 2, x, what[0], FALSE, FALSE, FALSE, 0);
4511 }
4512
4513 /* Middle columns */
4514 for (y = yval - 1; y <= yval + 1; y++) {
4515 place_monster_aux(wpos, y, xval - 9, what[0], FALSE, FALSE, FALSE, 0);
4516 place_monster_aux(wpos, y, xval + 9, what[0], FALSE, FALSE, FALSE, 0);
4517
4518 place_monster_aux(wpos, y, xval - 8, what[1], FALSE, FALSE, FALSE, 0);
4519 place_monster_aux(wpos, y, xval + 8, what[1], FALSE, FALSE, FALSE, 0);
4520
4521 place_monster_aux(wpos, y, xval - 7, what[1], FALSE, FALSE, FALSE, 0);
4522 place_monster_aux(wpos, y, xval + 7, what[1], FALSE, FALSE, FALSE, 0);
4523
4524 place_monster_aux(wpos, y, xval - 6, what[2], FALSE, FALSE, FALSE, 0);
4525 place_monster_aux(wpos, y, xval + 6, what[2], FALSE, FALSE, FALSE, 0);
4526
4527 place_monster_aux(wpos, y, xval - 5, what[2], FALSE, FALSE, FALSE, 0);
4528 place_monster_aux(wpos, y, xval + 5, what[2], FALSE, FALSE, FALSE, 0);
4529
4530 place_monster_aux(wpos, y, xval - 4, what[3], FALSE, FALSE, FALSE, 0);
4531 place_monster_aux(wpos, y, xval + 4, what[3], FALSE, FALSE, FALSE, 0);
4532
4533 place_monster_aux(wpos, y, xval - 3, what[3], FALSE, FALSE, FALSE, 0);
4534 place_monster_aux(wpos, y, xval + 3, what[3], FALSE, FALSE, FALSE, 0);
4535
4536 place_monster_aux(wpos, y, xval - 2, what[4], FALSE, FALSE, FALSE, 0);
4537 place_monster_aux(wpos, y, xval + 2, what[4], FALSE, FALSE, FALSE, 0);
4538 }
4539
4540 /* Above/Below the center monster */
4541 for (x = xval - 1; x <= xval + 1; x++) {
4542 place_monster_aux(wpos, yval + 1, x, what[5], FALSE, FALSE, FALSE, 0);
4543 place_monster_aux(wpos, yval - 1, x, what[5], FALSE, FALSE, FALSE, 0);
4544 }
4545
4546 /* Next to the center monster */
4547 place_monster_aux(wpos, yval, xval + 1, what[6], FALSE, FALSE, FALSE, 0);
4548 place_monster_aux(wpos, yval, xval - 1, what[6], FALSE, FALSE, FALSE, 0);
4549
4550 /* Center monster */
4551 place_monster_aux(wpos, yval, xval, what[7], FALSE, FALSE, FALSE, 0);
4552 }
4553
4554
4555
4556 /*
4557 * Hack -- fill in "vault" rooms
4558 */
4559 bool build_vault(struct worldpos *wpos, int yval, int xval, vault_type *v_ptr, player_type *p_ptr)
4560 {
4561 int bwy[8], bwx[8], i;
4562 int dx, dy, x, y, cx, cy, lev = getlevel(wpos);
4563 cptr t;
4564
4565 #ifdef MORGOTH_NO_TELE_VAULT
4566 #ifndef MORGOTH_NO_TELE_VAULTS
4567 bool morgoth_inside = FALSE;
4568 monster_type *m_ptr;
4569 #endif
4570 #endif
4571 bool perma_walled = FALSE, placed;
4572
4573 cave_type *c_ptr;
4574 cave_type **zcave;
4575 c_special *cs_ptr;
4576 dun_level *l_ptr = getfloor(wpos);
4577 bool hives = FALSE, mirrorlr = FALSE, mirrorud = FALSE,
4578 rotate = FALSE, force = FALSE;
4579 int ymax = v_ptr->hgt, xmax = v_ptr->wid;
4580 char *data = v_text + v_ptr->text;
4581
4582 u32b resf = make_resf(p_ptr), eff_resf;
4583 int eff_forbid_true = 0, eff_forbid_rand = 0;
4584
4585 if (!(zcave = getcave(wpos))) return FALSE;
4586
4587 if (v_ptr->flags1 & VF1_NO_PENETR) dun->no_penetr = TRUE;
4588 #if 0 /* Hives mess up the overall level structure too badly - mikaelh */
4589 if (v_ptr->flags1 & VF1_HIVES) hives = TRUE;
4590 #endif
4591
4592 /* artificially add random-artifact restrictions: */
4593 if (lev < 55 + rand_int(6) + rand_int(6)) resf |= RESF_NORANDART;
4594 if (lev < 75 + rand_int(6) + rand_int(6)) eff_forbid_rand = 80;
4595 // if (!(v_ptr->flags1 & VF1_NO_TELE)) eff_forbid_rand = 50; /* maybe too harsh, depends on amount of '8's in deep tele-ok-vaults */
4596
4597 if (v_ptr->flags1 & VF1_NO_TRUEARTS) resf |= RESF_NOTRUEART;
4598 if (v_ptr->flags1 & VF1_NO_RANDARTS) resf |= RESF_NORANDART;
4599 if ((v_ptr->flags1 & VF1_NO_EASY_TRUEARTS) && lev < 75 + rand_int(6) + rand_int(6)) resf |= RESF_NOTRUEART;
4600 if ((v_ptr->flags1 & VF1_NO_EASY_RANDARTS) && lev < 75 + rand_int(6) + rand_int(6)) resf |= RESF_NORANDART;
4601
4602 if (v_ptr->flags1 & VF1_RARE_TRUEARTS) eff_forbid_true = 80;
4603 if (v_ptr->flags1 & VF1_RARE_RANDARTS) eff_forbid_rand = 80;
4604
4605 if (!hives) { /* Hack -- avoid ugly results */
4606 if (!(v_ptr->flags1 & VF1_NO_MIRROR)) {
4607 if (magik(30)) mirrorlr = TRUE;
4608 if (magik(30)) mirrorud = TRUE;
4609 }
4610 if (!(v_ptr->flags1 & VF1_NO_ROTATE) && magik(30)) rotate = TRUE;
4611 }
4612
4613 cx = xval - ((rotate?ymax:xmax) / 2) * (mirrorlr?-1:1);
4614 cy = yval - ((rotate?xmax:ymax) / 2) * (mirrorud?-1:1);
4615
4616 /* At least 1/4 should be genetated */
4617 if (!in_bounds4(l_ptr, cy, cx))
4618 return FALSE;
4619
4620 /* Check for flags */
4621 if (v_ptr->flags1 & VF1_FORCE_FLAGS) force = TRUE;
4622 if (v_ptr->flags1 & VF1_NO_GENO && (magik(VAULT_FLAG_CHANCE) || force))
4623 l_ptr->flags1 |= LF1_NO_GENO;
4624 if (v_ptr->flags1 & VF1_NO_MAP && (magik(VAULT_FLAG_CHANCE) || force))
4625 l_ptr->flags1 |= LF1_NO_MAP;
4626 if (v_ptr->flags1 & VF1_NO_MAGIC_MAP && (magik(VAULT_FLAG_CHANCE) || force))
4627 l_ptr->flags1 |= LF1_NO_MAGIC_MAP;
4628 if (v_ptr->flags1 & VF1_NO_DESTROY && (magik(VAULT_FLAG_CHANCE) || force))
4629 l_ptr->flags1 |= LF1_NO_DESTROY;
4630 if (v_ptr->flags1 & VF1_NO_MAGIC && (magik(VAULT_FLAG_CHANCE) || force)
4631 && lev < 100)
4632 l_ptr->flags1 |= LF1_NO_MAGIC;
4633
4634 /* Clean the between gates arrays */
4635 for(i = 0; i < 8; i++)
4636 bwy[i] = bwx[i] = 9999;
4637
4638 /* Place dungeon features and objects */
4639 for (t = data, dy = 0; dy < ymax; dy++) {
4640 for (dx = 0; dx < xmax; dx++, t++) {
4641 eff_resf = resf;
4642 if (magik(eff_forbid_true)) eff_resf |= RESF_NOTRUEART;
4643 if (magik(eff_forbid_rand)) eff_resf |= RESF_NORANDART;
4644
4645 /* Extract the location */
4646 /* x = xval - (xmax / 2) + dx;
4647 y = yval - (ymax / 2) + dy; */
4648 x = cx + (rotate?dy:dx) * (mirrorlr?-1:1);
4649 y = cy + (rotate?dx:dy) * (mirrorud?-1:1);
4650
4651 /* FIXME - find a better solution */
4652 /* Is this any better? */
4653 if(!in_bounds4(l_ptr,y,x))
4654 continue;
4655
4656 /* Hack -- skip "non-grids" */
4657 if (*t == ' ') continue;
4658
4659 /* Access the grid */
4660 c_ptr = &zcave[y][x];
4661
4662 /* Lay down a floor */
4663 place_floor(wpos, y, x);
4664
4665 /* Remove previous monsters - mikaelh */
4666 delete_monster(wpos, y, x, TRUE);
4667
4668 /* Part of a vault */
4669 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
4670 if(v_ptr->flags1 & VF1_NO_TELEPORT)
4671 c_ptr->info |= CAVE_STCK;
4672
4673 /* Analyze the grid */
4674 switch (*t) {
4675 /* Granite wall (outer) */
4676 case '%':
4677 c_ptr->feat = FEAT_WALL_OUTER;
4678 break;
4679
4680 /* Granite wall (inner) */
4681 case '#':
4682 c_ptr->feat = FEAT_WALL_INNER;
4683 break;
4684
4685 /* Permanent wall (inner) */
4686 case 'X':
4687 c_ptr->feat = FEAT_PERM_INNER;
4688 perma_walled = TRUE;
4689 break;
4690
4691 /* Treasure/trap */
4692 case '*':
4693 if (rand_int(100) < 75)
4694 place_object(wpos, y, x, FALSE, FALSE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4695 if (rand_int(100) < 40)
4696 place_trap(wpos, y, x, 0);
4697 break;
4698
4699 /* Secret doors */
4700 case '+':
4701 place_secret_door(wpos, y, x);
4702 if (magik(20))
4703 {
4704 place_trap(wpos, y, x, 0);
4705 }
4706 break;
4707
4708 /* Trap */
4709 case '^':
4710 place_trap(wpos, y, x, 0);
4711 break;
4712
4713 #if 0 /* done later in 2nd pass - mikaelh */
4714 /* Monster */
4715 case '&':
4716 monster_level = lev + 5;
4717 place_monster(wpos, y, x, TRUE, TRUE);
4718 monster_level = lev;
4719 break;
4720
4721 /* Meaner monster */
4722 case '@':
4723 monster_level = lev + 11;
4724 monster_level_min = -1;
4725 place_monster(wpos, y, x, TRUE, TRUE);
4726 monster_level_min = 0;
4727 monster_level = lev;
4728 break;
4729
4730 /* Meaner monster, plus treasure */
4731 case '9':
4732 monster_level = lev + 9;
4733 monster_level_min = -1;
4734 place_monster(wpos, y, x, TRUE, TRUE);
4735 monster_level_min = 0;
4736 monster_level = lev;
4737 object_level = lev + 7;
4738 place_object(wpos, y, x, TRUE, FALSE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4739 object_level = lev;
4740 if (magik(40)) place_trap(wpos, y, x, 0);
4741 break;
4742
4743 /* Nasty (meanest) monster and treasure */
4744 case '8':
4745 monster_level = lev + 40;
4746 monster_level_min = -1;
4747 place_monster(wpos, y, x, TRUE, TRUE);
4748 monster_level_min = 0;
4749 monster_level = lev;
4750 object_level = lev + 20;
4751 place_object(wpos, y, x, TRUE, TRUE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4752 object_level = lev;
4753 if (magik(80)) place_trap(wpos, y, x, 0);
4754 l_ptr->flags2 |= LF2_VAULT_HI;
4755 #ifdef TEST_SERVER
4756 s_printf("DEBUG_FEELING: VAULT_HI by build_vault(), '8' monster\n");
4757 #endif
4758 break;
4759
4760 /* Monster and/or object */
4761 case ',':
4762 if (magik(50)) {
4763 monster_level = lev + 3;
4764 place_monster(wpos, y, x, TRUE, TRUE);
4765 monster_level = lev;
4766 }
4767 if (magik(50)) {
4768 object_level = lev + 7;
4769 place_object(wpos, y, x, FALSE, FALSE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4770 object_level = lev;
4771 }
4772 if (magik(50)) place_trap(wpos, y, x, 0);
4773 break;
4774 #endif
4775
4776 /* Between gates */
4777 case '0':
4778 case '1':
4779 case '2':
4780 case '3':
4781 case '4':
4782 case '5':
4783 case '6':
4784 case '7':
4785 {
4786 /* XXX not sure what will happen if the cave already has
4787 * another between gate */
4788 /* Not found before */
4789 if(bwy[*t - '0'] == 9999) {
4790 if (!(cs_ptr = AddCS(c_ptr, CS_BETWEEN))) {
4791 #if DEBUG_LEVEL > 0
4792 s_printf("oops, vault between gates generation failed(1st: %s)!!\n", wpos_format(0, wpos));
4793 #endif /* DEBUG_LEVEL */
4794 break;
4795 }
4796 cave_set_feat(wpos, y, x, FEAT_BETWEEN);
4797 bwy[*t - '0'] = y;
4798 bwx[*t - '0'] = x;
4799 }
4800 /* The second time */
4801 else {
4802 if (!(cs_ptr = AddCS(c_ptr, CS_BETWEEN))) {
4803 #if DEBUG_LEVEL > 0
4804 s_printf("oops, vault between gates generation failed(2nd: %s)!!\n", wpos_format(0, wpos));
4805 #endif /* DEBUG_LEVEL */
4806 break;
4807 }
4808 cave_set_feat(wpos, y, x, FEAT_BETWEEN);
4809 cs_ptr->sc.between.fy = bwy[*t - '0'];
4810 cs_ptr->sc.between.fx = bwx[*t - '0'];
4811
4812 cs_ptr = GetCS(&zcave[bwy[*t - '0']][bwx[*t - '0']], CS_BETWEEN);
4813 cs_ptr->sc.between.fy = y;
4814 cs_ptr->sc.between.fx = x;
4815 #if 0
4816 c_ptr->special = bwx[*t - '0'] + (bwy[*t - '0'] << 8);
4817 cave[bwy[*t - '0']][bwx[*t - '0']].special = x + (y << 8);
4818 #endif /* 0 */
4819 }
4820 break;
4821 }
4822 }
4823 }
4824 }
4825
4826 /* Another pass for monsters */
4827 for (t = data, dy = 0; dy < ymax; dy++) {
4828 for (dx = 0; dx < xmax; dx++, t++) {
4829 eff_resf = resf;
4830 if (magik(eff_forbid_true)) eff_resf |= RESF_NOTRUEART;
4831 if (magik(eff_forbid_rand)) eff_resf |= RESF_NORANDART;
4832
4833 /* Extract the location */
4834 /* x = xval - (xmax / 2) + dx;
4835 y = yval - (ymax / 2) + dy; */
4836 x = cx + (rotate?dy:dx) * (mirrorlr?-1:1);
4837 y = cy + (rotate?dx:dy) * (mirrorud?-1:1);
4838
4839 /* FIXME - find a better solution */
4840 /* Is this any better? */
4841 if(!in_bounds4(l_ptr,y,x)) continue;
4842
4843 /* Hack -- skip "non-grids" */
4844 if (*t == ' ') continue;
4845
4846 /* Access the grid */
4847 c_ptr = &zcave[y][x];
4848
4849 /* Analyze the grid */
4850 switch (*t) {
4851 /* Monster */
4852 case '&':
4853 monster_level = lev + 5;
4854 place_monster(wpos, y, x, TRUE, TRUE);
4855 monster_level = lev;
4856 break;
4857
4858 /* Meaner monster */
4859 case '@':
4860 monster_level = lev + 11;
4861 monster_level_min = -1;
4862 place_monster(wpos, y, x, TRUE, TRUE);
4863 monster_level_min = 0;
4864 monster_level = lev;
4865 break;
4866
4867 /* Meaner monster, plus treasure */
4868 case '9':
4869 monster_level = lev + 9;
4870 monster_level_min = -1;
4871 placed = place_monster(wpos, y, x, TRUE, TRUE);
4872 monster_level_min = 0;
4873 monster_level = lev;
4874 object_level = lev + 7;
4875 if (placed) place_object(wpos, y, x, TRUE, FALSE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4876 object_level = lev;
4877 if (magik(40)) place_trap(wpos, y, x, 0);
4878 break;
4879
4880 /* Nasty (meanest) monster and treasure */
4881 case '8':
4882 monster_level = lev + 40;
4883 monster_level_min = -1;
4884 placed = place_monster(wpos, y, x, TRUE, TRUE);
4885 monster_level_min = 0;
4886 monster_level = lev;
4887 object_level = lev + 20;
4888 if (placed) place_object(wpos, y, x, TRUE, TRUE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4889 object_level = lev;
4890 if (magik(80)) place_trap(wpos, y, x, 0);
4891 l_ptr->flags2 |= LF2_VAULT_HI;
4892 #ifdef TEST_SERVER
4893 s_printf("DEBUG_FEELING: VAULT_HI by build_vault(), '8' monster\n");
4894 #endif
4895 break;
4896
4897 /* Monster and/or object */
4898 case ',':
4899 placed = TRUE;
4900 if (magik(50)) {
4901 monster_level = lev + 3;
4902 placed = place_monster(wpos, y, x, TRUE, TRUE);
4903 monster_level = lev;
4904 }
4905 if (magik(50) && placed) {
4906 object_level = lev + 7;
4907 place_object(wpos, y, x, FALSE, FALSE, FALSE, eff_resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
4908 object_level = lev;
4909 }
4910 if (magik(50)) place_trap(wpos, y, x, 0);
4911 break;
4912 }
4913
4914 #ifdef MORGOTH_NO_TELE_VAULT
4915 #ifndef MORGOTH_NO_TELE_VAULTS
4916 if (c_ptr->m_idx > 0) {
4917 /* Check if Morgoth was just placed inside */
4918 /* Acquire monster pointer */
4919 m_ptr = &m_list[c_ptr->m_idx];
4920 /* check.. */
4921 if (m_ptr->r_idx == RI_MORGOTH) morgoth_inside = TRUE;
4922 }
4923 #endif
4924 #endif
4925 }
4926 }
4927
4928 /* Check if vault is perma_walled, and make its fields 'remember' that */
4929 if (perma_walled) {
4930 for (t = data, dy = 0; dy < ymax; dy++) {
4931 for (dx = 0; dx < xmax; dx++, t++) {
4932 /* Extract the location */
4933 /* x = xval - (xmax / 2) + dx;
4934 y = yval - (ymax / 2) + dy; */
4935 x = cx + (rotate?dy:dx) * (mirrorlr?-1:1);
4936 y = cy + (rotate?dx:dy) * (mirrorud?-1:1);
4937
4938 /* FIXME - find a better solution */
4939 /* Is this any better? */
4940 if(!in_bounds4(l_ptr,y,x)) continue;
4941
4942 /* Hack -- skip "non-grids" */
4943 if (*t == ' ') continue;
4944
4945 /* Access the grid */
4946 c_ptr = &zcave[y][x];
4947
4948 /* Remember that this field belongs to a perma-wall vault */
4949 c_ptr->info |= CAVE_ICKY_PERMA;
4950
4951 /* overridden by MORGOTH_NO_TELE_VAULTS:
4952 instead of making just that vault no-tele,
4953 now all vaults on the level are no-tele;
4954 performed in cave_gen (in generate.c too) */
4955 #ifdef MORGOTH_NO_TELE_VAULT
4956 #ifndef MORGOTH_NO_TELE_VAULTS
4957 if (morgoth_inside)
4958 /* Make it NO_TELEPORT */
4959 c_ptr->info |= CAVE_STCK;
4960 #endif
4961 #endif
4962 }
4963 }
4964 }
4965
4966 /* Reproduce itself */
4967 /* TODO: make a better routine! */
4968 if (hives)
4969 {
4970 if (magik(HIVE_CHANCE(lev)) && !magik(ymax))
4971 build_vault(wpos, yval + ymax, xval, v_ptr, p_ptr);
4972 if (magik(HIVE_CHANCE(lev)) && !magik(xmax))
4973 build_vault(wpos, yval, xval + xmax, v_ptr, p_ptr);
4974 }
4975
4976 l_ptr->flags2 |= LF2_VAULT;
4977 return TRUE;
4978 }
4979
4980
4981
4982 /*
4983 * Type 7 -- simple vaults (see "v_info.txt")
4984 */
4985 static void build_type7(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
4986 {
4987 vault_type *v_ptr;
4988 int xval, yval, tries = 1000;
4989 cave_type **zcave;
4990 if (!(zcave = getcave(wpos))) return;
4991
4992 /* Pick a lesser vault */
4993 while (--tries)
4994 {
4995 /* Access a random vault record */
4996 v_ptr = &v_info[rand_int(MAX_V_IDX)];
4997
4998 /* Accept the first lesser vault */
4999 if (v_ptr->typ == 7) break;
5000 }
5001 if (!tries) return; /* failure */
5002
5003 /* Try to allocate space for room. If fails, exit */
5004 if (!room_alloc(wpos, v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
5005 {
5006 return;
5007 }
5008
5009 /* Hack -- Build the vault */
5010 build_vault(wpos, yval, xval, v_ptr, p_ptr);
5011 }
5012
5013
5014
5015 /*
5016 * Type 8 -- greater vaults (see "v_info.txt")
5017 */
5018 static void build_type8(struct worldpos *wpos, int by0, int bx0, player_type *p_ptr)
5019 {
5020 dun_level *l_ptr = getfloor(wpos);
5021 vault_type *v_ptr;
5022 int xval, yval, tries = 1000;
5023 cave_type **zcave;
5024 if (!(zcave = getcave(wpos))) return;
5025
5026 /* Pick a greater vault */
5027 while (--tries)
5028 {
5029 /* Access a random vault record */
5030 v_ptr = &v_info[rand_int(MAX_V_IDX)];
5031
5032 /* Accept the first greater vault */
5033 if (v_ptr->typ == 8) break;
5034 }
5035 if (!tries) return; /* failure */
5036
5037 /* Try to allocate space for room. If fails, exit */
5038 if (!room_alloc(wpos, v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
5039 {
5040 return;
5041 }
5042
5043 /* Hack -- Build the vault */
5044 if (build_vault(wpos, yval, xval, v_ptr, p_ptr)) {
5045 l_ptr->flags2 |= LF2_VAULT_HI;
5046 #ifdef TEST_SERVER
5047 s_printf("DEBUG_FEELING: VAULT_HI by build_type8->build_vault\n");
5048 #endif
5049 }
5050
5051 }
5052
5053
5054 /* XXX XXX Here begins a big lump of ToME cake - Jir - */
5055 /* XXX XXX part II -- builders */
5056
5057 /*
5058 * DAG:
5059 * Build an vertical oval room.
5060 * For every grid in the possible square, check the distance.
5061 * If it's less than or == than the radius, make it a room square.
5062 * If its less, make it a normal grid. If it's == make it an outer
5063 * wall.
5064 */
5065 /* Don't allow outer walls that can be passed by walking diagonally? - C. Blue */
5066 #define BUILD_TYPE9_SOLID_OUTER_WALLS
5067 static void build_type9(worldpos *wpos, int by0, int bx0, player_type *p_ptr)
5068 {
5069 int rad, x, y, x0, y0, d;
5070 int light = FALSE;
5071 int dun_lev = getlevel(wpos);
5072 cave_type **zcave;
5073 if (!(zcave = getcave(wpos))) return;
5074
5075 /* Occasional light */
5076 if (randint(dun_lev) <= 5) light = TRUE;
5077
5078 /* Room size */
5079 rad = rand_int(10);
5080
5081 /* Try to allocate space for room. If fails, exit */
5082 if (!room_alloc(wpos, rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
5083
5084 for (x = x0 - rad; x <= x0 + rad; x++) {
5085 for (y = y0 - rad; y <= y0 + rad; y++) {
5086 #ifdef BUILD_TYPE9_SOLID_OUTER_WALLS
5087 d = distance(y0 * 10, x0 * 10, y * 10, x * 10);
5088 #else
5089 d = distance(y0, x0, y, x);
5090 #endif
5091
5092 #ifdef BUILD_TYPE9_SOLID_OUTER_WALLS
5093 if (d <= rad * 10 + 5 && d >= rad * 10 - 5) {
5094 #else
5095 if (d == rad) {
5096 #endif
5097 zcave[y][x].info |= (CAVE_ROOM);
5098 if (light) zcave[y][x].info |= (CAVE_GLOW);
5099 cave_set_feat(wpos, y, x, feat_wall_outer);
5100 }
5101
5102 #ifdef BUILD_TYPE9_SOLID_OUTER_WALLS
5103 if (d < rad * 10 - 5) {
5104 #else
5105 if (d < rad) {
5106 #endif
5107 zcave[y][x].info |= (CAVE_ROOM);
5108 if (light) zcave[y][x].info |= (CAVE_GLOW);
5109 place_floor(wpos, y, x);
5110 }
5111 }
5112 }
5113 }
5114
5115
5116 /*
5117 * Store routine for the fractal cave generator
5118 * this routine probably should be an inline function or a macro
5119 */
5120 static void store_height(worldpos *wpos, int x, int y, int x0, int y0, byte val,
5121 int xhsize, int yhsize, int cutoff)
5122 {
5123 cave_type **zcave;
5124 if (!(zcave = getcave(wpos))) return;
5125
5126 /* Only write to points that are "blank" */
5127 if (zcave[y+ y0 - yhsize][x + x0 - xhsize].feat != 255) return;
5128
5129 /* If on boundary set val > cutoff so walls are not as square */
5130 if (((x == 0) || (y == 0) || (x == xhsize * 2) || (y == yhsize * 2)) &&
5131 (val <= cutoff)) val = cutoff + 1;
5132
5133 /* Store the value in height-map format */
5134 /* Meant to be temporary, hence no cave_set_feat */
5135 zcave[y + y0 - yhsize][x + x0 - xhsize].feat = val;
5136
5137 return;
5138 }
5139
5140
5141
5142 /*
5143 * Explanation of the plasma fractal algorithm:
5144 *
5145 * A grid of points is created with the properties of a 'height-map'
5146 * This is done by making the corners of the grid have a random value.
5147 * The grid is then subdivided into one with twice the resolution.
5148 * The new points midway between two 'known' points can be calculated
5149 * by taking the average value of the 'known' ones and randomly adding
5150 * or subtracting an amount proportional to the distance between those
5151 * points. The final 'middle' points of the grid are then calculated
5152 * by averaging all four of the originally 'known' corner points. An
5153 * random amount is added or subtracted from this to get a value of the
5154 * height at that point. The scaling factor here is adjusted to the
5155 * slightly larger distance diagonally as compared to orthogonally.
5156 *
5157 * This is then repeated recursively to fill an entire 'height-map'
5158 * A rectangular map is done the same way, except there are different
5159 * scaling factors along the x and y directions.
5160 *
5161 * A hack to change the amount of correlation between points is done using
5162 * the grd variable. If the current step size is greater than grd then
5163 * the point will be random, otherwise it will be calculated by the
5164 * above algorithm. This makes a maximum distance at which two points on
5165 * the height map can affect each other.
5166 *
5167 * How fractal caves are made:
5168 *
5169 * When the map is complete, a cut-off value is used to create a cave.
5170 * Heights below this value are "floor", and heights above are "wall".
5171 * This also can be used to create lakes, by adding more height levels
5172 * representing shallow and deep water/ lava etc.
5173 *
5174 * The grd variable affects the width of passages.
5175 * The roug variable affects the roughness of those passages
5176 *
5177 * The tricky part is making sure the created cave is connected. This
5178 * is done by 'filling' from the inside and only keeping the 'filled'
5179 * floor. Walls bounding the 'filled' floor are also kept. Everything
5180 * else is converted to the normal granite FEAT_WALL_EXTRA.
5181 */
5182
5183
5184 /*
5185 * Note that this uses the cave.feat array in a very hackish way
5186 * the values are first set to zero, and then each array location
5187 * is used as a "heightmap"
5188 * The heightmap then needs to be converted back into the "feat" format.
5189 *
5190 * grd=level at which fractal turns on. smaller gives more mazelike caves
5191 * roug=roughness level. 16=normal. higher values make things more
5192 * convoluted small values are good for smooth walls.
5193 * size=length of the side of the square cave system.
5194 */
5195
5196 static void generate_hmap(worldpos *wpos, int y0, int x0, int xsiz, int ysiz, int grd,
5197 int roug, int cutoff)
5198 {
5199 int xhsize, yhsize, xsize, ysize, maxsize;
5200
5201 /*
5202 * fixed point variables- these are stored as 256 x normal value
5203 * this gives 8 binary places of fractional part + 8 places of normal part
5204 */
5205 u16b xstep, xhstep, ystep, yhstep, i, j, diagsize, xxsize, yysize;
5206
5207 cave_type **zcave;
5208 if (!(zcave = getcave(wpos))) return;
5209
5210
5211 /* Redefine size so can change the value if out of range */
5212 xsize = xsiz;
5213 ysize = ysiz;
5214
5215 /* Paranoia about size of the system of caves*/
5216 if (xsize > 254) xsize = 254;
5217 if (xsize < 4) xsize = 4;
5218 if (ysize > 254) ysize = 254;
5219 if (ysize < 4) ysize = 4;
5220
5221 /* Get offsets to middle of array */
5222 xhsize = xsize / 2;
5223 yhsize = ysize / 2;
5224
5225 /* Fix rounding problem */
5226 xsize = xhsize * 2;
5227 ysize = yhsize * 2;
5228
5229 /*
5230 * Scale factor for middle points:
5231 * About sqrt(2)*256 - correct for a square lattice
5232 * approximately correct for everything else.
5233 */
5234 diagsize = 362;
5235
5236 /* Maximum of xsize and ysize */
5237 maxsize = (xsize > ysize) ? xsize : ysize;
5238
5239 /* Clear the section */
5240 for (i = 0; i <= xsize; i++)
5241 {
5242 for (j = 0; j <= ysize; j++)
5243 {
5244 cave_type *c_ptr;
5245
5246 /* Access the grid */
5247 c_ptr = &zcave[j + y0 - yhsize][i + x0 - xhsize];
5248
5249 /* 255 is a flag for "not done yet" */
5250 c_ptr->feat = 255;
5251
5252 /* Clear icky flag because may be redoing the cave */
5253 c_ptr->info &= ~(CAVE_ICKY);
5254 }
5255 }
5256
5257 /* Set the corner values just in case grd>size. */
5258 store_height(wpos, 0, 0, x0, y0, maxsize, xhsize, yhsize, cutoff);
5259 store_height(wpos, 0, ysize, x0, y0, maxsize, xhsize, yhsize, cutoff);
5260 store_height(wpos, xsize, 0, x0, y0, maxsize, xhsize, yhsize, cutoff);
5261 store_height(wpos, xsize, ysize, x0, y0, maxsize, xhsize, yhsize, cutoff);
5262
5263 /* Set the middle square to be an open area. */
5264 store_height(wpos, xhsize, yhsize, x0, y0, 0, xhsize, yhsize, cutoff);
5265
5266
5267 /* Initialise the step sizes */
5268 xstep = xhstep = xsize*256;
5269 ystep = yhstep = ysize*256;
5270 xxsize = xsize*256;
5271 yysize = ysize*256;
5272
5273 /*
5274 * Fill in the rectangle with fractal height data - like the
5275 * 'plasma fractal' in fractint
5276 */
5277 while ((xstep/256 > 1) || (ystep/256 > 1))
5278 {
5279 /* Halve the step sizes */
5280 xstep = xhstep;
5281 xhstep /= 2;
5282 ystep = yhstep;
5283 yhstep /= 2;
5284
5285 /* Middle top to bottom */
5286 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
5287 {
5288 for (j = 0; j <= yysize; j += ystep)
5289 {
5290 /* If greater than 'grid' level then is random */
5291 if (xhstep/256 > grd)
5292 {
5293 store_height(wpos, i/256, j/256, x0, y0, randint(maxsize),
5294 xhsize, yhsize, cutoff);
5295 }
5296 else
5297 {
5298 cave_type *l, *r;
5299 byte val;
5300
5301 /* Left point */
5302 l = &zcave[j/256+y0-yhsize][(i-xhstep)/256+x0-xhsize];
5303
5304 /* Right point */
5305 r = &zcave[j/256+y0-yhsize][(i+xhstep)/256+x0-xhsize];
5306
5307 /* Average of left and right points + random bit */
5308 val = (l->feat + r->feat) / 2 +
5309 (randint(xstep/256) - xhstep/256) * roug / 16;
5310
5311 store_height(wpos, i/256, j/256, x0, y0, val,
5312 xhsize, yhsize, cutoff);
5313 }
5314 }
5315 }
5316
5317
5318 /* Middle left to right */
5319 for (j = yhstep; j <= yysize - yhstep; j += ystep)
5320 {
5321 for (i = 0; i <= xxsize; i += xstep)
5322 {
5323 /* If greater than 'grid' level then is random */
5324 if (xhstep/256 > grd)
5325 {
5326 store_height(wpos, i/256, j/256, x0, y0, randint(maxsize),
5327 xhsize, yhsize, cutoff);
5328 }
5329 else
5330 {
5331 cave_type *u, *d;
5332 byte val;
5333
5334 /* Up point */
5335 u = &zcave[(j-yhstep)/256+y0-yhsize][i/256+x0-xhsize];
5336
5337 /* Down point */
5338 d = &zcave[(j+yhstep)/256+y0-yhsize][i/256+x0-xhsize];
5339
5340 /* Average of up and down points + random bit */
5341 val = (u->feat + d->feat) / 2 +
5342 (randint(ystep/256) - yhstep/256) * roug / 16;
5343
5344 store_height(wpos, i/256, j/256, x0, y0, val,
5345 xhsize, yhsize, cutoff);
5346 }
5347 }
5348 }
5349
5350 /* Center */
5351 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
5352 {
5353 for (j = yhstep; j <= yysize - yhstep; j += ystep)
5354 {
5355 /* If greater than 'grid' level then is random */
5356 if (xhstep/256 > grd)
5357 {
5358 store_height(wpos, i/256, j/256, x0, y0, randint(maxsize),
5359 xhsize, yhsize, cutoff);
5360 }
5361 else
5362 {
5363 cave_type *ul, *dl, *ur, *dr;
5364 byte val;
5365
5366 /* Up-left point */
5367 ul = &zcave[(j-yhstep)/256+y0-yhsize][(i-xhstep)/256+x0-xhsize];
5368
5369 /* Down-left point */
5370 dl = &zcave[(j+yhstep)/256+y0-yhsize][(i-xhstep)/256+x0-xhsize];
5371
5372 /* Up-right point */
5373 ur = &zcave[(j-yhstep)/256+y0-yhsize][(i+xhstep)/256+x0-xhsize];
5374
5375 /* Down-right point */
5376 dr = &zcave[(j+yhstep)/256+y0-yhsize][(i+xhstep)/256+x0-xhsize];
5377
5378 /*
5379 * average over all four corners + scale by diagsize to
5380 * reduce the effect of the square grid on the shape
5381 * of the fractal
5382 */
5383 val = (ul->feat + dl->feat + ur->feat + dr->feat) / 4 +
5384 (randint(xstep/256) - xhstep/256) *
5385 (diagsize / 16) / 256 * roug;
5386
5387 store_height(wpos, i/256, j/256, x0, y0, val,
5388 xhsize, yhsize ,cutoff);
5389 }
5390 }
5391 }
5392 }
5393 }
5394
5395
5396 /*
5397 * Convert from height-map back to the normal Angband cave format
5398 */
5399 static bool hack_isnt_wall(worldpos *wpos, int y, int x, int cutoff)
5400 {
5401 cave_type **zcave;
5402 if (!(zcave = getcave(wpos))) return(FALSE);
5403
5404 /* Already done */
5405 if (zcave[y][x].info & CAVE_ICKY)
5406 {
5407 return (FALSE);
5408 }
5409
5410 else
5411 {
5412 /* Show that have looked at this square */
5413 zcave[y][x].info |= (CAVE_ICKY);
5414
5415 /* If less than cutoff then is a floor */
5416 if (zcave[y][x].feat <= cutoff)
5417 {
5418 place_floor(wpos, y, x);
5419 return (TRUE);
5420 }
5421
5422 /* If greater than cutoff then is a wall */
5423 else
5424 {
5425 cave_set_feat(wpos, y, x, feat_wall_outer);
5426 return (FALSE);
5427 }
5428 }
5429 }
5430
5431
5432 /*
5433 * Quick and nasty fill routine used to find the connected region
5434 * of floor in the middle of the cave
5435 */
5436 static void fill_hack(worldpos *wpos, int y0, int x0, int y, int x, int xsize, int ysize,
5437 int cutoff, int *amount)
5438 {
5439 int i, j;
5440 cave_type **zcave;
5441 if (!(zcave = getcave(wpos))) return;
5442
5443
5444 /* check 8 neighbours +self (self is caught in the isnt_wall function) */
5445 for (i = -1; i <= 1; i++)
5446 {
5447 for (j = -1; j <= 1; j++)
5448 {
5449 /* If within bounds */
5450 if ((x + i > 0) && (x + i < xsize) &&
5451 (y + j > 0) && (y + j < ysize))
5452 {
5453 /* If not a wall or floor done before */
5454 if (hack_isnt_wall(wpos, y + j + y0 - ysize / 2,
5455 x + i + x0 - xsize / 2, cutoff))
5456 {
5457 /* then fill from the new point*/
5458 fill_hack(wpos, y0, x0, y + j, x + i, xsize, ysize,
5459 cutoff, amount);
5460
5461 /* keep tally of size of cave system */
5462 (*amount)++;
5463 }
5464 }
5465
5466 /* Affect boundary */
5467 else
5468 {
5469 zcave[y0+y+j-ysize/2][x0+x+i-xsize/2].info |= (CAVE_ICKY);
5470 }
5471 }
5472 }
5473 }
5474
5475
5476 static bool generate_fracave(worldpos *wpos, int y0, int x0, int xsize, int ysize,
5477 int cutoff, bool light, bool room)
5478 {
5479 int x, y, i, amount, xhsize, yhsize;
5480 cave_type *c_ptr;
5481 cave_type **zcave;
5482 if (!(zcave = getcave(wpos))) return(FALSE);
5483
5484 /* Offsets to middle from corner */
5485 xhsize = xsize / 2;
5486 yhsize = ysize / 2;
5487
5488 /* Reset tally */
5489 amount = 0;
5490
5491 /*
5492 * Select region connected to center of cave system
5493 * this gets rid of alot of isolated one-sqaures that
5494 * can make teleport traps instadeaths...
5495 */
5496 fill_hack(wpos, y0, x0, yhsize, xhsize, xsize, ysize, cutoff, &amount);
5497
5498 /* If tally too small, try again */
5499 if (amount < 10)
5500 {
5501 /* Too small -- clear area and try again later */
5502 for (x = 0; x <= xsize; ++x)
5503 {
5504 for (y = 0; y < ysize; ++y)
5505 {
5506 place_filler(wpos, y0+y-yhsize, x0+x-xhsize);
5507 zcave[y0+y-yhsize][x0+x-xhsize].info &= ~(CAVE_ICKY|CAVE_ROOM);
5508 }
5509 }
5510 return FALSE;
5511 }
5512
5513
5514 /*
5515 * Do boundaries -- check to see if they are next to a filled region
5516 * If not then they are set to normal granite
5517 * If so then they are marked as room walls
5518 */
5519 for (i = 0; i <= xsize; ++i)
5520 {
5521 /* Access top boundary grid */
5522 c_ptr = &zcave[0 + y0 - yhsize][i + x0 - xhsize];
5523
5524 /* Next to a 'filled' region? -- set to be room walls */
5525 if (c_ptr->info & CAVE_ICKY)
5526 {
5527 cave_set_feat(wpos, 0+y0-yhsize, i+x0-xhsize, feat_wall_outer);
5528
5529 if (light) c_ptr->info |= (CAVE_GLOW);
5530 if (room)
5531 c_ptr->info |= (CAVE_ROOM);
5532 else
5533 place_filler(wpos, 0+y0-yhsize, i+x0-xhsize);
5534 }
5535
5536 /* Outside of the room -- set to be normal granite */
5537 else
5538 {
5539 place_filler(wpos, 0+y0-yhsize, i+x0-xhsize);
5540 }
5541
5542 /* Clear the icky flag -- don't need it any more */
5543 c_ptr->info &= ~(CAVE_ICKY);
5544
5545
5546 /* Access bottom boundary grid */
5547 c_ptr = &zcave[ysize + y0 - yhsize][i + x0 - xhsize];
5548
5549 /* Next to a 'filled' region? -- set to be room walls */
5550 if (c_ptr->info & CAVE_ICKY)
5551 {
5552 cave_set_feat(wpos, ysize+y0-yhsize, i+x0-xhsize, feat_wall_outer);
5553 if (light) c_ptr->info |= (CAVE_GLOW);
5554 if (room)
5555 c_ptr->info |= (CAVE_ROOM);
5556 else
5557 place_filler(wpos, ysize+y0-yhsize, i+x0-xhsize);
5558 }
5559
5560 /* Outside of the room -- set to be normal granite */
5561 else
5562 {
5563 place_filler(wpos, ysize+y0-yhsize, i+x0-xhsize);
5564 }
5565
5566 /* Clear the icky flag -- don't need it any more */
5567 c_ptr->info &= ~(CAVE_ICKY);
5568 }
5569
5570
5571 /* Do the left and right boundaries minus the corners (done above) */
5572 for (i = 1; i < ysize; ++i)
5573 {
5574 /* Access left boundary grid */
5575 c_ptr = &zcave[i + y0 - yhsize][0 + x0 - xhsize];
5576
5577 /* Next to a 'filled' region? -- set to be room walls */
5578 if (c_ptr->info & CAVE_ICKY)
5579 {
5580 cave_set_feat(wpos, i+y0-yhsize, 0+x0-xhsize, feat_wall_outer);
5581 if (light) c_ptr->info |= (CAVE_GLOW);
5582 if (room)
5583 {
5584 c_ptr->info |= (CAVE_ROOM);
5585 }
5586 else
5587 {
5588 place_filler(wpos, i+y0-yhsize, 0+x0-xhsize);
5589 }
5590 }
5591
5592 /* Outside of the room -- set to be normal granite */
5593 else
5594 {
5595 place_filler(wpos, i+y0-yhsize, 0+x0-xhsize);
5596 }
5597
5598 /* Clear the icky flag -- don't need it any more */
5599 c_ptr->info &= ~(CAVE_ICKY);
5600
5601
5602 /* Access left boundary grid */
5603 c_ptr = &zcave[i + y0 - yhsize][xsize + x0 - xhsize];
5604
5605 /* Next to a 'filled' region? -- set to be room walls */
5606 if (c_ptr->info & CAVE_ICKY)
5607 {
5608 cave_set_feat(wpos, i+y0-yhsize, xsize+x0-xhsize, feat_wall_outer);
5609 if (light) c_ptr->info |= (CAVE_GLOW);
5610 if (room)
5611 {
5612 c_ptr->info |= (CAVE_ROOM);
5613 }
5614 else
5615 {
5616 place_filler(wpos, i+y0-yhsize, xsize+x0-xhsize);
5617 }
5618 }
5619
5620 /* Outside of the room -- set to be normal granite */
5621 else
5622 {
5623 place_filler(wpos, i+y0-yhsize, xsize+x0-xhsize);
5624 }
5625
5626 /* Clear the icky flag -- don't need it any more */
5627 c_ptr->info &= ~(CAVE_ICKY);
5628 }
5629
5630
5631 /*
5632 * Do the rest: convert back to the normal format
5633 * In other variants, may want to check to see if cave.feat< some value
5634 * if so, set to be water:- this will make interesting pools etc.
5635 * (I don't do this for standard Angband.)
5636 */
5637 for (x = 1; x < xsize; ++x)
5638 {
5639 for(y = 1;y < ysize; ++y)
5640 {
5641 /* Access the grid */
5642 c_ptr = &zcave[y + y0 - yhsize][x + x0 - xhsize];
5643
5644 /* A floor grid to be converted */
5645 if ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) &&
5646 (c_ptr->info & CAVE_ICKY))
5647
5648 {
5649 /* Clear the icky flag in the filled region */
5650 c_ptr->info &= ~(CAVE_ICKY);
5651
5652 /* Set appropriate flags */
5653 if (light) c_ptr->info |= (CAVE_GLOW);
5654 if (room) c_ptr->info |= (CAVE_ROOM);
5655 }
5656
5657 /* A wall grid to be convereted */
5658 else if ((c_ptr->feat == feat_wall_outer) &&
5659 (c_ptr->info & CAVE_ICKY))
5660 {
5661 /* Clear the icky flag in the filled region */
5662 c_ptr->info &= ~(CAVE_ICKY);
5663
5664 /* Set appropriate flags */
5665 if (light) c_ptr->info |= (CAVE_GLOW);
5666 if (room)
5667 {
5668 c_ptr->info |= (CAVE_ROOM);
5669 }
5670 else
5671 {
5672 place_filler(wpos, y+y0-yhsize, x+x0-xhsize);
5673 }
5674 }
5675
5676 /* None of the above -- clear the unconnected regions */
5677 else
5678 {
5679 place_filler(wpos, y+y0-yhsize, x+x0-xhsize);
5680 c_ptr->info &= ~(CAVE_ICKY|CAVE_ROOM);
5681 }
5682 }
5683 }
5684
5685 /*
5686 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
5687 * Extra doors appear inside the system. (Its not very noticeable though.)
5688 * This can be removed by "filling" from the outside in. This allows
5689 * a separation from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal
5690 * walls are F.W.OUTER instead.)
5691 * The extra effort for what seems to be only a minor thing (even
5692 * non-existant if you think of the caves not as normal rooms, but as
5693 * holes in the dungeon), doesn't seem worth it.
5694 */
5695
5696 return (TRUE);
5697 }
5698
5699
5700 /*
5701 * Makes a cave system in the center of the dungeon
5702 */
5703 static void build_cavern(worldpos *wpos)
5704 {
5705 int grd, roug, cutoff, xsize, ysize, x0, y0;
5706 bool done, light, room;
5707 int dun_lev = getlevel(wpos);
5708
5709 light = done = room = FALSE;
5710 if (dun_lev <= randint(25)) light = TRUE;
5711
5712 /* Make a cave the size of the dungeon */
5713 #if 0
5714 xsize = cur_wid - 1;
5715 ysize = cur_hgt - 1;
5716 #endif /* 0 */
5717 ysize = dun->l_ptr->hgt - 1;
5718 xsize = dun->l_ptr->wid - 1;
5719 x0 = xsize / 2;
5720 y0 = ysize / 2;
5721
5722 /* Paranoia: make size even */
5723 xsize = x0 * 2;
5724 ysize = y0 * 2;
5725
5726 while (!done)
5727 {
5728 /* Testing values for these parameters: feel free to adjust */
5729 grd = 2^(randint(4) + 4);
5730
5731 /* Want average of about 16 */
5732 roug =randint(8) * randint(4);
5733
5734 /* About size/2 */
5735 cutoff = xsize / 2;
5736
5737 /* Make it */
5738 generate_hmap(wpos, y0, x0, xsize, ysize, grd, roug, cutoff);
5739
5740 /* Convert to normal format+ clean up*/
5741 done = generate_fracave(wpos, y0, x0, xsize, ysize, cutoff, light, room);
5742 }
5743 }
5744
5745
5746 /*
5747 * Driver routine to create fractal cave system
5748 */
5749 static void build_type10(worldpos *wpos, int by0, int bx0, player_type *p_ptr) {
5750 int grd, roug, cutoff, xsize, ysize, y0, x0;
5751
5752 bool done, light, room;
5753 int dun_lev = getlevel(wpos);
5754
5755 /* Get size: note 'Evenness'*/
5756 xsize = randint(22) * 2 + 6;
5757 ysize = randint(15) * 2 + 6;
5758
5759 /* Try to allocate space for room. If fails, exit */
5760 if (!room_alloc(wpos, xsize+1, ysize+1, FALSE, by0, bx0, &x0, &y0)) return;
5761
5762 light = done = FALSE;
5763 room = TRUE;
5764
5765 if (dun_lev <= randint(25)) light = TRUE;
5766
5767 while (!done) {
5768 /*
5769 * Note: size must be even or there are rounding problems
5770 * This causes the tunnels not to connect properly to the room
5771 */
5772
5773 /* Testing values for these parameters feel free to adjust */
5774 grd = 1 << randint(4);
5775
5776 /* Want average of about 16 */
5777 roug = randint(8) * randint(4);
5778
5779 /* About size/2 */
5780 cutoff = randint(xsize / 4) + randint(ysize / 4) +
5781 randint(xsize / 4) + randint(ysize / 4);
5782
5783 /* Make it */
5784 generate_hmap(wpos, y0, x0, xsize, ysize, grd, roug, cutoff);
5785
5786 /* Convert to normal format + clean up*/
5787 done = generate_fracave(wpos, y0, x0, xsize, ysize, cutoff, light, room);
5788 }
5789 }
5790
5791
5792 /*
5793 * Random vault generation from Z 2.5.1
5794 */
5795
5796 /*
5797 * Make a very small room centred at (x0, y0)
5798 *
5799 * This is used in crypts, and random elemental vaults.
5800 *
5801 * Note - this should be used only on allocated regions
5802 * within another room.
5803 */
5804 static void build_small_room(worldpos *wpos, int x0, int y0)
5805 {
5806 build_rectangle(wpos, y0 - 1, x0 - 1, y0 + 1, x0 + 1, feat_wall_inner, CAVE_ROOM);
5807
5808 /* Place a secret door on one side */
5809 switch (rand_int(4))
5810 {
5811 case 0:
5812 {
5813 place_secret_door(wpos, y0, x0 - 1);
5814 break;
5815 }
5816
5817 case 1:
5818 {
5819 place_secret_door(wpos, y0, x0 + 1);
5820 break;
5821 }
5822
5823 case 2:
5824 {
5825 place_secret_door(wpos, y0 - 1, x0);
5826 break;
5827 }
5828
5829 case 3:
5830 {
5831 place_secret_door(wpos, y0 + 1, x0);
5832 break;
5833 }
5834 }
5835
5836 /* Add inner open space */
5837 place_floor(wpos, y0, x0);
5838 }
5839
5840
5841 /*
5842 * Add a door to a location in a random vault
5843 *
5844 * Note that range checking has to be done in the calling routine.
5845 *
5846 * The doors must be INSIDE the allocated region.
5847 */
5848 static void add_door(worldpos *wpos, int x, int y)
5849 {
5850 cave_type **zcave;
5851 if (!(zcave = getcave(wpos))) return;
5852
5853 /* Need to have a wall in the center square */
5854 if (zcave[y][x].feat != feat_wall_outer) return;
5855
5856 /*
5857 * Look at:
5858 * x#x
5859 * .#.
5860 * x#x
5861 *
5862 * where x=don't care
5863 * .=floor, #=wall
5864 */
5865
5866 if (get_is_floor(wpos, x, y - 1) && get_is_floor(wpos, x, y + 1) &&
5867 (zcave[y][x - 1].feat == feat_wall_outer) &&
5868 (zcave[y][x + 1].feat == feat_wall_outer))
5869 {
5870 /* secret door */
5871 place_secret_door(wpos, y, x);
5872
5873 /* set boundarys so don't get wide doors */
5874 place_filler(wpos, y, x - 1);
5875 place_filler(wpos, y, x + 1);
5876 }
5877
5878
5879 /*
5880 * Look at:
5881 * x#x
5882 * .#.
5883 * x#x
5884 *
5885 * where x = don't care
5886 * .=floor, #=wall
5887 */
5888 if ((zcave[y - 1][x].feat == feat_wall_outer) &&
5889 (zcave[y + 1][x].feat == feat_wall_outer) &&
5890 get_is_floor(wpos, x - 1, y) && get_is_floor(wpos, x + 1, y))
5891 {
5892 /* secret door */
5893 place_secret_door(wpos, y, x);
5894
5895 /* set boundarys so don't get wide doors */
5896 place_filler(wpos, y - 1, x);
5897 place_filler(wpos, y + 1, x);
5898 }
5899 }
5900
5901
5902 /*
5903 * Fill the empty areas of a room with treasure and monsters.
5904 */
5905 static void fill_treasure(worldpos *wpos, int x1, int x2, int y1, int y2, int difficulty, player_type *p_ptr)
5906 {
5907 int x, y, cx, cy, size;
5908 s32b value;
5909 cave_type **zcave;
5910 int dun_lev = getlevel(wpos);
5911 bool placed;
5912 u32b resf = make_resf(p_ptr);
5913 if (!(zcave = getcave(wpos))) return;
5914
5915
5916 /* center of room:*/
5917 cx = (x1 + x2) / 2;
5918 cy = (y1 + y2) / 2;
5919
5920 /* Rough measure of size of vault= sum of lengths of sides */
5921 size = abs(x2 - x1) + abs(y2 - y1);
5922
5923 for (x = x1; x <= x2; x++)
5924 {
5925 for (y = y1; y <= y2; y++)
5926 {
5927 /*
5928 * Thing added based on distance to center of vault
5929 * Difficulty is 1-easy to 10-hard
5930 */
5931 value = (((s32b)distance(cy, cx, y, x) * 100) / size) +
5932 randint(10) - difficulty;
5933
5934 /* Hack -- Empty square part of the time */
5935 if ((randint(100) - difficulty * 3) > 50) value = 20;
5936
5937 /* If floor, shallow water or lava */
5938 if (get_is_floor(wpos, x, y) ||
5939 (zcave[y][x].feat == FEAT_DEEP_WATER))
5940
5941 #if 0
5942 (cave[y][x].feat == FEAT_SHAL_WATER) ||
5943 (cave[y][x].feat == FEAT_SHAL_LAVA))
5944 #endif /* 0 */
5945 {
5946 /* The smaller 'value' is, the better the stuff */
5947 if (value < 0)
5948 {
5949 /* Meanest monster + treasure */
5950 monster_level = dun_lev + 40;
5951 monster_level_min = -1;
5952 placed = place_monster(wpos, y, x, TRUE, TRUE);
5953 monster_level_min = 0;
5954 monster_level = dun_lev;
5955 object_level = dun_lev + 20;
5956 if (placed) place_object(wpos, y, x, TRUE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
5957 object_level = dun_lev;
5958 }
5959 else if (value < 5)
5960 {
5961 /* Mean monster +treasure */
5962 monster_level = dun_lev + 20;
5963 placed = place_monster(wpos, y, x, TRUE, TRUE);
5964 monster_level = dun_lev;
5965 object_level = dun_lev + 10;
5966 if (placed) place_object(wpos, y, x, TRUE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
5967 object_level = dun_lev;
5968 }
5969 else if (value < 10)
5970 {
5971 /* Monster */
5972 monster_level = dun_lev + 9;
5973 place_monster(wpos, y, x, TRUE, TRUE);
5974 monster_level = dun_lev;
5975 }
5976 else if (value < 17)
5977 {
5978 /* Intentional Blank space */
5979
5980 /*
5981 * (Want some of the vault to be empty
5982 * so have room for group monsters.
5983 * This is used in the hack above to lower
5984 * the density of stuff in the vault.)
5985 */
5986 }
5987 else if (value < 23)
5988 {
5989 /* Object or trap */
5990 if (rand_int(100) < 25)
5991 {
5992 place_object(wpos, y, x, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
5993 }
5994 if (rand_int(100) < 75)
5995 {
5996 place_trap(wpos, y, x, 0);
5997 }
5998 }
5999 else if (value < 30)
6000 {
6001 /* Monster and trap */
6002 monster_level = dun_lev + 5;
6003 place_monster(wpos, y, x, TRUE, TRUE);
6004 monster_level = dun_lev;
6005 place_trap(wpos, y, x, 0);
6006 }
6007 else if (value < 40)
6008 {
6009 /* Monster or object */
6010 placed = TRUE;
6011 if (rand_int(100) < 50)
6012 {
6013 monster_level = dun_lev + 3;
6014 placed = place_monster(wpos, y, x, TRUE, TRUE);
6015 monster_level = dun_lev;
6016 }
6017 if (rand_int(100) < 50)
6018 {
6019 object_level = dun_lev + 7;
6020 if (placed) place_object(wpos, y, x, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
6021 object_level = dun_lev;
6022 }
6023 }
6024 else if (value < 50)
6025 {
6026 /* Trap */
6027 place_trap(wpos, y, x, 0);
6028 }
6029 else
6030 {
6031 /* Various Stuff */
6032
6033 /* 20% monster, 40% trap, 20% object, 20% blank space */
6034 if (rand_int(100) < 20)
6035 {
6036 place_monster(wpos, y, x, TRUE, TRUE);
6037 }
6038 else if (rand_int(100) < 50)
6039 {
6040 place_trap(wpos, y, x, 0);
6041 }
6042 else if (rand_int(100) < 50)
6043 {
6044 place_object(wpos, y, x, FALSE, FALSE, FALSE, resf, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
6045 }
6046 }
6047
6048 }
6049 }
6050 }
6051 }
6052
6053
6054 /*
6055 * Creates a random vault that looks like a collection of bubbles
6056 *
6057 * It works by getting a set of coordinates that represent the center of
6058 * each bubble. The entire room is made by seeing which bubble center is
6059 * closest. If two centers are equidistant then the square is a wall,
6060 * otherwise it is a floor. The only exception is for squares really
6061 * near a center, these are always floor.
6062 * (It looks better than without this check.)
6063 *
6064 * Note: If two centers are on the same point then this algorithm will create a
6065 * blank bubble filled with walls. - This is prevented from happening.
6066 */
6067
6068 #define BUBBLENUM 10 /* number of bubbles */
6069
6070 static void build_bubble_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
6071 {
6072 /* array of center points of bubbles */
6073 coord center[BUBBLENUM];
6074
6075 int i, j, k, x = 0, y = 0;
6076 u16b min1, min2, temp;
6077 bool done;
6078 dun_level *l_ptr = getfloor(wpos);
6079
6080 /* Offset from center to top left hand corner */
6081 int xhsize = xsize / 2;
6082 int yhsize = ysize / 2;
6083
6084 cave_type **zcave;
6085 if (!(zcave = getcave(wpos))) return;
6086
6087 /* Allocate center of bubbles */
6088 center[0].x = randint(xsize - 3) + 1;
6089 center[0].y = randint(ysize - 3) + 1;
6090
6091 for (i = 1; i < BUBBLENUM; i++)
6092 {
6093 done = FALSE;
6094
6095 /* Get center and check to see if it is unique */
6096 for (k = 0; !done && (k < 2000); k++)
6097 {
6098 done = TRUE;
6099
6100 x = randint(xsize - 3) + 1;
6101 y = randint(ysize - 3) + 1;
6102
6103 for (j = 0; j < i; j++)
6104 {
6105 /* Rough test to see if there is an overlap */
6106 if ((x == center[j].x) || (y == center[j].y)) done = FALSE;
6107 }
6108 }
6109
6110 /* Too many failures */
6111 if (k >= 2000) return;
6112
6113 center[i].x = x;
6114 center[i].y = y;
6115 }
6116
6117 build_rectangle(wpos, y0 - yhsize, x0 - xhsize,
6118 y0 - yhsize + ysize - 1, x0 - xhsize + xsize - 1,
6119 feat_wall_outer, CAVE_ROOM | CAVE_ICKY);
6120
6121 /* Fill in middle with bubbles */
6122 for (x = 1; x < xsize - 1; x++)
6123 {
6124 for (y = 1; y < ysize - 1; y++)
6125 {
6126 cave_type *c_ptr;
6127
6128 /* Get distances to two closest centers */
6129
6130 /* Initialise */
6131 min1 = distance(y, x, center[0].y, center[0].x);
6132 min2 = distance(y, x, center[1].y, center[1].x);
6133
6134 if (min1 > min2)
6135 {
6136 /* Swap if in wrong order */
6137 temp = min1;
6138 min1 = min2;
6139 min2 = temp;
6140 }
6141
6142 /* Scan the rest */
6143 for (i = 2; i < BUBBLENUM; i++)
6144 {
6145 temp = distance(y, x, center[i].y, center[i].x);
6146
6147 if (temp < min1)
6148 {
6149 /* Smallest */
6150 min2 = min1;
6151 min1 = temp;
6152 }
6153 else if (temp < min2)
6154 {
6155 /* Second smallest */
6156 min2 = temp;
6157 }
6158 }
6159
6160 /* Access the grid */
6161 c_ptr = &zcave[y + y0 - yhsize][x + x0 - xhsize];
6162
6163 /*
6164 * Boundary at midpoint+ not at inner region of bubble
6165 *
6166 * SCSCSC: was feat_wall_outer
6167 */
6168 if (((min2 - min1) <= 2) && (!(min1 < 3)))
6169 {
6170 place_filler(wpos, y+y0-yhsize, x+x0-xhsize);
6171 }
6172
6173 /* Middle of a bubble */
6174 else
6175 {
6176 place_floor(wpos, y+y0-yhsize, x+x0-xhsize);
6177 }
6178
6179 /* Clean up rest of flags */
6180 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
6181 }
6182 }
6183
6184 /* Try to add some random doors */
6185 for (i = 0; i < 500; i++)
6186 {
6187 x = randint(xsize - 3) - xhsize + x0 + 1;
6188 y = randint(ysize - 3) - yhsize + y0 + 1;
6189 add_door(wpos, x, y);
6190 }
6191
6192 /* Fill with monsters and treasure, low difficulty */
6193 fill_treasure(wpos, x0 - xhsize + 1, x0 - xhsize + xsize - 2,
6194 y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint(5), p_ptr);
6195
6196 l_ptr->flags2 |= LF2_VAULT;
6197 }
6198
6199
6200 /*
6201 * Convert FEAT_WALL_EXTRA (used by random vaults) to normal dungeon wall
6202 */
6203 static void convert_extra(worldpos *wpos, int y1, int x1, int y2, int x2)
6204 {
6205 int x, y;
6206
6207 cave_type **zcave;
6208 if (!(zcave = getcave(wpos))) return;
6209
6210 for (x = x1; x <= x2; x++) {
6211 for (y = y1; y <= y2; y++) {
6212 /* CRASHES occured here, so maybe in_bound helps */
6213 if (!in_bounds(y, x)) continue;
6214
6215 if (zcave[y][x].feat == feat_wall_outer)
6216 place_filler(wpos, y, x);
6217 }
6218 }
6219 }
6220
6221
6222 /*
6223 * Overlay a rectangular room given its bounds
6224 *
6225 * This routine is used by build_room_vault (hence FEAT_WALL_OUTER)
6226 * The area inside the walls is not touched: only granite is removed
6227 * and normal walls stay
6228 */
6229 static void build_room(worldpos *wpos, int x1, int x2, int y1, int y2)
6230 {
6231 int x, y, xsize, ysize, temp;
6232
6233 cave_type **zcave;
6234 if (!(zcave = getcave(wpos))) return;
6235
6236 /* Check if rectangle has no width */
6237 if ((x1 == x2) || (y1 == y2)) return;
6238
6239 /* initialize */
6240 if (x1 > x2) {
6241 /* Swap boundaries if in wrong order */
6242 temp = x1;
6243 x1 = x2;
6244 x2 = temp;
6245 }
6246
6247 if (y1 > y2) {
6248 /* Swap boundaries if in wrong order */
6249 temp = y1;
6250 y1 = y2;
6251 y2 = temp;
6252 }
6253
6254 /* Get total widths */
6255 xsize = x2 - x1;
6256 ysize = y2 - y1;
6257
6258 build_rectangle(wpos, y1, x1, y2, x2, feat_wall_outer, CAVE_ROOM | CAVE_ICKY);
6259
6260 /* Middle */
6261 for (x = 1; x < xsize; x++)
6262 {
6263 for (y = 1; y < ysize; y++)
6264 {
6265 if (zcave[y1 + y][x1 + x].feat == feat_wall_outer)
6266 {
6267 /* Clear the untouched region */
6268 place_floor(wpos, y1 + y, x1 + x);
6269 zcave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
6270 }
6271 else
6272 {
6273 /* Make it a room -- but don't touch */
6274 zcave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
6275 }
6276 }
6277 }
6278 }
6279
6280
6281 /*
6282 * Create a random vault that looks like a collection of overlapping rooms
6283 */
6284 static void build_room_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
6285 {
6286 int i, x1, x2, y1, y2, xhsize, yhsize;
6287 dun_level *l_ptr = getfloor(wpos);
6288 cave_type **zcave;
6289 if (!(zcave = getcave(wpos))) return;
6290
6291 /* Get offset from center */
6292 xhsize = xsize / 2;
6293 yhsize = ysize / 2;
6294
6295 /* Fill area so don't get problems with arena levels */
6296 for (x1 = 0; x1 <= xsize; x1++) {
6297 int x = x0 - xhsize + x1;
6298
6299 for (y1 = 0; y1 <= ysize; y1++) {
6300 int y = y0 - yhsize + y1;
6301
6302 if (!in_bounds(y, x)) continue;
6303
6304 cave_set_feat(wpos, y, x, feat_wall_outer);
6305 zcave[y][x].info &= ~(CAVE_ICKY);
6306 }
6307 }
6308
6309 /* Add ten random rooms */
6310 for (i = 0; i < 10; i++) {
6311 x1 = randint(xhsize) * 2 + x0 - xhsize;
6312 x2 = randint(xhsize) * 2 + x0 - xhsize;
6313 y1 = randint(yhsize) * 2 + y0 - yhsize;
6314 y2 = randint(yhsize) * 2 + y0 - yhsize;
6315
6316 build_room(wpos, x1, x2, y1, y2);
6317 }
6318
6319 convert_extra(wpos, y0 - yhsize, x0 - xhsize, y0 - yhsize + ysize,
6320 x0 - xhsize + xsize);
6321
6322 /* Add some random doors */
6323 for (i = 0; i < 500; i++) {
6324 x1 = randint(xsize - 2) - xhsize + x0 + 1;
6325 y1 = randint(ysize - 2) - yhsize + y0 + 1;
6326 add_door(wpos, x1, y1);
6327 }
6328
6329 /* Fill with monsters and treasure, high difficulty */
6330 fill_treasure(wpos, x0 - xhsize + 1, x0 - xhsize + xsize - 1,
6331 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5) + 5, p_ptr);
6332
6333 l_ptr->flags2 |= LF2_VAULT_HI;
6334 #ifdef TEST_SERVER
6335 s_printf("DEBUG_FEELING: VAULT_HI by build_room_vault\n");
6336 #endif
6337 }
6338
6339
6340 /*
6341 * Create a random vault out of a fractal cave
6342 */
6343 static void build_cave_vault(worldpos *wpos, int x0, int y0, int xsiz, int ysiz, player_type *p_ptr)
6344 {
6345 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
6346 bool done, light, room;
6347 dun_level *l_ptr = getfloor(wpos);
6348 cave_type **zcave;
6349 if (!(zcave = getcave(wpos))) return;
6350
6351 /* Round to make sizes even */
6352 xhsize = xsiz / 2;
6353 yhsize = ysiz / 2;
6354 xsize = xhsize * 2;
6355 ysize = yhsize * 2;
6356
6357 light = done = FALSE;
6358 room = TRUE;
6359
6360 while (!done)
6361 {
6362 /* Testing values for these parameters feel free to adjust */
6363 grd = 2^rand_int(4);
6364
6365 /* Want average of about 16 */
6366 roug = randint(8) * randint(4);
6367
6368 /* About size/2 */
6369 cutoff = randint(xsize / 4) + randint(ysize / 4) +
6370 randint(xsize / 4) + randint(ysize / 4);
6371
6372 /* Make it */
6373 generate_hmap(wpos, y0, x0, xsize, ysize, grd, roug, cutoff);
6374
6375 /* Convert to normal format + clean up */
6376 done = generate_fracave(wpos, y0, x0, xsize, ysize, cutoff, light, room);
6377 }
6378
6379 /* Set icky flag because is a vault */
6380 for (x = 0; x <= xsize; x++)
6381 {
6382 for (y = 0; y <= ysize; y++)
6383 {
6384 zcave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
6385 }
6386 }
6387
6388 /* Fill with monsters and treasure, low difficulty */
6389 fill_treasure(wpos, x0 - xhsize + 1, x0 - xhsize + xsize - 1,
6390 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5), p_ptr);
6391
6392 l_ptr->flags2 |= LF2_VAULT;
6393 }
6394
6395
6396 /*
6397 * Maze vault -- rectangular labyrinthine rooms
6398 *
6399 * maze vault uses two routines:
6400 * r_visit - a recursive routine that builds the labyrinth
6401 * build_maze_vault - a driver routine that calls r_visit and adds
6402 * monsters, traps and treasure
6403 *
6404 * The labyrinth is built by creating a spanning tree of a graph.
6405 * The graph vertices are at
6406 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
6407 * and the edges are the vertical and horizontal nearest neighbors.
6408 *
6409 * The spanning tree is created by performing a suitably randomized
6410 * depth-first traversal of the graph. The only adjustable parameter
6411 * is the rand_int(3) below; it governs the relative density of
6412 * twists and turns in the labyrinth: smaller number, more twists.
6413 */
6414 static void r_visit(worldpos *wpos, int y1, int x1, int y2, int x2,
6415 int node, int dir, int *visited)
6416 {
6417 int i, j, m, n, temp, x, y, adj[4];
6418
6419 /* Dimensions of vertex array */
6420 m = (x2 - x1) / 2 + 1;
6421 n = (y2 - y1) / 2 + 1;
6422
6423 /* Mark node visited and set it to a floor */
6424 visited[node] = 1;
6425 x = 2 * (node % m) + x1;
6426 y = 2 * (node / m) + y1;
6427 place_floor(wpos, y, x);
6428
6429 /* Setup order of adjacent node visits */
6430 if (rand_int(3) == 0)
6431 {
6432 /* Pick a random ordering */
6433 for (i = 0; i < 4; i++)
6434 {
6435 adj[i] = i;
6436 }
6437 for (i = 0; i < 4; i++)
6438 {
6439 j = rand_int(4);
6440 temp = adj[i];
6441 adj[i] = adj[j];
6442 adj[j] = temp;
6443 }
6444 dir = adj[0];
6445 }
6446 else
6447 {
6448 /* Pick a random ordering with dir first */
6449 adj[0] = dir;
6450 for (i = 1; i < 4; i++)
6451 {
6452 adj[i] = i;
6453 }
6454 for (i = 1; i < 4; i++)
6455 {
6456 j = 1 + rand_int(3);
6457 temp = adj[i];
6458 adj[i] = adj[j];
6459 adj[j] = temp;
6460 }
6461 }
6462
6463 for (i = 0; i < 4; i++)
6464 {
6465 switch (adj[i])
6466 {
6467 /* (0,+) - check for bottom boundary */
6468 case 0:
6469 {
6470 if ((node / m < n - 1) && (visited[node + m] == 0))
6471 {
6472 place_floor(wpos, y + 1, x);
6473 r_visit(wpos, y1, x1, y2, x2, node + m, dir, visited);
6474 }
6475 break;
6476 }
6477
6478 /* (0,-) - check for top boundary */
6479 case 1:
6480 {
6481 if ((node / m > 0) && (visited[node - m] == 0))
6482 {
6483 place_floor(wpos, y - 1, x);
6484 r_visit(wpos, y1, x1, y2, x2, node - m, dir, visited);
6485 }
6486 break;
6487 }
6488
6489 /* (+,0) - check for right boundary */
6490 case 2:
6491 {
6492 if ((node % m < m - 1) && (visited[node + 1] == 0))
6493 {
6494 place_floor(wpos, y, x + 1);
6495 r_visit(wpos, y1, x1, y2, x2, node + 1, dir, visited);
6496 }
6497 break;
6498 }
6499
6500 /* (-,0) - check for left boundary */
6501 case 3:
6502 {
6503 if ((node % m > 0) && (visited[node - 1] == 0))
6504 {
6505 place_floor(wpos, y, x - 1);
6506 r_visit(wpos, y1, x1, y2, x2, node - 1, dir, visited);
6507 }
6508 break;
6509 }
6510 }
6511 }
6512 }
6513
6514
6515 static void build_maze_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
6516 {
6517 int y, x, dy, dx;
6518 int y1, x1, y2, x2;
6519 int m, n, num_vertices, *visited;
6520 bool light;
6521 cave_type *c_ptr;
6522 dun_level *l_ptr = getfloor(wpos);
6523 cave_type **zcave;
6524 int dun_lev = getlevel(wpos);
6525 if (!(zcave = getcave(wpos))) return;
6526
6527 /* Choose lite or dark */
6528 light = (dun_lev <= randint(25));
6529
6530 /* Pick a random room size - randomized by calling routine */
6531 dy = ysize / 2 - 1;
6532 dx = xsize / 2 - 1;
6533
6534 y1 = y0 - dy;
6535 x1 = x0 - dx;
6536 y2 = y0 + dy;
6537 x2 = x0 + dx;
6538
6539 /* Generate the room */
6540 for (y = y1 - 1; y <= y2 + 1; y++)
6541 {
6542 for (x = x1 - 1; x <= x2 + 1; x++)
6543 {
6544 c_ptr = &zcave[y][x];
6545
6546 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
6547
6548 if ((x == x1 - 1) || (x == x2 + 1) ||
6549 (y == y1 - 1) || (y == y2 + 1))
6550 {
6551 cave_set_feat(wpos, y, x, feat_wall_outer);
6552 }
6553 else
6554 {
6555 cave_set_feat(wpos, y, x, feat_wall_inner);
6556 }
6557 if (light) c_ptr->info |= (CAVE_GLOW);
6558 }
6559 }
6560
6561 /* Dimensions of vertex array */
6562 m = dx + 1;
6563 n = dy + 1;
6564 num_vertices = m * n;
6565
6566 /* Allocate an array for visited vertices */
6567 C_MAKE(visited, num_vertices, int);
6568
6569 /* Traverse the graph to create a spaning tree, pick a random root */
6570 r_visit(wpos, y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
6571
6572 /* Fill with monsters and treasure, low difficulty */
6573 fill_treasure(wpos, x1, x2, y1, y2, randint(5), p_ptr);
6574
6575 l_ptr->flags2 |= LF2_VAULT;
6576
6577 /* Free the array for visited vertices */
6578 C_FREE(visited, num_vertices, int);
6579 }
6580
6581
6582 /*
6583 * Build a "mini" checkerboard vault
6584 *
6585 * This is done by making a permanent wall maze and setting
6586 * the diagonal sqaures of the checker board to be granite.
6587 * The vault has two entrances on opposite sides to guarantee
6588 * a way to get in even if the vault abuts a side of the dungeon.
6589 */
6590 static void build_mini_c_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
6591 {
6592 int dy, dx;
6593 int y1, x1, y2, x2, y, x, total;
6594 int m, n, num_vertices;
6595 int *visited;
6596 dun_level *l_ptr = getfloor(wpos);
6597 cave_type **zcave;
6598 if (!(zcave = getcave(wpos))) return;
6599
6600 /* Pick a random room size */
6601 dy = ysize / 2 - 1;
6602 dx = xsize / 2 - 1;
6603
6604 y1 = y0 - dy;
6605 x1 = x0 - dx;
6606 y2 = y0 + dy;
6607 x2 = x0 + dx;
6608
6609
6610 /* Generate the room */
6611 for (y = y1 - 1; y <= y2 + 1; y++) {
6612 for (x = x1 - 1; x <= x2 + 1; x++) {
6613 zcave[y][x].info |= (CAVE_ROOM | CAVE_ICKY | CAVE_ICKY_PERMA);
6614
6615 /* Permanent walls */
6616 cave_set_feat(wpos, y, x, FEAT_PERM_INNER);
6617 }
6618 }
6619
6620
6621 /* Dimensions of vertex array */
6622 m = dx + 1;
6623 n = dy + 1;
6624 num_vertices = m * n;
6625
6626 /* Allocate an array for visited vertices */
6627 C_MAKE(visited, num_vertices, int);
6628
6629 /* Traverse the graph to create a spannng tree, pick a random root */
6630 r_visit(wpos, y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
6631
6632 /* Make it look like a checker board vault */
6633 for (x = x1; x <= x2; x++) {
6634 for (y = y1; y <= y2; y++) {
6635 total = x - x1 + y - y1;
6636
6637 /* If total is odd and is a floor, then make a wall */
6638 if ((total % 2 == 1) && get_is_floor(wpos, x, y))
6639 cave_set_feat(wpos, y, x, feat_wall_inner);
6640 }
6641 }
6642
6643 /* Make a couple of entrances */
6644 if (rand_int(2) == 0)
6645 {
6646 /* Left and right */
6647 y = randint(dy) + dy / 2;
6648 cave_set_feat(wpos, y1 + y, x1 - 1, feat_wall_outer);
6649 cave_set_feat(wpos, y1 + y, x2 + 1, feat_wall_outer);
6650 }
6651 else
6652 {
6653 /* Top and bottom */
6654 x = randint(dx) + dx / 2;
6655 cave_set_feat(wpos, y1 - 1, x1 + x, feat_wall_outer);
6656 cave_set_feat(wpos, y2 + 1, x1 + x, feat_wall_outer);
6657 }
6658
6659 /* Fill with monsters and treasure, highest difficulty */
6660 fill_treasure(wpos, x1, x2, y1, y2, 10, p_ptr);
6661
6662 l_ptr->flags2 |= LF2_VAULT_HI;
6663 #ifdef TEST_SERVER
6664 s_printf("DEBUG_FEELING: VAULT_HI by build_mini_c(heckerboard)_vault\n");
6665 #endif
6666
6667 /* Free the array for visited vertices */
6668 C_FREE(visited, num_vertices, int);
6669 }
6670
6671
6672 /*
6673 * Build a town/ castle by using a recursive algorithm.
6674 * Basically divide each region in a probalistic way to create
6675 * smaller regions. When the regions get too small stop.
6676 *
6677 * The power variable is a measure of how well defended a region is.
6678 * This alters the possible choices.
6679 */
6680 static void build_recursive_room(worldpos *wpos, int x1, int y1, int x2, int y2, int power)
6681 {
6682 int xsize, ysize;
6683 int x, y;
6684 int choice;
6685
6686 /* Temp variables */
6687 int t1, t2, t3, t4;
6688
6689 xsize = x2 - x1;
6690 ysize = y2 - y1;
6691
6692 if ((power < 3) && (xsize > 12) && (ysize > 12))
6693 {
6694 /* Need outside wall +keep */
6695 choice = 1;
6696 }
6697 else
6698 {
6699 if (power < 10)
6700 {
6701 /* Make rooms + subdivide */
6702 if ((randint(10) > 2) && (xsize < 8) && (ysize < 8))
6703 {
6704 choice = 4;
6705 }
6706 else
6707 {
6708 choice = randint(2) + 1;
6709 }
6710 }
6711 else
6712 {
6713 /* Mostly subdivide */
6714 choice = randint(3) + 1;
6715 }
6716 }
6717
6718 /* Based on the choice made above, do something */
6719 switch (choice)
6720 {
6721 /* Outer walls */
6722 case 1:
6723 {
6724 /* Top and bottom */
6725 for (x = x1; x <= x2; x++)
6726 {
6727 cave_set_feat(wpos, y1, x, feat_wall_outer);
6728 cave_set_feat(wpos, y2, x, feat_wall_outer);
6729 }
6730
6731 /* Left and right */
6732 for (y = y1 + 1; y < y2; y++)
6733 {
6734 cave_set_feat(wpos, y, x1, feat_wall_outer);
6735 cave_set_feat(wpos, y, x2, feat_wall_outer);
6736 }
6737
6738 /* Make a couple of entrances */
6739 if (rand_int(2) == 0)
6740 {
6741 /* Left and right */
6742 y = randint(ysize) + y1;
6743 place_floor(wpos, y, x1);
6744 place_floor(wpos, y, x2);
6745 }
6746 else
6747 {
6748 /* Top and bottom */
6749 x = randint(xsize) + x1;
6750 place_floor(wpos, y1, x);
6751 place_floor(wpos, y2, x);
6752 }
6753
6754 /* Select size of keep */
6755 t1 = randint(ysize / 3) + y1;
6756 t2 = y2 - randint(ysize / 3);
6757 t3 = randint(xsize / 3) + x1;
6758 t4 = x2 - randint(xsize / 3);
6759
6760 /* Do outside areas */
6761
6762 /* Above and below keep */
6763 build_recursive_room(wpos, x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
6764 build_recursive_room(wpos, x1 + 1, t2, x2 - 1, y2, power + 1);
6765
6766 /* Left and right of keep */
6767 build_recursive_room(wpos, x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
6768 build_recursive_room(wpos, t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
6769
6770 /* Make the keep itself: */
6771 x1 = t3;
6772 x2 = t4;
6773 y1 = t1;
6774 y2 = t2;
6775 xsize = x2 - x1;
6776 ysize = y2 - y1;
6777 power += 2;
6778
6779 /* Fall through */
6780 }
6781
6782 /* Try to build a room */
6783 case 4:
6784 {
6785 if ((xsize < 3) || (ysize < 3))
6786 {
6787 for (y = y1; y < y2; y++)
6788 {
6789 for (x = x1; x < x2; x++)
6790 {
6791 cave_set_feat(wpos, y, x, feat_wall_inner);
6792 }
6793 }
6794
6795 /* Too small */
6796 return;
6797 }
6798
6799 /* Make outside walls */
6800
6801 /* Top and bottom */
6802 for (x = x1 + 1; x <= x2 - 1; x++)
6803 {
6804 cave_set_feat(wpos, y1 + 1, x, feat_wall_inner);
6805 cave_set_feat(wpos, y2 - 1, x, feat_wall_inner);
6806 }
6807
6808 /* Left and right */
6809 for (y = y1 + 1; y <= y2 - 1; y++)
6810 {
6811 cave_set_feat(wpos, y, x1 + 1, feat_wall_inner);
6812 cave_set_feat(wpos, y, x2 - 1, feat_wall_inner);
6813 }
6814
6815 /* Make a door */
6816 y = randint(ysize - 3) + y1 + 1;
6817
6818 if (rand_int(2) == 0)
6819 {
6820 /* Left */
6821 place_floor(wpos, y, x1 + 1);
6822 }
6823 else
6824 {
6825 /* Right */
6826 place_floor(wpos, y, x2 - 1);
6827 }
6828
6829 /* Build the room */
6830 build_recursive_room(wpos, x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
6831
6832 break;
6833 }
6834
6835 /* Try and divide vertically */
6836 case 2:
6837 {
6838 if (xsize < 3)
6839 {
6840 /* Too small */
6841 for (y = y1; y < y2; y++)
6842 {
6843 for (x = x1; x < x2; x++)
6844 {
6845 cave_set_feat(wpos, y, x, feat_wall_inner);
6846 }
6847 }
6848 return;
6849 }
6850
6851 t1 = randint(xsize - 2) + x1 + 1;
6852 build_recursive_room(wpos, x1, y1, t1, y2, power - 2);
6853 build_recursive_room(wpos, t1 + 1, y1, x2, y2, power - 2);
6854
6855 break;
6856 }
6857
6858 /* Try and divide horizontally */
6859 case 3:
6860 {
6861 if (ysize < 3)
6862 {
6863 /* Too small */
6864 for (y = y1; y < y2; y++)
6865 {
6866 for (x = x1; x < x2; x++)
6867 {
6868 cave_set_feat(wpos, y, x, feat_wall_inner);
6869 }
6870 }
6871 return;
6872 }
6873
6874 t1 = randint(ysize - 2) + y1 + 1;
6875 build_recursive_room(wpos, x1, y1, x2, t1, power - 2);
6876 build_recursive_room(wpos, x1, t1 + 1, x2, y2, power - 2);
6877
6878 break;
6879 }
6880 }
6881 }
6882
6883
6884 /*
6885 * Build a castle
6886 *
6887 * Clear the region and call the recursive room routine.
6888 *
6889 * This makes a vault that looks like a castle or city in the dungeon.
6890 */
6891 static void build_castle_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
6892 {
6893 int dy, dx;
6894 int y1, x1, y2, x2;
6895 int y, x;
6896 dun_level *l_ptr = getfloor(wpos);
6897 cave_type **zcave;
6898 if (!(zcave = getcave(wpos))) return;
6899
6900 /* Pick a random room size */
6901 dy = ysize / 2 - 1;
6902 dx = xsize / 2 - 1;
6903
6904 y1 = y0 - dy;
6905 x1 = x0 - dx;
6906 y2 = y0 + dy;
6907 x2 = x0 + dx;
6908
6909 /* Generate the room */
6910 for (y = y1 - 1; y <= y2 + 1; y++)
6911 {
6912 for (x = x1 - 1; x <= x2 + 1; x++)
6913 {
6914 zcave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
6915
6916 /* Make everything a floor */
6917 place_floor(wpos, y, x);
6918 }
6919 }
6920
6921 /* Make the castle */
6922 build_recursive_room(wpos, x1, y1, x2, y2, randint(5));
6923
6924 /* Fill with monsters and treasure, low difficulty */
6925 fill_treasure(wpos, x1, x2, y1, y2, randint(3), p_ptr);
6926
6927 l_ptr->flags2 |= LF2_VAULT;
6928 }
6929
6930
6931 /*
6932 * Add outer wall to a floored region
6933 *
6934 * Note: no range checking is done so must be inside dungeon
6935 * This routine also stomps on doors
6936 */
6937 static void add_outer_wall(worldpos *wpos, int x, int y, int light, int x1, int y1,
6938 int x2, int y2)
6939 {
6940 int i, j;
6941
6942 cave_type **zcave;
6943 if (!(zcave = getcave(wpos))) return;
6944
6945 if (!in_bounds(y, x)) return; /* XXX */
6946
6947 /*
6948 * Hack -- Check to see if square has been visited before
6949 * if so, then exit (use room flag to do this)
6950 */
6951 if (zcave[y][x].info & CAVE_ROOM) return;
6952
6953 /* Set room flag */
6954 zcave[y][x].info |= (CAVE_ROOM);
6955
6956 if (get_is_floor(wpos, x, y))
6957 {
6958 for (i = -1; i <= 1; i++)
6959 {
6960 for (j = -1; j <= 1; j++)
6961 {
6962 if ((x + i >= x1) && (x + i <= x2) &&
6963 (y + j >= y1) && (y + j <= y2))
6964 {
6965 add_outer_wall(wpos, x + i, y + j, light, x1, y1, x2, y2);
6966 if (light) zcave[y][x].info |= CAVE_GLOW;
6967 }
6968 }
6969 }
6970 }
6971
6972 /* Set bounding walls */
6973 else if (zcave[y][x].feat == FEAT_WALL_EXTRA)
6974 {
6975 zcave[y][x].feat = feat_wall_outer;
6976 if (light == TRUE) zcave[y][x].info |= CAVE_GLOW;
6977 }
6978
6979 /* Set bounding walls */
6980 else if (zcave[y][x].feat == FEAT_PERM_OUTER)
6981 {
6982 if (light == TRUE) zcave[y][x].info |= CAVE_GLOW;
6983 }
6984 }
6985
6986
6987 /*
6988 * Hacked distance formula - gives the 'wrong' answer
6989 *
6990 * Used to build crypts
6991 */
6992 static int dist2(int x1, int y1, int x2, int y2,
6993 int h1, int h2, int h3, int h4)
6994 {
6995 int dx, dy;
6996 dx = abs(x2 - x1);
6997 dy = abs(y2 - y1);
6998
6999 /*
7000 * Basically this works by taking the normal pythagorean formula
7001 * and using an expansion to express this in a way without the
7002 * square root. This approximate formula is then perturbed to give
7003 * the distorted results. (I found this by making a mistake when I was
7004 * trying to fix the circular rooms.)
7005 */
7006
7007 /* h1-h4 are constants that describe the metric */
7008 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
7009 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
7010
7011 /* 128/181 is approx. 1/sqrt(2) */
7012 return (((dx + dy) * 128) / 181 +
7013 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
7014 }
7015
7016
7017 /*
7018 * Build target vault
7019 *
7020 * This is made by two concentric "crypts" with perpendicular
7021 * walls creating the cross-hairs.
7022 */
7023 static void build_target_vault(worldpos *wpos, int x0, int y0, int xsize, int ysize, player_type *p_ptr)
7024 {
7025 int rad, x, y;
7026 int h1, h2, h3, h4;
7027 dun_level *l_ptr = getfloor(wpos);
7028 cave_type **zcave;
7029 if (!(zcave = getcave(wpos))) return;
7030
7031
7032 /* Make a random metric */
7033 h1 = randint(32) - 16;
7034 h2 = randint(16);
7035 h3 = randint(32);
7036 h4 = randint(32) - 16;
7037
7038 /* Work out outer radius */
7039 if (xsize > ysize)
7040 {
7041 rad = ysize / 2;
7042 }
7043 else
7044 {
7045 rad = xsize / 2;
7046 }
7047
7048 /* Make floor */
7049 for (x = x0 - rad; x <= x0 + rad; x++)
7050 {
7051 for (y = y0 - rad; y <= y0 + rad; y++)
7052 {
7053 cave_type *c_ptr;
7054
7055 /* Access the grid */
7056 c_ptr = &zcave[y][x];
7057
7058 /* Clear room flag */
7059 c_ptr->info &= ~(CAVE_ROOM);
7060
7061 /* Grids in vaults are required to be "icky" */
7062 c_ptr->info |= (CAVE_ICKY);
7063
7064 /* Inside -- floor */
7065 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
7066 {
7067 place_floor(wpos, y, x);
7068 }
7069
7070 /* Outside -- make it granite so that arena works */
7071 else
7072 {
7073 c_ptr->feat = FEAT_WALL_EXTRA;
7074 }
7075
7076 /* Proper boundary for arena */
7077 if (((y + rad) == y0) || ((y - rad) == y0) ||
7078 ((x + rad) == x0) || ((x - rad) == x0))
7079 {
7080 cave_set_feat(wpos, y, x, feat_wall_outer);
7081 }
7082 }
7083 }
7084
7085 /* Find visible outer walls and set to be FEAT_OUTER */
7086 add_outer_wall(wpos, x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
7087 x0 + rad + 1, y0 + rad + 1);
7088
7089 /* Add inner wall */
7090 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
7091 {
7092 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
7093 {
7094 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
7095 {
7096 /* Make an internal wall */
7097 cave_set_feat(wpos, y, x, feat_wall_inner);
7098 }
7099 }
7100 }
7101
7102 /* Add perpendicular walls */
7103 for (x = x0 - rad; x <= x0 + rad; x++)
7104 {
7105 cave_set_feat(wpos, y0, x, feat_wall_inner);
7106 }
7107
7108 for (y = y0 - rad; y <= y0 + rad; y++)
7109 {
7110 cave_set_feat(wpos, y, x0, feat_wall_inner);
7111 }
7112
7113 /* Make inner vault */
7114 for (y = y0 - 1; y <= y0 + 1; y++)
7115 {
7116 cave_set_feat(wpos, y, x0 - 1, feat_wall_inner);
7117 cave_set_feat(wpos, y, x0 + 1, feat_wall_inner);
7118 }
7119 for (x = x0 - 1; x <= x0 + 1; x++)
7120 {
7121 cave_set_feat(wpos, y0 - 1, x, feat_wall_inner);
7122 cave_set_feat(wpos, y0 + 1, x, feat_wall_inner);
7123 }
7124
7125 place_floor(wpos, y0, x0);
7126
7127
7128 /*
7129 * Add doors to vault
7130 *
7131 * Get two distances so can place doors relative to centre
7132 */
7133 x = (rad - 2) / 4 + 1;
7134 y = rad / 2 + x;
7135
7136 add_door(wpos, x0 + x, y0);
7137 add_door(wpos, x0 + y, y0);
7138 add_door(wpos, x0 - x, y0);
7139 add_door(wpos, x0 - y, y0);
7140 add_door(wpos, x0, y0 + x);
7141 add_door(wpos, x0, y0 + y);
7142 add_door(wpos, x0, y0 - x);
7143 add_door(wpos, x0, y0 - y);
7144
7145 /* Fill with stuff - medium difficulty */
7146 fill_treasure(wpos, x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint(3) + 3, p_ptr);
7147
7148 l_ptr->flags2 |= LF2_VAULT;
7149 }
7150
7151
7152 /*
7153 * Random vaults
7154 */
7155 static void build_type11(worldpos *wpos, int by0, int bx0, player_type *p_ptr)
7156 {
7157 int y0, x0, xsize, ysize, vtype;
7158
7159 cave_type **zcave;
7160 int dun_lev = getlevel(wpos);
7161 if (!(zcave = getcave(wpos))) return;
7162
7163 /* Get size -- gig enough to look good, small enough to be fairly common */
7164 xsize = randint(22) + 22;
7165 ysize = randint(11) + 11;
7166
7167 /* Allocate in room_map. If will not fit, exit */
7168 if (!room_alloc(wpos, xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
7169
7170 /* (Sometimes) Cause a special feeling */
7171 if ((dun_lev <= 50) ||
7172 (randint((dun_lev - 40) * (dun_lev - 40) + 1) < 400))
7173 {
7174 good_item_flag = TRUE;
7175 }
7176
7177 /* Select type of vault */
7178 vtype = randint(8);
7179
7180 switch (vtype) {
7181 /* Build an appropriate room */
7182 case 1:
7183 build_bubble_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7184 break;
7185 case 2:
7186 build_room_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7187 break;
7188 case 3:
7189 build_cave_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7190 break;
7191 case 4:
7192 build_maze_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7193 break;
7194 case 5:
7195 build_mini_c_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7196 break;
7197 case 6:
7198 build_castle_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7199 break;
7200 case 7:
7201 build_target_vault(wpos, x0, y0, xsize, ysize, p_ptr);
7202 break;
7203 /* I know how to add a few more... give me some time. */
7204
7205 /* Paranoia */
7206 default:
7207 return;
7208 }
7209 }
7210
7211
7212 /*
7213 * Crypt room generation from Z 2.5.1
7214 */
7215
7216 /*
7217 * Build crypt room.
7218 * For every grid in the possible square, check the (fake) distance.
7219 * If it's less than the radius, make it a room square.
7220 *
7221 * When done fill from the inside to find the walls,
7222 */
7223 static void build_type12(worldpos *wpos, int by0, int bx0, player_type *p_ptr)
7224 {
7225 int rad, x, y, x0, y0;
7226 int light = FALSE;
7227 bool emptyflag = TRUE;
7228 int h1, h2, h3, h4;
7229
7230 cave_type **zcave;
7231 int dun_lev = getlevel(wpos);
7232 if (!(zcave = getcave(wpos))) return;
7233
7234 /* Make a random metric */
7235 h1 = randint(32) - 16;
7236 h2 = randint(16);
7237 h3 = randint(32);
7238 h4 = randint(32) - 16;
7239
7240 /* Occasional light */
7241 if (randint(dun_lev) <= 5) light = TRUE;
7242
7243 rad = randint(9);
7244
7245 /* Allocate in room_map. If will not fit, exit */
7246 if (!room_alloc(wpos, rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
7247
7248 /* Make floor */
7249 for (x = x0 - rad; x <= x0 + rad; x++)
7250 {
7251 for (y = y0 - rad; y <= y0 + rad; y++)
7252 {
7253 /* Clear room flag */
7254 zcave[y][x].info &= ~(CAVE_ROOM);
7255
7256 /* Inside -- floor */
7257 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
7258 {
7259 place_floor(wpos, y, x);
7260 }
7261 else if (distance(y0, x0, y, x) < 3)
7262 {
7263 place_floor(wpos, y, x);
7264 }
7265
7266 /* Outside -- make it granite so that arena works */
7267 else
7268 {
7269 cave_set_feat(wpos, y, x, feat_wall_outer);
7270 }
7271
7272 /* Proper boundary for arena */
7273 if (((y + rad) == y0) || ((y - rad) == y0) ||
7274 ((x + rad) == x0) || ((x - rad) == x0))
7275 {
7276 cave_set_feat(wpos, y, x, feat_wall_outer);
7277 }
7278 }
7279 }
7280
7281 /* Find visible outer walls and set to be FEAT_OUTER */
7282 add_outer_wall(wpos, x0, y0, light, x0 - rad - 1, y0 - rad - 1,
7283 x0 + rad + 1, y0 + rad + 1);
7284
7285 /* Check to see if there is room for an inner vault */
7286 for (x = x0 - 2; x <= x0 + 2; x++)
7287 {
7288 for (y = y0 - 2; y <= y0 + 2; y++)
7289 {
7290 if (!get_is_floor(wpos, x, y))
7291 {
7292 /* Wall in the way */
7293 emptyflag = FALSE;
7294 }
7295 }
7296 }
7297
7298 if (emptyflag && (rand_int(2) == 0))
7299 {
7300 /* Build the vault */
7301 build_small_room(wpos, x0, y0);
7302
7303 /* Place a treasure in the vault */
7304 place_object(wpos, y0, x0, FALSE, FALSE, FALSE, make_resf(p_ptr), default_obj_theme, 0, ITEM_REMOVAL_NEVER);
7305
7306 /* Let's guard the treasure well */
7307 vault_monsters(wpos, y0, x0, rand_int(2) + 3);
7308
7309 /* Traps naturally */
7310 vault_traps(wpos, y0, x0, 4, 4, rand_int(3) + 2);
7311 }
7312 }
7313
7314 /*
7315 * Maze dungeon generator
7316 */
7317
7318 /*
7319 * If we wasted static memory for this, it would look like:
7320 *
7321 * static char maze[(MAX_HGT / 2) + 2][(MAX_WID / 2) + 2];
7322 */
7323 typedef char maze_row[(MAX_WID / 2) + 2];
7324
7325 static void dig(maze_row *maze, int y, int x, int d)
7326 {
7327 int k;
7328 int dy = 0, dx = 0;
7329
7330 /*
7331 * first, open the wall of the new cell
7332 * in the direction we come from.
7333 */
7334 switch (d)
7335 {
7336 case 0:
7337 {
7338 maze[y][x] |= 4;
7339 break;
7340 }
7341
7342 case 1:
7343 {
7344 maze[y][x] |= 8;
7345 break;
7346 }
7347
7348 case 2:
7349 {
7350 maze[y][x] |= 1;
7351 break;
7352 }
7353
7354 case 3:
7355 {
7356 maze[y][x] |= 2;
7357 break;
7358 }
7359 }
7360
7361 /*
7362 * try to chage direction, here 50% times.
7363 * with smaller values (say 25%) the maze
7364 * is made of long straight corridors. with
7365 * greaters values (say 75%) the maze is
7366 * very "turny".
7367 */
7368 if (rand_range(1, 100) < 50) d = rand_range(0, 3);
7369
7370 for (k = 1; k <= 4; k++)
7371 {
7372 switch (d)
7373 {
7374 case 0:
7375 {
7376 dy = 0;
7377 dx = 1;
7378 break;
7379 }
7380
7381 case 1:
7382 {
7383 dy = -1;
7384 dx = 0;
7385 break;
7386 }
7387
7388 case 2:
7389 {
7390 dy = 0;
7391 dx = -1;
7392 break;
7393 }
7394
7395 case 3:
7396 {
7397 dy = 1;
7398 dx = 0;
7399 break;
7400 }
7401 }
7402
7403 if (maze[y + dy][x + dx] == 0)
7404 {
7405 /*
7406 * now, open the wall of the new cell
7407 * in the direction we go to.
7408 */
7409 switch (d)
7410 {
7411 case 0:
7412 {
7413 maze[y][x] |= 1;
7414 break;
7415 }
7416
7417 case 1:
7418 {
7419 maze[y][x] |= 2;
7420 break;
7421 }
7422
7423 case 2:
7424 {
7425 maze[y][x] |= 4;
7426 break;
7427 }
7428
7429 case 3:
7430 {
7431 maze[y][x] |= 8;
7432 break;
7433 }
7434 }
7435
7436 dig(maze, y + dy, x + dx, d);
7437 }
7438
7439 d = (d + 1) % 4;
7440 }
7441 }
7442
7443
7444 /* methinks it's not always necessary that the entire level is 'maze'? */
7445 static void generate_maze(worldpos *wpos, int corridor)
7446 {
7447 int i, j, d;
7448 int y, dy = 0;
7449 int x, dx = 0;
7450 int m_1 = 0, m_2 = 0;
7451 maze_row *maze;
7452
7453 int cur_hgt = dun->l_ptr->hgt;
7454 int cur_wid = dun->l_ptr->wid;
7455 int div = corridor + 1;
7456
7457 cave_type **zcave;
7458 if (!(zcave = getcave(wpos))) return;
7459
7460
7461 /* Allocate temporary memory */
7462 C_MAKE(maze, (MAX_HGT / 2) + 2, maze_row);
7463
7464 /*
7465 * the empty maze is:
7466 *
7467 * -1 -1 ... -1 -1
7468 * -1 0 0 -1
7469 * . .
7470 * . .
7471 * -1 0 0 -1
7472 * -1 -1 ... -1 -1
7473 *
7474 * -1 are so-called "sentinel value".
7475 * 0 are empty cells.
7476 *
7477 * walls are not represented, only cells.
7478 * at the end of the algorithm each cell
7479 * contains a value that is bit mask
7480 * representing surrounding walls:
7481 *
7482 * bit #1
7483 *
7484 * +------+
7485 * | |
7486 * bit #2 | | bit #0
7487 * | |
7488 * +------+
7489 *
7490 * bit #3
7491 *
7492 * d is the direction you are digging
7493 * to. d value is the bit number:
7494 * d=0 --> go east
7495 * d=1 --> go north
7496 * etc
7497 *
7498 * you need only 4 bits per cell.
7499 * this gives you a very compact
7500 * maze representation.
7501 *
7502 */
7503 for (j = 0; j <= (cur_hgt / div) + 1; j++)
7504 {
7505 for (i = 0; i <= (cur_wid / div) + 1; i++)
7506 {
7507 maze[j][i] = -1;
7508 }
7509 }
7510
7511 for (j = 1;j <= (cur_hgt / div); j++)
7512 {
7513 for (i = 1; i <= (cur_wid / div); i++)
7514 {
7515 maze[j][i] = 0;
7516 }
7517 }
7518
7519 y = rand_range(1, (cur_hgt / div));
7520 x = rand_range(1, (cur_wid / div));
7521 d = rand_range(0, 3);
7522
7523 dig(maze, y, x, d);
7524
7525 maze[y][x] = 0;
7526
7527 for (d = 0; d <= 3; d++)
7528 {
7529 switch (d)
7530 {
7531 case 0:
7532 {
7533 dy = 0;
7534 dx = 1;
7535 m_1 = 1;
7536 m_2 = 4;
7537 break;
7538 }
7539
7540 case 1:
7541 {
7542 dy = -1;
7543 dx = 0;
7544 m_1 = 2;
7545 m_2 = 8;
7546 break;
7547 }
7548
7549 case 2:
7550 {
7551 dy = 0;
7552 dx = -1;
7553 m_1 = 4;
7554 m_2 = 1;
7555 break;
7556 }
7557
7558 case 3:
7559 {
7560 dy = 1;
7561 dx = 0;
7562 m_1 = 8;
7563 m_2 = 2;
7564 break;
7565 }
7566 }
7567
7568 if ((maze[y + dy][x + dx] != -1) &&
7569 ((maze[y + dy][x + dx] & m_2) != 0))
7570 {
7571 maze[y][x] |= m_1;
7572 }
7573 }
7574
7575 /* Translate the maze bit array into a real dungeon map -- DG */
7576 for (j = 1; j <= (cur_hgt / div) - 2; j++)
7577 {
7578 for (i = 1; i <= (cur_wid / div) - 2; i++)
7579 {
7580 for (dx = 0; dx < corridor; dx++)
7581 {
7582 for (dy = 0; dy < corridor; dy++)
7583 {
7584 if (maze[j][i])
7585 {
7586 place_floor_respectedly(wpos, j * div + dy, i * div + dx);
7587 }
7588
7589 if (maze[j][i] & 1)
7590 {
7591 place_floor_respectedly(wpos, j * div + dy, i * div + dx + corridor);
7592 }
7593
7594 if(maze[j][i] & 8)
7595 {
7596 place_floor_respectedly(wpos, j * div + dy + corridor, i * div + dx);
7597 }
7598 }
7599 }
7600 }
7601 }
7602
7603 /* Free temporary memory */
7604 C_KILL(maze, (MAX_HGT / 2) + 2, maze_row);
7605 }
7606
7607
7608 #if 0 /* this would make a good bottleneck */
7609 /*
7610 * Generate a game of life level :) and make it evolve
7611 */
7612 void evolve_level(worldpos *wpos, bool noise)
7613 {
7614 int i, j;
7615
7616 int cw = 0, cf = 0;
7617
7618
7619 /* Add a bit of noise */
7620 if (noise)
7621 {
7622 for (i = 1; i < cur_wid - 1; i++)
7623 {
7624 for (j = 1; j < cur_hgt - 1; j++)
7625 {
7626 if (f_info[cave[j][i].feat].flags1 & FF1_WALL) cw++;
7627 if (f_info[cave[j][i].feat].flags1 & FF1_FLOOR) cf++;
7628 }
7629 }
7630
7631 for (i = 1; i < cur_wid - 1; i++)
7632 {
7633 for (j = 1; j < cur_hgt - 1; j++)
7634 {
7635 cave_type *c_ptr;
7636
7637 /* Access the grid */
7638 c_ptr = &cave[j][i];
7639
7640 /* Permanent features should stay */
7641 if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) continue;
7642
7643 /* Avoid evolving grids with object or monster */
7644 if (c_ptr->o_idx || c_ptr->m_idx) continue;
7645
7646 /* Avoid evolving player grid */
7647 if ((j == py) && (i == px)) continue;
7648
7649 if (magik(7))
7650 {
7651 if (cw > cf)
7652 {
7653 place_floor(j, i);
7654 }
7655 else
7656 {
7657 place_filler(j, i);
7658 }
7659 }
7660 }
7661 }
7662 }
7663
7664 for (i = 1; i < cur_wid - 1; i++)
7665 {
7666 for (j = 1; j < cur_hgt - 1; j++)
7667 {
7668 int x, y, c;
7669 cave_type *c_ptr;
7670
7671 /* Access the grid */
7672 c_ptr = &cave[j][i];
7673
7674 /* Permanent features should stay */
7675 if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) continue;
7676
7677 /* Avoid evolving grids with object or monster */
7678 if (c_ptr->o_idx || c_ptr->m_idx) continue;
7679
7680 /* Avoid evolving player grid */
7681 if ((j == py) && (i == px)) continue;
7682
7683
7684 /* Reset tally */
7685 c = 0;
7686
7687 /* Count number of surrounding walls */
7688 for (x = i - 1; x <= i + 1; x++)
7689 {
7690 for (y = j - 1; y <= j + 1; y++)
7691 {
7692 if ((x == i) && (y == j)) continue;
7693 if (f_info[cave[y][x].feat].flags1 & FF1_WALL) c++;
7694 }
7695 }
7696
7697 /*
7698 * Changed these parameters a bit, so that it doesn't produce
7699 * too open or too narrow levels -- pelpel
7700 */
7701 /* Starved or suffocated */
7702 if ((c < 4) || (c >= 7))
7703 {
7704 if (f_info[c_ptr->feat].flags1 & FF1_WALL)
7705 {
7706 place_floor(j, i);
7707 }
7708 }
7709
7710 /* Spawned */
7711 else if ((c == 4) || (c == 5))
7712 {
7713 if (!(f_info[c_ptr->feat].flags1 & FF1_WALL))
7714 {
7715 place_filler(j, i);
7716 }
7717 }
7718 }
7719 }
7720
7721 /* Notice changes */
7722 p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_FLOW | PU_MON_LITE);
7723 }
7724
7725
7726 static void gen_life_level(worldpos *wpos)
7727 {
7728 int i, j;
7729
7730 for (i = 1; i < cur_wid - 1; i++)
7731 {
7732 for (j = 1; j < cur_hgt - 1; j++)
7733 {
7734 cave[j][i].info = (CAVE_ROOM | CAVE_GLOW | CAVE_MARK);
7735 if (magik(45)) place_floor(j, i);
7736 else place_filler(j, i);
7737 }
7738 }
7739
7740 evolve_level(FALSE);
7741 evolve_level(FALSE);
7742 evolve_level(FALSE);
7743 }
7744 #endif /* 0 */
7745 /* XXX XXX Here ends the big lump of ToME cake */
7746
7747
7748 /* Copy (y, x) feat(usually door) to (y2,x2), and trap it if needed.
7749 * - Jir - */
7750 static void duplicate_door(worldpos *wpos, int y, int x, int y2, int x2)
7751 {
7752 #ifdef WIDE_CORRIDORS
7753 int tmp;
7754 cave_type **zcave;
7755 if (!(zcave = getcave(wpos))) return;
7756
7757 /* Place the same type of door */
7758 zcave[y2][x2].feat = zcave[y][x].feat;
7759
7760 /* let's trap this too ;) */
7761 if ((tmp = getlevel(wpos)) <= COMFORT_PASSAGE_DEPTH ||
7762 rand_int(TRAPPED_DOOR_RATE) > tmp + TRAPPED_DOOR_BASE) return;
7763 place_trap(wpos, y2, x2, 0);
7764 #endif
7765 }
7766
7767
7768
7769 /*
7770 * Constructs a tunnel between two points
7771 *
7772 * This function must be called BEFORE any streamers are created,
7773 * since we use the special "granite wall" sub-types to keep track
7774 * of legal places for corridors to pierce rooms.
7775 *
7776 * We use "door_flag" to prevent excessive construction of doors
7777 * along overlapping corridors.
7778 *
7779 * We queue the tunnel grids to prevent door creation along a corridor
7780 * which intersects itself.
7781 *
7782 * We queue the wall piercing grids to prevent a corridor from leaving
7783 * a room and then coming back in through the same entrance.
7784 *
7785 * We "pierce" grids which are "outer" walls of rooms, and when we
7786 * do so, we change all adjacent "outer" walls of rooms into "solid"
7787 * walls so that no two corridors may use adjacent grids for exits.
7788 *
7789 * The "solid" wall check prevents corridors from "chopping" the
7790 * corners of rooms off, as well as "silly" door placement, and
7791 * "excessively wide" room entrances.
7792 *
7793 * Useful "feat" values:
7794 * FEAT_WALL_EXTRA -- granite walls
7795 * FEAT_WALL_INNER -- inner room walls
7796 * FEAT_WALL_OUTER -- outer room walls
7797 * FEAT_WALL_SOLID -- solid room walls
7798 * FEAT_PERM_EXTRA -- shop walls (perma)
7799 * FEAT_PERM_INNER -- inner room walls (perma)
7800 * FEAT_PERM_OUTER -- outer room walls (perma)
7801 * FEAT_PERM_SOLID -- dungeon border (perma)
7802 */
7803 static void build_tunnel(struct worldpos *wpos, int row1, int col1, int row2, int col2) {
7804 int i, y, x, tmp;
7805 int tmp_row, tmp_col;
7806 int row_dir, col_dir;
7807 int start_row, start_col;
7808 int main_loop_count = 0;
7809
7810 bool door_flag = FALSE;
7811 cave_type *c_ptr;
7812
7813 dungeon_type *d_ptr = getdungeon(wpos);
7814 int dun_type;
7815 #ifdef IRONDEEPDIVE_MIXED_TYPES
7816 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
7817 else
7818 #endif
7819 dun_type = d_ptr->theme ? d_ptr->theme : d_ptr->type;
7820
7821 #if 0
7822 dungeon_info_type *di_ptr = &d_info[dun_type];
7823 #endif
7824
7825 cave_type **zcave;
7826 if (!(zcave = getcave(wpos))) return;
7827
7828 /* Reset the arrays */
7829 dun->tunn_n = 0;
7830 dun->wall_n = 0;
7831
7832 /* Save the starting location */
7833 start_row = row1;
7834 start_col = col1;
7835
7836 /* Start out in the correct direction */
7837 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
7838
7839 /* Keep going until done (or bored) */
7840 while ((row1 != row2) || (col1 != col2)) {
7841 /* Mega-Hack -- Paranoia -- prevent infinite loops */
7842 if (main_loop_count++ > 2000) break;
7843
7844 /* Allow bends in the tunnel */
7845 if (rand_int(100) < DUN_TUN_CHG) {
7846 /* Acquire the correct direction */
7847 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
7848
7849 /* Random direction */
7850 if (rand_int(100) < DUN_TUN_RND)
7851 rand_dir(&row_dir, &col_dir);
7852 }
7853
7854 /* Get the next location */
7855 tmp_row = row1 + row_dir;
7856 tmp_col = col1 + col_dir;
7857
7858
7859 /* Extremely Important -- do not leave the dungeon */
7860 while (!in_bounds(tmp_row, tmp_col)) {
7861 /* Acquire the correct direction */
7862 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
7863
7864 /* Random direction */
7865 if (rand_int(100) < DUN_TUN_RND)
7866 rand_dir(&row_dir, &col_dir);
7867
7868 /* Get the next location */
7869 tmp_row = row1 + row_dir;
7870 tmp_col = col1 + col_dir;
7871 }
7872
7873
7874 /* Access the location */
7875 c_ptr = &zcave[tmp_row][tmp_col];
7876
7877 /* Avoid the edge of the dungeon */
7878 if ((f_info[c_ptr->feat].flags2 & FF2_BOUNDARY)) continue;
7879
7880 /* Avoid the edge of vaults */
7881 if (c_ptr->feat == FEAT_PERM_OUTER) continue;
7882
7883 /* Avoid "solid" granite walls */
7884 if (c_ptr->feat == FEAT_WALL_SOLID) continue;
7885
7886 /*
7887 * Pierce "outer" walls of rooms
7888 * Cannot trust feat code any longer...
7889 */
7890 if ((c_ptr->feat == feat_wall_outer) &&
7891 (c_ptr->info & CAVE_ROOM)) {
7892 /* Acquire the "next" location */
7893 y = tmp_row + row_dir;
7894 x = tmp_col + col_dir;
7895
7896 /* Hack -- Avoid outer/solid permanent walls */
7897 if (zcave[y][x].feat == FEAT_PERM_OUTER) continue;
7898 if ((f_info[zcave[y][x].feat].flags2 & FF2_BOUNDARY)) continue;
7899
7900 /* Hack -- Avoid outer/solid granite walls */
7901 if ((zcave[y][x].feat == feat_wall_outer) &&
7902 (zcave[y][x].info & CAVE_ROOM)) continue;
7903 if (zcave[y][x].feat == FEAT_WALL_SOLID) continue;
7904
7905 /* Accept this location */
7906 row1 = tmp_row;
7907 col1 = tmp_col;
7908
7909 /* Save the wall location */
7910 if (dun->wall_n < WALL_MAX) {
7911 dun->wall[dun->wall_n].y = row1;
7912 dun->wall[dun->wall_n].x = col1;
7913 dun->wall_n++;
7914 }
7915
7916 #ifdef WIDE_CORRIDORS
7917 /* Save the wall location */
7918 if (dun->wall_n < WALL_MAX) {
7919 if (!(f_info[zcave[row1 + col_dir][col1 + row_dir].feat].flags2 & FF2_BOUNDARY) &&
7920 !(f_info[zcave[row1 + col_dir][col1 + row_dir].feat].flags2 & FF2_BOUNDARY))
7921 {
7922 dun->wall[dun->wall_n].y = row1 + col_dir;
7923 dun->wall[dun->wall_n].x = col1 + row_dir;
7924 dun->wall_n++;
7925 } else {
7926 dun->wall[dun->wall_n].y = row1;
7927 dun->wall[dun->wall_n].x = col1;
7928 dun->wall_n++;
7929 }
7930 }
7931 #endif
7932
7933 #ifdef WIDE_CORRIDORS
7934 /* Forbid re-entry near this piercing */
7935 for (y = row1 - 2; y <= row1 + 2; y++) {
7936 for (x = col1 - 2; x <= col1 + 2; x++) {
7937 /* Be sure we are "in bounds" */
7938 if (!in_bounds(y, x)) continue;
7939
7940 /* Convert adjacent "outer" walls as "solid" walls */
7941 if (zcave[y][x].feat == feat_wall_outer) {
7942 /* Change the wall to a "solid" wall */
7943 zcave[y][x].feat = FEAT_WALL_SOLID;
7944 }
7945 }
7946 }
7947 #else
7948 /* Forbid re-entry near this piercing */
7949 for (y = row1 - 1; y <= row1 + 1; y++) {
7950 for (x = col1 - 1; x <= col1 + 1; x++) {
7951 /* Convert adjacent "outer" walls as "solid" walls */
7952 if (zcave[y][x].feat == feat_wall_outer) {
7953 /* Change the wall to a "solid" wall */
7954 zcave[y][x].feat = FEAT_WALL_SOLID;
7955 }
7956 }
7957 }
7958 #endif
7959 }
7960
7961 /* Travel quickly through rooms */
7962 else if (c_ptr->info & CAVE_ROOM) {
7963 /* Accept the location */
7964 row1 = tmp_row;
7965 col1 = tmp_col;
7966 }
7967
7968 /* Tunnel through all other walls */
7969 else if ((c_ptr->feat == d_info[dun_type].fill_type[0]) ||
7970 (c_ptr->feat == d_info[dun_type].fill_type[1]) ||
7971 (c_ptr->feat == d_info[dun_type].fill_type[2]) ||
7972 #ifdef IRONDEEPDIVE_MIXED_TYPES
7973 (c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 0) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[3]) ||
7974 (c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 1) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[4])
7975 #else
7976 (c_ptr->feat == d_info[dun_type].fill_type[3]) ||
7977 (c_ptr->feat == d_info[dun_type].fill_type[4])
7978 #endif
7979 ) {
7980 /* Accept this location */
7981 row1 = tmp_row;
7982 col1 = tmp_col;
7983
7984 /* Save the tunnel location */
7985 if (dun->tunn_n < TUNN_MAX) {
7986 dun->tunn[dun->tunn_n].y = row1;
7987 dun->tunn[dun->tunn_n].x = col1;
7988 dun->tunn_n++;
7989 }
7990
7991 #ifdef WIDE_CORRIDORS
7992 /* Note that this is incredibly hacked */
7993
7994 /* Make sure we're in bounds */
7995 if (in_bounds(row1 + col_dir, col1 + row_dir)) {
7996 /* New spot to be hollowed out */
7997 c_ptr = &zcave[row1 + col_dir][col1 + row_dir];
7998
7999 /* Make sure it's a wall we want to tunnel */
8000 if ((c_ptr->feat == d_info[dun_type].fill_type[0]) ||
8001 (c_ptr->feat == d_info[dun_type].fill_type[1]) ||
8002 (c_ptr->feat == d_info[dun_type].fill_type[2]) ||
8003 #ifdef IRONDEEPDIVE_MIXED_TYPES
8004 (c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 0) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[3]) ||
8005 (c_ptr->feat == d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 1) ? iddc[ABS(wpos->wz)].next : dun_type)].fill_type[4]) ||
8006 #else
8007 (c_ptr->feat == d_info[dun_type].fill_type[3]) ||
8008 (c_ptr->feat == d_info[dun_type].fill_type[4]) ||
8009 #endif
8010 c_ptr->feat == FEAT_WALL_EXTRA) {
8011 /* Save the tunnel location */
8012 if (dun->tunn_n < TUNN_MAX) {
8013 dun->tunn[dun->tunn_n].y = row1 + col_dir;
8014 dun->tunn[dun->tunn_n].x = col1 + row_dir;
8015 dun->tunn_n++;
8016 }
8017 }
8018 }
8019 #endif
8020
8021 /* Allow door in next grid */
8022 door_flag = FALSE;
8023 }
8024
8025 /* Handle corridor intersections or overlaps */
8026 else {
8027 /* Accept the location */
8028 row1 = tmp_row;
8029 col1 = tmp_col;
8030
8031 /* Collect legal door locations */
8032 if (!door_flag) {
8033 /* Save the door location */
8034 if (dun->door_n < DOOR_MAX) {
8035 dun->door[dun->door_n].y = row1;
8036 dun->door[dun->door_n].x = col1;
8037 dun->door_n++;
8038 }
8039
8040 #ifdef WIDE_CORRIDORS
8041 #if 0
8042 /* Save the next door location */
8043 if (dun->door_n < DOOR_MAX) {
8044 if (in_bounds(row1 + col_dir, col1 + row_dir)) {
8045 dun->door[dun->door_n].y = row1 + col_dir;
8046 dun->door[dun->door_n].x = col1 + row_dir;
8047 dun->door_n++;
8048 }
8049
8050 /* Hack -- Duplicate the previous door */
8051 else {
8052 dun->door[dun->door_n].y = row1;
8053 dun->door[dun->door_n].x = col1;
8054 dun->door_n++;
8055 }
8056 }
8057 #endif /* 0 */
8058 #endif
8059
8060 /* No door in next grid */
8061 door_flag = TRUE;
8062 }
8063
8064 /* Hack -- allow pre-emptive tunnel termination */
8065 if (rand_int(100) >= DUN_TUN_CON) {
8066 /* Distance between row1 and start_row */
8067 tmp_row = row1 - start_row;
8068 if (tmp_row < 0) tmp_row = (-tmp_row);
8069
8070 /* Distance between col1 and start_col */
8071 tmp_col = col1 - start_col;
8072 if (tmp_col < 0) tmp_col = (-tmp_col);
8073
8074 /* Terminate the tunnel */
8075 if ((tmp_row > 10) || (tmp_col > 10)) break;
8076 }
8077 }
8078 }
8079
8080
8081 /* Turn the tunnel into corridor */
8082 for (i = 0; i < dun->tunn_n; i++) {
8083 /* Access the grid */
8084 y = dun->tunn[i].y;
8085 x = dun->tunn[i].x;
8086
8087 /* Access the grid */
8088 c_ptr = &zcave[y][x];
8089
8090 /* Clear previous contents, add a floor */
8091 place_floor(wpos, y, x);
8092 }
8093
8094
8095 /* Apply the piercings that we found */
8096 for (i = 0; i < dun->wall_n; i++) {
8097 /* Access the grid */
8098 y = dun->wall[i].y;
8099 x = dun->wall[i].x;
8100
8101 /* Access the grid */
8102 c_ptr = &zcave[y][x];
8103
8104 /* Clear previous contents, add up floor */
8105 place_floor(wpos, y, x);
8106
8107 /* Occasional doorway */
8108 /* Some dungeons don't have doors at all */
8109 if ((
8110 #ifdef IRONDEEPDIVE_MIXED_TYPES
8111 in_irondeepdive(wpos) ? (!(d_info[iddc[ABS(wpos->wz)].type].flags1 & (DF1_NO_DOORS))) :
8112 #endif
8113 (!(d_ptr->flags1 & (DF1_NO_DOORS)))) &&
8114 rand_int(100) < DUN_TUN_PEN) {
8115 #ifdef WIDE_CORRIDORS
8116 /* hack: prepare 2nd door part for door_makes_no_sense() check */
8117 int x2, y2;
8118
8119 /* Make sure both halves get a door */
8120 if (i % 2) {
8121 /* Access the grid */
8122 y2 = dun->wall[i - 1].y;
8123 x2 = dun->wall[i - 1].x;
8124 } else {
8125 /* Access the grid */
8126 y2 = dun->wall[i + 1].y;
8127 x2 = dun->wall[i + 1].x;
8128
8129 /* Increment counter */
8130 i++;
8131 }
8132
8133 #ifdef ENABLE_DOOR_CHECK
8134 /* hack! provisional feat */
8135 zcave[y2][x2].feat = FEAT_WALL_EXTRA;
8136 #endif
8137 #endif
8138
8139 /* Place a random door */
8140 place_random_door(wpos, y, x);
8141
8142 #ifdef WIDE_CORRIDORS
8143 /* Place the same type of door */
8144 zcave[y2][x2].feat = zcave[y][x].feat;
8145
8146 /* let's trap this too ;) */
8147 if ((tmp = getlevel(wpos)) <= COMFORT_PASSAGE_DEPTH ||
8148 rand_int(TRAPPED_DOOR_RATE) > tmp + TRAPPED_DOOR_BASE) continue;
8149 place_trap(wpos, y2, x2, 0);
8150 #endif
8151 }
8152 }
8153 }
8154
8155
8156
8157
8158 /*
8159 * Count the number of "corridor" grids adjacent to the given grid.
8160 *
8161 * Note -- Assumes "in_bounds(y1, x1)"
8162 *
8163 * XXX XXX This routine currently only counts actual "empty floor"
8164 * grids which are not in rooms. We might want to also count stairs,
8165 * open doors, closed doors, etc.
8166 */
8167 static int next_to_corr(struct worldpos *wpos, int y1, int x1) {
8168 int i, y, x, k = 0;
8169 cave_type *c_ptr;
8170 dungeon_type *dt_ptr = getdungeon(wpos);
8171 int dun_type;
8172 cave_type **zcave;
8173
8174 #ifdef IRONDEEPDIVE_MIXED_TYPES
8175 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
8176 else
8177 #endif
8178 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
8179
8180 if (!(zcave = getcave(wpos))) return(FALSE);
8181
8182 /* Scan adjacent grids */
8183 for (i = 0; i < 4; i++) {
8184 /* Extract the location */
8185 y = y1 + ddy_ddd[i];
8186 x = x1 + ddx_ddd[i];
8187
8188 /* Skip non floors */
8189 if (!cave_floor_bold(zcave, y, x)) continue;
8190 /* Access the grid */
8191 c_ptr = &zcave[y][x];
8192
8193 /* Skip non "empty floor" grids */
8194 if ((c_ptr->feat != d_info[dun_type].floor[0]) &&
8195 (c_ptr->feat != d_info[dun_type].floor[1]) &&
8196 (c_ptr->feat != d_info[dun_type].floor[2]) &&
8197 #ifdef IRONDEEPDIVE_MIXED_TYPES
8198 (c_ptr->feat != d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 0) ? iddc[ABS(wpos->wz)].next : dun_type)].floor[3]) &&
8199 (c_ptr->feat != d_info[((in_irondeepdive(wpos) && iddc[ABS(wpos->wz)].step > 1) ? iddc[ABS(wpos->wz)].next : dun_type)].floor[4]))
8200 #else
8201 (c_ptr->feat != d_info[dun_type].floor[3]) &&
8202 (c_ptr->feat != d_info[dun_type].floor[4]))
8203 #endif
8204 continue;
8205
8206 /* Skip grids inside rooms */
8207 if (c_ptr->info & CAVE_ROOM) continue;
8208
8209 /* Count these grids */
8210 k++;
8211 }
8212
8213 /* Return the number of corridors */
8214 return (k);
8215 }
8216
8217
8218 /*
8219 * Determine if the given location is "between" two walls,
8220 * and "next to" two corridor spaces. XXX XXX XXX
8221 *
8222 * Assumes "in_bounds(y,x)"
8223 */
8224 #if 0
8225 static bool possible_doorway(struct worldpos *wpos, int y, int x)
8226 {
8227 cave_type **zcave;
8228 if (!(zcave = getcave(wpos))) return(FALSE);
8229
8230 /* Count the adjacent corridors */
8231 if (next_to_corr(wpos, y, x) >= 2)
8232 {
8233 /* Check Vertical */
8234 if ((zcave[y-1][x].feat >= FEAT_MAGMA) &&
8235 (zcave[y+1][x].feat >= FEAT_MAGMA))
8236 {
8237 return (TRUE);
8238 }
8239
8240 /* Check Horizontal */
8241 if ((zcave[y][x-1].feat >= FEAT_MAGMA) &&
8242 (zcave[y][x+1].feat >= FEAT_MAGMA))
8243 {
8244 return (TRUE);
8245 }
8246 }
8247
8248 /* No doorway */
8249 return (FALSE);
8250 }
8251 #else /* 0 */
8252 static int possible_doorway(struct worldpos *wpos, int y, int x)
8253 {
8254 cave_type **zcave;
8255 if (!(zcave = getcave(wpos))) return(FALSE);
8256
8257 /* Count the adjacent corridors */
8258 if (next_to_corr(wpos, y, x) >= 2)
8259 {
8260 /* Hack -- avoid doors next to doors */
8261 if (is_door(zcave[y-1][x].feat) ||
8262 is_door(zcave[y+1][x].feat) ||
8263 is_door(zcave[y][x-1].feat) ||
8264 is_door(zcave[y][x+1].feat))
8265 return (-1);
8266
8267 /* Check Vertical */
8268 if ((zcave[y-1][x].feat >= FEAT_MAGMA) &&
8269 (zcave[y+1][x].feat >= FEAT_MAGMA))
8270 {
8271 return (8);
8272 }
8273 #if 1
8274 if (in_bounds(y-2, x) &&
8275 (zcave[y-2][x].feat >= FEAT_MAGMA) &&
8276 (zcave[y+1][x].feat >= FEAT_MAGMA))
8277 {
8278 return (1);
8279 }
8280 if (in_bounds(y+2, x) &&
8281 (zcave[y-1][x].feat >= FEAT_MAGMA) &&
8282 (zcave[y+2][x].feat >= FEAT_MAGMA))
8283 {
8284 return (0);
8285 }
8286 #endif /* 0 */
8287
8288 /* Check Horizontal */
8289 if ((zcave[y][x-1].feat >= FEAT_MAGMA) &&
8290 (zcave[y][x+1].feat >= FEAT_MAGMA))
8291 {
8292 return (8);
8293 }
8294 #if 1
8295 if (in_bounds(y, x-2) &&
8296 (zcave[y][x-2].feat >= FEAT_MAGMA) &&
8297 (zcave[y][x+1].feat >= FEAT_MAGMA))
8298 {
8299 return (3);
8300 }
8301 if (in_bounds(y, x+2) &&
8302 (zcave[y][x-1].feat >= FEAT_MAGMA) &&
8303 (zcave[y][x+2].feat >= FEAT_MAGMA))
8304 {
8305 return (2);
8306 }
8307 #endif /* 0 */
8308 }
8309
8310 /* No doorway */
8311 return (-1);
8312 }
8313 #endif /* 0 */
8314
8315
8316 #if 0
8317 /*
8318 * Places door at y, x position if at least 2 walls found
8319 */
8320 static void try_door(struct worldpos *wpos, int y, int x)
8321 {
8322 cave_type **zcave;
8323 if (!(zcave = getcave(wpos))) return;
8324
8325 /* Paranoia */
8326 if (!in_bounds(y, x)) return;
8327
8328 /* Ignore walls */
8329 if (zcave[y][x].feat >= FEAT_MAGMA) return;
8330
8331 /* Ignore room grids */
8332 if (zcave[y][x].info & CAVE_ROOM) return;
8333
8334 /* Occasional door (if allowed) */
8335 if ((rand_int(100) < DUN_TUN_JCT) && possible_doorway(wpos, y, x))
8336 {
8337 /* Place a door */
8338 place_random_door(wpos, y, x);
8339 }
8340 }
8341 #endif /* 0 */
8342
8343 /*
8344 * Places doors around y, x position
8345 */
8346 static void try_doors(worldpos *wpos, int y, int x) {
8347 bool dir_ok[4];
8348 int dir_next[4];
8349 int i, k, n;
8350 int yy, xx;
8351
8352 dungeon_type *d_ptr = getdungeon(wpos);
8353 cave_type **zcave;
8354 if (!(zcave = getcave(wpos))) return;
8355
8356 /* Some dungeons don't have doors at all */
8357 if (
8358 #ifdef IRONDEEPDIVE_MIXED_TYPES
8359 in_irondeepdive(wpos) ? (d_info[iddc[ABS(wpos->wz)].type].flags1 & (DF1_NO_DOORS)) :
8360 #endif
8361 (d_ptr->flags1 & (DF1_NO_DOORS)))
8362 return;
8363
8364 /* Reset tally */
8365 n = 0;
8366
8367 /* Look four cardinal directions */
8368 for (i = 0; i < 4; i++) {
8369 /* Assume NG */
8370 dir_ok[i] = FALSE;
8371
8372 /* Access location */
8373 yy = y + ddy_ddd[i];
8374 xx = x + ddx_ddd[i];
8375
8376 /* Out of level boundary */
8377 if (!in_bounds(yy, xx)) continue;
8378
8379 /* Ignore walls */
8380 if (zcave[y][x].feat >= FEAT_MAGMA
8381 || zcave[y][x].feat == FEAT_PERM_CLEAR) /* paranoia for now (dungeon floors don't have this feat) */
8382 continue;
8383
8384 /* Ignore room grids */
8385 if (zcave[y][x].info & CAVE_ROOM) continue;
8386
8387 /* Not a doorway */
8388 if ((dir_next[i] = possible_doorway(wpos, yy, xx)) < 0) continue;
8389
8390 /* Accept the direction */
8391 dir_ok[i] = TRUE;
8392
8393 /* Count good spots */
8394 n++;
8395 }
8396
8397 /* Use the traditional method 75% of time */
8398 if (rand_int(100) < 75) {
8399 for (i = 0; i < 4; i++) {
8400 /* Bad locations */
8401 if (!dir_ok[i]) continue;
8402
8403 /* Place one of various kinds of doors */
8404 if (rand_int(100) < DUN_TUN_JCT) {
8405 /* Access location */
8406 yy = y + ddy_ddd[i];
8407 xx = x + ddx_ddd[i];
8408
8409 #ifdef ENABLE_DOOR_CHECK
8410 /* hack for door_makes_no_sense() check */
8411 zcave[yy + ddy_ddd[dir_next[i]]][xx + ddx_ddd[dir_next[i]]].feat = FEAT_WALL_EXTRA;
8412 #endif
8413
8414 /* Place a door */
8415 place_random_door(wpos, yy, xx);
8416
8417 duplicate_door(wpos, yy, xx, yy + ddy_ddd[dir_next[i]], xx + ddx_ddd[dir_next[i]]);
8418 }
8419 }
8420 }
8421
8422 /* Use alternative method */
8423 else {
8424 /* A crossroad */
8425 if (n == 4) {
8426 /* Clear OK flags XXX */
8427 for (i = 0; i < 4; i++) dir_ok[i] = FALSE;
8428
8429 /* Put one or two secret doors */
8430 dir_ok[rand_int(4)] = TRUE;
8431 dir_ok[rand_int(4)] = TRUE;
8432 }
8433
8434 /* A T-shaped intersection or two possible doorways */
8435 else if ((n == 3) || (n == 2)) {
8436 /* Pick one random location from the list */
8437 k = rand_int(n);
8438
8439 for (i = 0; i < 4; i++) {
8440 /* Reject all but k'th OK direction */
8441 if (dir_ok[i] && (k-- != 0)) dir_ok[i] = FALSE;
8442 }
8443 }
8444
8445 /* Place secret door(s) */
8446 for (i = 0; i < 4; i++) {
8447 /* Bad location */
8448 if (!dir_ok[i]) continue;
8449
8450 /* Access location */
8451 yy = y + ddy_ddd[i];
8452 xx = x + ddx_ddd[i];
8453
8454 #ifdef ENABLE_DOOR_CHECK
8455 /* hack for door_makes_no_sense() check */
8456 zcave[yy + ddy_ddd[dir_next[i]]][xx + ddx_ddd[dir_next[i]]].feat = FEAT_WALL_EXTRA;
8457 #endif
8458
8459 /* Place a secret door */
8460 place_secret_door(wpos, yy, xx);
8461
8462 duplicate_door(wpos, yy, xx, yy + ddy_ddd[dir_next[i]], xx + ddx_ddd[dir_next[i]]);
8463 }
8464 }
8465 }
8466
8467
8468
8469
8470 /*
8471 * Attempt to build a room of the given type at the given block
8472 *
8473 * Note that we restrict the number of "crowded" rooms to reduce
8474 * the chance of overflowing the monster list during level creation.
8475 */
8476 static bool room_build(struct worldpos *wpos, int y, int x, int typ, player_type *p_ptr) {
8477 dungeon_type *d_ptr = getdungeon(wpos);
8478
8479 /* Restrict level */
8480 if (getlevel(wpos) < room[typ].level) return (FALSE);
8481
8482 /* Restrict "crowded" rooms */
8483 if (dun->crowded && ((typ == 5) || (typ == 6))) return (FALSE);
8484
8485 /* Less rooms/vaults in some dungeons? */
8486 if (d_ptr) {
8487 if ((
8488 #ifdef IRONDEEPDIVE_MIXED_TYPES
8489 in_irondeepdive(wpos) ? (d_info[iddc[ABS(wpos->wz)].type].flags3 & DF3_NO_VAULTS) :
8490 #endif
8491 (d_ptr->flags3 & DF3_NO_VAULTS))
8492 && (typ == 7 || typ == 8 || typ == 11))
8493 return FALSE;
8494
8495 if ((
8496 #ifdef IRONDEEPDIVE_MIXED_TYPES
8497 in_irondeepdive(wpos) ? (d_info[iddc[ABS(wpos->wz)].type].flags3 & DF3_FEW_ROOMS) :
8498 #endif
8499 (d_ptr->flags3 & DF3_FEW_ROOMS))
8500 && rand_int(20))
8501 return FALSE;
8502
8503 #ifdef IDDC_FEWER_VAULTS
8504 if (in_irondeepdive(wpos) && rand_int(4) &&
8505 (typ == 7 || typ == 8 || typ == 11))
8506 return FALSE;
8507 #endif
8508 }
8509
8510 #if 0
8511 /* Extract blocks */
8512 y1 = y0 + room[typ].dy1;
8513 y2 = y0 + room[typ].dy2;
8514 x1 = x0 + room[typ].dx1;
8515 x2 = x0 + room[typ].dx2;
8516
8517 /* Never run off the screen */
8518 if ((y1 < 0) || (y2 >= dun->row_rooms)) return (FALSE);
8519 if ((x1 < 0) || (x2 >= dun->col_rooms)) return (FALSE);
8520
8521 /* Verify open space */
8522 for (y = y1; y <= y2; y++) {
8523 for (x = x1; x <= x2; x++) {
8524 if (dun->room_map[y][x]) return (FALSE);
8525 }
8526 }
8527
8528 /* XXX XXX XXX It is *extremely* important that the following */
8529 /* calculation is *exactly* correct to prevent memory errors */
8530
8531 /* Acquire the location of the room */
8532 y = ((y1 + y2 + 1) * BLOCK_HGT) / 2;
8533 x = ((x1 + x2 + 1) * BLOCK_WID) / 2;
8534 #endif /* 0 */
8535
8536 /* Build a room */
8537 switch (typ)
8538 {
8539 /* Build an appropriate room */
8540 case 12: build_type12(wpos, y, x, p_ptr); break;
8541 case 11: build_type11(wpos, y, x, p_ptr); break;
8542 case 10: build_type10(wpos, y, x, p_ptr); break;
8543 case 9: build_type9 (wpos, y, x, p_ptr); break;
8544 case 8: build_type8 (wpos, y, x, p_ptr); break;
8545 case 7: build_type7 (wpos, y, x, p_ptr); break;
8546 case 6: build_type6 (wpos, y, x, p_ptr); break;
8547 case 5: build_type5 (wpos, y, x, p_ptr); break;
8548 case 4: build_type4 (wpos, y, x, p_ptr); break;
8549 case 3: build_type3 (wpos, y, x, p_ptr); break;
8550 case 2: build_type2 (wpos, y, x, p_ptr); break;
8551 case 1: build_type1 (wpos, y, x, p_ptr); break;
8552
8553 /* Paranoia */
8554 default: return (FALSE);
8555 }
8556
8557 #if 0
8558 /* Save the room location */
8559 if (dun->cent_n < CENT_MAX) {
8560 dun->cent[dun->cent_n].y = y;
8561 dun->cent[dun->cent_n].x = x;
8562 dun->cent_n++;
8563 }
8564
8565 /* Reserve some blocks */
8566 for (y = y1; y <= y2; y++) {
8567 for (x = x1; x <= x2; x++) {
8568 dun->room_map[y][x] = TRUE;
8569 }
8570 }
8571
8572 /* Count "crowded" rooms */
8573 if ((typ == 5) || (typ == 6)) dun->crowded = TRUE;
8574 #endif /* 0 */
8575
8576 /* Success */
8577 return (TRUE);
8578 }
8579
8580
8581 /*
8582 * Build probability tables for walls and floors and set feat_wall_outer
8583 * and feat_wall_inner according to the current information in d_info.txt
8584 *
8585 * *hint* *hint* with this made extern, and we no longer have to
8586 * store fill_type and floor_type in the savefile...
8587 */
8588 static void init_feat_info(worldpos *wpos) {
8589 int i, j;
8590 int cur_depth, max_depth;
8591 int p1, p2;
8592 int floor_lim[5];
8593 int fill_lim[5];
8594
8595 int dun_lev = getlevel(wpos);
8596 dungeon_type *dt_ptr = getdungeon(wpos);
8597 int dun_type;
8598 #ifdef IRONDEEPDIVE_MIXED_TYPES
8599 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
8600 else
8601 #endif
8602 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
8603
8604 dungeon_info_type *d_ptr = &d_info[dun_type];
8605 dun_level *l_ptr = getfloor(wpos); /* for DIGGING */
8606
8607 /* Default dungeon? */
8608 if (!dun_type) {
8609 feat_wall_outer = FEAT_WALL_OUTER; /* Outer wall of rooms */
8610 feat_wall_inner = FEAT_WALL_INNER; /* Inner wall of rooms */
8611
8612 for (i = 0; i < 1000; i++) {
8613 floor_type[i] = FEAT_FLOOR;
8614 fill_type[i] = FEAT_WALL_EXTRA; /* Dungeon filler */
8615 }
8616
8617 return;
8618 }
8619
8620 /* Retrieve dungeon depth info (base 1, to avoid zero divide errors) */
8621 #ifdef IRONDEEPDIVE_MIXED_TYPES
8622 if (in_irondeepdive(wpos)) {
8623 cur_depth = dun_lev;
8624 max_depth = d_ptr->maxdepth + 2; //hardcode (ew, fix for the 2 transitions levels, so max > cur in probability calcs)
8625 } else
8626 #endif
8627 {
8628 cur_depth = (dun_lev - d_ptr->mindepth) + 1;
8629 max_depth = (d_ptr->maxdepth - d_ptr->mindepth) + 1;
8630 }
8631
8632 /* Set room wall types */
8633 feat_wall_outer = d_ptr->outer_wall;
8634 feat_wall_inner = d_ptr->inner_wall;
8635 /* for DIGGING */
8636 if (feat_wall_outer == FEAT_SHAL_WATER || feat_wall_inner == FEAT_SHAL_WATER ||
8637 feat_wall_outer == FEAT_DEEP_WATER || feat_wall_inner == FEAT_DEEP_WATER)
8638 l_ptr->flags1 |= LF1_WATER | LF1_NO_LAVA;
8639 if (feat_wall_outer == FEAT_SHAL_LAVA || feat_wall_inner == FEAT_SHAL_LAVA ||
8640 feat_wall_outer == FEAT_DEEP_LAVA || feat_wall_inner == FEAT_DEEP_LAVA)
8641 l_ptr->flags1 |= LF1_LAVA | LF1_NO_WATER;
8642
8643
8644 /* Setup probability info -- Floors */
8645 for (i = 0; i < 5; i++) {
8646 p1 = d_ptr->floor_percent[i][0];
8647 p2 = d_ptr->floor_percent[i][1];
8648
8649 #ifdef IRONDEEPDIVE_MIXED_TYPES
8650 /* note: We make the assumption, that tile types of
8651 fields 1,2,3 have no two that are the same */
8652 /* hack the first 3 default probabilities for IDDC */
8653 if (i < 3) {
8654 if (d_ptr->floor[3] == d_ptr->floor[i]) {
8655 p1 -= d_ptr->floor_percent[3][0];
8656 p2 -= d_ptr->floor_percent[3][1];
8657 }
8658 if (d_ptr->floor[4] == d_ptr->floor[i]) {
8659 p1 -= d_ptr->floor_percent[4][0];
8660 p2 -= d_ptr->floor_percent[4][1];
8661 }
8662 }
8663 /* paranoia extreme */
8664 if (p1 < 0) p1 = 0;
8665 if (p2 < 0) p2 = 0;
8666 #endif
8667
8668 floor_lim[i] = (i == 5 - 1 ? 100 : (i > 0 ? floor_lim[i - 1] : 0) + p1 + (p2 - p1) * cur_depth / max_depth);
8669
8670 if (p1 != 0 || p2 != 0) {
8671 /* for DIGGING */
8672 if (d_ptr->floor[i] == FEAT_SHAL_WATER || d_ptr->floor[i] == FEAT_DEEP_WATER)
8673 l_ptr->flags1 |= LF1_WATER | LF1_NO_LAVA;
8674 if (d_ptr->floor[i] == FEAT_SHAL_LAVA || d_ptr->floor[i] == FEAT_DEEP_LAVA)
8675 l_ptr->flags1 |= LF1_LAVA | LF1_NO_WATER;
8676
8677 /* for streamer/river hack: don't build shallow ones if dungeon floor itself is deep */
8678 if (d_ptr->floor[i] == FEAT_DEEP_WATER
8679 || d_ptr->floor[i] == FEAT_SHAL_WATER) /* also build deep rivers on shallow base floor! */
8680 l_ptr->flags1 |= LF1_DEEP_WATER;
8681 if (d_ptr->floor[i] == FEAT_DEEP_LAVA
8682 || d_ptr->floor[i] == FEAT_SHAL_LAVA) /* also build deep rivers on shallow base floor! */
8683 {
8684 l_ptr->flags1 |= LF1_DEEP_LAVA;
8685 #ifdef TEST_SERVER /* debug */
8686 s_printf("deep-lava (%d,%d,%d)\n", wpos->wx, wpos->wy, wpos->wz);
8687 #endif
8688 }
8689 }
8690 }
8691
8692 /* Setup probability info -- Fillers */
8693 for (i = 0; i < 5; i++) {
8694 p1 = d_ptr->fill_percent[i][0];
8695 p2 = d_ptr->fill_percent[i][1];
8696
8697 #ifdef IRONDEEPDIVE_MIXED_TYPES
8698 /* note: We make the assumption, that tile types of
8699 fields 1,2,3 have no two that are the same */
8700 /* hack the first 3 default probabilities for IDDC */
8701 if (i < 3) {
8702 if (d_ptr->fill_type[3] == d_ptr->fill_type[i]) {
8703 p1 -= d_ptr->fill_percent[3][0];
8704 p2 -= d_ptr->fill_percent[3][1];
8705 }
8706 if (d_ptr->fill_type[4] == d_ptr->fill_type[i]) {
8707 p1 -= d_ptr->fill_percent[4][0];
8708 p2 -= d_ptr->fill_percent[4][1];
8709 }
8710 }
8711 /* paranoia extreme */
8712 if (p1 < 0) p1 = 0;
8713 if (p2 < 0) p2 = 0;
8714 #endif
8715
8716 fill_lim[i] = (i == 5 - 1 ? 100 : (i > 0 ? fill_lim[i - 1] : 0) + p1 + (p2 - p1) * cur_depth / max_depth);
8717 /* for DIGGING */
8718 if (p1 != 0 || p2 != 0) {
8719 if (d_ptr->fill_type[i] == FEAT_SHAL_WATER || d_ptr->fill_type[i] == FEAT_DEEP_WATER)
8720 l_ptr->flags1 |= LF1_WATER | LF1_NO_LAVA;
8721 if (d_ptr->fill_type[i] == FEAT_SHAL_LAVA || d_ptr->fill_type[i] == FEAT_DEEP_LAVA)
8722 l_ptr->flags1 |= LF1_LAVA | LF1_NO_WATER;
8723 }
8724 }
8725 /* fix double-negative flag */
8726 if ((l_ptr->flags1 & LF1_NO_WATER) && (l_ptr->flags1 & LF1_NO_LAVA))
8727 l_ptr->flags1 &= ~(LF1_NO_WATER | LF1_NO_LAVA);
8728
8729 #if 0
8730 /* for DIGGING */
8731 if (get_skill(SKILL_DRUID) &&
8732 (p_ptr->druid_extra & CLASS_FLOOD_LEVEL))
8733 l_ptr->flags1 |= LF1_WATER | LF1_NO_LAVA;
8734 #endif
8735 /* Fill the arrays of floors and walls in the good proportions */
8736 for (i = 0; i < 1000; i++) {
8737 #if 0
8738 /* Mega-HACK -- if a druid request a flooded level, he/she obtains it */
8739 if (get_skill(SKILL_DRUID) &&
8740 (p_ptr->druid_extra & CLASS_FLOOD_LEVEL))
8741 {
8742 if (i < 333)
8743 {
8744 floor_type[i] = FEAT_DEEP_WATER;
8745 }
8746 else
8747 {
8748 floor_type[i] = FEAT_SHAL_WATER;
8749 }
8750 }
8751 else
8752 #endif /* 0 */
8753 {
8754 for (j = 0; j < 5; j++) {
8755 if (i < floor_lim[j] || j == 5 - 1) {
8756 #ifdef IRONDEEPDIVE_MIXED_TYPES
8757 if (in_irondeepdive(wpos)) {
8758 if (iddc[ABS(wpos->wz)].step > 1) {
8759 switch (j) {
8760 case 3:
8761 case 4:
8762 floor_type[i] = d_info[iddc[ABS(wpos->wz)].next].floor[j];
8763 break;
8764 default:
8765 floor_type[i] = d_ptr->floor[j];
8766 break;
8767 }
8768 } else if (iddc[ABS(wpos->wz)].step > 0) {
8769 switch (j) {
8770 case 3:
8771 floor_type[i] = d_info[iddc[ABS(wpos->wz)].next].floor[j];
8772 break;
8773 default:
8774 floor_type[i] = d_ptr->floor[j];
8775 break;
8776 }
8777 } else floor_type[i] = d_ptr->floor[j];
8778 } else
8779 #endif
8780 floor_type[i] = dt_ptr->theme ? d_info[dt_ptr->theme].floor[j] : d_ptr->floor[j];
8781 break;
8782 }
8783 }
8784 }
8785
8786 for (j = 0; j < 5; j++) {
8787 if (i < fill_lim[j] || j == 5 - 1) {
8788 #ifdef IRONDEEPDIVE_MIXED_TYPES
8789 if (in_irondeepdive(wpos)) {
8790 if (iddc[ABS(wpos->wz)].step > 1) {
8791 switch (j) {
8792 case 3:
8793 case 4:
8794 fill_type[i] = d_info[iddc[ABS(wpos->wz)].next].fill_type[j];
8795 break;
8796 default:
8797 fill_type[i] = d_ptr->fill_type[j];
8798 break;
8799 }
8800 } else if (iddc[ABS(wpos->wz)].step > 0) {
8801 switch (j) {
8802 case 3:
8803 fill_type[i] = d_info[iddc[ABS(wpos->wz)].next].fill_type[j];
8804 break;
8805 default:
8806 fill_type[i] = d_ptr->fill_type[j];
8807 break;
8808 }
8809 } else fill_type[i] = d_ptr->fill_type[j];
8810 } else
8811 #endif
8812 fill_type[i] = dt_ptr->theme ? d_info[dt_ptr->theme].fill_type[j] : d_ptr->fill_type[j];
8813 break;
8814 }
8815 }
8816 }
8817 }
8818
8819
8820 /*
8821 * Fill a level with wall type specified in A: or L: line of d_info.txt
8822 *
8823 * 'use_floor', when it is TRUE, tells the function to use floor type
8824 * terrains (L:) instead of walls (A:).
8825 *
8826 * Filling behaviour can be controlled by the second parameter 'smooth',
8827 * with the following options available:
8828 *
8829 * smooth behaviour
8830 * ------ ------------------------------------------------------------
8831 * 0 Fill the entire level with fill_type[0] / floor[0]
8832 * 1 All the grids are randomly selected (== --P5.1.2)
8833 * 2 Slightly smoothed -- look like scattered patches
8834 * 3 More smoothed -- tend to look like caverns / small scale map
8835 * 4-- Max smoothing -- tend to look like landscape/island/
8836 * continent etc.
8837 * Added by C. Blue for Nether Realm:
8838 * 9 Like 2, just greatly reduced chance to place walls.
8839 *
8840 * I put it here, because there's another filler generator in
8841 * wild.c, but it works better there, in fact...
8842 *
8843 * CAVEAT: smoothness of 3 or greater doesn't work well with the
8844 * current secret door implementation. Outer walls also need some
8845 * rethinking.
8846 *
8847 * -- pelpel
8848 */
8849
8850 /*
8851 * Thou shalt not invoke the name of thy RNG in vain.
8852 * The Angband RNG generates 28 bit pseudo-random number, hence
8853 * 28 / 2 = 14
8854 */
8855 #define MAX_SHIFTS 14
8856
8857 static void fill_level(worldpos *wpos, bool use_floor, byte smooth) {
8858 int y, x;
8859 int step;
8860 int shift;
8861
8862 int cur_hgt = dun->l_ptr->hgt;
8863 int cur_wid = dun->l_ptr->wid;
8864
8865 dungeon_type *dt_ptr = getdungeon(wpos);
8866 int dun_type;
8867 #ifdef IRONDEEPDIVE_MIXED_TYPES
8868 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
8869 else
8870 #endif
8871 dun_type = dt_ptr->theme ? dt_ptr->theme : dt_ptr->type;
8872
8873 cave_type **zcave;
8874 if (!(zcave = getcave(wpos))) return;
8875
8876 /* Convert smoothness to initial step */
8877 if (smooth == 0) step = 0;
8878 else if (smooth == 1) step = 1;
8879 else if (smooth == 2) step = 2;
8880 else if (smooth == 3) step = 4;
8881 else if (smooth == 9) step = 2;
8882 else step = 8;
8883
8884 /*
8885 * Paranoia -- step must be less than or equal to a half of
8886 * width or height, whichever shorter
8887 */
8888 if ((cur_hgt < 16) && (step > 4)) step = 4;
8889 if ((cur_wid < 16) && (step > 4)) step = 4;
8890
8891
8892 /* Special case -- simple fill */
8893 if (step == 0)
8894 {
8895 byte filler;
8896
8897 /* Pick a filler XXX XXX XXX */
8898 if (use_floor) filler = d_info[dun_type].floor[0];
8899 else filler = d_info[dun_type].fill_type[0];
8900
8901 /* Fill the level with the filler without calling RNG */
8902 for (y = 1; y < cur_hgt - 1; y++)
8903 {
8904 for (x = 1; x < cur_wid - 1; x++)
8905 {
8906 cave_set_feat(wpos, y, x, filler);
8907 }
8908 }
8909
8910 /* Done */
8911 return;
8912 }
8913
8914
8915 /*
8916 * Fill starting positions -- every 'step' grids horizontally and
8917 * vertically
8918 */
8919 for (y = 0; y < cur_hgt; y += ((step == 9) ? 2 : step)) {
8920 for (x = 0; x < cur_wid; x += ((step == 9) ? 2 : step)) {
8921 /*
8922 * Place randomly selected terrain feature using the prebuilt
8923 * probability table
8924 *
8925 * By slightly modifying this, you can build streamers as
8926 * well as normal fillers all at once, but this calls for
8927 * modifications to the other part of the dungeon generator.
8928 */
8929 if (use_floor) place_floor(wpos, y, x);
8930 else if (smooth != 9) place_filler(wpos, y, x);
8931 else if (magik(15)) place_filler(wpos, y, x);
8932 else place_floor(wpos, y, x);
8933 }
8934 }
8935
8936
8937 /*
8938 * Fill spaces between, randomly picking one of their neighbours
8939 *
8940 * This simple yet powerful algorithm was described by Mike Anderson:
8941 *
8942 * A B A | B A a B
8943 * -> --+-- -> d e b
8944 * D C D | C D c C
8945 *
8946 * a can be either A or B, b B or C, c C or D and d D or A.
8947 * e is chosen from A, B, C and D.
8948 * Subdivide and repeat the process as many times as you like.
8949 *
8950 * All the nasty tricks that obscure this simplicity are mine (^ ^;)
8951 */
8952
8953 /* Initialise bit shift counter */
8954 shift = MAX_SHIFTS;
8955
8956 /* Repeat subdivision until all the grids are filled in */
8957 while ((step = step >> 1) > 0)
8958 {
8959 bool y_even, x_even;
8960 s16b y_wrap, x_wrap;
8961 s16b y_sel, x_sel;
8962 u32b selector = 0;
8963
8964 /* Hacklette -- Calculate wrap-around locations */
8965 y_wrap = ((cur_hgt - 1) / (step * 2)) * (step * 2);
8966 x_wrap = ((cur_wid - 1) / (step * 2)) * (step * 2);
8967
8968 /* Initialise vertical phase */
8969 y_even = 0;
8970
8971 for (y = 0; y < cur_hgt; y += step)
8972 {
8973 /* Flip vertical phase */
8974 y_even = !y_even;
8975
8976 /* Initialise horizontal phase */
8977 x_even = 0;
8978
8979 for (x = 0; x < cur_wid; x += step)
8980 {
8981 /* Flip horizontal phase */
8982 x_even = !x_even;
8983
8984 /* Already filled in by previous iterations */
8985 if (y_even && x_even) continue;
8986
8987 /*
8988 * Retrieve next two bits from pseudo-random bit sequence
8989 *
8990 * You can do well not caring so much about their randomness.
8991 *
8992 * This is not really necessary, but I don't like to invoke
8993 * relatively expensive RNG when we can do with much smaller
8994 * number of calls.
8995 */
8996 if (shift >= MAX_SHIFTS)
8997 {
8998 selector = rand_int(0x10000000L);
8999 shift = 0;
9000 }
9001 else
9002 {
9003 selector >>= 2;
9004 shift++;
9005 }
9006
9007 /* Vertically in sync */
9008 if (y_even) y_sel = y;
9009
9010 /* Bit 1 selects neighbouring y */
9011 else y_sel = (selector & 2) ? y + step : y - step;
9012
9013 /* Horizontally in sync */
9014 if (x_even) x_sel = x;
9015
9016 /* Bit 0 selects neighbouring x */
9017 else x_sel = (selector & 1) ? x + step : x - step;
9018
9019 /* Hacklette -- Fix out of range indices by wrapping around */
9020 if (y_sel >= cur_hgt) y_sel = 0;
9021 else if (y_sel < 0) y_sel = y_wrap;
9022 if (x_sel >= cur_wid) x_sel = 0;
9023 else if (x_sel < 0) x_sel = x_wrap;
9024
9025 /*
9026 * Fill the grid with terrain feature of the randomly
9027 * picked up neighbour
9028 */
9029 cave_set_feat(wpos, y, x, zcave[y_sel][x_sel].feat);
9030 }
9031 }
9032 }
9033 }
9034
9035
9036 /* check if there's an allocated floor within 1000ft interval that has a dungeon town.
9037 Interval center points are same as peak chance points for random town generation,
9038 ie 1k, 2k, 3k.. - C. Blue */
9039 static bool no_nearby_dungeontown(struct worldpos *wpos) {
9040 int i, max;
9041 struct worldpos tpos;
9042 struct dungeon_type *d_ptr = getdungeon(wpos);
9043
9044 tpos.wx = wpos->wx;
9045 tpos.wy = wpos->wy;
9046 max = 19; /* check +0..+19 ie 20 floors */
9047
9048 /* tower */
9049 if (wpos->wz > 0) {
9050 tpos.wz = ((wpos->wz + 9) / 20) * 20 - 9;
9051 /* forbid too shallow towns anyway (paranoia if called without checking first) */
9052 if (tpos.wz <= 0) return TRUE;
9053 /* stay in bounds */
9054 if (d_ptr->maxdepth < tpos.wz + max) max = d_ptr->maxdepth - tpos.wz;
9055
9056 for (i = 0; i <= max; i++) {
9057 if (isdungeontown(&tpos)) return FALSE;
9058 tpos.wz++;
9059 }
9060 }
9061 /* dungeon */
9062 else {
9063 tpos.wz = ((wpos->wz - 9) / 20) * 20 + 9;
9064 /* forbid too shallow towns anyway (paranoia if called without checking first) */
9065 if (tpos.wz >= 0) return TRUE;
9066 /* stay in bounds */
9067 if (d_ptr->maxdepth < -tpos.wz + max) max = d_ptr->maxdepth + tpos.wz;
9068
9069 for (i = 0; i <= max; i++) {
9070 if (isdungeontown(&tpos)) return FALSE;
9071 tpos.wz--;
9072 }
9073 }
9074 return TRUE;
9075 }
9076
9077 /*
9078 * Generate a new dungeon level
9079 *
9080 * Note that "dun_body" adds about 4000 bytes of memory to the stack.
9081 */
9082 /*
9083 * Hrm, I know you wish to rebalance it -- but please implement
9084 * d_info stuffs first.. it's coded as such :) - Jir -
9085 */
9086 /* bad hack - Modify monster rarities for a particular IDDC theme live,
9087 and also in actual dungeons if desired (sandworm lair needs moar sandworms?) - C. Blue
9088 TODO: Move this into a specific d_info flag that boosts a monster's rarity! */
9089 #define HACK_MONSTER_RARITIES
9090 static void cave_gen(struct worldpos *wpos, player_type *p_ptr) {
9091 int i, k, y, x, y1 = 0, x1 = 0, dun_lev;
9092 #ifdef ARCADE_SERVER
9093 int mx, my;
9094 #endif
9095 bool netherrealm_level = FALSE, nr_bottom = FALSE;
9096 int build_special_store = 0; /* 0 = don't build a dungeon store,
9097 1 = build deep dungeon store,
9098 2 = build low-level dungeon store,
9099 3 = build ironman supply store
9100 4 = build specific ironman supply store: hidden library
9101 5 = build specific ironman supply store: deep supply
9102 - C. Blue */
9103
9104 bool destroyed = FALSE;
9105 bool empty_level = FALSE, dark_empty = TRUE;
9106 bool cavern = FALSE;
9107 bool maze = FALSE, permaze = FALSE, bonus = FALSE;
9108
9109 monster_type *m_ptr;
9110 bool morgoth_inside = FALSE;
9111
9112 cave_type *cr_ptr, *csbm_ptr, *c_ptr;
9113 struct c_special *cs_ptr;
9114
9115 dun_data dun_body;
9116
9117 /* Wipe the dun_data structure - mikaelh */
9118 WIPE(&dun_body, dun_data);
9119
9120 cave_type **zcave;
9121 dungeon_type *d_ptr = getdungeon(wpos);
9122 int feat_boundary;
9123
9124 /* Don't build one of these on 1x1 (super small) levels,
9125 to avoid insta(ghost)kill if a player recalls into that pit - C. Blue */
9126 bool tiny_level = FALSE;
9127 bool town = FALSE, random_town_allowed; /* for ironman */
9128 #ifdef IRONDEEPDIVE_STATIC_TOWNS
9129 bool town_static = FALSE;
9130 #endif
9131 bool fountains_of_blood = FALSE; /* for vampires */
9132
9133 #ifdef HACK_MONSTER_RARITIES
9134 int hack_monster_idx = 0;//, hack_dun_idx; /* for Sandworm Lair/theme, sigh */
9135 int hack_monster_rarity = 0; //silly compiler warnings
9136 int hack_dun_table_idx = -1;
9137 int hack_dun_table_prob1 = 0, hack_dun_table_prob2 = 0, hack_dun_table_prob3 = 0; //silly compiler warnings
9138 #endif
9139
9140 bool streamers = FALSE, wall_streamers = FALSE;
9141
9142 u32b df1_small = DF1_SMALL, df1_smallest = DF1_SMALLEST;
9143 int dtype = 0;
9144 u32b dflags1 = 0x0, dflags2 = 0x0, dflags3 = 0x0;
9145
9146 #ifdef IRONDEEPDIVE_EXPAND_SMALL
9147 if (in_irondeepdive(wpos)) {
9148 /* expand small to normal and smallest to small */
9149 df1_small = DF1_SMALLEST;
9150 df1_smallest = 0x0;
9151 }
9152 #endif
9153
9154 #ifdef IRONDEEPDIVE_MIXED_TYPES
9155 if (in_irondeepdive(wpos)) {
9156 dtype = iddc[ABS(wpos->wz)].type;
9157 dflags1 = d_info[dtype].flags1;
9158 dflags2 = d_info[dtype].flags2;
9159 dflags3 = d_info[dtype].flags3;
9160 } else
9161 #endif
9162 if (d_ptr) {
9163 if (d_ptr->theme) {
9164 /* custom 'wilderness' (type-0) dungeon, admin-added */
9165 dtype = d_ptr->theme;
9166 /* start with original flags of this type-0 dungeon */
9167 dflags1 = d_ptr->flags1;
9168 dflags2 = d_ptr->flags2;
9169 dflags3 = d_ptr->flags3;
9170 /* add 'theme' flags that don't mess up our main flags too much */
9171 dflags1 |= (d_info[dtype].flags1 & DF1_THEME_MASK);
9172 dflags2 |= (d_info[dtype].flags2 & DF2_THEME_MASK);
9173 dflags3 |= (d_info[dtype].flags3 & DF3_THEME_MASK);
9174 } else {
9175 /* normal dungeon from d_info.txt */
9176 dtype = d_ptr->type;
9177 dflags1 = d_ptr->flags1;
9178 dflags2 = d_ptr->flags2;
9179 dflags3 = d_ptr->flags3;
9180 }
9181 }
9182
9183 dun_lev = getlevel(wpos);
9184 /* Global data */
9185 dun = &dun_body;
9186 dun->l_ptr = getfloor(wpos);
9187 //dun->l_ptr->flags1 = 0;
9188 dun->l_ptr->flags2 = 0;
9189 dun->l_ptr->monsters_generated = dun->l_ptr->monsters_spawned = dun->l_ptr->monsters_killed = 0;
9190
9191 /* Random seed for checking if a player logs back in on the same
9192 [static] floor that he logged out, or if it has changed. - C. Blue */
9193 dun->l_ptr->id = rand_int(0xFFFF) << 16;
9194 dun->l_ptr->id += rand_int(0xFFFF);
9195
9196 /* test if we want fountains of blood in this dungeon - C. Blue */
9197 #if 0//needs dungeon_info_type and all
9198 /* Process all dungeon-specific monster generation rules */
9199 for (i = 0; i < 5; i++) {
9200 rule_type *rule = &d_ptr->rules[i];
9201 if (!rule->percent) break;
9202 if (rule->percent >= 70 && rule->mode != 4 && (rule->mflags3 & RF3_UNDEAD))
9203 fountains_of_blood = TRUE;
9204 }
9205 #else
9206 /* yay for hard-coding "The Paths of the Dead".. ;-|
9207 (it's the only affected dungeon anyway) */
9208 if (dtype == DI_PATHS_DEAD) fountains_of_blood = TRUE;
9209 #endif
9210
9211 if (!(zcave = getcave(wpos))) return;
9212
9213 /* added this for quest dungeons */
9214 if (d_ptr->quest) {
9215 qi_stage *q_qstage = &q_info[d_ptr->quest].stage[d_ptr->quest_stage];
9216
9217 /* all floors are static? */
9218 if (q_qstage->dun_static)
9219 new_players_on_depth(wpos, FALSE, 1);
9220
9221 /* final floor is premade? */
9222 if (ABS(wpos->wz) == d_ptr->maxdepth && q_qstage->dun_final_tpref) {
9223 int xs = q_qstage->dun_final_tpref_x, ys = q_qstage->dun_final_tpref_y;
9224 process_dungeon_file(q_qstage->dun_final_tpref, wpos, &ys, &xs, MAX_HGT, MAX_WID, TRUE);
9225 return;
9226 }
9227 }
9228
9229
9230 /* in case of paranoia, note that ALL normal dungeons (in d_info, and
9231 currently all admin-created type-0 'wilderness' dungeons too) are
9232 DF2_RANDOM ;) -- there is no exception */
9233 if (!d_ptr->flags2 & DF2_RANDOM) return;
9234
9235
9236 /* Hack -- Don't tell players about it (for efficiency) */
9237 level_generation_time = TRUE;
9238
9239 /* Fill the arrays of floors and walls in the good proportions */
9240 init_feat_info(wpos);
9241
9242 /* Are we in Nether Realm? Needed for shop creation later on */
9243 if (in_netherrealm(wpos)) netherrealm_level = TRUE;
9244
9245 /* Note that Ultra-small levels (1/2 x 1/2 panel) actually result
9246 from the rand_int in 'Small level', not from 'Very small'! - C. Blue */
9247
9248 /* Very small (1 x 1 panel) level */
9249 if (
9250 #ifdef IRONDEEPDIVE_MIXED_TYPES
9251 in_irondeepdive(wpos) ? (!(dflags1 & DF1_BIG) && (dflags1 & df1_smallest)) :
9252 #endif
9253 (!(dflags1 & DF1_BIG) && (dflags1 & DF1_SMALLEST))) {
9254 dun->l_ptr->hgt = SCREEN_HGT;
9255 dun->l_ptr->wid = SCREEN_WID;
9256 }
9257 /* Small level */
9258 else if (
9259 #ifdef IRONDEEPDIVE_MIXED_TYPES
9260 #ifdef IRONDEEPDIVE_BIG_IF_POSSIBLE
9261 in_irondeepdive(wpos) ? (!(dflags1 & DF1_BIG) && (dflags1 & df1_small)) : /* rarely small */
9262 #else
9263 in_irondeepdive(wpos) ? (!(dflags1 & DF1_BIG) && ((dflags1 & df1_small) || (!rand_int(SMALL_LEVEL * 2)))) : /* rarely small */
9264 #endif
9265 #endif
9266 (!(dflags1 & DF1_BIG) && ((dflags1 & DF1_SMALL) || (!rand_int(SMALL_LEVEL))))) {
9267 #if 0 /* No more ultra-small levels for now (1/2 x 1/2 panel), and no max size here either :) - C. Blue*/
9268 dun->l_ptr->wid = MAX_WID - rand_int(MAX_WID / SCREEN_WID * 2) * (SCREEN_WID / 2);
9269 dun->l_ptr->hgt = MAX_HGT - rand_int(MAX_HGT / SCREEN_HGT * 2 - 1) * (SCREEN_HGT / 2);*/
9270 #else
9271 dun->l_ptr->wid = MAX_WID - randint(MAX_WID / SCREEN_WID * 2 - 2) * (SCREEN_WID / 2);
9272 dun->l_ptr->hgt = MAX_HGT - randint(MAX_HGT / SCREEN_HGT * 2 - 2) * (SCREEN_HGT / 2);
9273 #endif
9274 }
9275 /* Normal level */
9276 else {
9277 dun->l_ptr->wid = MAX_WID;
9278 dun->l_ptr->hgt = MAX_HGT;
9279 }
9280
9281 #ifdef ARCADE_SERVER
9282 dun->l_ptr->hgt = SCREEN_HGT*2;
9283 dun->l_ptr->wid = SCREEN_WID*2;
9284 if(tron_dark && wpos->wz == 11)
9285 dun->l_ptr->flags1 |= DF1_FORGET;
9286 if(tron_forget && wpos->wz == 11)
9287 dun->l_ptr->flags1 |= LF1_NO_MAP;
9288 #else
9289
9290 dun->l_ptr->flags1 = 0;
9291 if (dun_lev < 100 && magik(NO_MAGIC_CHANCE)) dun->l_ptr->flags1 |= LF1_NO_MAGIC;
9292 if (magik(NO_GENO_CHANCE)) dun->l_ptr->flags1 |= LF1_NO_GENO;
9293 if (magik(NO_MAP_CHANCE) && dun_lev >= 5) dun->l_ptr->flags1 |= LF1_NO_MAP;
9294 if (magik(NO_MAGIC_MAP_CHANCE)) dun->l_ptr->flags1 |= LF1_NO_MAGIC_MAP;
9295 if (magik(NO_DESTROY_CHANCE)) dun->l_ptr->flags1 |= LF1_NO_DESTROY;
9296 #endif
9297
9298 //#ifdef NETHERREALM_BOTTOM_RESTRICT
9299 /* no probability travel out of Zu-Aon's floor */
9300 if (netherrealm_bottom(wpos)) {
9301 /* removing other bad flags though, to make it fair */
9302 dun->l_ptr->flags1 = LF1_NO_MAGIC;
9303 }
9304 //#endif
9305
9306 /* copy dun flags to dunlev */
9307 if ((dflags1 & DF1_FORGET)) {
9308 dun->l_ptr->flags1 |= LF1_NO_MAP;
9309 s_printf("FORGET\n");
9310 }
9311 if ((dflags2 & DF2_NO_MAGIC_MAP)) dun->l_ptr->flags1 |= LF1_NO_MAGIC_MAP;
9312 if ((dflags1 & DF1_NO_DESTROY)) dun->l_ptr->flags1 |= LF1_NO_DESTROY;
9313
9314 /* experimental stuff */
9315 if ((dflags3 & DF3_NO_TELE)) dun->l_ptr->flags2 |= LF2_NO_TELE;
9316 if ((dflags3 & DF3_NO_ESP)) dun->l_ptr->flags2 |= LF2_NO_ESP;
9317 if ((dflags3 & DF3_LIMIT_ESP)) dun->l_ptr->flags2 |= LF2_LIMIT_ESP;
9318 if ((dflags3 & DF3_NO_SUMMON)) dun->l_ptr->flags2 |= LF2_NO_SUMMON;
9319
9320 /* Hack -- NO_MAP often comes with NO_MAGIC_MAP */
9321 if ((dun->l_ptr->flags1 & LF1_NO_MAP) && magik(55))
9322 dun->l_ptr->flags1 |= LF1_NO_MAGIC_MAP;
9323
9324 /* PvP arena isn't special except that *destruction* doesn't work */
9325 if (wpos->wx == WPOS_PVPARENA_X && wpos->wy == WPOS_PVPARENA_Y && wpos->wz == WPOS_PVPARENA_Z)
9326 dun->l_ptr->flags1 = LF1_NO_DESTROY;
9327
9328 /* IRONMAN allows recalling at bottom/top */
9329 if (d_ptr && (d_ptr->flags2 & DF2_IRON)
9330 && !(d_ptr->flags2 & DF2_NO_EXIT_WOR)) {
9331 if ((wpos->wz < 0 && wild_info[wpos->wy][wpos->wx].dungeon->maxdepth == -wpos->wz) ||
9332 (wpos->wz > 0 && wild_info[wpos->wy][wpos->wx].tower->maxdepth == wpos->wz))
9333 dun->l_ptr->flags1 |= LF1_IRON_RECALL;
9334 /* IRONMAN allows recalling sometimes, if IRONFIX or IRONRND */
9335 else if (d_ptr && (dun_lev >= 20) && ( /* was 30 */
9336 (!p_ptr->dummy_option_8 &&
9337 (((d_ptr->flags2 & DF2_IRONRND1) && magik(20)) ||
9338 ((d_ptr->flags2 & DF2_IRONRND2) && magik(12)) ||
9339 ((d_ptr->flags2 & DF2_IRONRND3) && magik(8)) ||
9340 ((d_ptr->flags2 & DF2_IRONRND4) && magik(5))))
9341 ||
9342 ((d_ptr->flags2 & DF2_IRONFIX1) && !(wpos->wz % 5)) ||
9343 ((d_ptr->flags2 & DF2_IRONFIX2) && !(wpos->wz % 10))||
9344 ((d_ptr->flags2 & DF2_IRONFIX3) && !(wpos->wz % 15)) ||
9345 ((d_ptr->flags2 & DF2_IRONFIX4) && !(wpos->wz % 20)))) {
9346 dun->l_ptr->flags1 |= LF1_IRON_RECALL;
9347 /* Generate ironman town too? */
9348 if (d_ptr->flags2 & DF2_TOWNS_IRONRECALL) town = TRUE;
9349 }
9350 }
9351
9352
9353 /* Dungeon towns */
9354 random_town_allowed = TRUE;
9355
9356 #ifdef IRONDEEPDIVE_FIXED_TOWNS
9357 if (is_fixed_irondeepdive_town(wpos, dun_lev)) {
9358 p_ptr->IDDC_found_rndtown = FALSE;
9359 town = TRUE;
9360 #ifdef IRONDEEPDIVE_STATIC_TOWNS
9361 town_static = TRUE;
9362 #endif
9363 #ifdef IRONDEEPDIVE_FIXED_TOWN_WITHDRAWAL
9364 dun->l_ptr->flags1 |= LF1_IRON_RECALL;
9365 #endif
9366 }
9367 #ifdef IRONDEEPDIVE_EXTRA_FIXED_TOWNS
9368 else if (is_extra_fixed_irondeepdive_town(wpos, dun_lev)) {
9369 town = TRUE;
9370 //not static!
9371 //no withdrawal allowed!
9372 }
9373 /* prevent further random towns being generated in IDDC
9374 if extra fixed towns are enabled */
9375 random_town_allowed = FALSE;
9376 #endif
9377 #endif
9378 /* Generate town? */
9379 #if 0 /* towns become rarer the deeper we go? */
9380 if (dun_lev > 2 && (town ||
9381 ((d_ptr->flags2 & DF2_TOWNS_FIX) && !(dun_lev %
9382 (dun_lev <= 30 ? 10 : (dun_lev <= 60 ? 15 : 20)))) ||
9383 ((d_ptr->flags2 & DF2_TOWNS_RND) && magik(
9384 (dun_lev <= 30 ? 10 : (dun_lev <= 60 ? 7 : 5)))) )) {
9385 #else /* towns have high probability around n*1000ft floors, otherwise rare (for IRONDEEPDIVE) \
9386 Also: No towns at Morgy depth or beyond. */
9387 k = 0;
9388 if (dun_lev > 2 && (town ||
9389 (random_town_allowed &&
9390 (dun_lev < 100 && (!p_ptr->IDDC_found_rndtown || !in_irondeepdive(wpos)) && (
9391 ((d_ptr->flags2 & DF2_TOWNS_FIX) && !(dun_lev % 20)) ||
9392 (!p_ptr->dummy_option_8 && (d_ptr->flags2 & DF2_TOWNS_RND) &&
9393 #if 0 /* for generic dungeons maybe */
9394 magik(30 / (ABS(((dun_lev + 10) % 20) - 10) + 1))
9395 #else /* irondeepdive specifically: no towns before 900 ft or around the static towns at 2k and 4k */
9396 magik(k = 25 / ( /* 35 -> 82.6% chance per -450..+500ft interval; 30 -> 78.8%; 25 -> 70.5%; 20 -> 62.3%; 15 -> 40.5%, 10 -> 35.4%, 5 -> 14.2% */
9397 /* 900..1500ft: 35 -> %; 30 ->70.8%; 25 -> 62.7%; 20 -> %; 15 -> %, 10 -> %, 5 -> % */
9398 (dun_lev >= 18 && (dun_lev <= 40 - 10 || dun_lev > 40 + 10) && (dun_lev <= 80 - 10 || dun_lev > 80 + 10)) ?
9399 ABS(((dun_lev + 10) % 20) - 10) + 1 : 999
9400 ))
9401 #endif
9402 /* and new: no 2 towns within the same 1000ft interval (anti-cheeze, as if..) */
9403 && no_nearby_dungeontown(wpos)
9404 )))))) {
9405 if (k) {
9406 if (in_irondeepdive(wpos)) p_ptr->IDDC_found_rndtown = TRUE;
9407 s_printf("Generated random dungeon town at %d%% chance for player %s.\n", k, p_ptr->name);
9408 dun->l_ptr->flags1 |= LF1_RANDOM_TOWN;
9409 }
9410 #endif
9411 bool lit = rand_int(3) == 0;
9412 /* prepare level: max size and permanent walls */
9413 dun->l_ptr->wid = MAX_WID;
9414 dun->l_ptr->hgt = MAX_HGT;
9415 for (y = 0; y < MAX_HGT; y++) {
9416 for (x = 0; x < MAX_WID; x++) {
9417 c_ptr = &zcave[y][x];
9418 c_ptr->feat = FEAT_PERM_MOUNTAIN;//FEAT_HIGH_MOUNT_SOLID;
9419 if (lit) c_ptr->info |= CAVE_GLOW;
9420 }
9421 }
9422
9423 /* add the town */
9424 s_printf("DF2_TOWNS_: Adding a town at %d,%d,%d.\n", wpos->wx, wpos->wy, wpos->wz);
9425 dun->l_ptr->flags1 |= LF1_DUNGEON_TOWN | LF1_NO_DESTROY;
9426 dun->l_ptr->flags1 &= ~(LF1_NO_MAP | LF1_NO_MAGIC_MAP);
9427 town_gen_hack(wpos);
9428
9429 #ifdef IRONDEEPDIVE_STATIC_TOWNS
9430 if (town_static) {
9431 /* reattach objects and monsters */
9432 setup_objects();
9433 /* target dummies */
9434 setup_monsters();
9435 }
9436 #endif
9437
9438 level_generation_time = FALSE;
9439 return;
9440 }
9441
9442
9443 /* not too big levels for 'Arena Monster Challenge' event */
9444 if (ge_special_sector &&
9445 wpos->wx == WPOS_ARENA_X && wpos->wy == WPOS_ARENA_Y && wpos->wz == WPOS_ARENA_Z) {
9446 dun->l_ptr->wid = MAX_WID / 2;
9447 dun->l_ptr->hgt = MAX_HGT / 2;
9448 dun->l_ptr->flags1 &= ~(LF1_NO_MAGIC | LF1_NO_GENO | LF1_NO_MAP | LF1_NO_MAGIC_MAP);
9449 dun->l_ptr->flags1 |= LF1_NO_DESTROY;
9450 }
9451
9452 /* remember if it's a tiny level and avoid building certain room types consequently */
9453 #if 0
9454 if (dun->l_ptr->wid <= SCREEN_WID && dun->l_ptr->hgt <= (SCREEN_HGT * 3) / 2 ||
9455 dun->l_ptr->wid <= (SCREEN_WID * 3) / 2 && dun->l_ptr->hgt <= SCREEN_HGT) tiny_level = TRUE;
9456 #else
9457 if (dun->l_ptr->wid * dun->l_ptr->hgt <= (SCREEN_WID * SCREEN_HGT * 3) / 2) tiny_level = TRUE;
9458 #endif
9459
9460 /* So as not to generate too 'crowded' levels */
9461 dun->ratio = 100 * dun->l_ptr->wid * dun->l_ptr->hgt / MAX_HGT / MAX_WID;
9462
9463 /* Possible cavern */
9464 if (rand_int(dun_lev) > DUN_CAVERN && magik(DUN_CAVERN2)) {
9465 cavern = TRUE;
9466
9467 #if 0
9468 /* Make a large fractal cave in the middle of the dungeon */
9469 if (cheat_room) {
9470 msg_print("Cavern on level.");
9471 }
9472 #endif /* 0 */
9473 }
9474
9475
9476 /* Possible "destroyed" level */
9477 if ((dun_lev > 10) && (rand_int(DUN_DEST) == 0)) destroyed = TRUE;
9478
9479 /* Hack -- No destroyed "quest" levels */
9480 if (is_xorder(wpos) || (dun->l_ptr->flags1 & LF1_NO_DESTROY))
9481 destroyed = FALSE;
9482
9483 /* Hack -- Watery caves */
9484 dun->watery = !(dflags3 & DF3_NOT_WATERY) && dun_lev > 5 &&
9485 ((((dun_lev + WATERY_OFFSET) % WATERY_CYCLE) >= (WATERY_CYCLE - WATERY_RANGE))?
9486 magik(WATERY_BELT_CHANCE) : magik(DUN_RIVER_CHANCE - dun_lev * DUN_RIVER_REDUCE / 100));
9487
9488 maze = (!cavern && rand_int(DUN_MAZE_FACTOR) < dun_lev - 10) ? TRUE : FALSE;
9489 if (dflags1 & DF1_MAZE) maze = TRUE;
9490
9491 if (maze) permaze = magik(DUN_MAZE_PERMAWALL);
9492
9493 if (!maze && !cavern &&
9494 ((dflags1 & (DF1_EMPTY)) || (!rand_int(EMPTY_LEVEL) && !(dflags3 & DF3_NOT_EMPTY)))) {
9495 empty_level = TRUE;
9496 if ((randint(DARK_EMPTY) != 1 || (randint(100) > dun_lev)))
9497 dark_empty = FALSE;
9498 }
9499
9500 if (dflags3 & DF3_NO_EMPTY) empty_level = FALSE;
9501 if (dflags3 & DF3_NO_DESTROYED) destroyed = FALSE;
9502 if (dflags3 & DF3_NO_MAZE) maze = permaze = FALSE;
9503
9504 /* Hack for bottom of Nether Realm */
9505 if (netherrealm_level && dun_lev == netherrealm_end) {
9506 destroyed = FALSE;
9507 empty_level = TRUE; dark_empty = TRUE;
9508 cavern = FALSE;
9509 maze = FALSE; permaze = FALSE; bonus = FALSE;
9510 nr_bottom = TRUE;
9511 }
9512
9513 /* All dungeons get their own visuals now, if defined in B-line in d_info - C. Blue */
9514 feat_boundary = d_info[dtype].feat_boundary;
9515
9516 /* Hack -- Start with permawalls
9517 * Hope run-length do a good job :) */
9518 for (y = 0; y < MAX_HGT; y++) {
9519 for (x = 0; x < MAX_WID; x++) {
9520 c_ptr = &zcave[y][x];
9521
9522 #ifdef BIG_MAP
9523 /* new visuals - also for non-big map mode actually possible */
9524 if (x >= dun->l_ptr->wid || y >= dun->l_ptr->hgt) c_ptr->feat = FEAT_PERM_FILL;
9525 else
9526 #endif
9527 /* Create granite (? granite != permanent) wall */
9528 c_ptr->feat = feat_boundary;
9529
9530 /* Illuminate Arena if needed */
9531 if (empty_level && !dark_empty) c_ptr->info |= CAVE_GLOW;
9532 }
9533 }
9534
9535 #if 0
9536 /* Hack -- then curve with basic granite */
9537 for (y = 1; y < dun->l_ptr->hgt - 1; y++) {
9538 for (x = 1; x < dun->l_ptr->wid - 1; x++) {
9539 c_ptr = &zcave[y][x];
9540
9541 /* Create granite wall */
9542 c_ptr->feat = empty_level ? FEAT_FLOOR :
9543 (permaze ? FEAT_PERM_INNER : FEAT_WALL_EXTRA);
9544 }
9545 }
9546 #else /* 0 */
9547
9548 /*
9549 * Hack -- Start with fill_type's
9550 *
9551 * Need a way to know appropriate smoothing factor for the current
9552 * dungeon. Maybe we need another d_info flag/value.
9553 */
9554 /* Hack -- then curve with basic granite */
9555 if (permaze) {
9556 for (y = 1; y < dun->l_ptr->hgt - 1; y++) {
9557 for (x = 1; x < dun->l_ptr->wid - 1; x++) {
9558 c_ptr = &zcave[y][x];
9559
9560 /* Create permawall */
9561 c_ptr->feat = FEAT_PERM_INNER;
9562 }
9563 }
9564 }
9565 #ifdef IRONDEEPDIVE_MIXED_TYPES
9566 //if (in_irondeepdive(wpos)) fill_level(wpos, empty_level, iddc[ABS(wpos->wz)].step ? rand_int(4) : d_info[iddc[ABS(wpos->wz)].type].fill_method); //Random smooth! (was 1+randint(3))
9567 if (in_irondeepdive(wpos))
9568 fill_level(wpos, empty_level, iddc[ABS(wpos->wz)].step <= 1 ?
9569 d_info[iddc[ABS(wpos->wz)].type].fill_method :
9570 d_info[iddc[ABS(wpos->wz)].next].fill_method);
9571 else
9572 #endif
9573 fill_level(wpos, empty_level, d_info[d_ptr->type].fill_method);
9574 #endif /* 0 */
9575
9576 if (cavern) build_cavern(wpos);
9577
9578
9579 /* Actual maximum number of rooms on this level */
9580 /* dun->row_rooms = MAX_HGT / BLOCK_HGT;
9581 dun->col_rooms = MAX_WID / BLOCK_WID; */
9582
9583 dun->row_rooms = dun->l_ptr->hgt / BLOCK_HGT;
9584 dun->col_rooms = dun->l_ptr->wid / BLOCK_WID;
9585
9586 /* Initialize the room table */
9587 for (y = 0; y < dun->row_rooms; y++)
9588 for (x = 0; x < dun->col_rooms; x++)
9589 dun->room_map[y][x] = FALSE;
9590
9591
9592 /* No "crowded" rooms yet */
9593 dun->crowded = FALSE;
9594
9595 #ifdef HACK_MONSTER_RARITIES
9596 /* bad hack: temporarily make sandworms very common in Sandworm Lair.
9597 I added this especially for themed IDDC, which would otherwise mean
9598 a bunch of pretty empty levels (or just lame worms mostly) - C. Blue */
9599 if (dtype == DI_SANDWORM_LAIR) {
9600 alloc_entry *table = alloc_race_table_dun[DI_SANDWORM_LAIR];
9601
9602 //hack_dun_idx = DI_SANDWORM_LAIR;
9603
9604 hack_monster_idx = 1031;
9605 hack_monster_rarity = r_info[1031].rarity;
9606 r_info[1031].rarity = 1;
9607
9608 i = 0;
9609 do {
9610 if (table[i].index == 1031) {
9611 hack_dun_table_idx = i;
9612 hack_dun_table_prob1 = table[i].prob1;
9613 hack_dun_table_prob2 = table[i].prob2;
9614 hack_dun_table_prob3 = table[i].prob3;
9615 table[i].prob1 = 10000;
9616 table[i].prob2 = 10000;
9617 table[i].prob3 = 10000;
9618 break;
9619 }
9620 i++;
9621 } while (i < max_r_idx); /* paranoia */
9622 }
9623 #endif
9624
9625 /* No rooms yet */
9626 dun->cent_n = 0;
9627
9628 if (!nr_bottom) {
9629 /* Build some rooms */
9630 if (!maze || !(dflags1 & DF1_MAZE)) for (i = 0; i < DUN_ROOMS; i++) {
9631 /* Pick a block for the room */
9632 y = rand_int(dun->row_rooms);
9633 x = rand_int(dun->col_rooms);
9634
9635 /* Align dungeon rooms */
9636 if (dungeon_align) {
9637 /* Slide some rooms right */
9638 if ((x % 3) == 0) x++;
9639
9640 /* Slide some rooms left */
9641 if ((x % 3) == 2) x--;
9642 }
9643
9644 /* Destroyed levels are boring */
9645 if (destroyed) {
9646 /* The deeper you are, the more cavelike the rooms are */
9647
9648 /* no caves when cavern exists: they look bad */
9649 k = randint(100);
9650
9651 if (!cavern && (k < dun_lev) && !tiny_level) {
9652 /* Type 10 -- Fractal cave */
9653 if (room_build(wpos, y, x, 10, p_ptr)) continue;
9654 } else {
9655 /* Attempt a "trivial" room */
9656 #if 0
9657 if ((d_ptr->flags1 & DF1_CIRCULAR_ROOMS) &&
9658 room_build(y, x, 9, p_ptr)))
9659 #endif /* 0 */
9660 if (magik(30) && room_build(wpos, y, x, 9, p_ptr)) continue;
9661 else if (room_build(wpos, y, x, 1, p_ptr)) continue;
9662 }
9663
9664 #if 0
9665 /* Attempt a "trivial" room */
9666 if (room_build(wpos, y, x, 1, p_ptr)) continue;
9667 #endif /* 0 */
9668
9669 /* Never mind */
9670 continue;
9671 }
9672
9673 /* Attempt an "unusual" room */
9674 if (rand_int(DUN_UNUSUAL) < dun_lev) {
9675 /* Roll for room type */
9676 k = rand_int(100);
9677
9678 /* Attempt a very unusual room */
9679
9680 if (rand_int(DUN_UNUSUAL) < dun_lev
9681 #if 1 /* tiny levels don't get any DUN_UNUSUAL room types at all */
9682 && !tiny_level) {
9683 #else /* tiny levels don't get nests, pits or greater vaults */
9684 ) {
9685 if (tiny_level) k = rand_int(65) + 35;
9686 #endif
9687 /* Type 5 -- Monster nest (10%) */
9688 if ((k < 10) && room_build(wpos, y, x, 5, p_ptr)) continue;
9689
9690 /* Type 6 -- Monster pit (15%) */
9691 if ((k < 25) && room_build(wpos, y, x, 6, p_ptr)) continue;
9692
9693 /* Type 8 -- Greater vault (10%) */
9694 if ((k < 35) && room_build(wpos, y, x, 8, p_ptr)) continue;
9695
9696 /* Type 11 -- Random vault (10%) */
9697 if ((k < 45) && room_build(wpos, y, x, 11, p_ptr)) continue;
9698
9699 /* Type 7 -- Lesser vault (15%) */
9700 if ((k < 60) && room_build(wpos, y, x, 7, p_ptr)) continue;
9701 } else {
9702 /* Type 4 -- Large room (25%) */
9703 if ((k < 25) && room_build(wpos, y, x, 4, p_ptr)) continue;
9704
9705 /* Type 3 -- Cross room (20%) */
9706 if ((k < 45) && room_build(wpos, y, x, 3, p_ptr)) continue;
9707
9708 /* Type 2 -- Overlapping (20%) */
9709 if ((k < 65) && room_build(wpos, y, x, 2, p_ptr)) continue;
9710 }
9711
9712 /* Type 10 -- Fractal cave (15%) */
9713 if ((k < 80) && room_build(wpos, y, x, 10, p_ptr)) continue;
9714
9715 /* Type 9 -- Circular (10%) */
9716 /* Hack - build standard rectangular rooms if needed */
9717 if (k < 90) {
9718 if (((dflags1 & DF1_CIRCULAR_ROOMS) || magik(70)) &&
9719 room_build(wpos, y, x, 1, p_ptr))
9720 continue;
9721 else if (room_build(wpos, y, x, 9, p_ptr)) continue;
9722 }
9723
9724 /* Type 12 -- Crypt (10%) */
9725 if ((k < 100) && room_build(wpos, y, x, 12, p_ptr)) continue;
9726 }
9727
9728 /* Attempt a trivial room */
9729 if ((dflags1 & DF1_CAVE) || magik(50)) {
9730 if (room_build(wpos, y, x, 10, p_ptr)) continue;
9731 } else {
9732 if (((dflags1 & DF1_CIRCULAR_ROOMS) || magik(30)) &&
9733 room_build(wpos, y, x, 9, p_ptr))
9734 continue;
9735 else if (room_build(wpos, y, x, 1, p_ptr)) continue;
9736 }
9737 }
9738 }
9739
9740 #if 1
9741 /* XXX the walls here should 'mimic' the surroundings,
9742 * however I omitted it to spare 522 c_special - Jir */
9743 /* Special boundary walls -- Top + bottom */
9744 for (x = 0; x < dun->l_ptr->wid; x++) {
9745 /* Clear previous contents, add "solid" perma-wall */
9746 zcave[0][x].feat = feat_boundary;
9747 zcave[dun->l_ptr->hgt - 1][x].feat = feat_boundary;
9748 }
9749 /* Special boundary walls -- Left + right */
9750 for (y = 0; y < dun->l_ptr->hgt; y++) {
9751 zcave[y][0].feat = feat_boundary;
9752 zcave[y][dun->l_ptr->wid - 1].feat = feat_boundary;
9753 }
9754 #endif /* 0 */
9755
9756 if (!(dflags1 & (DF1_MAZE | DF1_LIFE_LEVEL)) &&
9757 !(dflags1 & DF1_NO_STREAMERS))
9758 streamers = TRUE;
9759 if (!(dflags1 & (DF1_MAZE | DF1_LIFE_LEVEL)) &&
9760 !(dflags3 & DF3_NO_WALL_STREAMERS))
9761 wall_streamers = TRUE;
9762
9763 if (maze) generate_maze(wpos, (dflags1 & DF1_MAZE) ? 1 : randint(3));
9764 else {
9765 if (!nr_bottom) {
9766 /* Hack -- Scramble the room order */
9767 for (i = 0; i < dun->cent_n; i++) {
9768 int pick1 = rand_int(dun->cent_n);
9769 int pick2 = rand_int(dun->cent_n);
9770 y1 = dun->cent[pick1].y;
9771 x1 = dun->cent[pick1].x;
9772 dun->cent[pick1].y = dun->cent[pick2].y;
9773 dun->cent[pick1].x = dun->cent[pick2].x;
9774 dun->cent[pick2].y = y1;
9775 dun->cent[pick2].x = x1;
9776 }
9777
9778 /* Start with no tunnel doors */
9779 dun->door_n = 0;
9780
9781 /* Hack -- connect the first room to the last room */
9782 y = dun->cent[dun->cent_n-1].y;
9783 x = dun->cent[dun->cent_n-1].x;
9784
9785 /* Connect all the rooms together */
9786 for (i = 0; i < dun->cent_n; i++) {
9787 /* Connect the room to the previous room */
9788 build_tunnel(wpos, dun->cent[i].y, dun->cent[i].x, y, x);
9789
9790 /* Remember the "previous" room */
9791 y = dun->cent[i].y;
9792 x = dun->cent[i].x;
9793 }
9794
9795 /* Place intersection doors */
9796 for (i = 0; i < dun->door_n; i++) {
9797 /* Extract junction location */
9798 y = dun->door[i].y;
9799 x = dun->door[i].x;
9800
9801 /* Try placing doors */
9802 #if 0
9803 try_door(wpos, y, x - 1);
9804 try_door(wpos, y, x + 1);
9805 try_door(wpos, y - 1, x);
9806 try_door(wpos, y + 1, x);
9807 #endif /* 0 */
9808 try_doors(wpos, y , x);
9809 }
9810 }
9811
9812 if (wall_streamers) {
9813 /* Hack -- Add some magma streamers */
9814 for (i = 0; i < DUN_STR_MAG; i++)
9815 build_streamer(wpos, FEAT_MAGMA, DUN_STR_MC, FALSE);
9816
9817 /* Hack -- Add some quartz streamers */
9818 for (i = 0; i < DUN_STR_QUA; i++)
9819 build_streamer(wpos, FEAT_QUARTZ, DUN_STR_QC, FALSE);
9820
9821 /* Add some sand streamers */
9822 if (((dflags1 & DF1_SAND_VEIN) && !rand_int(4)) ||
9823 magik(DUN_SANDWALL)) {
9824 build_streamer(wpos, FEAT_SANDWALL, DUN_STR_SC, FALSE);
9825 }
9826 }
9827
9828 /* Hack -- Add some rivers if requested */
9829 if ((dflags1 & DF1_WATER_RIVER) && !rand_int(4))
9830 add_river(wpos, FEAT_DEEP_WATER, FEAT_SHAL_WATER);
9831
9832 if ((dflags1 & DF1_LAVA_RIVER) && !rand_int(4))
9833 add_river(wpos, FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
9834
9835 if ((dflags1 & DF1_WATER_RIVERS) || (dun->watery)) {
9836 int max = 3 + rand_int(2);
9837
9838 for (i = 0; i < max; i++) {
9839 if (rand_int(3) == 0) add_river(wpos, FEAT_DEEP_WATER, FEAT_SHAL_WATER);
9840 }
9841 }
9842 if ((dflags1 & DF1_LAVA_RIVERS)) {
9843 int max = 2 + rand_int(2);
9844
9845 for (i = 0; i < max; i++) {
9846 if (rand_int(3) == 0) add_river(wpos, FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
9847 }
9848 }
9849
9850 #if 0
9851 /* Hack -- Add some water streamers */
9852 if (dun->watery) {
9853 #if 0
9854 get_mon_num_hook = vault_aux_aquatic;
9855
9856 /* Prepare allocation table */
9857 get_mon_num_prep();
9858 #endif /* 0 */
9859
9860 for (i = 0; i < DUN_STR_WAT; i++)
9861 build_streamer(wpos, FEAT_DEEP_WATER, 0, TRUE);
9862
9863 lake_level(wpos);
9864
9865 #if 0
9866 /* Remove restriction */
9867 get_mon_num_hook = dungeon_aux;
9868
9869 /* Prepare allocation table */
9870 get_mon_num_prep();
9871 #endif /* 0 */
9872 }
9873 #endif /* 0 */
9874
9875 #ifdef VOLCANIC_FLOOR /* experimental - this might be too costly on cpu: add volcanic floor around lava rivers - C. Blue */
9876 for (x = 0; x < dun->l_ptr->wid; x++)
9877 for (y = 0; y < dun->l_ptr->hgt; y++) {
9878 if (zcave[y][x].feat != FEAT_SHAL_LAVA && zcave[y][x].feat != FEAT_DEEP_LAVA) continue;
9879 for (i = 0; i < 4; i++) {
9880 k = zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat;
9881 switch (k) {
9882 case FEAT_WEB:
9883 case FEAT_CROP:
9884 case FEAT_FLOWER:
9885 case FEAT_IVY:
9886 case FEAT_GRASS:
9887 /* never persist */
9888 zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat = FEAT_ASH;
9889 continue;
9890 case FEAT_SNOW:
9891 case FEAT_SHAL_WATER:
9892 case FEAT_DARK_PIT:
9893 case FEAT_ICE:
9894 case FEAT_MUD:
9895 case FEAT_ICE_WALL:
9896 /* never persist */
9897 zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat = FEAT_VOLCANIC;
9898 continue;
9899 case FEAT_TREE:
9900 case FEAT_BUSH://mh
9901 /* never persist */
9902 zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat = FEAT_DEAD_TREE;
9903 continue;
9904 case FEAT_SAND:
9905 case FEAT_FLOOR:
9906 case FEAT_LOOSE_DIRT:
9907 case FEAT_DIRT:
9908 /* rarely persist */
9909 if (!rand_int(7)) continue;
9910 zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat = FEAT_VOLCANIC;
9911 default:
9912 continue;
9913 }
9914 }
9915 }
9916 #endif
9917
9918 /* Destroy the level if necessary */
9919 if (destroyed) destroy_level(wpos);
9920 }
9921
9922 if (!(dun->l_ptr->flags1 & LF1_NO_STAIR)) {
9923 /* place downstairs and upstairs -
9924 currently, more downstairs are generated in general than upstairs,
9925 so venturing into dungeons is actually easier than climbing up towers! */
9926 if (!in_netherrealm(wpos)) {
9927 /* Place 3 or 4 down stairs near some walls */
9928 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(3, 4) * dun->ratio / 100 + 1, 3, NULL);
9929 /* Place 2 or 3 up stairs near some walls */
9930 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, rand_range(2, 3), 3, NULL);
9931
9932 #if 0 /* we need a way to create the way back */
9933 /* Place 1 or 2 (typo of '0 or 1'?) down shafts near some walls */
9934 if (!(d_ptr->flags2 & DF2_NO_SHAFT)) alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN, rand_range(0, 1), 3, NULL);
9935
9936 /* Place 0 or 1 up shafts near some walls */
9937 if (!(d_ptr->flags2 & DF2_NO_SHAFT)) alloc_stairs((d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP, rand_range(0, 1), 3, NULL);
9938 #endif /* 0 */
9939
9940 /* Hack -- add *more* stairs for lowbie's sake */
9941 if (dun_lev <= COMFORT_PASSAGE_DEPTH) {
9942 /* Place 2 or 3 down stairs near some walls */
9943 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(2, 3), 3, NULL);
9944
9945 /* Place 2 or 3 up stairs near some walls */
9946 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, rand_range(2, 3), 3, NULL);
9947 }
9948
9949 /* Hack -- add *more* downstairs for Highlander Tournament event */
9950 if (sector00separation && wpos->wx == WPOS_HIGHLANDER_X && wpos->wy == WPOS_HIGHLANDER_Y &&
9951 wpos->wz * WPOS_HIGHLANDER_Z > 0 && dun_lev > COMFORT_PASSAGE_DEPTH) {
9952 /* Place 3 or 4 down stairs near some walls */
9953 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(2, 4), 2, NULL);
9954 }
9955
9956 /* in the Nether Realm, stairs leading onwards must not be generated close to stairs backwards,
9957 or rogues could cloak-scum for them to be next to each other (albeit ridiculously tedious probably, *probably*..) */
9958 } else if (!netherrealm_bottom(wpos)) {
9959 struct stairs_list stairs[5];
9960 for (i = 0; i != 5 - 1; i++) stairs[i].x = -1; /* init usable elements */
9961 stairs[i].y = -1; /* mark final 'terminator' element */
9962
9963 if (netherrealm_wpos_z < 1) {
9964 /* Place 2 down stairs near some walls */
9965 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, 2, 2, stairs);
9966 /* Place 1 up stairs near some walls */
9967 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, 1, 2, stairs);
9968 } else {
9969 /* Place 2 up stairs near some walls */
9970 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, 2, 2, stairs);
9971 /* Place 1 down stairs near some walls */
9972 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, 1, 2, stairs);
9973 }
9974
9975 } else {
9976 /* place 1 staircase */
9977 if (netherrealm_wpos_z < 1)
9978 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, 1, 2, NULL);
9979 else
9980 alloc_stairs(wpos, (d_ptr->flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, 1, 2, NULL);
9981 }
9982
9983 }
9984
9985 #if 0
9986 process_hooks(HOOK_GEN_LEVEL, "(d)", is_xorder(dun_lev));
9987 #endif
9988
9989 /* Determine the character location */
9990 new_player_spot(wpos);
9991
9992
9993 /* Add streamers of trees, water, or lava -KMW- */
9994 if (streamers) {
9995 int num;
9996
9997 /*
9998 * Flat levels (was: levels 1--2)
9999 *
10000 * Small trees (penetrate walls)
10001 */
10002 if ((dflags1 & DF1_FLAT) && (randint(20) > 15)) {
10003 num = randint(DUN_STR_QUA);
10004
10005 for (i = 0; i < num; i++)
10006 build_streamer2(wpos, FEAT_IVY, 1);
10007 }
10008
10009 /*
10010 * Levels 1 -- 33 (was: 1 -- 19)
10011 *
10012 * Shallow water (preserve walls)
10013 * Deep water (penetrate walls)
10014 */
10015 if ((dun_lev <= 33) && (randint(20) > 15)) {
10016 num = randint(DUN_STR_QUA - 1);
10017
10018 for (i = 0; i < num; i++)
10019 build_streamer2(wpos, (dun->l_ptr->flags1 & LF1_DEEP_WATER) ? FEAT_DEEP_WATER : FEAT_SHAL_WATER, 0);
10020
10021 if (randint(20) > 15) {
10022 num = randint(DUN_STR_QUA);
10023
10024 for (i = 0; i < num; i++)
10025 build_streamer2(wpos, FEAT_DEEP_WATER, 1);
10026 }
10027 }
10028
10029 /*
10030 * Levels 34 -- (was: 20 --)
10031 */
10032 else if (dun_lev > 33) {
10033 /*
10034 * Shallow lava (preserve walls)
10035 * Deep lava (penetrate walls)
10036 */
10037 if (randint(20) > 15) {
10038 num = randint(DUN_STR_QUA);
10039
10040 for (i = 0; i < num; i++)
10041 build_streamer2(wpos, (dun->l_ptr->flags1 & LF1_DEEP_LAVA) ? FEAT_DEEP_LAVA : FEAT_SHAL_LAVA, 0);
10042
10043 if (randint(20) > 15) {
10044 num = randint(DUN_STR_QUA - 1);
10045
10046 for (i = 0; i < num; i++)
10047 build_streamer2(wpos, FEAT_DEEP_LAVA, 1);
10048 }
10049 }
10050
10051 /*
10052 * Shallow water (preserve walls)
10053 * Deep water (penetrate walls)
10054 */
10055 else if (randint(20) > 15) {
10056 num = randint(DUN_STR_QUA - 1);
10057
10058 for (i = 0; i < num; i++)
10059 build_streamer2(wpos, (dun->l_ptr->flags1 & LF1_DEEP_WATER) ? FEAT_DEEP_WATER : FEAT_SHAL_WATER, 0);
10060
10061 if (randint(20) > 15) {
10062 num = randint(DUN_STR_QUA);
10063
10064 for (i = 0; i < num; i++)
10065 build_streamer2(wpos, FEAT_DEEP_WATER, 1);
10066 }
10067 }
10068 }
10069 }
10070
10071 /* ugly hack to fix the buggy extra bottom line that gets added to non-maxed levels sometimes:
10072 just overwrite it with filler tiles. */
10073 for (x = 0; x < MAX_WID; x++)
10074 for (y = dun->l_ptr->hgt; y < MAX_HGT; y++)
10075 zcave[y][x].feat = FEAT_PERM_FILL;
10076 #if 1 /* prevent extra right-side lines too? do these even occur? */
10077 for (x = dun->l_ptr->wid; x < MAX_WID; x++)
10078 for (y = 0; y < dun->l_ptr->hgt; y++) //the rest is already covered by the previous check above
10079 zcave[y][x].feat = FEAT_PERM_FILL;
10080 #endif
10081
10082 /* Possibly create dungeon boss aka FINAL_GUARDIAN.
10083 Rarity 1 in r_info.txt for those bosses now means:
10084 1 in <rarity> chance to generate the boss. - C. Blue */
10085 if (
10086 #ifdef IRONDEEPDIVE_MIXED_TYPES
10087 in_irondeepdive(wpos) ?
10088 ((k = d_info[iddc[ABS(wpos->wz)].type].final_guardian)
10089 && d_info[iddc[ABS(wpos->wz)].type].maxdepth == ABS(wpos->wz)
10090 #ifndef IDDC_GUARANTEED_FG /* not guaranteed spawn? (default) */
10091 && !rand_int((r_info[k].rarity + 1) / 2)
10092 #endif
10093 ) :
10094 #endif
10095 ((k = d_info[d_ptr->type].final_guardian)
10096 && d_ptr->maxdepth == ABS(wpos->wz)
10097 && !rand_int(r_info[k].rarity))) {
10098 // s_printf("Attempting to generate FINAL_GUARDIAN %d (1 in %d)\n", k, r_info[k].rarity);
10099 summon_override_checks = SO_FORCE_DEPTH; /* allow >20 level OoD if desired */
10100 alloc_monster_specific(wpos, k, 20, TRUE);
10101 summon_override_checks = SO_NONE;
10102 #if 0
10103 /* debug: break here? */
10104 level_generation_time = FALSE;
10105 return;
10106 #endif
10107 }
10108
10109 /* Basic "amount" */
10110 k = (dun_lev / 3);
10111
10112 if (k > 10) k = 10;
10113 k = k * dun->ratio / 100 + 1;
10114 if (k < 2) k = 2;
10115
10116 if (empty_level || maze) {
10117 k *= 2;
10118 bonus = TRUE;
10119 }
10120
10121 /* Pick a base number of monsters */
10122 i = MIN_M_ALLOC_LEVEL + randint(8);
10123 i = i * dun->ratio / 100 + 1;
10124
10125 /* dungeon has especially many monsters? */
10126 if ((d_ptr->flags3 & DF3_MANY_MONSTERS)) i = (i * 3) / 2;
10127 if ((d_ptr->flags3 & DF3_VMANY_MONSTERS)) i *= 2;
10128
10129 /* Put some monsters in the dungeon */
10130 for (i = i + k; i > 0; i--)
10131 (void)alloc_monster(wpos, 0, TRUE);
10132
10133 #ifdef ENABLE_MAIA
10134 /* Force a pair of darkling and candlebearer when there is at least
10135 * one divine on level that needs it.
10136 */
10137 if (dun_lev >= 12 && dun_lev <= 20 &&
10138 p_ptr && p_ptr->prace == RACE_MAIA && !p_ptr->ptrait) {
10139 //5 + randint(dun->row_rooms - 5), x1 = randint(dun->col_rooms - 5);
10140 int x, y, x1, y1, tries = 2000;
10141 do {
10142 x1 = rand_int(dun->l_ptr->wid - 6) + 3;
10143 y1 = rand_int(dun->l_ptr->hgt - 6) + 3;
10144 } while (!(cave_empty_bold(zcave, y1, x1) &&
10145 (zcave[y1][x1].info & CAVE_ROOM)) &&
10146 --tries);
10147 if (!tries) scatter(wpos, &y, &x, y1, x1, 20, FALSE);
10148 else {
10149 x = x1;
10150 y = y1;
10151 }
10152
10153 if (rand_int(2) == 1) place_monster_one(wpos, y, x, RI_CANDLEBEARER, FALSE, FALSE, FALSE, 0, 0);
10154 else place_monster_one(wpos, y, x, RI_DARKLING, FALSE, FALSE, FALSE, 0, 0);
10155 }
10156 #endif
10157
10158 #ifdef HACK_MONSTER_RARITIES
10159 /* unhack */
10160 if (hack_monster_idx) {
10161 alloc_entry *table = alloc_race_table_dun[DI_SANDWORM_LAIR];
10162 if (hack_dun_table_idx != -1) {
10163 table[hack_dun_table_idx].prob1 = hack_dun_table_prob1;
10164 table[hack_dun_table_idx].prob2 = hack_dun_table_prob2;
10165 table[hack_dun_table_idx].prob3 = hack_dun_table_prob3;
10166 }
10167 r_info[hack_monster_idx].rarity = hack_monster_rarity;
10168 }
10169 #endif
10170
10171 #ifndef ARCADE_SERVER
10172 if (!nr_bottom) {
10173 /* Place some traps in the dungeon */
10174 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_TRAP,
10175 randint(k * (bonus ? 3 : 1)), p_ptr);
10176
10177 /* Put some rubble in corridors */
10178 alloc_object(wpos, ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k), p_ptr);
10179
10180 /* Put some objects in rooms */
10181 alloc_object(wpos, ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3) * dun->ratio / 100 + 1, p_ptr);
10182
10183 /* Put some objects/gold in the dungeon */
10184 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3) * dun->ratio / 100 + 1, p_ptr);
10185 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3) * dun->ratio / 100 + 1, p_ptr);
10186
10187 /* Put some between gates */
10188 alloc_object(wpos, ALLOC_SET_ROOM, ALLOC_TYP_BETWEEN, randnor(DUN_AMT_BETWEEN, 3) * dun->ratio / 100 + 1, p_ptr);
10189
10190 /* Put some fountains */
10191 alloc_object(wpos, ALLOC_SET_ROOM, fountains_of_blood ? ALLOC_TYP_FOUNTAIN_OF_BLOOD : ALLOC_TYP_FOUNTAIN, randnor(DUN_AMT_FOUNTAIN, 3) * dun->ratio / 100 + 1, p_ptr);
10192 }
10193 /* It's done */
10194 #else
10195 if (!nr_bottom && wpos->wz < 0) {
10196 /* Place some traps in the dungeon */
10197 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_TRAP,
10198 randint(k * (bonus ? 3 : 1)), p_ptr);
10199
10200 /* Put some rubble in corridors */
10201 alloc_object(wpos, ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k), p_ptr);
10202
10203 /* Put some objects in rooms */
10204 alloc_object(wpos, ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3) * dun->ratio / 100 + 1, p_ptr);
10205
10206 /* Put some objects/gold in the dungeon */
10207 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3) * dun->ratio / 100 + 1, p_ptr);
10208 alloc_object(wpos, ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3) * dun->ratio / 100 + 1, p_ptr);
10209
10210 /* Put some between gates */
10211 alloc_object(wpos, ALLOC_SET_ROOM, ALLOC_TYP_BETWEEN, randnor(DUN_AMT_BETWEEN, 3) * dun->ratio / 100 + 1, p_ptr);
10212
10213 /* Put some fountains */
10214 alloc_object(wpos, ALLOC_SET_ROOM, fountains_of_blood ? ALLOC_TYP_FOUNTAIN_OF_BLOOD : ALLOC_TYP_FOUNTAIN, randnor(DUN_AMT_FOUNTAIN, 3) * dun->ratio / 100 + 1, p_ptr);
10215 }
10216 /* It's done */
10217 #endif
10218
10219 #if 0
10220 /* Put some altars */ /* No god, no alter */
10221 alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_ALTAR, randnor(DUN_AMT_ALTAR, 3) * dun->ratio / 100 + 1, p_ptr);
10222 #endif
10223
10224 #ifdef ARCADE_SERVER
10225 if(wpos->wz > 0) {
10226 for(mx = 1; mx < 131; mx++) {
10227 for(my = 1; my < 43; my++) {
10228 cave_set_feat(wpos, my, mx, 1);
10229 }
10230 }
10231 }
10232 if(wpos->wz > 0 && wpos->wz < 7) {
10233
10234 for(my = 1; my < 8; my++) {
10235 for(mx = 63; mx < 70; mx++) {
10236 cave_set_feat(wpos, my, mx, 209);
10237 }
10238 }
10239 for(my = 36; my < 43; my++) {
10240 for(mx = 63; mx < 70; mx++) {
10241 cave_set_feat(wpos, my, mx, 209);
10242 }
10243 }
10244 for(my = 19; my < 26; my++) {
10245 for(mx = 1; mx < 8; mx++) {
10246 cave_set_feat(wpos, my, mx, 209);
10247 }
10248 }
10249 for(my = 19; my < 26; my++) {
10250 for(mx = 124; mx < 131; mx++) {
10251 cave_set_feat(wpos, my, mx, 209);
10252 }
10253 }
10254 }
10255
10256
10257 if (wpos->wz == 7) {
10258 for(mx = 1; mx<21; mx++)
10259 cave_set_feat(wpos, 11, mx, 61);
10260 for(mx = 1; mx < 12; mx++)
10261 cave_set_feat(wpos, mx, 21, 61);
10262 }
10263
10264 if (wpos->wz == 9) {
10265 for(mx = 1; mx < 131; mx++) {
10266 for(my = 1; my < 43; my++) {
10267 cave_set_feat(wpos, my, mx, 187);
10268 }
10269 }
10270 }
10271
10272 #endif
10273
10274 #ifdef ENABLE_DOOR_CHECK
10275 #if 0 /* special secondary check maybe, apart from the usual door_makes_no_sense() -- THIS IS JUST A DOODLE - NON FUNCTIONAL! */
10276 /* scan level for weird doors and remove them */
10277 for (x = 0; x < MAX_WID; x++)
10278 for (y = 0; y < MAX_HGT; y++) {
10279 k = zcave[y][x].feat;
10280 if ((k < FEAT_DOOR_HEAD || k > FEAT_DOOR_TAIL) && k != FEAT_SECRET) continue;
10281 if (door_makes_no_sense(zcave, x, y))
10282 ;
10283 //zcave[y][x] = FEAT_FLOOR;
10284 }
10285 #endif
10286 #endif
10287
10288 level_generation_time = FALSE;
10289
10290
10291 /* A little evilness:
10292 If Morgoth was generated on this level, make all vaults NO_TELE.
10293 In addition to this, Morgoth's 'live-spawn' instead of being
10294 generated along with the level should be prevented (place_monster_one in monster2.c). */
10295 #ifdef MORGOTH_NO_TELE_VAULTS
10296 for (y = 1; y < dun->l_ptr->hgt - 1; y++) {
10297 for (x = 1; x < dun->l_ptr->wid - 1; x++) {
10298 cr_ptr = &zcave[y][x];
10299 if (cr_ptr->m_idx) {
10300 /* Check if Morgoth was just generated along with this dungeon level */
10301 m_ptr = &m_list[cr_ptr->m_idx];
10302 if (m_ptr->r_idx == RI_MORGOTH) morgoth_inside = TRUE;
10303 }
10304 if (morgoth_inside) break;
10305 }
10306 if (morgoth_inside) break;
10307 }
10308 if (morgoth_inside) {
10309 /* make all vaults NO_TELE */
10310 for (y = 1; y < dun->l_ptr->hgt - 1; y++) {
10311 for (x = 1; x < dun->l_ptr->wid - 1; x++) {
10312 cr_ptr = &zcave[y][x];
10313 /* Only those vaults with PERMA_WALL walls */
10314 if (cr_ptr->info & (CAVE_ICKY_PERMA)) cr_ptr->info |= (CAVE_STCK);
10315 }
10316 }
10317 }
10318 #endif
10319
10320
10321 /* Check for half void jump gates, resulting from partial vaults
10322 which contain void gates and were cut at the level border - C. Blue */
10323 /*.. */
10324
10325
10326 /* Create secret dungeon shop entrances (never on Morgoth's depth) -C. Blue */
10327 /* Nether Realm has an overriding shop creation routing. */
10328 if (!netherrealm_level) {
10329 bool store_failed = FALSE; /* avoid checking for a different type of store if one already failed, warping probabilities around */
10330
10331 /* Check for building deep store (Rare & expensive stores) */
10332 if ((!dungeon_store_timer) && (dun_lev >= 60) && (dun_lev != 100))
10333 build_special_store = 1;
10334
10335 /* Not for special dungeons (easy csw/resattr): */
10336 // if ((!challenge_dungeon && !(d_ptr->flags3 & DF3_NO_SIMPLE_STORES)) ||
10337 if (!(d_ptr->flags3 & DF3_NO_SIMPLE_STORES)) {
10338 /* Check for building low-level store (Herbalist) */
10339 if ((!build_special_store) &&
10340 (!dungeon_store2_timer) && (dun_lev >= 10) && (dun_lev <= 30))
10341 build_special_store = 2;
10342
10343 /* Build one of several misc stores for basic items of certain type */
10344 //todo: maybe use the new d_ptr->store_timer for randomly generated stores
10345 #ifdef TEST_SERVER
10346 if (!store_failed && (!build_special_store) && (dun_lev >= 13)) {
10347 if (!rand_int(5)) build_special_store = 3;
10348 else store_failed = TRUE;
10349 }
10350 #else
10351 #ifdef RPG_SERVER
10352 if (!store_failed && (!build_special_store) && (d_ptr->flags2 & DF2_IRON) && (dun_lev >= 13)) {
10353 // ((dun_lev + rand_int(3) - 1) % 5 == 0)) build_special_store = 3;
10354 if (!rand_int(5)) build_special_store = 3;
10355 else store_failed = TRUE;
10356 }
10357 #endif
10358 #endif
10359 }
10360
10361 /* Build one of several misc stores for basic items of certain type, like on RPG server above */
10362 if (!store_failed && (!build_special_store) && (d_ptr->flags2 & DF2_MISC_STORES) && (dun_lev >= 13)) {
10363 if (!rand_int(5)) build_special_store = 3;
10364 else store_failed = TRUE;
10365 }
10366
10367 /* Build hidden library if desired (good for challenge dungeons actually) */
10368 if (//!store_failed &&
10369 (!build_special_store) && (d_ptr->flags3 & DF3_HIDDENLIB) && (dun_lev >= 8)) {
10370 if (!rand_int(dun_lev / 2 + 1)) build_special_store = 4;
10371 else store_failed = TRUE;
10372 }
10373
10374 /* Build deep supplies store if desired (good for challenge dungeons actually) */
10375 if (//!store_failed &&
10376 (!build_special_store) && (d_ptr->flags3 & DF3_DEEPSUPPLY) && (dun_lev >= 80)) {
10377 if (!rand_int(5)) build_special_store = 5;
10378 else {
10379 s_printf("DUNGEON_STORE: DEEPSUPPLY failed.\n");
10380 store_failed = TRUE;
10381 }
10382 }
10383
10384 /* if failed, we're done */
10385 if (!build_special_store) return;
10386 /* reset deep shop timeout */
10387 if (build_special_store == 1)
10388 dungeon_store_timer = 2 + rand_int(cfg.dungeon_shop_timeout); /* reset timeout (in minutes) */
10389 /* reset low-level shop timeout */
10390 if (build_special_store == 2)
10391 dungeon_store2_timer = 2 + rand_int(cfg.dungeon_shop_timeout); /* reset timeout (in minutes) */
10392 /* build only one special shop in the Nether Realm */
10393 } else if (((dun_lev - 166) % 5 != 0) || (dun_lev == netherrealm_end)) return;
10394
10395 /* Try to create a dungeon store */
10396 if ((rand_int(1000) < cfg.dungeon_shop_chance) || netherrealm_level ||
10397 (build_special_store == 3 || build_special_store == 4 || build_special_store == 5)) {
10398 /* Try hard to place one */
10399 for (i = 0; i < 300; i++) {
10400 y = rand_int(dun->l_ptr->hgt-4)+2;
10401 x = rand_int(dun->l_ptr->wid-4)+2;
10402 csbm_ptr = &zcave[y][x];
10403 /* Must be in a wall, must not be in perma wall. Outside of vaults. */
10404 if ((f_info[csbm_ptr->feat].flags1 & FF1_WALL) &&
10405 !(f_info[csbm_ptr->feat].flags1 & FF1_PERMANENT) &&
10406 !(csbm_ptr->info & CAVE_ICKY))
10407 {
10408 /* must have at least 1 'free' adjacent field */
10409 bool found1free = FALSE;
10410 for (k = 0; k < 8; k++) {
10411 switch (k) {
10412 case 0: x1 = x - 1; y1 = y - 1; break;
10413 case 1: x1 = x; y1 = y - 1; break;
10414 case 2: x1 = x + 1; y1 = y - 1; break;
10415 case 3: x1 = x + 1; y1 = y; break;
10416 case 4: x1 = x + 1; y1 = y + 1; break;
10417 case 5: x1 = x; y1 = y + 1; break;
10418 case 6: x1 = x - 1; y1 = y + 1; break;
10419 case 7: x1 = x - 1; y1 = y; break;
10420 }
10421 cr_ptr = &zcave[y1][x1];
10422 if (!(f_info[cr_ptr->feat].flags1 & FF1_WALL))
10423 found1free = TRUE;
10424 }
10425
10426 if (found1free) {
10427 /* Must have at least 3 solid adjacent fields,
10428 that are also adjacent to each other,
10429 and the 3-chain mustn't start at a corner! >:) Mwhahaha.. */
10430 int r = 0; /* Counts adjacent solid fields */
10431 for (k = 0; k < (8 - 1 + 3); k++)
10432 if (r < 3) {
10433 switch (k % 8) {
10434 case 0:x1 = x - 1; y1 = y - 1; break;
10435 case 1:x1 = x; y1 = y - 1; break;
10436 case 2:x1 = x + 1; y1 = y - 1; break;
10437 case 3:x1 = x + 1; y1 = y; break;
10438 case 4:x1 = x + 1; y1 = y + 1; break;
10439 case 5:x1 = x; y1 = y + 1; break;
10440 case 6:x1 = x - 1; y1 = y + 1; break;
10441 case 7:x1 = x - 1; y1 = y; break;
10442 }
10443 cr_ptr = &zcave[y1][x1];
10444 if ((f_info[cr_ptr->feat].flags1 & FF1_WALL)) {
10445 if (r != 0) r++;
10446 /* chain mustn't start in a diagonal corner..: */
10447 if ((r == 0) && ((k % 2) == 1)) r++;
10448 } else {
10449 r = 0;
10450 }
10451 }
10452 if (r >= 3) {
10453 /* Ok, create a secret store! */
10454 if ((cs_ptr = AddCS(csbm_ptr, CS_SHOP))) {
10455 csbm_ptr->feat = FEAT_SHOP;
10456 csbm_ptr->info |= CAVE_NOPK;
10457 /* Declare this to be a room & illuminate */
10458 csbm_ptr->info |= CAVE_ROOM | CAVE_GLOW;
10459 if (!netherrealm_level) {
10460 if (build_special_store == 1) {
10461 if (cfg.dungeon_shop_type == 999){
10462 switch (rand_int(3)) {
10463 case 1:cs_ptr->sc.omni = STORE_JEWELX;break; /*Rare Jewelry Shop */
10464 case 2:cs_ptr->sc.omni = STORE_SHOESX;break; /*Rare Footwear Shop */
10465 default: cs_ptr->sc.omni = STORE_BLACKS;break; /*The Secret Black Market */
10466 }
10467 } else {
10468 cs_ptr->sc.omni = cfg.dungeon_shop_type;
10469 }
10470 } else if (build_special_store == 2) {
10471 cs_ptr->sc.omni = STORE_HERBALIST;
10472 } else if (build_special_store == 3) {
10473 //Add specialist stores? - the_sandman
10474 switch (rand_int(7)) {
10475 /* case 1: cs_ptr->sc.omni = STORE_SPEC_AXE;break;
10476 case 2: cs_ptr->sc.omni = STORE_SPEC_BLUNT;break;
10477 case 3: cs_ptr->sc.omni = STORE_SPEC_POLE;break;
10478 case 4: cs_ptr->sc.omni = STORE_SPEC_SWORD;break;*/
10479 case 0: cs_ptr->sc.omni = STORE_HIDDENLIBRARY; break;
10480 case 1: case 2: cs_ptr->sc.omni = STORE_SPEC_CLOSECOMBAT; break;
10481 case 3: cs_ptr->sc.omni = STORE_SPEC_POTION; break;
10482 case 4: cs_ptr->sc.omni = STORE_SPEC_SCROLL; break;
10483 case 5: cs_ptr->sc.omni = STORE_SPEC_ARCHER; break;
10484 default: cs_ptr->sc.omni = STORE_STRADER; break;
10485 }
10486 } else if (build_special_store == 4)
10487 cs_ptr->sc.omni = STORE_HIDDENLIBRARY;
10488 else if (build_special_store == 5)
10489 cs_ptr->sc.omni = STORE_DEEPSUPPLY;
10490 } else {
10491 cs_ptr->sc.omni = STORE_BTSUPPLY;
10492 }
10493 s_printf("DUNGEON_STORE: %d (%d,%d,%d)\n", cs_ptr->sc.omni, wpos->wx, wpos->wy, wpos->wz);
10494 return;
10495 }
10496 }
10497 }
10498 }
10499 }
10500
10501 /* Creation failed because no spot was found! */
10502 /* So let's allow it on the next level then.. */
10503 if (!netherrealm_level) {
10504 if (build_special_store == 1)
10505 dungeon_store_timer = 0;
10506 else
10507 dungeon_store2_timer = 0;
10508 }
10509 }
10510 }
10511
10512
10513
10514 /*
10515 * Builds a store at a given (row, column)
10516 *
10517 * Note that the solid perma-walls are at x=0/65 and y=0/21
10518 *
10519 * As of 2.7.4 (?) the stores are placed in a more "user friendly"
10520 * configuration, such that the four "center" buildings always
10521 * have at least four grids between them, to allow easy running,
10522 * and the store doors tend to face the middle of town.
10523 *
10524 * The stores now lie inside boxes from 3-9 and 12-18 vertically,
10525 * and from 7-17, 21-31, 35-45, 49-59. Note that there are thus
10526 * always at least 2 open grids between any disconnected walls.
10527 */
10528 /*
10529 * XXX hrm apartment allows wraithes to intrude..
10530 */
10531 /* NOTE: This function no longer is used for normal town generation;
10532 * this can be used to build 'extra' towns for some purpose, though.
10533 */
10534 //TL;DR: nowadays _only_ used in town_gen_hack(), for dungeon (ironman) towns - C. Blue
10535 static void build_store(struct worldpos *wpos, int n, int yy, int xx) {
10536 int i, y, x, y0, x0, y1, x1, y2, x2, tmp;
10537 int size = 0;
10538 cave_type *c_ptr;
10539 bool flat = FALSE, trad = FALSE;
10540 struct c_special *cs_ptr;
10541
10542 /* turn ponds into lava pools if floor is usually lava, maybe change other feats too */
10543 bool lava_floor = FALSE;
10544 dungeon_type *d_ptr = getdungeon(wpos);
10545 int dun_type = 0;
10546
10547 if (d_ptr) {
10548 #ifdef IRONDEEPDIVE_MIXED_TYPES
10549 if (in_irondeepdive(wpos)) dun_type = iddc[ABS(wpos->wz)].type;
10550 else
10551 #endif
10552 dun_type = d_ptr->theme ? d_ptr->theme : d_ptr->type;
10553
10554 for (i = 0; i < 5; i++)
10555 if (d_info[dun_type].floor[i] == FEAT_SHAL_LAVA ||
10556 d_info[dun_type].floor[i] == FEAT_DEEP_LAVA)
10557 lava_floor = TRUE;
10558 //d_info[iddc[ABS(wpos->wz)].next].floor[i];
10559 }
10560
10561 cave_type **zcave;
10562 if (!(zcave = getcave(wpos))) return; /*multitowns*/
10563
10564 y0 = yy * 11 + 5;
10565 x0 = xx * 16 + 12;
10566
10567 /* Determine the store boundaries */
10568 y1 = y0 - randint((yy == 0) ? 3 : 2);
10569 y2 = y0 + randint((yy == 1) ? 3 : 2);
10570 x1 = x0 - randint(5);
10571 x2 = x0 + randint(5);
10572
10573 /* Hack -- make building 9's as large as possible */
10574 if (n == STORE_NINE) {
10575 y1 = y0 - 3;
10576 y2 = y0 + 3;
10577 x1 = x0 - 5;
10578 x2 = x0 + 5;
10579 }
10580
10581 /* Hack -- make building 8's larger */
10582 if (n == STORE_HOME || n == STORE_HOME_DUN) {
10583 y1 = y0 - 1 - randint(2);
10584 y2 = y0 + 1 + randint(2);
10585 x1 = x0 - 3 - randint(2);
10586 x2 = x0 + 3 + randint(2);
10587 }
10588
10589 /* Hack -- try 'apartment house' */
10590 if (n == STORE_HOUSE && magik(60)) {
10591 y1 = y0 - 1 - randint(2);
10592 y2 = y0 + 1 + randint(2);
10593 x1 = x0 - 3 - randint(3);
10594 x2 = x0 + 3 + randint(2);
10595 if ((x2 - x1) % 2) x2--;
10596 if ((y2 - y1) % 2) y2--;
10597 if ((x2 - x1) >= 4 && (y2 - y1) >= 4 && magik(60)) flat = TRUE;
10598 }
10599
10600 /* Hack -- try 'apartment house' */
10601 if (n == STORE_HOUSE) {
10602 if (!magik(MANG_HOUSE_RATE)) trad = TRUE;
10603 }
10604
10605 /* Build an invulnerable rectangular building */
10606 for (y = y1; y <= y2; y++) {
10607 for (x = x1; x <= x2; x++) {
10608 /* Get the grid */
10609 c_ptr = &zcave[y][x];
10610
10611 /* Clear previous contents, add "basic" perma-wall */
10612 c_ptr->feat = (n == 13) ? FEAT_WALL_HOUSE : FEAT_PERM_EXTRA;
10613
10614 /* Hack -- The buildings are illuminated and known */
10615 /* c_ptr->info |= (CAVE_GLOW); */
10616 }
10617 }
10618
10619 /* Hack -- Make store "8" (the old home) empty */
10620 if (n == STORE_HOME || n == STORE_HOME_DUN) {
10621 for (y = y1 + 1; y < y2; y++) {
10622 for (x = x1 + 1; x < x2; x++) {
10623 /* Get the grid */
10624 c_ptr = &zcave[y][x];
10625
10626 /* Clear contents */
10627 c_ptr->feat = FEAT_FLOOR;
10628
10629 /* Declare this to be a room */
10630 c_ptr->info |= (CAVE_ROOM | CAVE_GLOW | CAVE_NOPK);
10631 }
10632 }
10633
10634 /* Hack -- have everyone start in the tavern */
10635 new_level_down_y(wpos, (y1 + y2) / 2);
10636 new_level_down_x(wpos, (x1 + x2) / 2);
10637 }
10638
10639 /* Make doorways, fill with grass and trees */
10640 if (n == STORE_DOORWAY) {
10641 for (y = y1 + 1; y < y2; y++) {
10642 for (x = x1 + 1; x < x2; x++) {
10643 /* Get the grid */
10644 c_ptr = &zcave[y][x];
10645
10646 /* Clear contents */
10647 c_ptr->feat = FEAT_GRASS;
10648 }
10649 }
10650
10651 y = (y1 + y2) / 2;
10652 x = (x1 + x2) / 2;
10653
10654 zcave[y1][x].feat = FEAT_GRASS;
10655 zcave[y2][x].feat = FEAT_GRASS;
10656 zcave[y][x1].feat = FEAT_GRASS;
10657 zcave[y][x2].feat = FEAT_GRASS;
10658
10659 for (i = 0; i < 5; i++) {
10660 y = rand_range(y1 + 1, y2 - 1);
10661 x = rand_range(x1 + 1, x2 - 1);
10662
10663 c_ptr = &zcave[y][x];
10664
10665 c_ptr->feat = lava_floor ? FEAT_DEAD_TREE: FEAT_TREE;
10666 }
10667
10668 return;
10669 }
10670
10671 /* Pond */
10672 if (n == STORE_POND) {
10673 for (y = y1; y <= y2; y++) {
10674 for (x = x1; x <= x2; x++) {
10675 /* Get the grid */
10676 c_ptr = &zcave[y][x];
10677
10678 /* Fill with water */
10679 c_ptr->feat = lava_floor ? FEAT_DEEP_LAVA : FEAT_DEEP_WATER;
10680 }
10681 }
10682
10683 /* Make the pond not so "square" */
10684 zcave[y1][x1].feat = FEAT_DIRT;
10685 zcave[y1][x2].feat = FEAT_DIRT;
10686 zcave[y2][x1].feat = FEAT_DIRT;
10687 zcave[y2][x2].feat = FEAT_DIRT;
10688
10689 return;
10690 }
10691
10692 /* Building with stairs */
10693 if (n == STORE_FEAT_MORE || n == STORE_FEAT_LESS) {
10694 for (y = y1; y <= y2; y++) {
10695 for (x = x1; x <= x2; x++) {
10696 /* Get the grid */
10697 c_ptr = &zcave[y][x];
10698
10699 /* Empty it */
10700 c_ptr->feat = FEAT_FLOOR;
10701
10702 /* Put some grass */
10703 if (randint(100) < 50)
10704 c_ptr->feat = FEAT_GRASS;
10705 c_ptr->info |= CAVE_NOPK;
10706 }
10707 }
10708
10709 x = (x1 + x2) / 2;
10710 y = (y1 + y2) / 2;
10711
10712 /* Access the stair grid */
10713 c_ptr = &zcave[y][x];
10714
10715 /* Clear previous contents, add down stairs */
10716 if (n == STORE_FEAT_MORE) {
10717 c_ptr->feat = FEAT_MORE;
10718 new_level_up_y(wpos, y);
10719 new_level_up_x(wpos, x);
10720 #if 0 /* moved down, see below. Should be ok/better? */
10721 new_level_rand_y(wpos, y);
10722 new_level_rand_x(wpos, x);
10723 #endif
10724 } else {
10725 c_ptr->feat = FEAT_LESS;
10726 new_level_down_y(wpos, y);
10727 new_level_down_x(wpos, x);
10728 }
10729 new_level_rand_y(wpos, y);
10730 new_level_rand_x(wpos, x);
10731 return;
10732 }
10733
10734 /* Forest */
10735 if (n == STORE_FOREST) {
10736 int xc, yc, max_dis;
10737
10738 /* Find the center of the forested area */
10739 xc = (x1 + x2) / 2;
10740 yc = (y1 + y2) / 2;
10741
10742 /* Find the max distance from center */
10743 max_dis = distance(y2, x2, yc, xc);
10744
10745 for (y = y1; y <= y2; y++) {
10746 for (x = x1; x <= x2; x++) {
10747 int chance;
10748
10749 /* Get the grid */
10750 c_ptr = &zcave[y][x];
10751
10752 /* Empty it */
10753 c_ptr->feat = FEAT_GRASS;
10754
10755 /* Calculate chance of a tree */
10756 chance = 100 * (distance(y, x, yc, xc));
10757 chance /= max_dis;
10758 chance = 80 - chance;
10759
10760 /* Put some trees */
10761 if (randint(100) < chance)
10762 c_ptr->feat = lava_floor ? FEAT_DEAD_TREE : FEAT_TREE;
10763 }
10764 }
10765
10766 return;
10767 }
10768
10769 /* House */
10770 if (n == STORE_HOUSE) {
10771 #ifdef USE_MANG_HOUSE
10772 if (!trad) {
10773 for (y = y1 + 1; y < y2; y++) {
10774 for (x = x1 + 1; x < x2; x++) {
10775 /* Get the grid */
10776 c_ptr = &zcave[y][x];
10777
10778 /* Fill with floor */
10779 c_ptr->feat = FEAT_FLOOR;
10780
10781 /* Make it "icky" */
10782 c_ptr->info |= CAVE_ICKY;
10783 }
10784 }
10785 }
10786 #endif /* USE_MANG_HOUSE */
10787
10788 if (!flat) {
10789 /* Setup some "house info" */
10790 size = (x2 - x1 - 1) * (y2 - y1 - 1);
10791
10792 MAKE(houses[num_houses].dna, struct dna_type);
10793 houses[num_houses].x = x1;
10794 houses[num_houses].y = y1;
10795 houses[num_houses].flags = HF_RECT | HF_STOCK;
10796 if (trad) houses[num_houses].flags |= HF_TRAD;
10797 houses[num_houses].coords.rect.width = x2 - x1 + 1;
10798 houses[num_houses].coords.rect.height = y2 - y1 + 1;
10799 wpcopy(&houses[num_houses].wpos, wpos);
10800 houses[num_houses].dna->price = initial_house_price(&houses[num_houses]);
10801 }
10802 /* Hack -- apartment house */
10803 else {
10804 int doory = 0, doorx = 0, dy, dx;
10805 struct c_special *cs_ptr;
10806 if (magik(75)) doorx = rand_int((x2 - x1 - 1) / 2);
10807 else doory = rand_int((y2 - y1 - 1) / 2);
10808
10809 for (x = x1; x <= x2; x++) {
10810 /* Get the grid */
10811 c_ptr = &zcave[(y1 + y2) / 2][x];
10812
10813 /* Clear previous contents, add "basic" perma-wall */
10814 c_ptr->feat = FEAT_PERM_EXTRA;
10815 }
10816
10817 for (y = y1; y <= y2; y++) {
10818 /* Get the grid */
10819 c_ptr = &zcave[y][(x1 + x2) / 2];
10820
10821 /* Clear previous contents, add "basic" perma-wall */
10822 c_ptr->feat = FEAT_PERM_EXTRA;
10823 }
10824
10825 /* Setup some "house info" */
10826 size = ((x2 - x1) / 2 - 1) * ((y2 - y1) / 2 - 1);
10827
10828 for (i = 0; i < 4; i++) {
10829 #if 1
10830 dx = (i < 2 ? x1 : x2);
10831 dy = ((i % 2) ? y2 : y1);
10832 #endif /* 1 */
10833 x = ( i < 2 ? x1 : x1 + (x2 - x1) / 2);
10834 y = ((i % 2) ? y1 + (y2 - y1) / 2 : y1);
10835 c_ptr = &zcave[y][x];
10836
10837 /* Remember price */
10838 MAKE(houses[num_houses].dna, struct dna_type);
10839 houses[num_houses].x = x;
10840 houses[num_houses].y = y;
10841 houses[num_houses].flags = HF_RECT | HF_STOCK | HF_APART;
10842 if (trad) houses[num_houses].flags |= HF_TRAD;
10843 houses[num_houses].coords.rect.width = (x2 - x1) / 2 + 1;
10844 houses[num_houses].coords.rect.height = (y2 - y1) / 2 + 1;
10845 wpcopy(&houses[num_houses].wpos, wpos);
10846 houses[num_houses].dna->price = initial_house_price(&houses[num_houses]);
10847
10848 /* MEGAHACK -- add doors here and return */
10849
10850 #if 1 /* savedata sometimes forget about it and crashes.. */
10851 dx += (i < 2 ? doorx : 0 - doorx);
10852 dy += ((i % 2) ? 0 - doory : doory);
10853 #endif /* 1 */
10854
10855 c_ptr = &zcave[dy][dx];
10856
10857 /* hack -- only create houses that aren't already loaded from disk */
10858 if ((tmp = pick_house(wpos, dy, dx)) == -1) {
10859 /* Store door location information */
10860 c_ptr->feat = FEAT_HOME;
10861 if ((cs_ptr = AddCS(c_ptr, CS_DNADOOR))) {
10862 cs_ptr->sc.ptr = houses[num_houses].dna;
10863 }
10864 houses[num_houses].dx = dx;
10865 houses[num_houses].dy = dy;
10866 houses[num_houses].dna->creator = 0L;
10867 houses[num_houses].dna->owner = 0L;
10868
10869 #ifndef USE_MANG_HOUSE_ONLY
10870 /* This can be changed later */
10871 /* XXX maybe new owner will be unhappy if size>STORE_INVEN_MAX;
10872 * this will be fixed when STORE_INVEN_MAX will be removed. - Jir
10873 */
10874 if (trad) {
10875 size = (size >= STORE_INVEN_MAX) ? STORE_INVEN_MAX : size;
10876 houses[num_houses].stock_size = size;
10877 houses[num_houses].stock_num = 0;
10878 /* TODO: pre-allocate some when launching the server */
10879 C_MAKE(houses[num_houses].stock, size, object_type);
10880 } else {
10881 houses[num_houses].stock_size = 0;
10882 houses[num_houses].stock_num = 0;
10883 }
10884 #endif /* USE_MANG_HOUSE */
10885
10886 /* One more house */
10887 num_houses++;
10888 if ((house_alloc - num_houses) < 32) {
10889 GROW(houses, house_alloc, house_alloc + 512, house_type);
10890 house_alloc += 512;
10891 }
10892 } else {
10893 KILL(houses[num_houses].dna, struct dna_type);
10894 c_ptr->feat = FEAT_HOME;
10895 if((cs_ptr = AddCS(c_ptr, CS_DNADOOR))){
10896 cs_ptr->sc.ptr = houses[tmp].dna;
10897 }
10898 }
10899 }
10900
10901 return;
10902 }
10903 }
10904
10905
10906 /* Pick a door direction (S,N,E,W) */
10907 tmp = rand_int(4);
10908
10909 /* Re-roll "annoying" doors */
10910 while (((tmp == 0) && ((yy % 2) == 1)) ||
10911 ((tmp == 1) && ((yy % 2) == 0)) ||
10912 ((tmp == 2) && ((xx % 2) == 1)) ||
10913 ((tmp == 3) && ((xx % 2) == 0)))
10914 {
10915 /* Pick a new direction */
10916 tmp = rand_int(4);
10917 }
10918
10919 /* Extract a "door location" */
10920 switch (tmp) {
10921 /* Bottom side */
10922 case 0:
10923 y = y2;
10924 x = rand_range(x1, x2);
10925 break;
10926
10927 /* Top side */
10928 case 1:
10929 y = y1;
10930 x = rand_range(x1, x2);
10931 break;
10932
10933 /* Right side */
10934 case 2:
10935 y = rand_range(y1, y2);
10936 x = x2;
10937 break;
10938
10939 /* Left side */
10940 default:
10941 y = rand_range(y1, y2);
10942 x = x1;
10943 break;
10944 }
10945
10946 /* Access the grid */
10947 c_ptr = &zcave[y][x];
10948
10949 /* Some buildings get special doors */
10950 if (n == STORE_HOUSE && !flat) {
10951 /* hack -- only create houses that aren't already loaded from disk */
10952 if ((i = pick_house(wpos, y, x)) == -1) {
10953 /* Store door location information */
10954 c_ptr->feat = FEAT_HOME;
10955 if ((cs_ptr = AddCS(c_ptr, CS_DNADOOR))){
10956 cs_ptr->sc.ptr = houses[num_houses].dna;
10957 }
10958 houses[num_houses].dx = x;
10959 houses[num_houses].dy = y;
10960 houses[num_houses].dna->creator = 0L;
10961 houses[num_houses].dna->owner = 0L;
10962
10963 #ifndef USE_MANG_HOUSE_ONLY
10964 /* This can be changed later */
10965 /* XXX maybe new owner will be unhappy if size>STORE_INVEN_MAX;
10966 * this will be fixed when STORE_INVEN_MAX will be removed. - Jir
10967 */
10968 if (trad) {
10969 size = (size >= STORE_INVEN_MAX) ? STORE_INVEN_MAX : size;
10970 houses[num_houses].stock_size = size;
10971 houses[num_houses].stock_num = 0;
10972 /* TODO: pre-allocate some when launching the server */
10973 C_MAKE(houses[num_houses].stock, size, object_type);
10974 } else {
10975 houses[num_houses].stock_size = 0;
10976 houses[num_houses].stock_num = 0;
10977 }
10978 #endif /* USE_MANG_HOUSE_ONLY */
10979
10980 /* One more house */
10981 num_houses++;
10982 if ((house_alloc - num_houses) < 32) {
10983 GROW(houses, house_alloc, house_alloc + 512, house_type);
10984 house_alloc += 512;
10985 }
10986 }
10987 else {
10988 KILL(houses[num_houses].dna, struct dna_type);
10989 c_ptr->feat = FEAT_HOME;
10990 if((cs_ptr = AddCS(c_ptr, CS_DNADOOR))){
10991 cs_ptr->sc.ptr = houses[i].dna;
10992 }
10993 }
10994 }
10995 else if (n == STORE_AUCTION) /* auctionhouse */
10996 {
10997 c_ptr->feat = FEAT_PERM_EXTRA; /* wants to work */
10998
10999 } else {
11000 /* Clear previous contents, add a store door */
11001 c_ptr->feat = FEAT_SHOP; /* TODO: put CS_SHOP */
11002 c_ptr->info |= CAVE_NOPK;
11003
11004 if ((cs_ptr = AddCS(c_ptr, CS_SHOP)))
11005 cs_ptr->sc.omni = n;
11006
11007 for (y1 = y - 1; y1 <= y + 1; y1++) {
11008 for (x1 = x - 1; x1 <= x + 1; x1++) {
11009 /* Get the grid */
11010 c_ptr = &zcave[y1][x1];
11011
11012 /* Declare this to be a room */
11013 c_ptr->info |= CAVE_ROOM | CAVE_GLOW;
11014 /* Illuminate the store */
11015 }
11016 }
11017 }
11018 }
11019
11020 /*
11021 * Build a road.
11022 */
11023 static void place_street(struct worldpos *wpos, int vert, int place)
11024 {
11025 int y, x, y1, y2, x1, x2;
11026 cave_type **zcave;
11027 if (!(zcave = getcave(wpos))) return;
11028
11029 /* Vertical streets */
11030 if (vert) {
11031 x = place * 32 + 20;
11032 x1 = x - 2;
11033 x2 = x + 2;
11034
11035 y1 = 5;
11036 y2 = MAX_HGT - 5;
11037 } else {
11038 y = place * 22 + 10;
11039 y1 = y - 2;
11040 y2 = y + 2;
11041
11042 x1 = 5;
11043 x2 = MAX_WID - 5;
11044 }
11045
11046 for (y = y1; y <= y2; y++) {
11047 for (x = x1; x <= x2; x++) {
11048 if (zcave[y][x].feat != FEAT_FLOOR)
11049 zcave[y][x].feat = FEAT_GRASS;
11050 }
11051 }
11052
11053 if (vert) {
11054 x1++;
11055 x2--;
11056 } else {
11057 y1++;
11058 y2--;
11059 }
11060
11061 for (y = y1; y <= y2; y++) {
11062 for (x = x1; x <= x2; x++) {
11063 zcave[y][x].feat = FEAT_FLOOR;
11064 }
11065 }
11066 }
11067
11068
11069
11070 /*
11071 * Generate the "consistent" town features, and place the player
11072 *
11073 * Hack -- play with the R.N.G. to always yield the same town
11074 * layout, including the size and shape of the buildings, the
11075 * locations of the doorways, and the location of the stairs.
11076 *
11077 * C. Blue: Modified/extended for creation of dungeon towns,
11078 * especially for ironman dungeons/towers.
11079 */
11080
11081 /* (For dungeon towns.) Don't clutter all stores in the
11082 center, but spread them out a bit - C. Blue: */
11083 #define NEW_TOWNGENHACK_METHOD
11084
11085 static void town_gen_hack(struct worldpos *wpos) {
11086 bool dungeon_town = (wpos->wz != 0);
11087 wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
11088 struct dungeon_type *d_ptr = wpos->wz != 0 ? (wpos->wz > 0 ? wild->tower : wild->dungeon) : NULL;
11089
11090 int y, x, k, n;
11091 // int max_rooms = (max_st_idx > 72 ? 72 : max_st_idx), base_stores = MAX_BASE_STORES; <- not working, because the amount of buildings will be too small -> repeated-stores-glitch appears.
11092 int max_rooms = 72, base_stores = MAX_BASE_STORES;
11093 #ifdef NEW_TOWNGENHACK_METHOD
11094 int posx[base_stores], posy[base_stores], pos[6 * 4];
11095 #endif
11096 #ifdef DEVEL_TOWN_COMPATIBILITY
11097 /* -APD- the location of the auction house */
11098 int auction_x = -1, auction_y = -1;
11099 #endif
11100 int rooms[max_rooms];
11101
11102 cave_type **zcave, *c_ptr;
11103 if (!(zcave = getcave(wpos))) return;
11104
11105
11106 /* Hack -- Use the "simple" RNG */
11107 Rand_quick = TRUE;
11108
11109 /* Hack -- Induce consistant town layout */
11110 #if 0 /* was ok, but now.. */
11111 Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X);
11112 #else /* ..we have ironman towns in the dungeon, too - C. Blue */
11113 /* Well, actually we could just use completely random seed for wpos != 0
11114 and just x,y dependant seed for wpos == 0. Might even be preferrable. */
11115 if (!wpos->wz) Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X);
11116 else
11117 //Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X + wpos->wz * MAX_WILD_X * MAX_WILD_Y); /* Always same dungeon town at particular wpos */
11118 Rand_value = seed_town + (wpos->wx + wpos->wy * MAX_WILD_X) + turn / (cfg.fps * 3600 * 24); /* Different dungeon towns every 24h! */
11119 #endif
11120
11121
11122 #ifdef IRONDEEPDIVE_FIXED_TOWNS
11123 /* predefined town layout instead of generating randomly? */
11124 k = getlevel(wpos);
11125 if (is_fixed_irondeepdive_town(wpos, k)) {
11126 /* Kurzel suggested to use the cities of Menegroth and Nargothrond, seems good */
11127
11128 /* 2000ft - generate Menegroth */
11129 if (k == 40) {
11130 /* overlay town */
11131 x = y = 0;
11132 process_dungeon_file("t_menegroth.txt", wpos, &y, &x, MAX_HGT, MAX_WID, TRUE);
11133
11134 /* prepare basic floor */
11135 for (y = 1; y < MAX_HGT - 1; y++) {
11136 for (x = 1; x < MAX_WID - 1; x++) {
11137 c_ptr = &zcave[y][x];
11138 /* hack: fix staircase direction to match the dungeon type */
11139 if (c_ptr->feat == FEAT_MORE && wpos->wz > 0) c_ptr->feat = FEAT_LESS;
11140
11141 /* convert remaining empty grids to floor */
11142 if (c_ptr->feat) continue;
11143
11144 c_ptr->feat = FEAT_DIRT;
11145 if (!rand_int(5)) c_ptr->feat = FEAT_GRASS;
11146 }
11147 }
11148 }
11149
11150 /* 4000ft - generate Nargothrond */
11151 else if (k == 80) {
11152 /* overlay town */
11153 x = y = 0;
11154 process_dungeon_file("t_nargothrond.txt", wpos, &y, &x, MAX_HGT, MAX_WID, TRUE);
11155
11156 /* prepare basic floor */
11157 for (y = 1; y < MAX_HGT - 1; y++) {
11158 for (x = 1; x < MAX_WID - 1; x++) {
11159 c_ptr = &zcave[y][x];
11160
11161 /* hack: fix staircase direction to match the dungeon type */
11162 if (c_ptr->feat == FEAT_MORE && wpos->wz > 0) c_ptr->feat = FEAT_LESS;
11163
11164 /* convert remaining empty grids to floor */
11165 if (c_ptr->feat) continue;
11166
11167 c_ptr->feat = FEAT_FLOOR;
11168 if (rand_int(4)) c_ptr->feat = FEAT_GRASS;
11169 }
11170 }
11171 }
11172
11173 /* Hack -- use the "complex" RNG -- and we're done here! */
11174 Rand_quick = FALSE;
11175 return;
11176 }
11177 #endif
11178
11179
11180 /* Hack -- Start with basic floors */
11181 for (y = 1; y < MAX_HGT - 1; y++) {
11182 for (x = 1; x < MAX_WID - 1; x++) {
11183 c_ptr = &zcave[y][x];
11184 /* Clear all features, set to "empty floor" */
11185 #ifdef IRONDEEPDIVE_MIXED_TYPES
11186 if (in_irondeepdive(wpos)) {
11187 c_ptr->feat = d_info[iddc[ABS(wpos->wz)].type].floor[4]; //avoid strange [0] dominant types (4 is transition safe)
11188 if (rand_int(4)) c_ptr->feat = d_info[iddc[ABS(wpos->wz)].type].floor[0]; //strange types are OK if few?
11189 else if (rand_int(100) < 15) c_ptr->feat = d_info[iddc[ABS(wpos->wz)].type].fill_type[0]; //basic "granite"
11190 } else
11191 #endif
11192 { /* any default town */
11193 c_ptr->feat = FEAT_DIRT;
11194
11195 if (rand_int(4)) c_ptr->feat = FEAT_GRASS;
11196 else if (rand_int(100) < 15) c_ptr->feat = FEAT_TREE; /* gotta add FEAT_BUSH without screwing up the rng seed */
11197 }
11198 }
11199 }
11200
11201 /* Place horizontal "streets" */
11202 for (y = 0; y < 3; y++)
11203 place_street(wpos, 0, y);
11204
11205 /* Place vertical "streets" */
11206 for (x = 0; x < 6; x++)
11207 place_street(wpos, 1, x);
11208
11209 #if 0 /* disable 'deprecated' auction house for paranoia? */
11210 #ifdef DEVEL_TOWN_COMPATIBILITY
11211 /* -APD- place the auction house near the central stores */
11212 auction_x = rand_int(5) + 3;
11213 if ( (auction_x == 3) || (auction_x == 8) ) auction_y = rand_int(1) + 1;
11214 else auction_y = (rand_int(1) * 3) + 1; /* 1 or 4 */
11215 #endif
11216 #endif
11217
11218 /* Prepare an Array of "remaining stores", and count them */
11219 for (n = 0; n < base_stores; n++) {
11220 /* For dungeon towns, skip '8' since it allows exploiting 100% riskfree combat.
11221 Not true anymore, if STORE_HOME_DUN is used instead. But there is no home in
11222 the middle of the dungeon anyway. >:p */
11223 if (n == STORE_HOME && dungeon_town) rooms[n] = STORE_POND;
11224 /* allocate base store
11225 (dungeon towns use offset of +70 to avoid collision with normal town stores) */
11226 else rooms[n] = n + (dungeon_town ? STORE_GENERAL_DUN : 0);
11227 }
11228 for (n = base_stores; n < base_stores + 10; n++) rooms[n] = STORE_POND;
11229 for (n = base_stores + 10; n < base_stores + 20; n++) rooms[n] = STORE_FOREST;
11230 for (n = base_stores + 20; n < base_stores + 40; n++) rooms[n] = STORE_DOORWAY;
11231 for (n = base_stores + 40; n < max_rooms; n++) rooms[n] = STORE_HOUSE;
11232 #if 0 /* what is/was STORE_NINE? disabling it for now */
11233 for (n = max_rooms - 10; n < max_rooms - 7; n++) rooms[n] = STORE_NINE;
11234 #endif
11235
11236 /* staircases */
11237 if (wild->flags & WILD_F_DOWN)
11238 rooms[max_rooms - 2] = STORE_FEAT_MORE;
11239 if (wild->flags & WILD_F_UP)
11240 rooms[max_rooms - 1] = STORE_FEAT_LESS;
11241
11242 /* Dungeon towns get some extra treatment: */
11243 if (dungeon_town) {
11244 /* make dungeon towns look more destroyed */
11245 if (rand_int(2)) build_streamer(wpos, FEAT_TREE, 0, TRUE);
11246 if (rand_int(2)) build_streamer(wpos, FEAT_IVY, 0, TRUE);
11247 #if 0 /* these obstruct stores a bit too much maybe */
11248 if (rand_int(2)) build_streamer(wpos, FEAT_QUARTZ, 0, TRUE);
11249 if (rand_int(2)) build_streamer(wpos, FEAT_MAGMA, 0, TRUE);
11250 #endif
11251 if (rand_int(2)) {
11252 if (rand_int(2)) build_streamer(wpos, FEAT_SHAL_WATER, 0, TRUE);
11253 if (rand_int(2)) build_streamer(wpos, FEAT_DEEP_WATER, 0, TRUE);
11254 } else {
11255 if (rand_int(2)) build_streamer(wpos, FEAT_SHAL_LAVA, 0, TRUE);
11256 if (rand_int(2)) build_streamer(wpos, FEAT_DEEP_LAVA, 0, TRUE);
11257 }
11258
11259 /* For ironman dungeons: Set x,y coords when entering the level,
11260 since we don't place a 'staircase room' in the opposite
11261 direction that would set the coords for us. */
11262 if ((d_ptr->flags1 & (DF1_NO_UP | DF1_FORCE_DOWN)) || (d_ptr->flags2 & DF2_IRON)) {
11263 n = 1000;
11264 while (n--) {
11265 x = rand_int(MAX_WID - 2) + 1;
11266 y = rand_int(MAX_HGT - 2) + 1;
11267 if (cave_floor_bold(zcave, y, x)) break;
11268 }
11269 if (!n) {
11270 x = 2;
11271 y = 2;
11272 }
11273 if (wpos->wz < 0) {
11274 new_level_down_x(wpos, x);
11275 new_level_down_y(wpos, y);
11276 } else {
11277 new_level_up_x(wpos, x);
11278 new_level_up_y(wpos, y);
11279 }
11280 }
11281
11282 #if 0 /* why, actually? :) */
11283 /* Add additional staircases */
11284 if (wild->flags & WILD_F_DOWN) {
11285 rooms[max_rooms - 4] = STORE_FEAT_MORE;
11286 rooms[max_rooms - 6] = STORE_FEAT_MORE;
11287 }
11288 if (wild->flags & WILD_F_UP) {
11289 rooms[max_rooms - 3] = STORE_FEAT_LESS;
11290 rooms[max_rooms - 5] = STORE_FEAT_LESS;
11291 }
11292 #endif
11293 }
11294
11295 #ifdef NEW_TOWNGENHACK_METHOD
11296 /* pick random locations for the base stores */
11297 n = 6 * 4;
11298 for (k = 0; k < n; k++) pos[k] = k;
11299 for (x = 0; x < MAX_BASE_STORES; x++) {
11300 k = rand_int(n);
11301 posx[x] = pos[k] / 4 + 3;
11302 posy[x] = pos[k] % 4 + 1;
11303 n--;
11304 pos[k] = pos[n];
11305 }
11306 #endif
11307
11308 /* Place base stores */
11309 #ifndef NEW_TOWNGENHACK_METHOD
11310 n = max_rooms;
11311 for (y = 2; y < 5; y++) {
11312 for (x = 4; x < 8; x++) {
11313 /* hack if we place less base stores than spots are available */
11314 if (n == max_rooms - base_stores) continue;
11315
11316 /* Pick a random unplaced store */
11317 k = rand_int(n - (max_rooms - base_stores));
11318
11319 /* Build that store at the proper location */
11320 #if 0 /* I think I took this out for highlander town, but no need maybe; also required for ironman towns! - C. Blue */
11321 /* No Black Market in additional towns - C. Blue */
11322 if (rooms[k] != STORE_BLACK + (dungeon_town ? STORE_GENERAL_DUN : 0)) /* add +70 to get the dungeon version of the store */
11323 build_store(wpos, rooms[k], y, x);
11324 //else build_store(wpos, STORE_HERBALIST, y, x);
11325 #else
11326 build_store(wpos, rooms[k], y, x);
11327 #endif
11328
11329 /* One less store */
11330 n--;
11331
11332 /* Shift the stores down, remove one store */
11333 rooms[k] = rooms[n - (max_rooms - base_stores)];
11334 }
11335 }
11336 #else
11337 for (k = 0; k < MAX_BASE_STORES; k++) {
11338 /* Build that store at the proper location */
11339 #if 0 /* I think I took this out for highlander town, but no need maybe; also required for ironman towns! - C. Blue */
11340 /* No Black Market in additional towns - C. Blue */
11341 if (rooms[k] != STORE_BLACK + (dungeon_town ? STORE_GENERAL_DUN : 0)) /* add +70 to get the dungeon version of the store */
11342 build_store(wpos, rooms[k], posy[k], posx[k]);
11343 //else build_store(wpos, STORE_HERBALIST, y, x);
11344 #else
11345 build_store(wpos, rooms[k], posy[k], posx[k]);
11346 #endif
11347 }
11348 n = max_rooms - base_stores;
11349 #endif
11350
11351
11352 /* temporarily disable all the "useless" stores (eg houses)?
11353 (warning: also includes 'stair stores'?) */
11354 #if 1
11355 /* Place two rows of stores */
11356 for (y = 0; y < 6; y++) {
11357 /* Place four stores per row */
11358 for (x = 0; x < 12; x++) {
11359 /* Make sure we haven't already placed this one */
11360 #ifndef NEW_TOWNGENHACK_METHOD
11361 if (y >= 2 && y <= 4 && x >= 4 && x <= 7) continue;
11362 #else
11363 for (k = 0; k < MAX_BASE_STORES; k++) {
11364 if (posx[k] == x && posy[k] == y) {
11365 k = MAX_BASE_STORES + 1; //loop hack
11366 break;
11367 }
11368 }
11369 if (k == MAX_BASE_STORES + 1) continue;
11370 #endif
11371
11372 /* Pick a random unplaced store */
11373 k = rand_int(n) + base_stores;
11374
11375 /* don't build "homes" in dungeon towns */
11376 if (!(rooms[k] == STORE_HOUSE && dungeon_town)) {
11377 #ifdef DEVEL_TOWN_COMPATIBILITY
11378 if ( (y != auction_y) || (x != auction_x) ) {
11379 /* Build that store at the proper location */
11380 build_store(wpos, rooms[k], y, x);
11381 } else { /* auction time! */
11382 build_store(wpos, STORE_AUCTION, y, x);
11383 }
11384 #else
11385 build_store(wpos, rooms[k], y, x);
11386 #endif
11387 }
11388
11389 /* One less building */
11390 n--;
11391
11392 /* Shift the stores down, remove one store */
11393 rooms[k] = rooms[n + base_stores];
11394 }
11395 }
11396 #endif
11397
11398 /* Hack -- use the "complex" RNG */
11399 Rand_quick = FALSE;
11400 }
11401
11402
11403
11404
11405 /*
11406 * Town logic flow for generation of new town
11407 *
11408 * We start with a fully wiped cave of normal floors.
11409 *
11410 * Note that town_gen_hack() plays games with the R.N.G.
11411 *
11412 * This function does NOT do anything about the owners of the stores,
11413 * nor the contents thereof. It only handles the physical layout.
11414 *
11415 * We place the player on the stairs at the same time we make them.
11416 *
11417 * Hack -- since the player always leaves the dungeon by the stairs,
11418 * he is always placed on the stairs, even if he left the dungeon via
11419 * word of recall or teleport level.
11420 */
11421
11422 /*
11423 Hack -- since boundary walls are a 'good thing' for many of the algorithms
11424 used, the feature FEAT_PERM_CLEAR was created. It is used to create an
11425 invisible boundary wall for town and wilderness levels, keeping the
11426 algorithms happy, and the players fooled.
11427
11428 */
11429
11430 static void town_gen(struct worldpos *wpos) {
11431 int y, x, type = -1, i, x2, y2;
11432 int xstart = 0, ystart = 0; /* dummy, for now */
11433
11434 cave_type *c_ptr;
11435 cave_type **zcave;
11436 if (!(zcave = getcave(wpos))) return;
11437
11438 for (i = 0; i < numtowns; i++) {
11439 if (town[i].x == wpos->wx && town[i].y == wpos->wy) {
11440 type = town[i].type;
11441 break;
11442 }
11443 }
11444
11445 if (type < 0) {
11446 s_printf("TRIED TO GENERATE NON-ALLOCATED TOWN! %s\n",
11447 wpos_format(0, wpos));
11448 return;
11449 }
11450
11451 /* Perma-walls -- North/South*/
11452 for (x = 0; x < MAX_WID; x++) {
11453 /* North wall */
11454 c_ptr = &zcave[0][x];
11455
11456 /* Clear previous contents, add "clear" perma-wall */
11457 c_ptr->feat = FEAT_PERM_CLEAR;
11458
11459 /* Illuminate and memorize the walls
11460 c_ptr->info |= (CAVE_GLOW | CAVE_MARK);*/
11461
11462 /* South wall */
11463 c_ptr = &zcave[MAX_HGT-1][x];
11464
11465 /* Clear previous contents, add "clear" perma-wall */
11466 c_ptr->feat = FEAT_PERM_CLEAR;
11467
11468 /* Illuminate and memorize the walls
11469 c_ptr->info |= (CAVE_GLOW);*/
11470 }
11471
11472 /* Perma-walls -- West/East */
11473 for (y = 0; y < MAX_HGT; y++) {
11474 /* West wall */
11475 c_ptr = &zcave[y][0];
11476
11477 /* Clear previous contents, add "clear" perma-wall */
11478 c_ptr->feat = FEAT_PERM_CLEAR;
11479
11480 /* Illuminate and memorize the walls
11481 c_ptr->info |= (CAVE_GLOW);*/
11482
11483 /* East wall */
11484 c_ptr = &zcave[y][MAX_WID-1];
11485
11486 /* Clear previous contents, add "clear" perma-wall */
11487 c_ptr->feat = FEAT_PERM_CLEAR;
11488
11489 /* Illuminate and memorize the walls
11490 c_ptr->info |= (CAVE_GLOW);*/
11491 }
11492
11493 /* XXX this will be changed very soon - Jir -
11494 * It's no good hardcoding things like this.. */
11495 #if 1
11496 if (type > 0 || type < 6) {
11497 /* Hack -- Use the "simple" RNG */
11498 Rand_quick = TRUE;
11499
11500 /* Hack -- Induce consistant town layout */
11501 Rand_value = seed_town+(wpos->wx+wpos->wy*MAX_WILD_X);
11502
11503 /* Hack -- fill with trees
11504 * This should be determined by wilderness information */
11505 for (x = 2; x < MAX_WID - 2; x++) {
11506 for (y = 2; y < MAX_HGT - 2; y++) {
11507 /* Access the grid */
11508 c_ptr = &zcave[y][x];
11509
11510 /* Clear previous contents, add forest */
11511 //c_ptr->feat = magik(98) ? FEAT_TREE : FEAT_GRASS;
11512 i = magik(town_profile[type].ratio) ? town_profile[type].feat1 : town_profile[type].feat2;
11513 /* hack: swap trees and bushes depending on season on world surface */
11514 if ((i == FEAT_TREE || i == FEAT_BUSH) && !wpos->wz)
11515 i = get_seasonal_tree();
11516 c_ptr->feat = i;
11517 }
11518 }
11519
11520 /* XXX The space is needed to prevent players from getting
11521 * stack when entering into a town from wilderness.
11522 * TODO: devise a better way */
11523 /* Perma-walls -- North/South*/
11524 for (x = 1; x < MAX_WID - 1; x++) {
11525 /* North wall */
11526 c_ptr = &zcave[1][x];
11527
11528 /* Clear previous contents, add "clear" perma-wall */
11529 c_ptr->feat = FEAT_GRASS;
11530
11531 /* Illuminate and memorize the walls
11532 c_ptr->info |= (CAVE_GLOW | CAVE_MARK);*/
11533
11534 /* South wall */
11535 c_ptr = &zcave[MAX_HGT-2][x];
11536
11537 /* Clear previous contents, add "clear" perma-wall */
11538 c_ptr->feat = FEAT_GRASS;
11539
11540 /* Illuminate and memorize the walls
11541 c_ptr->info |= (CAVE_GLOW);*/
11542 }
11543
11544 /* Perma-walls -- West/East */
11545 for (y = 1; y < MAX_HGT - 1; y++) {
11546 /* West wall */
11547 c_ptr = &zcave[y][1];
11548
11549 /* Clear previous contents, add "clear" perma-wall */
11550 c_ptr->feat = FEAT_GRASS;
11551
11552 /* Illuminate and memorize the walls
11553 c_ptr->info |= (CAVE_GLOW);*/
11554
11555 /* East wall */
11556 c_ptr = &zcave[y][MAX_WID-2];
11557
11558 /* Clear previous contents, add "clear" perma-wall */
11559 c_ptr->feat = FEAT_GRASS;
11560
11561 /* Illuminate and memorize the walls
11562 c_ptr->info |= (CAVE_GLOW);*/
11563 }
11564 /* Hack -- use the "complex" RNG */
11565 Rand_quick = FALSE;
11566
11567 #if 0
11568 process_dungeon_file("t_info.txt", wpos, &ystart, &xstart,
11569 MAX_HGT, MAX_WID, TRUE);
11570 #endif // 0
11571 switch(type) {
11572 case TOWN_BREE:
11573 #ifndef ARCADE_SERVER
11574 process_dungeon_file("t_bree.txt", wpos, &ystart, &xstart,
11575 MAX_HGT, MAX_WID, TRUE);
11576 #else
11577 process_dungeon_file("t_bree_arcade.txt", wpos, &ystart, &xstart,
11578 MAX_HGT, MAX_WID, TRUE);
11579 #endif
11580 break;
11581 case TOWN_GONDOLIN:
11582 process_dungeon_file("t_gondol.txt", wpos, &ystart, &xstart,
11583 MAX_HGT, MAX_WID, TRUE);
11584 break;
11585 case TOWN_MINAS_ANOR:
11586 process_dungeon_file("t_minas.txt", wpos, &ystart, &xstart,
11587 MAX_HGT, MAX_WID, TRUE);
11588 break;
11589 case TOWN_LOTHLORIEN:
11590 process_dungeon_file("t_lorien.txt", wpos, &ystart, &xstart,
11591 MAX_HGT, MAX_WID, TRUE);
11592 break;
11593 case TOWN_KHAZADDUM:
11594 process_dungeon_file("t_khazad.txt", wpos, &ystart, &xstart,
11595 MAX_HGT, MAX_WID, TRUE);
11596 break;
11597 default:
11598 town_gen_hack(wpos);
11599 break;
11600 }
11601 }
11602 else town_gen_hack(wpos);
11603 #else
11604 process_dungeon_file("t_info.txt", wpos, &ystart, &xstart,
11605 MAX_HGT, MAX_WID, TRUE);
11606 #endif
11607
11608 /* apply player-switchability so noone cannot block the store too badly */
11609 for (x = 1; x < MAX_WID - 1; x++) {
11610 for (y = 1; y < MAX_HGT - 1; y++) {
11611 if (zcave[y][x].feat != FEAT_SHOP) continue;
11612 for (x2 = x - 1; x2 <= x + 1; x2++) {
11613 for (y2 = y - 1; y2 <= y + 1; y2++) {
11614 if (!in_bounds(y2, x2)) continue;
11615 zcave[y2][x2].info |= CAVE_SWITCH;
11616 }
11617 }
11618 }
11619 }
11620 }
11621
11622
11623
11624
11625
11626 /*
11627 * Allocate the space needed for a dungeon level
11628 */
11629 void alloc_dungeon_level(struct worldpos *wpos)
11630 {
11631 int i;
11632 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
11633 struct dungeon_type *d_ptr;
11634 cave_type **zcave;
11635
11636 /* Allocate the array of rows */
11637 zcave = C_NEW(MAX_HGT, cave_type*);
11638
11639 /* Allocate each row */
11640 for (i = 0; i < MAX_HGT; i++) {
11641 /* Allocate it */
11642 C_MAKE(zcave[i], MAX_WID, cave_type);
11643 }
11644
11645 if (wpos->wz) {
11646 struct dun_level *dlp;
11647 d_ptr = (wpos->wz > 0 ? w_ptr->tower : w_ptr->dungeon);
11648 dlp = &d_ptr->level[ABS(wpos->wz) - 1];
11649 dlp->cave = zcave;
11650 } else {
11651 w_ptr->cave = zcave;
11652
11653 /* init ambient sfx */
11654 w_ptr->ambient_sfx_dummy = FALSE;
11655 switch (w_ptr->type) { /* ---- ensure consistency with process_ambient_sfx() ---- */
11656 case WILD_RIVER:
11657 case WILD_LAKE:
11658 case WILD_SWAMP:
11659 w_ptr->ambient_sfx_timer = 4 + rand_int(4);
11660 break;
11661 case WILD_ICE:
11662 case WILD_MOUNTAIN:
11663 case WILD_WASTELAND:
11664 w_ptr->ambient_sfx_timer = 30 + rand_int(60);
11665 break;
11666 //case WILD_SHORE:
11667 case WILD_OCEAN:
11668 w_ptr->ambient_sfx_timer = 30 + rand_int(60);
11669 break;
11670 case WILD_FOREST:
11671 case WILD_DENSEFOREST:
11672 if (IS_DAY) w_ptr->ambient_sfx_timer = 10 + rand_int(20);
11673 else w_ptr->ambient_sfx_timer = 20 + rand_int(40);
11674 break;
11675 default: //compromise for wilderness-travel ambient sfx hacking
11676 w_ptr->ambient_sfx_timer = 30 + rand_int(5); //should be > than time required for travelling across 1 wilderness sector
11677 w_ptr->ambient_sfx_dummy = TRUE;
11678 break;
11679 }
11680 }
11681 }
11682
11683 /*
11684 * Deallocate the space needed for a dungeon level
11685 */
11686 void dealloc_dungeon_level(struct worldpos *wpos) {
11687 int i, j;
11688 wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
11689 cave_type **zcave;
11690 object_type *o_ptr;
11691 char o_name[ONAME_LEN];
11692 cave_type *c_ptr;
11693 dun_level *l_ptr = getfloor(wpos);
11694
11695 /* master-level-unstaticing as done in slash command /treset
11696 will already call dealloc_dungeon_level, so -> NULL pointer. */
11697 if (!(zcave = getcave(wpos))) return;
11698
11699 if (l_ptr && (l_ptr->flags2 & LF2_COLLAPSING)) nether_realm_collapsing = FALSE;
11700
11701 /* for obtaining statistical IDDC information: */
11702 //if (in_irondeepdive(wpos)) log_floor_coverage(l_ptr, wpos);
11703
11704 #if DEBUG_LEVEL > 1
11705 s_printf("deallocating %s\n", wpos_format(0, wpos));
11706 #endif
11707
11708 /* Untie links between dungeon stores and real towns */
11709 if (l_ptr && l_ptr->fake_town_num) {
11710 town[l_ptr->fake_town_num - 1].dlev_id = 0;
11711 l_ptr->fake_town_num = 0;
11712 }
11713
11714 /* Delete any monsters/objects on that level */
11715 /* Hack -- don't wipe wilderness monsters/objects
11716 (especially important for preserving items in town inns). */
11717 if (wpos->wz
11718 #ifdef IRONDEEPDIVE_FIXED_TOWNS
11719 #ifdef IRONDEEPDIVE_STATIC_TOWNS
11720 && !is_fixed_irondeepdive_town(wpos, getlevel(wpos))
11721 #endif
11722 #endif
11723 ) {
11724 wipe_m_list_special(wpos);
11725 wipe_o_list_special(wpos);
11726 } else {
11727 #ifdef IRONDEEPDIVE_FIXED_TOWNS
11728 #ifdef IRONDEEPDIVE_STATIC_TOWNS
11729 if (!wpos->wz)
11730 #endif
11731 #endif
11732 save_guildhalls(wpos); /* has to be done here */
11733
11734 /* remove 'deposited' true artefacts from wilderness */
11735 if (cfg.anti_arts_wild) {
11736 for(i = 0; i < o_max; i++){
11737 o_ptr = &o_list[i];
11738 if (o_ptr->k_idx && inarea(&o_ptr->wpos, wpos) &&
11739 undepositable_artifact_p(o_ptr)) {
11740 object_desc(0, o_name, o_ptr, FALSE, 0);
11741 s_printf("WILD_ART_DEALLOC: %s of %s erased at (%d, %d, %d)\n",
11742 o_name, lookup_player_name(o_ptr->owner), o_ptr->wpos.wx, o_ptr->wpos.wy, o_ptr->wpos.wz);
11743 handle_art_d(o_ptr->name1);
11744 WIPE(o_ptr, object_type);
11745 }
11746 }
11747 }
11748 }
11749
11750 for (i = 0; i < MAX_HGT; i++) {
11751 /* Erase all special feature stuff - mikaelh */
11752 for (j = 0; j < MAX_WID; j++) {
11753 c_ptr = &zcave[i][j];
11754 FreeCS(c_ptr);
11755 }
11756
11757 /* Dealloc that row */
11758 C_KILL(zcave[i], MAX_WID, cave_type);
11759 }
11760 /* Deallocate the array of rows */
11761 C_FREE(zcave, MAX_HGT, cave_type *);
11762 if (wpos->wz) {
11763 struct dun_level *dlp;
11764 struct dungeon_type *d_ptr;
11765 d_ptr = (wpos->wz > 0 ? w_ptr->tower : w_ptr->dungeon);
11766 dlp = &d_ptr->level[ABS(wpos->wz) - 1];
11767 dlp->cave = NULL;
11768 }
11769 else w_ptr->cave = NULL;
11770 }
11771
11772 /* added 'force' to delete it even if someone is still inside,
11773 that player gets recalled to surface in that case. - C. Blue */
11774 static void del_dungeon(struct worldpos *wpos, bool tower, bool force) {
11775 struct dungeon_type *d_ptr;
11776 int i, j;
11777 struct worldpos twpos;
11778 wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
11779 player_type *p_ptr;
11780
11781 s_printf("%s at (%d,%d) attempt remove\n", (tower ? "Tower" : "Dungeon"), wpos->wx, wpos->wy);
11782
11783 wpcopy(&twpos, wpos);
11784 d_ptr = (tower ? wild->tower : wild->dungeon);
11785 if (d_ptr->flags2 & DF2_DELETED) {
11786 #ifdef DUNGEON_VISIT_BONUS
11787 #if 0 /* bs ^^' */
11788 for (i = 1; i <= dungeon_id_max; i++) {
11789 if (dungeon_x[i] == wpos->wx &&
11790 dungeon_y[i] == wpos->wy &&
11791 dungeon_tower[i] == tower) {
11792 struct dungeon_type *d2_ptr, *d3_ptr;
11793 s_printf("removing dungeon of index %d, new amount of dungeons is %d.\n", i, dungeon_id_max - 1);
11794 for (; i < dungeon_id_max; i++) {
11795 d2_ptr = (dungeon_tower[i] ?
11796 wild_info[dungeon_y[i]][dungeon_x[i]].tower :
11797 wild_info[dungeon_y[i]][dungeon_x[i]].dungeon);
11798 d3_ptr = (dungeon_tower[i + 1] ?
11799 wild_info[dungeon_y[i + 1]][dungeon_x[i + 1]].tower :
11800 wild_info[dungeon_y[i + 1]][dungeon_x[i + 1]].dungeon);
11801 d2_ptr->id = d3_ptr->id;
11802
11803 dungeon_tower[i] = dungeon_tower[i + 1];
11804 dungeon_x[i] = dungeon_x[i + 1];
11805 dungeon_y[i] = dungeon_y[i + 1];
11806 dungeon_visit_frequency[i] = dungeon_visit_frequency[i + 1];
11807 dungeon_bonus[i] = dungeon_bonus[i + 1];
11808 }
11809 dungeon_id_max--;
11810 break;
11811 }
11812 }
11813 #else
11814 struct dungeon_type *d2_ptr;
11815 s_printf("removing dungeon of index %d, new amount of dungeons is %d.\n", d_ptr->id, dungeon_id_max - 1);
11816 for (i = d_ptr->id + 1; i <= dungeon_id_max; i++) {
11817 d2_ptr = (dungeon_tower[i] ?
11818 wild_info[dungeon_y[i]][dungeon_x[i]].tower :
11819 wild_info[dungeon_y[i]][dungeon_x[i]].dungeon);
11820 d2_ptr->id--;
11821
11822 dungeon_tower[i - 1] = dungeon_tower[i];
11823 dungeon_x[i - 1] = dungeon_x[i];
11824 dungeon_y[i - 1] = dungeon_y[i];
11825 dungeon_visit_frequency[i - 1] = dungeon_visit_frequency[i];
11826 dungeon_bonus[i - 1] = dungeon_bonus[i];
11827 }
11828 dungeon_id_max--;
11829 #endif
11830 #endif
11831 s_printf("Deleted flag\n");
11832 /* deallocate all floors */
11833 for (i = 0; i < d_ptr->maxdepth; i++) {
11834 twpos.wz = (tower ? i + 1 : 0 - (i + 1));
11835 if (d_ptr->level[i].ondepth) { /* someone is still inside! */
11836 if (force) s_printf("Dungeon deletion: ondepth on floor %d - forcing out.\n", i);
11837 else s_printf("Dungeon deletion: ondepth on floor %d - cancelling.\n", i);
11838 if (!force) return;
11839 for (j = 1; j <= NumPlayers; j++) {
11840 p_ptr = Players[j];
11841 if (inarea(&p_ptr->wpos, &twpos)) {
11842 p_ptr->recall_pos.wx = wpos->wx;
11843 p_ptr->recall_pos.wy = wpos->wy;
11844 p_ptr->recall_pos.wz = 0;
11845 if (tower) recall_player(j, "Suddenly the tower crumbles and you are back to the outside world!");
11846 else recall_player(j, "Suddenly the dungeon crumbles and you are back to the outside world!");
11847 }
11848 }
11849 d_ptr->level[i].ondepth = 0;//obsolete?
11850 }
11851 if (d_ptr->level[i].cave) dealloc_dungeon_level(&twpos);
11852 C_KILL(d_ptr->level[i].uniques_killed, MAX_R_IDX, char);
11853 }
11854 /* free the floors all at once */
11855 C_KILL(d_ptr->level, d_ptr->maxdepth, struct dun_level);
11856 /* free the dungeon struct */
11857 if (tower)
11858 KILL(wild->tower, struct dungeon_type);
11859 else
11860 KILL(wild->dungeon, struct dungeon_type);
11861 } else {
11862 s_printf("%s at (%d,%d) restored\n", (tower ? "Tower" : "Dungeon"), wpos->wx, wpos->wy);
11863 /* This really should not happen, but just in case */
11864 /* Re allow access to the non deleted dungeon */
11865 wild->flags |= (tower ? WILD_F_UP : WILD_F_DOWN);
11866 }
11867 s_printf("%s at (%d,%d) removed\n", (tower ? "Tower" : "Dungeon"), wpos->wx, wpos->wy);
11868 #if 0
11869 /* Release the lock */
11870 wild->flags &= ~(tower ? WILD_F_LOCKUP : WILD_F_LOCKDOWN);
11871 #endif
11872 }
11873
11874 void rem_dungeon(struct worldpos *wpos, bool tower) {
11875 struct dungeon_type *d_ptr;
11876 wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
11877
11878 d_ptr = (tower ? wild->tower : wild->dungeon);
11879 if (!d_ptr) return;
11880 #if 0
11881 /* Lock so that dungeon cannot be overwritten while in use */
11882 wild->flags |= (tower ? WILD_F_LOCKUP : WILD_F_LOCKDOWN);
11883 #endif
11884 /* This will prevent players entering the dungeon */
11885 wild->flags &= ~(tower ? WILD_F_UP : WILD_F_DOWN);
11886
11887 d_ptr->flags2 |= DF2_DELETED;
11888 del_dungeon(wpos, tower, TRUE); /* Hopefully first time */
11889 }
11890
11891 /* 'type' refers to t_info[] */
11892 void add_dungeon(struct worldpos *wpos, int baselevel, int maxdep, u32b flags1, u32b flags2, u32b flags3, bool tower, int type, int theme, int quest, int quest_stage) {
11893 #ifdef RPG_SERVER
11894 bool found_town = FALSE;
11895 #endif
11896 int i;
11897 wilderness_type *wild;
11898 struct dungeon_type *d_ptr;
11899 wild = &wild_info[wpos->wy][wpos->wx];
11900
11901 /* Hack -- override the specification */
11902 if (type) tower = (d_info[type].flags1 & DF1_TOWER) ? TRUE : FALSE;
11903 #if 0
11904 if (wild->flags & (tower ? WILD_F_LOCKUP : WILD_F_LOCKDOWN)) {
11905 s_printf("add_dungeon failed due to WILD_F_LOCK%s.\n", tower ? "UP" : "DOWN");
11906 return;
11907 }
11908 #endif
11909 #ifdef DUNGEON_VISIT_BONUS
11910 /* new paranoid debug code: cancel adding of dungeon if wild_info _seems_ to already have a dungeon in place. */
11911 if (wild->flags & (tower ? WILD_F_UP : WILD_F_DOWN)) {
11912 s_printf("DEBUG: add_dungeon failed (%d,%d,%s) due to already existing wild_f_ flag.\n",
11913 wpos->wx, wpos->wy, tower ? "tower" : "dungeon");
11914 return;
11915 }
11916 if (tower ? wild->tower : wild->dungeon) {
11917 s_printf("DEBUG: add_dungeon failed (%d,%d,%s) due to already existing wild-> structure.\n",
11918 wpos->wx, wpos->wy, tower ? "tower" : "dungeon");
11919 return;
11920 }
11921 #endif
11922
11923 wild->flags |= (tower ? WILD_F_UP : WILD_F_DOWN); /* no checking */
11924 if (tower)
11925 MAKE(wild->tower, struct dungeon_type);
11926 else
11927 MAKE(wild->dungeon, struct dungeon_type);
11928 d_ptr = (tower ? wild->tower : wild->dungeon);
11929
11930 d_ptr->type = type;
11931 d_ptr->theme = theme;
11932 d_ptr->quest = quest;
11933 d_ptr->quest_stage = quest_stage;
11934
11935 #ifdef DUNGEON_VISIT_BONUS
11936 d_ptr->id = ++dungeon_id_max;
11937 dungeon_x[dungeon_id_max] = wpos->wx;
11938 dungeon_y[dungeon_id_max] = wpos->wy;
11939 dungeon_tower[dungeon_id_max] = tower;
11940 /* mostly affects highlander dungeon: */
11941 set_dungeon_bonus(dungeon_id_max, TRUE);
11942 s_printf("adding dungeon of index %d.\n", dungeon_id_max);
11943 #endif
11944
11945 if (type) {
11946 /* XXX: flags1, flags2 can be affected if specified so? */
11947 d_ptr->baselevel = d_info[type].mindepth;
11948 d_ptr->maxdepth = d_info[type].maxdepth - d_ptr->baselevel + 1;
11949 d_ptr->flags1 = d_info[type].flags1 | flags1;
11950 d_ptr->flags2 = d_info[type].flags2 | flags2 | DF2_RANDOM;
11951 d_ptr->flags3 = d_info[type].flags3 | flags3;
11952 } else {
11953 d_ptr->baselevel = baselevel;
11954 d_ptr->flags1 = flags1;
11955 d_ptr->flags2 = flags2;
11956 d_ptr->flags3 = flags3;
11957 d_ptr->maxdepth = maxdep;
11958 }
11959 if (wpos->wx == WPOS_IRONDEEPDIVE_X && wpos->wy == WPOS_IRONDEEPDIVE_Y &&
11960 (tower ? (WPOS_IRONDEEPDIVE_Z > 0) : (WPOS_IRONDEEPDIVE_Z < 0)))
11961 d_ptr->flags3 |= DF3_NO_DUNGEON_BONUS | DF3_EXP_20 | DF3_LUCK_PROG_IDDC;
11962
11963 #ifdef RPG_SERVER /* Make towers/dungeons harder - C. Blue */
11964 /* If this dungeon was originally intended to be 'real' ironman,
11965 don't make it EASIER by this! (by applying either IRONFIX or IRONRND flags) */
11966 if (!(flags2 & DF2_IRON)) {
11967 for (i = 0; i < numtowns; i++)
11968 if (town[i].x == wpos->wx && town[i].y == wpos->wy) {
11969 found_town = TRUE;
11970 /* Bree has special rules: */
11971 if (in_bree(wpos)) {
11972 /* exempt training tower, since it's empty anyway
11973 (ie monster/item spawn is prevented) and we
11974 need it for "arena monster challenge" event */
11975 if (tower) continue;
11976
11977 d_ptr->flags2 |= DF2_IRON;
11978 } else {
11979 /* any other town.. */
11980 d_ptr->flags2 |= DF2_IRON | DF2_IRONFIX2;
11981 }
11982 }
11983 if (!found_town) {
11984 /* hack - exempt the Shores of Valinor! */
11985 if (d_ptr->baselevel != 200) {
11986 d_ptr->flags2 |= DF2_IRON | DF2_IRONRND1;
11987 // d_ptr->flags1 |= DF1_NO_UP;
11988 }
11989 }
11990 }
11991 #endif
11992
11993 #if 0 /* unused - mikaelh */
11994 for (i = 0; i < 10; i++) {
11995 d_ptr->r_char[i] = '\0';
11996 d_ptr->nr_char[i] = '\0';
11997 }
11998 if (race != (char*)NULL)
11999 strcpy(d_ptr->r_char, race);
12000 if (exclude != (char*)NULL)
12001 strcpy(d_ptr->nr_char, exclude);
12002 #endif
12003
12004 C_MAKE(d_ptr->level, d_ptr->maxdepth, struct dun_level);
12005 for (i = 0; i < d_ptr->maxdepth; i++) {
12006 C_MAKE(d_ptr->level[i].uniques_killed, MAX_R_IDX, char);
12007 }
12008
12009 s_printf("add_dungeon completed (type %d, %s).\n", type, tower ? "tower" : "dungeon");
12010 }
12011
12012 /*
12013 * Generates a random dungeon level -RAK-
12014 *
12015 * Hack -- regenerate any "overflow" levels
12016 *
12017 * Hack -- allow auto-scumming via a gameplay option.
12018 */
12019
12020 void generate_cave(struct worldpos *wpos, player_type *p_ptr) {
12021 int i, num;
12022 cave_type **zcave;
12023 struct worldpos twpos;
12024
12025 wpcopy(&twpos, wpos);
12026 zcave = getcave(wpos);
12027
12028 server_dungeon = FALSE;
12029
12030 /* Generate */
12031 for (num = 0; TRUE; num++) {
12032 bool okay = TRUE;
12033 cptr why = NULL;
12034
12035 /* Added 'restore from backup' here, maybe it helps vs crash */
12036 wpcopy(wpos, &twpos);
12037 zcave = getcave(wpos);
12038
12039 /* Hack -- Reset heaps */
12040 /*o_max = 1;
12041 m_max = 1;*/
12042 #if 1 /*cave should have already been wiped from 'alloc_dungon_level' */
12043 /* Start with a blank cave */
12044 for (i = 0; i < MAX_HGT; i++) {
12045 /* CRASHES occured here :( */
12046
12047 /* Wipe a whole row at a time */
12048 C_WIPE(zcave[i], MAX_WID, cave_type);
12049 }
12050 #endif
12051
12052 /* Mega-Hack -- no player yet */
12053 /*px = py = 0;*/
12054
12055
12056 /* Mega-Hack -- no panel yet */
12057 /*panel_row_min = 0;
12058 panel_row_max = 0;
12059 panel_col_min = 0;
12060 panel_col_max = 0;*/
12061
12062 /* Reset the monster generation level */
12063 monster_level = getlevel(wpos);
12064
12065 /* Reset the object generation level */
12066 object_level = getlevel(wpos);
12067
12068 /* Build the town */
12069 if (istown(wpos)) {
12070 /* Small town */
12071 /*cur_hgt = SCREEN_HGT;
12072 cur_wid = SCREEN_WID;*/
12073
12074 /* Determine number of panels */
12075 /*max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
12076 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;*/
12077
12078 /* Assume illegal panel */
12079 /*panel_row = max_panel_rows;
12080 panel_col = max_panel_cols;*/
12081
12082 {
12083 int retval = -1, type;
12084 for(i = 0; i < numtowns; i++) {
12085 if(town[i].x == wpos->wx && town[i].y == wpos->wy) {
12086 retval = i;
12087 break;
12088 }
12089 }
12090 if (retval < 0) {
12091 s_printf("add_dungeon failed in generate_cave!! %s\n", wpos_format(0, wpos));
12092 return; /* This should never.. */
12093 }
12094 type = town[retval].type;
12095 for (i = 0; i < 2; i++) {
12096 if (town_profile[type].dungeons[i])
12097 add_dungeon(wpos, 0, 0, 0x0, 0x0, 0x0, FALSE, town_profile[type].dungeons[i], 0, 0, 0);
12098 }
12099 }
12100 /* Make a town */
12101 town_gen(wpos);
12102 setup_objects();
12103 setup_monsters();
12104 }
12105
12106 /* Build wilderness */
12107 else if (!wpos->wz) {
12108 wilderness_gen(wpos);
12109 }
12110
12111 /* Build a real level */
12112 else {
12113 process_hooks(HOOK_GEN_LEVEL, "d", wpos);
12114 /* Big dungeon */
12115 /*cur_hgt = MAX_HGT;
12116 cur_wid = MAX_WID;*/
12117
12118 /* Determine number of panels */
12119 /*max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
12120 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;*/
12121
12122 /* Assume illegal panel */
12123 /*panel_row = max_panel_rows;
12124 panel_col = max_panel_cols;*/
12125
12126 /* Set restrictions on placed objects */
12127 place_object_restrictor = RESF_NOHIDSM; /* no high DSMs that could be wiz-lite-looted */
12128 /* Make a dungeon */
12129 cave_gen(wpos, p_ptr);
12130 /* Lift restrictions on placed objects again */
12131 place_object_restrictor = RESF_NONE;
12132 }
12133
12134 /* Prevent object over-flow */
12135 if (o_max >= MAX_O_IDX) {
12136 /* Message */
12137 why = "too many objects";
12138
12139 /* Message */
12140 okay = FALSE;
12141 }
12142
12143 /* Prevent monster over-flow */
12144 if (m_max >= MAX_M_IDX) {
12145 /* Message */
12146 why = "too many monsters";
12147
12148 /* Message */
12149 okay = FALSE;
12150 }
12151
12152 /* Accept */
12153 if (okay) break;
12154
12155
12156 /* Message */
12157 if (why) s_printf("Generation restarted (%s)\n", why);
12158
12159 /* Wipe the objects */
12160 if (wpos->wz) wipe_o_list_special(wpos);
12161 else wipe_o_list(wpos);//no reason not to protect house items here, is there?
12162
12163 /* Wipe the monsters */
12164 wipe_m_list(wpos);
12165
12166 /* Compact some objects, if necessary */
12167 if (o_max >= MAX_O_IDX * 3 / 4)
12168 compact_objects(32, FALSE);
12169
12170 /* Compact some monsters, if necessary */
12171 if (m_max >= MAX_M_IDX * 3 / 4)
12172 compact_monsters(32, FALSE);
12173 }
12174
12175 /* Change features depending on season,
12176 and change lighting depending on daytime */
12177 wpos_apply_season_daytime(wpos, zcave);
12178
12179 /* Dungeon level ready */
12180 server_dungeon = TRUE;
12181 }
12182
12183 /* (Can ONLY be used on surface worldmap sectors.)
12184 Rebuilds a level, without re-adding dungeons, because this
12185 function assumes that the level has already been generated.
12186 Used for season change. - C. Blue */
12187 void regenerate_cave(struct worldpos *wpos) {
12188 cave_type **zcave;
12189
12190 int i;
12191 player_type *p_ptr;
12192
12193 /* world surface only, to keep it simple */
12194 if (wpos->wz) return;
12195 /* paranoia */
12196 if (!(zcave = getcave(wpos))) return;
12197
12198 #if 0 /* kills all house walls and doors on allocated town area levels! */
12199 /* Build the town */
12200 if (istown(wpos)) {
12201 /* Make a town */
12202 town_gen(wpos);
12203 }
12204 /* Build wilderness */
12205 else if (!wpos->wz) {
12206 wilderness_gen(wpos);
12207 }
12208 #else /* what a pain */
12209 /* mad hack:
12210 remove players from level, regenerate it completely, bring players back */
12211 for (i = 1; i <= NumPlayers; i++) {
12212 p_ptr = Players[i];
12213 if (inarea(&p_ptr->wpos, wpos)) p_ptr->wpos.wz = 9999;
12214 }
12215
12216 dealloc_dungeon_level(wpos);
12217 alloc_dungeon_level(wpos);
12218 generate_cave(wpos, NULL);
12219
12220 for (i = 1; i <= NumPlayers; i++) {
12221 p_ptr = Players[i];
12222 if (p_ptr->wpos.wz == 9999) p_ptr->wpos.wz = 0;
12223 }
12224
12225 /* regrab zcave, _rarely_ crash otherwise:
12226 happened in actual cases when the 2nd season switch occurred after
12227 server startup in the fashion summer->autumn->winter. Haven't tested
12228 it much more. */
12229 if (!(zcave = getcave(wpos))) {
12230 s_printf("REGENERATE_CAVE FAILED TO REGRAB ZCAVE!\n");
12231 return;
12232 }
12233 #endif
12234
12235 /* Change features depending on season,
12236 and change lighting depending on daytime */
12237 wpos_apply_season_daytime(wpos, zcave);
12238 }
12239
12240 /* determine whether a feature should be a tree or a
12241 bush, depending on the season - C. Blue */
12242 int get_seasonal_tree(void) {
12243 switch (season) {
12244 case SEASON_SPRING: return (magik(70) ? FEAT_TREE : FEAT_BUSH); break;
12245 case SEASON_SUMMER: return (magik(90) ? FEAT_TREE : FEAT_BUSH); break;
12246 case SEASON_AUTUMN: return (magik(90) ? FEAT_TREE : FEAT_BUSH); break;
12247 case SEASON_WINTER: return (magik(95) ? FEAT_TREE : FEAT_BUSH); break;
12248 }
12249 return (FEAT_HIGH_MOUNTAIN); /* just to clear compiler warning */
12250 }
12251
12252 #ifdef ENABLE_DOOR_CHECK
12253 /* Check that a door that is about to be placed makes actually at least slight sense.
12254 Mostly disallow doors that have no 'wall with hinges' next to them,
12255 ie doors hanging in the air freely.
12256 Current disadvantage: Enabling this will prevent 'quad-doors' which may look
12257 cool as *big* entrance to a room. - C. Blue */
12258 #define DOOR_FLOOR(feat) \
12259 (((feat < FEAT_DOOR_HEAD || feat > FEAT_DOOR_TAIL) \
12260 && feat != FEAT_SECRET) && \
12261 (f_info[feat].flags1 & FF1_FLOOR))
12262 #define DOOR_WALL(feat) \
12263 (((feat < FEAT_DOOR_HEAD || feat > FEAT_DOOR_TAIL) \
12264 && feat != FEAT_SECRET) && \
12265 !(f_info[feat].flags1 & FF1_FLOOR))
12266 //#define DOOR_SEPARATING
12267 static bool door_makes_no_sense(cave_type **zcave, int x, int y) {
12268 int tmp, feat;
12269 bool walls = FALSE; //disallow duplicate door that 'hangs in the air'
12270 #ifdef DOOR_SEPARATING
12271 int ok_step = 0;
12272 int adjacent_floors = 0; //allow an exception via 'collapsed passage' excuse ;)
12273 #endif
12274
12275
12276 /* Check that this door makes any sense */
12277 feat = zcave[y + ddy_cyc[0]][x + ddx_cyc[0]].feat;
12278
12279 #ifdef DOOR_SEPARATING
12280 /* check 'sustaining-wall' condition */
12281 if (DOOR_WALL(feat)) walls = TRUE;
12282
12283 /* check the other stuff */
12284 if (DOOR_FLOOR(feat)) {
12285 ok_step = 1;
12286 adjacent_floors = 1;
12287 }
12288 #else
12289 /* check 'sustaining-wall' condition */
12290 if (DOOR_WALL(feat)) return FALSE;
12291 #endif
12292
12293
12294 for (tmp = 1; tmp < 8; tmp++) {
12295 feat = zcave[y + ddy_cyc[tmp]][x + ddx_cyc[tmp]].feat;
12296
12297 #ifdef DOOR_SEPARATING /* we can assume it has withered or been destroyed, so the door is useless now but still there! */
12298 /* check 'sustaining-wall' condition */
12299 if (!walls && DOOR_WALL(feat)) walls = TRUE;
12300
12301 /* optional: check 'collapsed passage' exception */
12302 if (DOOR_FLOOR(feat)) adjacent_floors++;
12303
12304 /* check that the door actually separates any passages */
12305 switch (ok_step) {
12306 case 0:
12307 if (DOOR_FLOOR(feat)) ok_step = 2;
12308 break;
12309 case 2:
12310 if (!DOOR_FLOOR(feat)) ok_step = 4;
12311 break;
12312 case 4:
12313 if (DOOR_FLOOR(feat)) return FALSE;
12314 break;
12315 case 1:
12316 if (!DOOR_FLOOR(feat)) ok_step = 3;
12317 break;
12318 case 3:
12319 if (DOOR_FLOOR(feat)) ok_step = 5;
12320 break;
12321 case 5:
12322 if (!DOOR_FLOOR(feat)) return FALSE;
12323 break;
12324 }
12325 #else
12326 /* check 'sustaining-wall' condition */
12327 if (!walls && DOOR_WALL(feat)) return FALSE;
12328 #endif
12329 }
12330
12331 #ifdef DOOR_SEPARATING
12332 /* condition of 'sustaining wall'? */
12333 if (!walls) return TRUE;
12334
12335
12336 /* exception for 'collapsed passages'? */
12337 if (adjacent_floors <= 3) return FALSE;
12338 #endif
12339
12340 #if 0 /* debug */
12341 zcave[y][x].feat = FEAT_SEALED_DOOR;
12342 s_printf("TRUE\n");
12343 #endif
12344
12345 return TRUE;
12346 }
12347 #endif
12348