1 /* File: generate.c */
2
3 /* Purpose: Dungeon generation */
4
5 /*
6 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
7 *
8 * This software may be copied and distributed for educational, research, and
9 * not for profit purposes provided that this copyright and statement are
10 * included in all such copies.
11 */
12
13 #include "mangband.h"
14
15
16 /*
17 * Note that Level generation is *not* an important bottleneck,
18 * though it can be annoyingly slow on older machines... Thus
19 * we emphasize "simplicity" and "correctness" over "speed".
20 *
21 * This entire file is only needed for generating levels.
22 * This may allow smart compilers to only load it when needed.
23 *
24 * Consider the "v_info.txt" file for vault generation.
25 *
26 * In this file, we use the "special" granite and perma-wall sub-types,
27 * where "basic" is normal, "inner" is inside a room, "outer" is the
28 * outer wall of a room, and "solid" is the outer wall of the dungeon
29 * or any walls that may not be pierced by corridors. Thus the only
30 * wall type that may be pierced by a corridor is the "outer granite"
31 * type. The "basic granite" type yields the "actual" corridors.
32 *
33 * Note that we use the special "solid" granite wall type to prevent
34 * multiple corridors from piercing a wall in two adjacent locations,
35 * which would be messy, and we use the special "outer" granite wall
36 * to indicate which walls "surround" rooms, and may thus be "pierced"
37 * by corridors entering or leaving the room.
38 *
39 * Note that a tunnel which attempts to leave a room near the "edge"
40 * of the dungeon in a direction toward that edge will cause "silly"
41 * wall piercings, but will have no permanently incorrect effects,
42 * as long as the tunnel can *eventually* exit from another side.
43 * And note that the wall may not come back into the room by the
44 * hole it left through, so it must bend to the left or right and
45 * then optionally re-enter the room (at least 2 grids away). This
46 * is not a problem since every room that is large enough to block
47 * the passage of tunnels is also large enough to allow the tunnel
48 * to pierce the room itself several times.
49 *
50 * Note that no two corridors may enter a room through adjacent grids,
51 * they must either share an entryway or else use entryways at least
52 * two grids apart. This prevents "large" (or "silly") doorways.
53 *
54 * To create rooms in the dungeon, we first divide the dungeon up
55 * into "blocks" of 11x11 grids each, and require that all rooms
56 * occupy a rectangular group of blocks. As long as each room type
57 * reserves a sufficient number of blocks, the room building routines
58 * will not need to check bounds. Note that most of the normal rooms
59 * actually only use 23x11 grids, and so reserve 33x11 grids.
60 *
61 * Note that the use of 11x11 blocks (instead of the old 33x11 blocks)
62 * allows more variability in the horizontal placement of rooms, and
63 * at the same time has the disadvantage that some rooms (two thirds
64 * of the normal rooms) may be "split" by panel boundaries. This can
65 * induce a situation where a player is in a room and part of the room
66 * is off the screen. It may be annoying enough to go back to 33x11
67 * blocks to prevent this visual situation.
68 *
69 * Note that the dungeon generation routines are much different (2.7.5)
70 * and perhaps "DUN_ROOMS" should be less than 50.
71 *
72 * XXX XXX XXX Note that it is possible to create a room which is only
73 * connected to itself, because the "tunnel generation" code allows a
74 * tunnel to leave a room, wander around, and then re-enter the room.
75 *
76 * XXX XXX XXX Note that it is possible to create a set of rooms which
77 * are only connected to other rooms in that set, since there is nothing
78 * explicit in the code to prevent this from happening. But this is less
79 * likely than the "isolated room" problem, because each room attempts to
80 * connect to another room, in a giant cycle, thus requiring at least two
81 * bizarre occurances to create an isolated section of the dungeon.
82 *
83 * Note that (2.7.9) monster pits have been split into monster "nests"
84 * and monster "pits". The "nests" have a collection of monsters of a
85 * given type strewn randomly around the room (jelly, animal, or undead),
86 * while the "pits" have a collection of monsters of a given type placed
87 * around the room in an organized manner (orc, troll, giant, dragon, or
88 * demon). Note that both "nests" and "pits" are now "level dependant",
89 * and both make 16 "expensive" calls to the "get_mon_num()" function.
90 *
91 * Note that the cave grid flags changed in a rather drastic manner
92 * for Angband 2.8.0 (and 2.7.9+), in particular, dungeon terrain
93 * features, such as doors and stairs and traps and rubble and walls,
94 * are all handled as a set of 64 possible "terrain features", and
95 * not as "fake" objects (440-479) as in pre-2.8.0 versions.
96 *
97 * The 64 new "dungeon features" will also be used for "visual display"
98 * but we must be careful not to allow, for example, the user to display
99 * hidden traps in a different way from floors, or secret doors in a way
100 * different from granite walls, or even permanent granite in a different
101 * way from granite. XXX XXX XXX
102 */
103
104
105 /*
106 * Dungeon generation values
107 */
108 #define DUN_ROOMS 50 /* Number of rooms to attempt */
109 #define DUN_UNUSUAL 200 /* Level/chance of unusual room */
110 #define DUN_DEST 15 /* 1/chance of having a destroyed level */
111
112 /*
113 * Dungeon tunnel generation values
114 */
115 #define DUN_TUN_RND 10 /* Chance of random direction */
116 #define DUN_TUN_CHG 30 /* Chance of changing direction */
117 #define DUN_TUN_CON 15 /* Chance of extra tunneling */
118 #define DUN_TUN_PEN 25 /* Chance of doors at room entrances */
119 #define DUN_TUN_JCT 90 /* Chance of doors at tunnel junctions */
120
121 /*
122 * Dungeon streamer generation values
123 */
124 #define DUN_STR_DEN 5 /* Density of streamers */
125 #define DUN_STR_RNG 2 /* Width of streamers */
126 #define DUN_STR_MAG 3 /* Number of magma streamers */
127 #define DUN_STR_MC 90 /* 1/chance of treasure per magma */
128 #define DUN_STR_QUA 2 /* Number of quartz streamers */
129 #define DUN_STR_QC 40 /* 1/chance of treasure per quartz */
130
131 /*
132 * Dungeon treausre allocation values
133 */
134 #define DUN_AMT_ROOM 9 /* Amount of objects for rooms */
135 #define DUN_AMT_ITEM 3 /* Amount of objects for rooms/corridors */
136 #define DUN_AMT_GOLD 3 /* Amount of treasure for rooms/corridors */
137
138 /*
139 * Hack -- Dungeon allocation "places"
140 */
141 #define ALLOC_SET_CORR 1 /* Hallway */
142 #define ALLOC_SET_ROOM 2 /* Room */
143 #define ALLOC_SET_BOTH 3 /* Anywhere */
144
145 /*
146 * Hack -- Dungeon allocation "types"
147 */
148 #define ALLOC_TYP_RUBBLE 1 /* Rubble */
149 #define ALLOC_TYP_TRAP 3 /* Trap */
150 #define ALLOC_TYP_GOLD 4 /* Gold */
151 #define ALLOC_TYP_OBJECT 5 /* Object */
152
153
154
155 /*
156 * The "size" of a "generation block" in grids
157 */
158 #define BLOCK_HGT 11
159 #define BLOCK_WID 11
160
161 /*
162 * Maximum numbers of rooms along each axis (currently 6x6)
163 */
164 #define MAX_ROOMS_ROW (MAX_HGT / BLOCK_HGT)
165 #define MAX_ROOMS_COL (MAX_WID / BLOCK_WID)
166
167
168 /*
169 * Bounds on some arrays used in the "dun_data" structure.
170 * These bounds are checked, though usually this is a formality.
171 */
172 #define CENT_MAX 100
173 #define DOOR_MAX 400
174 #define WALL_MAX 1000
175 #define TUNN_MAX 1800
176
177
178 /*
179 * Maximal number of room types
180 */
181 #define ROOM_MAX 9
182
183
184
185 /*
186 * Simple structure to hold a map location
187 */
188
189 typedef struct coord coord;
190
191 struct coord
192 {
193 byte y;
194 byte x;
195 };
196
197
198 /*
199 * Room type information
200 */
201
202 typedef struct room_data room_data;
203
204 struct room_data
205 {
206 /* Required size in blocks */
207 s16b dy1, dy2, dx1, dx2;
208
209 /* Hack -- minimum level */
210 s16b level;
211 };
212
213
214 /*
215 * Structure to hold all "dungeon generation" data
216 */
217
218 typedef struct dun_data dun_data;
219
220 struct dun_data
221 {
222 /* Array of centers of rooms */
223 int cent_n;
224 coord cent[CENT_MAX];
225
226 /* Array of possible door locations */
227 int door_n;
228 coord door[DOOR_MAX];
229
230 /* Array of wall piercing locations */
231 int wall_n;
232 coord wall[WALL_MAX];
233
234 /* Array of tunnel grids */
235 int tunn_n;
236 coord tunn[TUNN_MAX];
237
238 /* Number of blocks along each axis */
239 int row_rooms;
240 int col_rooms;
241
242 /* Array of which blocks are used */
243 bool room_map[MAX_ROOMS_ROW][MAX_ROOMS_COL];
244
245 /* Hack -- there is a pit/nest on this level */
246 bool crowded;
247 };
248
249
250 /*
251 * Dungeon generation data -- see "cave_gen()"
252 */
253 static dun_data *dun;
254
255
256 /*
257 * Array of room types (assumes 11x11 blocks)
258 */
259 static room_data room[ROOM_MAX] =
260 {
261 { 0, 0, 0, 0, 0 }, /* 0 = Nothing */
262 { 0, 0, -1, 1, 1 }, /* 1 = Simple (33x11) */
263 { 0, 0, -1, 1, 1 }, /* 2 = Overlapping (33x11) */
264 { 0, 0, -1, 1, 3 }, /* 3 = Crossed (33x11) */
265 { 0, 0, -1, 1, 3 }, /* 4 = Large (33x11) */
266 { 0, 0, -1, 1, 5 }, /* 5 = Monster nest (33x11) */
267 { 0, 0, -1, 1, 5 }, /* 6 = Monster pit (33x11) */
268 { 0, 1, -1, 1, 5 }, /* 7 = Lesser vault (33x22) */
269 { -1, 2, -2, 3, 10 } /* 8 = Greater vault (66x44) */
270 };
271
272
273
274 /*
275 * Always picks a correct direction
276 */
correct_dir(int * rdir,int * cdir,int y1,int x1,int y2,int x2)277 static void correct_dir(int *rdir, int *cdir, int y1, int x1, int y2, int x2)
278 {
279 /* Extract vertical and horizontal directions */
280 *rdir = (y1 == y2) ? 0 : (y1 < y2) ? 1 : -1;
281 *cdir = (x1 == x2) ? 0 : (x1 < x2) ? 1 : -1;
282
283 /* Never move diagonally */
284 if (*rdir && *cdir)
285 {
286 if (randint0(100) < 50)
287 {
288 *rdir = 0;
289 }
290 else
291 {
292 *cdir = 0;
293 }
294 }
295 }
296
297
298 /*
299 * Pick a random direction
300 */
rand_dir(int * rdir,int * cdir)301 static void rand_dir(int *rdir, int *cdir)
302 {
303 /* Pick a random direction */
304 int i = randint0(4);
305
306 /* Extract the dy/dx components */
307 *rdir = ddy_ddd[i];
308 *cdir = ddx_ddd[i];
309 }
310
311
312 /*
313 * Returns random co-ordinates for player starts
314 */
new_player_spot(int Depth)315 static void new_player_spot(int Depth)
316 {
317 int y, x;
318
319 /* Place the player */
320 while (1)
321 {
322 /* Pick a legal spot */
323 y = rand_range(1, MAX_HGT - 2);
324 x = rand_range(1, MAX_WID - 2);
325
326 /* Must be a "naked" floor grid */
327 if (!cave_naked_bold(Depth, y, x)) continue;
328
329 /* Refuse to start on anti-teleport grids */
330 if (cave[Depth][y][x].info & CAVE_ICKY) continue;
331
332 /* Done */
333 break;
334 }
335
336 /* Save the new grid */
337 level_rand_y[Depth] = y;
338 level_rand_x[Depth] = x;
339 }
340
341
342
343 /*
344 * Count the number of walls adjacent to the given grid.
345 *
346 * Note -- Assumes "in_bounds(y, x)"
347 *
348 * We count only granite walls and permanent walls.
349 */
next_to_walls(int Depth,int y,int x)350 static int next_to_walls(int Depth, int y, int x)
351 {
352 int k = 0;
353
354 if (cave[Depth][y+1][x].feat >= FEAT_WALL_EXTRA) k++;
355 if (cave[Depth][y-1][x].feat >= FEAT_WALL_EXTRA) k++;
356 if (cave[Depth][y][x+1].feat >= FEAT_WALL_EXTRA) k++;
357 if (cave[Depth][y][x-1].feat >= FEAT_WALL_EXTRA) k++;
358
359 return (k);
360 }
361
362
363
364 /*
365 * Convert existing terrain type to rubble
366 */
place_rubble_aux(int Depth,int y,int x)367 static void place_rubble_aux(int Depth, int y, int x)
368 {
369 cave_type *c_ptr = &cave[Depth][y][x];
370
371 /* Create rubble */
372 c_ptr->feat = FEAT_RUBBLE;
373 }
374
375 /*
376 * Find secondary spot for rubble
377 *
378 * Note: unlike doors, first element might generate anywhere,
379 * leaving the possibility of useless rubble. That is intenteded
380 */
place_rubble(int Depth,int y,int x)381 static void place_rubble(int Depth, int y, int x)
382 {
383 int i,j;
384
385 place_rubble_aux(Depth, y, x);
386
387 for (j = -1; j < 2; j++) {
388 for (i = -1; i < 2; i++) {
389 /* Skip corners */
390 if (abs(i+j) != 1) continue;
391
392 /* Check Bounds */
393 if (!in_bounds(Depth, y+j, x+i)) continue;
394
395 /* Totally useless AKA Require a certain number of adjacent walls */
396 if (next_to_walls(Depth, y+j, x+i) < 2) continue;
397
398 /* Require wall grid */
399 if (cave_naked_bold(Depth, y+j, x+i)) continue;
400
401 /* Require usefullness -- Not nessecary, since first element sucks anyway */
402 /* if (next_to_walls(Depth, y+j*-1, x+i*-1) < 1) continue; */
403
404 /* Require an empty grid on the opposite side */
405 if (!cave_naked_bold(Depth, y+j*-1, x+i*-1)) continue;
406
407 /* Place on the opposite side */
408 place_rubble_aux(Depth, y+j*-1, x+i*-1);
409
410 /* Done */
411 return;
412 }
413 }
414 /* None */
415 }
416
417 /*
418 * Convert existing terrain type to "up stairs"
419 */
place_up_stairs(int Depth,int y,int x)420 static void place_up_stairs(int Depth, int y, int x)
421 {
422 cave_type *c_ptr = &cave[Depth][y][x];
423
424 /* Create up stairs */
425 c_ptr->feat = FEAT_LESS;
426 }
427
428
429 /*
430 * Convert existing terrain type to "down stairs"
431 */
place_down_stairs(int Depth,int y,int x)432 static void place_down_stairs(int Depth, int y, int x)
433 {
434 cave_type *c_ptr = &cave[Depth][y][x];
435
436 /* Create down stairs */
437 c_ptr->feat = FEAT_MORE;
438 }
439
440
441
442
443
444 /*
445 * Place an up/down staircase at given location
446 */
place_random_stairs(int Depth,int y,int x)447 static void place_random_stairs(int Depth, int y, int x)
448 {
449 /* Paranoia */
450 if (!cave_clean_bold(Depth, y, x)) return;
451
452 /* Choose a staircase */
453 if (!Depth)
454 {
455 place_down_stairs(Depth, y, x);
456 }
457 else if (is_quest(Depth) || (Depth >= MAX_DEPTH-1))
458 {
459 place_up_stairs(Depth, y, x);
460 }
461 else if (randint0(100) < 50)
462 {
463 place_down_stairs(Depth, y, x);
464 }
465 else
466 {
467 place_up_stairs(Depth, y, x);
468 }
469 }
470
471
472 /*
473 * Place a locked door at the given location
474 */
place_locked_door(int Depth,int y,int x)475 static void place_locked_door(int Depth, int y, int x)
476 {
477 cave_type *c_ptr = &cave[Depth][y][x];
478
479 /* Create locked door */
480 c_ptr->feat = FEAT_DOOR_HEAD + (byte_hack)randint1(7);
481 }
482
483
484 /*
485 * Place a secret door at the given location
486 */
place_secret_door(int Depth,int y,int x)487 static void place_secret_door(int Depth, int y, int x)
488 {
489 cave_type *c_ptr = &cave[Depth][y][x];
490
491 /* Create secret door */
492 c_ptr->feat = FEAT_SECRET;
493 }
494
495
496 /*
497 * Place a random type of closed door at the given location.
498 */
place_closed_door(int Depth,int y,int x)499 void place_closed_door(int Depth, int y, int x)
500 {
501 int tmp;
502
503 /* Choose an object */
504 tmp = randint0(400);
505
506 /* Closed doors (300/400) */
507 if (tmp < 300)
508 {
509 /* Create closed door */
510 cave_set_feat(Depth, y, x, FEAT_DOOR_HEAD + 0x00);
511 }
512
513 /* Locked doors (99/400) */
514 else if (tmp < 399)
515 {
516 /* Create locked door */
517 cave_set_feat(Depth, y, x, FEAT_DOOR_HEAD + randint1(7));
518 }
519
520 /* Stuck doors (1/400) */
521 else
522 {
523 /* Create jammed door */
524 cave_set_feat(Depth, y, x, FEAT_DOOR_HEAD + 0x08 + randint0(8));
525 }
526 }
527
528
529 /*
530 * Place a random type of door at the given location
531 */
place_random_door(int Depth,int y,int x)532 static void place_random_door(int Depth, int y, int x)
533 {
534 int tmp;
535
536 cave_type *c_ptr = &cave[Depth][y][x];
537
538 /* Choose an object */
539 tmp = randint0(1000);
540
541 /* Open doors (300/1000) */
542 if (tmp < 300)
543 {
544 /* Create open door */
545 c_ptr->feat = FEAT_OPEN;
546 }
547
548 /* Broken doors (100/1000) */
549 else if (tmp < 400)
550 {
551 /* Create broken door */
552 c_ptr->feat = FEAT_BROKEN;
553 }
554
555 /* Secret doors (200/1000) */
556 else if (tmp < 600)
557 {
558 /* Create secret door */
559 c_ptr->feat = FEAT_SECRET;
560 }
561
562 /* Closed doors (300/1000) */
563 else if (tmp < 900)
564 {
565 /* Create closed door */
566 c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
567 }
568
569 /* Locked doors (99/1000) */
570 else if (tmp < 999)
571 {
572 /* Create locked door */
573 c_ptr->feat = FEAT_DOOR_HEAD + (byte_hack)randint1(7);
574 }
575
576 /* Stuck doors (1/1000) */
577 else
578 {
579 /* Create jammed door */
580 c_ptr->feat = FEAT_DOOR_HEAD + 0x08 + (byte_hack)randint0(8);
581 }
582 }
583
584
585
586 /*
587 * Places some staircases near walls
588 */
alloc_stairs(int Depth,int feat,int num,int walls)589 static void alloc_stairs(int Depth, int feat, int num, int walls)
590 {
591 int y, x, i, j, flag;
592
593 cave_type *c_ptr;
594
595
596 /* Place "num" stairs */
597 for (i = 0; i < num; i++)
598 {
599 /* Place some stairs */
600 for (flag = FALSE; !flag; )
601 {
602 /* Try several times, then decrease "walls" */
603 for (j = 0; !flag && j <= 3000; j++)
604 {
605 /* Pick a random grid */
606 y = randint0(Depth ? MAX_HGT : MAX_HGT);
607 x = randint0(Depth ? MAX_WID : MAX_WID);
608
609 /* Require "naked" floor grid */
610 if (!cave_naked_bold(Depth, y, x)) continue;
611
612 /* Require a certain number of adjacent walls */
613 if (next_to_walls(Depth, y, x) < walls) continue;
614
615 /* Access the grid */
616 c_ptr = &cave[Depth][y][x];
617
618 /* Town -- must go down */
619 if (!Depth)
620 {
621 /* Clear previous contents, add down stairs */
622 c_ptr->feat = FEAT_MORE;
623 }
624
625 /* Quest -- must go up */
626 else if (is_quest(Depth) || (Depth >= MAX_DEPTH-1))
627 {
628 /* Clear previous contents, add up stairs */
629 c_ptr->feat = FEAT_LESS;
630
631 /* Set this to be the starting location for people going down */
632 level_down_y[Depth] = y;
633 level_down_x[Depth] = x;
634 }
635
636 /* Requested type */
637 else
638 {
639 /* Clear previous contents, add stairs */
640 c_ptr->feat = feat;
641
642 if (feat == FEAT_LESS)
643 {
644 /* Set this to be the starting location for people going down */
645 level_down_y[Depth] = y;
646 level_down_x[Depth] = x;
647 }
648 if (feat == FEAT_MORE)
649 {
650 /* Set this to be the starting location for people going up */
651 level_up_y[Depth] = y;
652 level_up_x[Depth] = x;
653 }
654 }
655
656 /* All done */
657 flag = TRUE;
658 }
659
660 /* Require fewer walls */
661 if (walls) walls--;
662 }
663 }
664 }
665
666
667
668
669 /*
670 * Allocates some objects (using "place" and "type")
671 */
alloc_object(int Depth,int set,int typ,int num)672 static void alloc_object(int Depth, int set, int typ, int num)
673 {
674 int y, x, k;
675
676 /* Place some objects */
677 for (k = 0; k < num; k++)
678 {
679 /* Pick a "legal" spot */
680 while (TRUE)
681 {
682 bool room;
683
684 /* Location */
685 y = randint0(Depth ? MAX_HGT : MAX_HGT);
686 x = randint0(Depth ? MAX_WID : MAX_WID);
687
688 /* Require "naked" floor grid */
689 if (!cave_naked_bold(Depth, y, x)) continue;
690
691 /* Check for "room" */
692 room = (cave[Depth][y][x].info & CAVE_ROOM) ? TRUE : FALSE;
693
694 /* Require corridor? */
695 if ((set == ALLOC_SET_CORR) && room) continue;
696
697 /* Require room? */
698 if ((set == ALLOC_SET_ROOM) && !room) continue;
699
700 /* Accept it */
701 break;
702 }
703
704 /* Place something */
705 switch (typ)
706 {
707 case ALLOC_TYP_RUBBLE:
708 {
709 place_rubble(Depth, y, x);
710 break;
711 }
712
713 case ALLOC_TYP_TRAP:
714 {
715 place_trap(Depth, y, x);
716 break;
717 }
718
719 case ALLOC_TYP_GOLD:
720 {
721 place_gold(Depth, y, x);
722 break;
723 }
724
725 case ALLOC_TYP_OBJECT:
726 {
727 place_object(Depth, y, x, FALSE, FALSE, 0);
728 break;
729 }
730 }
731 }
732 }
733
734
735
736 /*
737 * Places "streamers" of rock through dungeon
738 *
739 * Note that their are actually six different terrain features used
740 * to represent streamers. Three each of magma and quartz, one for
741 * basic vein, one with hidden gold, and one with known gold. The
742 * hidden gold types are currently unused.
743 */
build_streamer(int Depth,int feat,int chance)744 static void build_streamer(int Depth, int feat, int chance)
745 {
746 int i, tx, ty;
747 int y, x, dir;
748
749 cave_type *c_ptr;
750
751 /* Hack -- Choose starting point */
752 y = rand_spread((Depth ? MAX_HGT : MAX_HGT) / 2, 10);
753 x = rand_spread((Depth ? MAX_WID : MAX_WID) / 2, 15);
754
755 /* Choose a random compass direction */
756 dir = ddd[randint0(8)];
757
758 /* Place streamer into dungeon */
759 while (TRUE)
760 {
761 /* One grid per density */
762 for (i = 0; i < DUN_STR_DEN; i++)
763 {
764 int d = DUN_STR_RNG;
765
766 /* Pick a nearby grid */
767 while (1)
768 {
769 ty = rand_spread(y, d);
770 tx = rand_spread(x, d);
771 if (!in_bounds2(Depth, ty, tx)) continue;
772 break;
773 }
774
775 /* Access the grid */
776 c_ptr = &cave[Depth][ty][tx];
777
778 /* Only convert "granite" walls */
779 if (c_ptr->feat < FEAT_WALL_EXTRA) continue;
780 if (c_ptr->feat > FEAT_WALL_SOLID) continue;
781
782 /* Clear previous contents, add proper vein type */
783 c_ptr->feat = feat;
784
785 /* Hack -- Add some (known) treasure */
786 if (randint0(chance) == 0) c_ptr->feat += 0x04;
787 }
788
789 /* Advance the streamer */
790 y += ddy[dir];
791 x += ddx[dir];
792
793 /* Quit before leaving the dungeon */
794 if (!in_bounds(Depth, y, x)) break;
795 }
796 }
797
798
799 /*
800 * Build a destroyed level
801 */
destroy_level(int Depth)802 static void destroy_level(int Depth)
803 {
804 int y1, x1, y, x, k, t, n;
805
806 cave_type *c_ptr;
807
808 /* Note destroyed levels */
809 /*if (cheat_room) msg_print("Destroyed Level");*/
810
811 /* Drop a few epi-centers (usually about two) */
812 for (n = 0; n < randint1(5); n++)
813 {
814 /* Pick an epi-center */
815 y1 = rand_range(5, (Depth ? MAX_HGT : MAX_HGT) - 6);
816 x1 = rand_range(5, (Depth ? MAX_WID : MAX_WID) - 6);
817
818 /* Big area of affect */
819 for (y = (y1 - 15); y <= (y1 + 15); y++)
820 {
821 for (x = (x1 - 15); x <= (x1 + 15); x++)
822 {
823 /* Skip illegal grids */
824 if (!in_bounds(Depth, y, x)) continue;
825
826 /* Extract the distance */
827 k = distance(y1, x1, y, x);
828
829 /* Stay in the circle of death */
830 if (k >= 16) continue;
831
832 /* Delete the monster (if any) */
833 delete_monster(Depth, y, x);
834
835 /* Destroy valid grids */
836 if (cave_valid_bold(Depth, y, x))
837 {
838 /* Delete the object (if any) */
839 delete_object(Depth, y, x);
840
841 /* Access the grid */
842 c_ptr = &cave[Depth][y][x];
843
844 /* Wall (or floor) type */
845 t = randint0(200);
846
847 /* Granite */
848 if (t < 20)
849 {
850 /* Create granite wall */
851 c_ptr->feat = FEAT_WALL_EXTRA;
852 }
853
854 /* Quartz */
855 else if (t < 70)
856 {
857 /* Create quartz vein */
858 c_ptr->feat = FEAT_QUARTZ;
859 }
860
861 /* Magma */
862 else if (t < 100)
863 {
864 /* Create magma vein */
865 c_ptr->feat = FEAT_MAGMA;
866 }
867
868 /* Floor */
869 else
870 {
871 /* Create floor */
872 c_ptr->feat = FEAT_FLOOR;
873 }
874
875 /* No longer part of a room or vault */
876 c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
877
878 /* No longer illuminated or known */
879 c_ptr->info &= ~CAVE_GLOW;
880 }
881 }
882 }
883 }
884 }
885
886
887
888 /*
889 * Create up to "num" objects near the given coordinates
890 * Only really called by some of the "vault" routines.
891 */
vault_objects(int Depth,int y,int x,int num)892 static void vault_objects(int Depth, int y, int x, int num)
893 {
894 int i, j, k;
895
896 /* Attempt to place 'num' objects */
897 for (; num > 0; --num)
898 {
899 /* Try up to 11 spots looking for empty space */
900 for (i = 0; i < 11; ++i)
901 {
902 /* Pick a random location */
903 while (1)
904 {
905 j = rand_spread(y, 2);
906 k = rand_spread(x, 3);
907 if (!in_bounds(Depth, j, k)) continue;
908 break;
909 }
910
911 /* Require "clean" floor space */
912 if (!cave_clean_bold(Depth, j, k)) continue;
913
914 /* Place an item */
915 if (randint0(100) < 75)
916 {
917 place_object(Depth, j, k, FALSE, FALSE, ORIGIN_SPECIAL);
918 }
919
920 /* Place gold */
921 else
922 {
923 place_gold(Depth, j, k);
924 }
925
926 /* Placement accomplished */
927 break;
928 }
929 }
930 }
931
place_wall(int Depth,int y1,int y2,int x1,int x2,int wall_type)932 void place_wall(int Depth, int y1, int y2, int x1, int x2, int wall_type)
933 {
934 int y, x;
935
936 cave_type *c_ptr;
937
938 /* Place the outer walls */
939 for (y = y1 - 1; y <= y2 + 1; y++)
940 {
941 c_ptr = &cave[Depth][y][x1-1];
942 c_ptr->feat = wall_type;
943 c_ptr = &cave[Depth][y][x2+1];
944 c_ptr->feat = wall_type;
945 }
946 for (x = x1 - 1; x <= x2 + 1; x++)
947 {
948 c_ptr = &cave[Depth][y1-1][x];
949 c_ptr->feat = wall_type;
950 c_ptr = &cave[Depth][y2+1][x];
951 c_ptr->feat = wall_type;
952 }
953 }
954
place_double_wall(int Depth,int y1,int y2,int x1,int x2)955 void place_double_wall(int Depth, int y1, int y2, int x1, int x2)
956 {
957 place_wall(Depth, y1, y2, x1, x2, FEAT_WALL_OUTER);
958 place_wall(Depth, y1 + 2, y2 - 2, x1 + 2, x2 - 2, FEAT_WALL_INNER);
959 }
960
place_floor(int Depth,bool light,int y1,int y2,int x1,int x2)961 void place_floor(int Depth, bool light, int y1, int y2, int x1, int x2)
962 {
963 cave_type *c_ptr;
964
965 int y, x;
966
967 /* Place a full floor under the room */
968 for (y = y1 - 1; y <= y2 + 1; y++)
969 {
970 for (x = x1 - 1; x <= x2 + 1; x++)
971 {
972 c_ptr = &cave[Depth][y][x];
973 c_ptr->feat = FEAT_FLOOR;
974 c_ptr->info |= CAVE_ROOM;
975 if (light) c_ptr->info |= CAVE_GLOW;
976 }
977 }
978 }
979
place_double_room(int Depth,bool light,int y1,int y2,int x1,int x2)980 void place_double_room(int Depth, bool light, int y1, int y2, int x1, int x2)
981 {
982 place_floor(Depth, light, y1, y2, x1, x2);
983
984 place_double_wall(Depth, y1, y2, x1, x2);
985 }
986
place_cross_room(int Depth,bool light,int y1a,int y2a,int x1a,int x2a,int y1b,int y2b,int x1b,int x2b)987 void place_cross_room(int Depth, bool light, int y1a, int y2a, int x1a, int x2a, int y1b, int y2b, int x1b, int x2b)
988 {
989 int y, x;
990
991 cave_type *c_ptr;
992
993 /* Place a full floor for room "a" */
994 place_floor(Depth, light, y1a, y2a, x1a, x2a);
995
996 /* Place a full floor for room "b" */
997 place_floor(Depth, light, y1b, y2b, x1b, x2b);
998
999
1000 /* Place the walls around room "a" */
1001 place_wall(Depth, y1a, y2a, x1a, x2a, FEAT_WALL_OUTER);
1002
1003 /* Place the walls around room "b" */
1004 place_wall(Depth, y1b, y2b, x1b, x2b, FEAT_WALL_OUTER);
1005
1006
1007 /* Replace the floor for room "a" */
1008 for (y = y1a; y <= y2a; y++)
1009 {
1010 for (x = x1a; x <= x2a; x++)
1011 {
1012 c_ptr = &cave[Depth][y][x];
1013 c_ptr->feat = FEAT_FLOOR;
1014 }
1015 }
1016
1017 /* Replace the floor for room "b" */
1018 for (y = y1b; y <= y2b; y++)
1019 {
1020 for (x = x1b; x <= x2b; x++)
1021 {
1022 c_ptr = &cave[Depth][y][x];
1023 c_ptr->feat = FEAT_FLOOR;
1024 }
1025 }
1026 }
1027
1028 /*
1029 * Place a trap with a given displacement of point
1030 */
vault_trap_aux(int Depth,int y,int x,int yd,int xd)1031 static void vault_trap_aux(int Depth, int y, int x, int yd, int xd)
1032 {
1033 int count, y1, x1;
1034
1035 /* Place traps */
1036 for (count = 0; count <= 5; count++)
1037 {
1038 /* Get a location */
1039 while (1)
1040 {
1041 y1 = rand_spread(y, yd);
1042 x1 = rand_spread(x, xd);
1043 if (!in_bounds(Depth, y1, x1)) continue;
1044 break;
1045 }
1046
1047 /* Require "naked" floor grids */
1048 if (!cave_naked_bold(Depth, y1, x1)) continue;
1049
1050 /* Place the trap */
1051 place_trap(Depth, y1, x1);
1052
1053 /* Done */
1054 break;
1055 }
1056 }
1057
1058
1059 /*
1060 * Place some traps with a given displacement of given location
1061 */
vault_traps(int Depth,int y,int x,int yd,int xd,int num)1062 static void vault_traps(int Depth, int y, int x, int yd, int xd, int num)
1063 {
1064 int i;
1065
1066 for (i = 0; i < num; i++)
1067 {
1068 vault_trap_aux(Depth, y, x, yd, xd);
1069 }
1070 }
1071
1072
1073 /*
1074 * Hack -- Place some sleeping monsters near the given location
1075 */
vault_monsters(int Depth,int y1,int x1,int num)1076 static void vault_monsters(int Depth, int y1, int x1, int num)
1077 {
1078 int k, i, y, x;
1079
1080 /* Try to summon "num" monsters "near" the given location */
1081 for (k = 0; k < num; k++)
1082 {
1083 /* Try nine locations */
1084 for (i = 0; i < 9; i++)
1085 {
1086 int d = 1;
1087
1088 /* Pick a nearby location */
1089 scatter(Depth, &y, &x, y1, x1, d, 0);
1090
1091 /* Require "empty" floor grids */
1092 if (!cave_empty_bold(Depth, y, x)) continue;
1093
1094 /* Place the monster (allow groups) */
1095 monster_level = Depth + 2;
1096 (void)place_monster(Depth, y, x, TRUE, TRUE);
1097 monster_level = Depth;
1098 }
1099 }
1100 }
1101
1102
1103
1104
1105 /*
1106 * Room building routines.
1107 *
1108 * Six basic room types:
1109 * 1 -- normal
1110 * 2 -- overlapping
1111 * 3 -- cross shaped
1112 * 4 -- large room with features
1113 * 5 -- monster nests
1114 * 6 -- monster pits
1115 * 7 -- simple vaults
1116 * 8 -- greater vaults
1117 */
1118
1119
1120 /*
1121 * Type 1 -- normal rectangular rooms
1122 */
build_type1(int Depth,int yval,int xval)1123 static void build_type1(int Depth, int yval, int xval)
1124 {
1125 int y, x, y2, x2;
1126 int y1, x1;
1127
1128 bool light;
1129
1130 cave_type *c_ptr;
1131
1132
1133 /* Choose lite or dark */
1134 light = (Depth <= randint1(25));
1135
1136
1137 /* Pick a room size */
1138 y1 = yval - randint1(4);
1139 y2 = yval + randint1(3);
1140 x1 = xval - randint1(11);
1141 x2 = xval + randint1(11);
1142
1143 place_floor(Depth, light, y1, y2, x1, x2);
1144
1145 place_wall(Depth, y1, y2, x1, x2, FEAT_WALL_OUTER);
1146
1147 /* Hack -- Occasional pillar room */
1148 if (randint0(20) == 0)
1149 {
1150 for (y = y1; y <= y2; y += 2)
1151 {
1152 for (x = x1; x <= x2; x += 2)
1153 {
1154 c_ptr = &cave[Depth][y][x];
1155 c_ptr->feat = FEAT_WALL_INNER;
1156 }
1157 }
1158 }
1159
1160 /* Hack -- Occasional ragged-edge room */
1161 else if (randint0(50) == 0)
1162 {
1163 for (y = y1 + 2; y <= y2 - 2; y += 2)
1164 {
1165 c_ptr = &cave[Depth][y][x1];
1166 c_ptr->feat = FEAT_WALL_INNER;
1167 c_ptr = &cave[Depth][y][x2];
1168 c_ptr->feat = FEAT_WALL_INNER;
1169 }
1170 for (x = x1 + 2; x <= x2 - 2; x += 2)
1171 {
1172 c_ptr = &cave[Depth][y1][x];
1173 c_ptr->feat = FEAT_WALL_INNER;
1174 c_ptr = &cave[Depth][y2][x];
1175 c_ptr->feat = FEAT_WALL_INNER;
1176 }
1177 }
1178 }
1179
1180
1181 /*
1182 * Type 2 -- Overlapping rectangular rooms
1183 */
build_type2(int Depth,int yval,int xval)1184 static void build_type2(int Depth, int yval, int xval)
1185 {
1186 int y1a, x1a, y2a, x2a;
1187 int y1b, x1b, y2b, x2b;
1188
1189 bool light;
1190
1191
1192 /* Choose lite or dark */
1193 light = (Depth <= randint1(25));
1194
1195
1196 /* Determine extents of the first room */
1197 y1a = yval - randint1(4);
1198 y2a = yval + randint1(3);
1199 x1a = xval - randint1(11);
1200 x2a = xval + randint1(10);
1201
1202 /* Determine extents of the second room */
1203 y1b = yval - randint1(3);
1204 y2b = yval + randint1(4);
1205 x1b = xval - randint1(10);
1206 x2b = xval + randint1(11);
1207
1208
1209 place_cross_room(Depth, light, y1a, y2a, x1a, x2a, y1b, y2b, x1b, x2b);
1210 }
1211
1212
1213
1214 /*
1215 * Type 3 -- Cross shaped rooms
1216 *
1217 * Builds a room at a row, column coordinate
1218 *
1219 * Room "a" runs north/south, and Room "b" runs east/east
1220 * So the "central pillar" runs from x1a,y1b to x2a,y2b.
1221 *
1222 * Note that currently, the "center" is always 3x3, but I think that
1223 * the code below will work (with "bounds checking") for 5x5, or even
1224 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
1225 */
build_type3(int Depth,int yval,int xval)1226 static void build_type3(int Depth, int yval, int xval)
1227 {
1228 int y, x, dy, dx, wy, wx;
1229 int y1a, x1a, y2a, x2a;
1230 int y1b, x1b, y2b, x2b;
1231
1232 bool light;
1233
1234 cave_type *c_ptr;
1235
1236
1237
1238 /* Choose lite or dark */
1239 light = (Depth <= randint1(25));
1240
1241
1242 /* For now, always 3x3 */
1243 wx = wy = 1;
1244
1245 /* Pick max vertical size (at most 4) */
1246 dy = rand_range(3, 4);
1247
1248 /* Pick max horizontal size (at most 15) */
1249 dx = rand_range(3, 11);
1250
1251
1252 /* Determine extents of the north/south room */
1253 y1a = yval - dy;
1254 y2a = yval + dy;
1255 x1a = xval - wx;
1256 x2a = xval + wx;
1257
1258 /* Determine extents of the east/west room */
1259 y1b = yval - wy;
1260 y2b = yval + wy;
1261 x1b = xval - dx;
1262 x2b = xval + dx;
1263
1264
1265 place_cross_room(Depth, light, y1a, y2a, x1a, x2a, y1b, y2b, x1b, x2b);
1266
1267
1268 /* Special features (3/4) */
1269 switch (randint0(4))
1270 {
1271 /* Large solid middle pillar */
1272 case 1:
1273 for (y = y1b; y <= y2b; y++)
1274 {
1275 for (x = x1a; x <= x2a; x++)
1276 {
1277 c_ptr = &cave[Depth][y][x];
1278 c_ptr->feat = FEAT_WALL_INNER;
1279 }
1280 }
1281 break;
1282
1283 /* Inner treasure vault */
1284 case 2:
1285
1286 /* Build the vault */
1287 for (y = y1b; y <= y2b; y++)
1288 {
1289 c_ptr = &cave[Depth][y][x1a];
1290 c_ptr->feat = FEAT_WALL_INNER;
1291 c_ptr = &cave[Depth][y][x2a];
1292 c_ptr->feat = FEAT_WALL_INNER;
1293 }
1294 for (x = x1a; x <= x2a; x++)
1295 {
1296 c_ptr = &cave[Depth][y1b][x];
1297 c_ptr->feat = FEAT_WALL_INNER;
1298 c_ptr = &cave[Depth][y2b][x];
1299 c_ptr->feat = FEAT_WALL_INNER;
1300 }
1301
1302 /* Place a secret door on the inner room */
1303 switch (randint0(4))
1304 {
1305 case 0: place_secret_door(Depth, y1b, xval); break;
1306 case 1: place_secret_door(Depth, y2b, xval); break;
1307 case 2: place_secret_door(Depth, yval, x1a); break;
1308 case 3: place_secret_door(Depth, yval, x2a); break;
1309 }
1310
1311 /* Place a treasure in the vault */
1312 place_object(Depth, yval, xval, FALSE, FALSE, ORIGIN_SPECIAL);
1313
1314 /* Let's guard the treasure well */
1315 vault_monsters(Depth, yval, xval, randint0(2) + 3);
1316
1317 /* Traps naturally */
1318 vault_traps(Depth, yval, xval, 4, 4, randint0(3) + 2);
1319
1320 break;
1321
1322
1323 /* Something else */
1324 case 3:
1325
1326 /* Occasionally pinch the center shut */
1327 if (randint0(3) == 0)
1328 {
1329 /* Pinch the east/west sides */
1330 for (y = y1b; y <= y2b; y++)
1331 {
1332 if (y == yval) continue;
1333 c_ptr = &cave[Depth][y][x1a - 1];
1334 c_ptr->feat = FEAT_WALL_INNER;
1335 c_ptr = &cave[Depth][y][x2a + 1];
1336 c_ptr->feat = FEAT_WALL_INNER;
1337 }
1338
1339 /* Pinch the north/south sides */
1340 for (x = x1a; x <= x2a; x++)
1341 {
1342 if (x == xval) continue;
1343 c_ptr = &cave[Depth][y1b - 1][x];
1344 c_ptr->feat = FEAT_WALL_INNER;
1345 c_ptr = &cave[Depth][y2b + 1][x];
1346 c_ptr->feat = FEAT_WALL_INNER;
1347 }
1348
1349 /* Sometimes shut using secret doors */
1350 if (randint0(3) == 0)
1351 {
1352 place_secret_door(Depth, yval, x1a - 1);
1353 place_secret_door(Depth, yval, x2a + 1);
1354 place_secret_door(Depth, y1b - 1, xval);
1355 place_secret_door(Depth, y2b + 1, xval);
1356 }
1357 }
1358
1359 /* Occasionally put a "plus" in the center */
1360 else if (randint0(3) == 0)
1361 {
1362 c_ptr = &cave[Depth][yval][xval];
1363 c_ptr->feat = FEAT_WALL_INNER;
1364 c_ptr = &cave[Depth][y1b][xval];
1365 c_ptr->feat = FEAT_WALL_INNER;
1366 c_ptr = &cave[Depth][y2b][xval];
1367 c_ptr->feat = FEAT_WALL_INNER;
1368 c_ptr = &cave[Depth][yval][x1a];
1369 c_ptr->feat = FEAT_WALL_INNER;
1370 c_ptr = &cave[Depth][yval][x2a];
1371 c_ptr->feat = FEAT_WALL_INNER;
1372 }
1373
1374 /* Occasionally put a pillar in the center */
1375 else if (randint0(3) == 0)
1376 {
1377 c_ptr = &cave[Depth][yval][xval];
1378 c_ptr->feat = FEAT_WALL_INNER;
1379 }
1380
1381 break;
1382 }
1383 }
1384
1385
1386 /*
1387 * Type 4 -- Large room with inner features
1388 *
1389 * Possible sub-types:
1390 * 1 - Just an inner room with one door
1391 * 2 - An inner room within an inner room
1392 * 3 - An inner room with pillar(s)
1393 * 4 - Inner room has a maze
1394 * 5 - A set of four inner rooms
1395 */
build_type4(int Depth,int yval,int xval)1396 static void build_type4(int Depth, int yval, int xval)
1397 {
1398 int y, x, y1, x1;
1399 int y2, x2, tmp;
1400
1401 bool light;
1402
1403 cave_type *c_ptr;
1404
1405 /* Large room */
1406 y1 = yval - 4;
1407 y2 = yval + 4;
1408 x1 = xval - 11;
1409 x2 = xval + 11;
1410
1411 /* Choose lite or dark */
1412 light = (Depth <= randint1(25));
1413
1414 place_double_room(Depth, light, y1, y2, x1, x2);
1415
1416 /* The inner room */
1417 y1 = y1 + 2;
1418 y2 = y2 - 2;
1419 x1 = x1 + 2;
1420 x2 = x2 - 2;
1421
1422 /* Inner room variations */
1423 switch (randint1(5))
1424 {
1425 /* Just an inner room with a monster */
1426 case 1:
1427
1428 /* Place a secret door */
1429 switch (randint1(4))
1430 {
1431 case 1: place_secret_door(Depth, y1 - 1, xval); break;
1432 case 2: place_secret_door(Depth, y2 + 1, xval); break;
1433 case 3: place_secret_door(Depth, yval, x1 - 1); break;
1434 case 4: place_secret_door(Depth, yval, x2 + 1); break;
1435 }
1436
1437 /* Place a monster in the room */
1438 vault_monsters(Depth, yval, xval, 1);
1439
1440 break;
1441
1442
1443 /* Treasure Vault (with a door) */
1444 case 2:
1445
1446 /* Place a secret door */
1447 switch (randint1(4))
1448 {
1449 case 1: place_secret_door(Depth, y1 - 1, xval); break;
1450 case 2: place_secret_door(Depth, y2 + 1, xval); break;
1451 case 3: place_secret_door(Depth, yval, x1 - 1); break;
1452 case 4: place_secret_door(Depth, yval, x2 + 1); break;
1453 }
1454
1455 /* Place another inner room */
1456 for (y = yval - 1; y <= yval + 1; y++)
1457 {
1458 for (x = xval - 1; x <= xval + 1; x++)
1459 {
1460 if ((x == xval) && (y == yval)) continue;
1461 c_ptr = &cave[Depth][y][x];
1462 c_ptr->feat = FEAT_WALL_INNER;
1463 }
1464 }
1465
1466 /* Place a locked door on the inner room */
1467 switch (randint1(4))
1468 {
1469 case 1: place_locked_door(Depth, yval - 1, xval); break;
1470 case 2: place_locked_door(Depth, yval + 1, xval); break;
1471 case 3: place_locked_door(Depth, yval, xval - 1); break;
1472 case 4: place_locked_door(Depth, yval, xval + 1); break;
1473 }
1474
1475 /* Monsters to guard the "treasure" */
1476 vault_monsters(Depth, yval, xval, randint1(3) + 2);
1477
1478 /* Object (80%) */
1479 if (randint0(100) < 80)
1480 {
1481 place_object(Depth, yval, xval, FALSE, FALSE, ORIGIN_SPECIAL);
1482 }
1483
1484 /* Stairs (20%) */
1485 else
1486 {
1487 place_random_stairs(Depth, yval, xval);
1488 }
1489
1490 /* Traps to protect the treasure */
1491 vault_traps(Depth, yval, xval, 4, 10, 2 + randint1(3));
1492
1493 break;
1494
1495
1496 /* Inner pillar(s). */
1497 case 3:
1498
1499 /* Place a secret door */
1500 switch (randint1(4))
1501 {
1502 case 1: place_secret_door(Depth, y1 - 1, xval); break;
1503 case 2: place_secret_door(Depth, y2 + 1, xval); break;
1504 case 3: place_secret_door(Depth, yval, x1 - 1); break;
1505 case 4: place_secret_door(Depth, yval, x2 + 1); break;
1506 }
1507
1508 /* Large Inner Pillar */
1509 for (y = yval - 1; y <= yval + 1; y++)
1510 {
1511 for (x = xval - 1; x <= xval + 1; x++)
1512 {
1513 c_ptr = &cave[Depth][y][x];
1514 c_ptr->feat = FEAT_WALL_INNER;
1515 }
1516 }
1517
1518 /* Occasionally, two more Large Inner Pillars */
1519 if (randint0(2) == 0)
1520 {
1521 tmp = randint1(2);
1522 for (y = yval - 1; y <= yval + 1; y++)
1523 {
1524 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
1525 {
1526 c_ptr = &cave[Depth][y][x];
1527 c_ptr->feat = FEAT_WALL_INNER;
1528 }
1529 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
1530 {
1531 c_ptr = &cave[Depth][y][x];
1532 c_ptr->feat = FEAT_WALL_INNER;
1533 }
1534 }
1535 }
1536
1537 /* Occasionally, some Inner rooms */
1538 if (randint0(3) == 0)
1539 {
1540 /* Long horizontal walls */
1541 for (x = xval - 5; x <= xval + 5; x++)
1542 {
1543 c_ptr = &cave[Depth][yval-1][x];
1544 c_ptr->feat = FEAT_WALL_INNER;
1545 c_ptr = &cave[Depth][yval+1][x];
1546 c_ptr->feat = FEAT_WALL_INNER;
1547 }
1548
1549 /* Close off the left/right edges */
1550 c_ptr = &cave[Depth][yval][xval-5];
1551 c_ptr->feat = FEAT_WALL_INNER;
1552 c_ptr = &cave[Depth][yval][xval+5];
1553 c_ptr->feat = FEAT_WALL_INNER;
1554
1555 /* Secret doors (random top/bottom) */
1556 place_secret_door(Depth, yval - 3 + (randint1(2) * 2), xval - 3);
1557 place_secret_door(Depth, yval - 3 + (randint1(2) * 2), xval + 3);
1558
1559 /* Monsters */
1560 vault_monsters(Depth, yval, xval - 2, randint1(2));
1561 vault_monsters(Depth, yval, xval + 2, randint1(2));
1562
1563 /* Objects */
1564 if (randint0(3) == 0) place_object(Depth, yval, xval - 2, FALSE, FALSE, ORIGIN_SPECIAL);
1565 if (randint0(3) == 0) place_object(Depth, yval, xval + 2, FALSE, FALSE, ORIGIN_SPECIAL);
1566 }
1567
1568 break;
1569
1570
1571 /* Maze inside. */
1572 case 4:
1573
1574 /* Place a secret door */
1575 switch (randint1(4))
1576 {
1577 case 1: place_secret_door(Depth, y1 - 1, xval); break;
1578 case 2: place_secret_door(Depth, y2 + 1, xval); break;
1579 case 3: place_secret_door(Depth, yval, x1 - 1); break;
1580 case 4: place_secret_door(Depth, yval, x2 + 1); break;
1581 }
1582
1583 /* Maze (really a checkerboard) */
1584 for (y = y1; y <= y2; y++)
1585 {
1586 for (x = x1; x <= x2; x++)
1587 {
1588 if (0x1 & (x + y))
1589 {
1590 c_ptr = &cave[Depth][y][x];
1591 c_ptr->feat = FEAT_WALL_INNER;
1592 }
1593 }
1594 }
1595
1596 /* Monsters just love mazes. */
1597 vault_monsters(Depth, yval, xval - 5, randint1(3));
1598 vault_monsters(Depth, yval, xval + 5, randint1(3));
1599
1600 /* Traps make them entertaining. */
1601 vault_traps(Depth, yval, xval - 3, 2, 8, randint1(3));
1602 vault_traps(Depth, yval, xval + 3, 2, 8, randint1(3));
1603
1604 /* Mazes should have some treasure too. */
1605 vault_objects(Depth, yval, xval, 3);
1606
1607 break;
1608
1609
1610 /* Four small rooms. */
1611 case 5:
1612
1613 /* Inner "cross" */
1614 for (y = y1; y <= y2; y++)
1615 {
1616 c_ptr = &cave[Depth][y][xval];
1617 c_ptr->feat = FEAT_WALL_INNER;
1618 }
1619 for (x = x1; x <= x2; x++)
1620 {
1621 c_ptr = &cave[Depth][yval][x];
1622 c_ptr->feat = FEAT_WALL_INNER;
1623 }
1624
1625 /* Doors into the rooms */
1626 if (randint0(100) < 50)
1627 {
1628 int i = randint1(10);
1629 place_secret_door(Depth, y1 - 1, xval - i);
1630 place_secret_door(Depth, y1 - 1, xval + i);
1631 place_secret_door(Depth, y2 + 1, xval - i);
1632 place_secret_door(Depth, y2 + 1, xval + i);
1633 }
1634 else
1635 {
1636 int i = randint1(3);
1637 place_secret_door(Depth, yval + i, x1 - 1);
1638 place_secret_door(Depth, yval - i, x1 - 1);
1639 place_secret_door(Depth, yval + i, x2 + 1);
1640 place_secret_door(Depth, yval - i, x2 + 1);
1641 }
1642
1643 /* Treasure, centered at the center of the cross */
1644 vault_objects(Depth, yval, xval, 2 + randint1(2));
1645
1646 /* Gotta have some monsters. */
1647 vault_monsters(Depth, yval + 1, xval - 4, randint1(4));
1648 vault_monsters(Depth, yval + 1, xval + 4, randint1(4));
1649 vault_monsters(Depth, yval - 1, xval - 4, randint1(4));
1650 vault_monsters(Depth, yval - 1, xval + 4, randint1(4));
1651
1652 break;
1653 }
1654 }
1655
1656
1657 /*
1658 * The following functions are used to determine if the given monster
1659 * is appropriate for inclusion in a monster nest or monster pit or
1660 * the given type.
1661 *
1662 * None of the pits/nests are allowed to include "unique" monsters,
1663 * or monsters which can "multiply".
1664 *
1665 * Some of the pits/nests are asked to avoid monsters which can blink
1666 * away or which are invisible. This is probably a hack.
1667 *
1668 * The old method made direct use of monster "names", which is bad.
1669 *
1670 * Note the use of Angband 2.7.9 monster race pictures in various places.
1671 */
1672
1673
1674 /*
1675 * Helper function for "monster nest (jelly)"
1676 */
vault_aux_jelly(int r_idx)1677 static bool vault_aux_jelly(int r_idx)
1678 {
1679 monster_race *r_ptr = &r_info[r_idx];
1680
1681 /* Decline unique monsters */
1682 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1683
1684 /* Require icky thing, jelly, mold, or mushroom */
1685 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1686
1687 /* Okay */
1688 return (TRUE);
1689 }
1690
1691
1692 /*
1693 * Helper function for "monster nest (animal)"
1694 */
vault_aux_animal(int r_idx)1695 static bool vault_aux_animal(int r_idx)
1696 {
1697 monster_race *r_ptr = &r_info[r_idx];
1698
1699 /* Decline unique monsters */
1700 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1701
1702 /* Require "animal" flag */
1703 if (!(r_ptr->flags3 & RF3_ANIMAL)) return (FALSE);
1704
1705 /* Okay */
1706 return (TRUE);
1707 }
1708
1709
1710 /*
1711 * Helper function for "monster nest (undead)"
1712 */
vault_aux_undead(int r_idx)1713 static bool vault_aux_undead(int r_idx)
1714 {
1715 monster_race *r_ptr = &r_info[r_idx];
1716
1717 /* Decline unique monsters */
1718 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1719
1720 /* Require Undead */
1721 if (!(r_ptr->flags3 & RF3_UNDEAD)) return (FALSE);
1722
1723 /* Okay */
1724 return (TRUE);
1725 }
1726
1727
1728 /*
1729 * Helper function for "monster pit (orc)"
1730 */
vault_aux_orc(int r_idx)1731 static bool vault_aux_orc(int r_idx)
1732 {
1733 monster_race *r_ptr = &r_info[r_idx];
1734
1735 /* Decline unique monsters */
1736 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1737
1738 /* Hack -- Require "o" monsters */
1739 if (!strchr("o", r_ptr->d_char)) return (FALSE);
1740
1741 /* Okay */
1742 return (TRUE);
1743 }
1744
1745
1746 /*
1747 * Helper function for "monster pit (troll)"
1748 */
vault_aux_troll(int r_idx)1749 static bool vault_aux_troll(int r_idx)
1750 {
1751 monster_race *r_ptr = &r_info[r_idx];
1752
1753 /* Decline unique monsters */
1754 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1755
1756 /* Hack -- Require "T" monsters */
1757 if (!strchr("T", r_ptr->d_char)) return (FALSE);
1758
1759 /* Okay */
1760 return (TRUE);
1761 }
1762
1763
1764 /*
1765 * Helper function for "monster pit (giant)"
1766 */
vault_aux_giant(int r_idx)1767 static bool vault_aux_giant(int r_idx)
1768 {
1769 monster_race *r_ptr = &r_info[r_idx];
1770
1771 /* Decline unique monsters */
1772 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1773
1774 /* Hack -- Require "P" monsters */
1775 if (!strchr("P", r_ptr->d_char)) return (FALSE);
1776
1777 /* Okay */
1778 return (TRUE);
1779 }
1780
1781
1782 /*
1783 * Hack -- breath type for "vault_aux_dragon()"
1784 */
1785 static u32b vault_aux_dragon_mask4;
1786
1787
1788 /*
1789 * Helper function for "monster pit (dragon)"
1790 */
vault_aux_dragon(int r_idx)1791 static bool vault_aux_dragon(int r_idx)
1792 {
1793 monster_race *r_ptr = &r_info[r_idx];
1794
1795 /* Decline unique monsters */
1796 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1797
1798 /* Hack -- Require "d" or "D" monsters */
1799 if (!strchr("Dd", r_ptr->d_char)) return (FALSE);
1800
1801 /* Hack -- Require correct "breath attack" */
1802 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1803
1804 /* Okay */
1805 return (TRUE);
1806 }
1807
1808
1809 /*
1810 * Helper function for "monster pit (demon)"
1811 */
vault_aux_demon(int r_idx)1812 static bool vault_aux_demon(int r_idx)
1813 {
1814 monster_race *r_ptr = &r_info[r_idx];
1815
1816 /* Decline unique monsters */
1817 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
1818
1819 /* Hack -- Require "U" monsters */
1820 if (!strchr("U", r_ptr->d_char)) return (FALSE);
1821
1822 /* Okay */
1823 return (TRUE);
1824 }
1825
1826
1827
1828 /*
1829 * Type 5 -- Monster nests
1830 *
1831 * A monster nest is a "big" room, with an "inner" room, containing
1832 * a "collection" of monsters of a given type strewn about the room.
1833 *
1834 * The monsters are chosen from a set of 64 randomly selected monster
1835 * races, to allow the nest creation to fail instead of having "holes".
1836 *
1837 * Note the use of the "get_mon_num_prep()" function, and the special
1838 * "get_mon_num_hook()" restriction function, to prepare the "monster
1839 * allocation table" in such a way as to optimize the selection of
1840 * "appropriate" non-unique monsters for the nest.
1841 *
1842 * Currently, a monster nest is one of
1843 * a nest of "jelly" monsters (Dungeon level 5 and deeper)
1844 * a nest of "animal" monsters (Dungeon level 30 and deeper)
1845 * a nest of "undead" monsters (Dungeon level 50 and deeper)
1846 *
1847 * Note that the "get_mon_num()" function may (rarely) fail, in which
1848 * case the nest will be empty, and will not affect the level rating.
1849 *
1850 * Note that "monster nests" will never contain "unique" monsters.
1851 */
build_type5(int Depth,int yval,int xval)1852 static void build_type5(int Depth, int yval, int xval)
1853 {
1854 int y, x, y1, x1, y2, x2;
1855
1856 int tmp, i;
1857
1858 s16b what[64];
1859
1860 cptr name;
1861
1862 bool empty = FALSE;
1863
1864
1865 /* Large room */
1866 y1 = yval - 4;
1867 y2 = yval + 4;
1868 x1 = xval - 11;
1869 x2 = xval + 11;
1870
1871 place_double_room(Depth, FALSE, y1, y2, x1, x2);
1872
1873 /* Advance to the center room */
1874 y1 = y1 + 2;
1875 y2 = y2 - 2;
1876 x1 = x1 + 2;
1877 x2 = x2 - 2;
1878
1879 /* Place a secret door */
1880 switch (randint1(4))
1881 {
1882 case 1: place_secret_door(Depth, y1 - 1, xval); break;
1883 case 2: place_secret_door(Depth, y2 + 1, xval); break;
1884 case 3: place_secret_door(Depth, yval, x1 - 1); break;
1885 case 4: place_secret_door(Depth, yval, x2 + 1); break;
1886 }
1887
1888
1889 /* Hack -- Choose a nest type */
1890 tmp = randint1(Depth);
1891
1892 /* Monster nest (jelly) */
1893 if (tmp < 30)
1894 {
1895 /* Describe */
1896 name = "jelly";
1897
1898 /* Restrict to jelly */
1899 get_mon_num_hook = vault_aux_jelly;
1900 }
1901
1902 /* Monster nest (animal) */
1903 else if (tmp < 50)
1904 {
1905 /* Describe */
1906 name = "animal";
1907
1908 /* Restrict to animal */
1909 get_mon_num_hook = vault_aux_animal;
1910 }
1911
1912 /* Monster nest (undead) */
1913 else
1914 {
1915 /* Describe */
1916 name = "undead";
1917
1918 /* Restrict to undead */
1919 get_mon_num_hook = vault_aux_undead;
1920 }
1921
1922 /* Prepare allocation table */
1923 get_mon_num_prep();
1924
1925
1926 /* Pick some monster types */
1927 for (i = 0; i < 64; i++)
1928 {
1929 /* Get a (hard) monster type */
1930 what[i] = get_mon_num(Depth + 10);
1931
1932 /* Notice failure */
1933 if (!what[i]) empty = TRUE;
1934 }
1935
1936
1937 /* Remove restriction */
1938 get_mon_num_hook = NULL;
1939
1940 /* Prepare allocation table */
1941 get_mon_num_prep();
1942
1943
1944 /* Oops */
1945 if (empty) return;
1946
1947
1948 /* Describe */
1949 /*if (cheat_room)*/
1950 {
1951 /* Room type */
1952 /*msg_format("Monster nest (%s)", name);*/
1953 }
1954
1955
1956 /* Increase the level rating */
1957 rating += 10;
1958
1959 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1960 if ((Depth <= 40) && (randint1(Depth*Depth + 1) < 300))
1961 {
1962 good_item_flag = TRUE;
1963 }
1964
1965
1966 /* Place some monsters */
1967 for (y = yval - 2; y <= yval + 2; y++)
1968 {
1969 for (x = xval - 9; x <= xval + 9; x++)
1970 {
1971 int r_idx = what[randint0(64)];
1972
1973 /* Place that "random" monster (no groups) */
1974 (void)place_monster_aux(Depth, y, x, r_idx, FALSE, FALSE);
1975 }
1976 }
1977 }
1978
1979
1980
1981 /*
1982 * Type 6 -- Monster pits
1983 *
1984 * A monster pit is a "big" room, with an "inner" room, containing
1985 * a "collection" of monsters of a given type organized in the room.
1986 *
1987 * Monster types in the pit
1988 * orc pit (Dungeon Level 5 and deeper)
1989 * troll pit (Dungeon Level 20 and deeper)
1990 * giant pit (Dungeon Level 40 and deeper)
1991 * dragon pit (Dungeon Level 60 and deeper)
1992 * demon pit (Dungeon Level 80 and deeper)
1993 *
1994 * The inside room in a monster pit appears as shown below, where the
1995 * actual monsters in each location depend on the type of the pit
1996 *
1997 * #####################
1998 * #0000000000000000000#
1999 * #0112233455543322110#
2000 * #0112233467643322110#
2001 * #0112233455543322110#
2002 * #0000000000000000000#
2003 * #####################
2004 *
2005 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
2006 * to request 16 "appropriate" monsters, sorting them by level, and using
2007 * the "even" entries in this sorted list for the contents of the pit.
2008 *
2009 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
2010 * which is handled by requiring a specific "breath" attack for all of the
2011 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
2012 * be present in many of the dragon pits, if they have the proper breath.
2013 *
2014 * Note the use of the "get_mon_num_prep()" function, and the special
2015 * "get_mon_num_hook()" restriction function, to prepare the "monster
2016 * allocation table" in such a way as to optimize the selection of
2017 * "appropriate" non-unique monsters for the pit.
2018 *
2019 * Note that the "get_mon_num()" function may (rarely) fail, in which case
2020 * the pit will be empty, and will not effect the level rating.
2021 *
2022 * Note that "monster pits" will never contain "unique" monsters.
2023 */
build_type6(int Depth,int yval,int xval)2024 static void build_type6(int Depth, int yval, int xval)
2025 {
2026 int tmp, what[16];
2027
2028 int i, j, y, x, y1, x1, y2, x2;
2029
2030 bool empty = FALSE;
2031
2032 cptr name;
2033
2034 /* Large room */
2035 y1 = yval - 4;
2036 y2 = yval + 4;
2037 x1 = xval - 11;
2038 x2 = xval + 11;
2039
2040 place_double_room(Depth, FALSE, y1, y2, x1, x2);
2041
2042 /* Advance to the center room */
2043 y1 = y1 + 2;
2044 y2 = y2 - 2;
2045 x1 = x1 + 2;
2046 x2 = x2 - 2;
2047
2048 /* Place a secret door */
2049 switch (randint1(4))
2050 {
2051 case 1: place_secret_door(Depth, y1 - 1, xval); break;
2052 case 2: place_secret_door(Depth, y2 + 1, xval); break;
2053 case 3: place_secret_door(Depth, yval, x1 - 1); break;
2054 case 4: place_secret_door(Depth, yval, x2 + 1); break;
2055 }
2056
2057
2058 /* Choose a pit type */
2059 tmp = randint1(Depth);
2060
2061 /* Orc pit */
2062 if (tmp < 20)
2063 {
2064 /* Message */
2065 name = "orc";
2066
2067 /* Restrict monster selection */
2068 get_mon_num_hook = vault_aux_orc;
2069 }
2070
2071 /* Troll pit */
2072 else if (tmp < 40)
2073 {
2074 /* Message */
2075 name = "troll";
2076
2077 /* Restrict monster selection */
2078 get_mon_num_hook = vault_aux_troll;
2079 }
2080
2081 /* Giant pit */
2082 else if (tmp < 60)
2083 {
2084 /* Message */
2085 name = "giant";
2086
2087 /* Restrict monster selection */
2088 get_mon_num_hook = vault_aux_giant;
2089 }
2090
2091 /* Dragon pit */
2092 else if (tmp < 80)
2093 {
2094 /* Pick dragon type */
2095 switch (randint0(6))
2096 {
2097 /* Black */
2098 case 0:
2099 {
2100 /* Message */
2101 name = "acid dragon";
2102
2103 /* Restrict dragon breath type */
2104 vault_aux_dragon_mask4 = RF4_BR_ACID;
2105
2106 /* Done */
2107 break;
2108 }
2109
2110 /* Blue */
2111 case 1:
2112 {
2113 /* Message */
2114 name = "electric dragon";
2115
2116 /* Restrict dragon breath type */
2117 vault_aux_dragon_mask4 = RF4_BR_ELEC;
2118
2119 /* Done */
2120 break;
2121 }
2122
2123 /* Red */
2124 case 2:
2125 {
2126 /* Message */
2127 name = "fire dragon";
2128
2129 /* Restrict dragon breath type */
2130 vault_aux_dragon_mask4 = RF4_BR_FIRE;
2131
2132 /* Done */
2133 break;
2134 }
2135
2136 /* White */
2137 case 3:
2138 {
2139 /* Message */
2140 name = "cold dragon";
2141
2142 /* Restrict dragon breath type */
2143 vault_aux_dragon_mask4 = RF4_BR_COLD;
2144
2145 /* Done */
2146 break;
2147 }
2148
2149 /* Green */
2150 case 4:
2151 {
2152 /* Message */
2153 name = "poison dragon";
2154
2155 /* Restrict dragon breath type */
2156 vault_aux_dragon_mask4 = RF4_BR_POIS;
2157
2158 /* Done */
2159 break;
2160 }
2161
2162 /* Multi-hued */
2163 default:
2164 {
2165 /* Message */
2166 name = "multi-hued dragon";
2167
2168 /* Restrict dragon breath type */
2169 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
2170 RF4_BR_FIRE | RF4_BR_COLD |
2171 RF4_BR_POIS);
2172
2173 /* Done */
2174 break;
2175 }
2176
2177 }
2178
2179 /* Restrict monster selection */
2180 get_mon_num_hook = vault_aux_dragon;
2181 }
2182
2183 /* Demon pit */
2184 else
2185 {
2186 /* Message */
2187 name = "demon";
2188
2189 /* Restrict monster selection */
2190 get_mon_num_hook = vault_aux_demon;
2191 }
2192
2193 /* Prepare allocation table */
2194 get_mon_num_prep();
2195
2196
2197 /* Pick some monster types */
2198 for (i = 0; i < 16; i++)
2199 {
2200 /* Get a (hard) monster type */
2201 what[i] = get_mon_num(Depth + 10);
2202
2203 /* Notice failure */
2204 if (!what[i]) empty = TRUE;
2205 }
2206
2207
2208 /* Remove restriction */
2209 get_mon_num_hook = NULL;
2210
2211 /* Prepare allocation table */
2212 get_mon_num_prep();
2213
2214
2215 /* Oops */
2216 if (empty) return;
2217
2218
2219 /* XXX XXX XXX */
2220 /* Sort the entries */
2221 for (i = 0; i < 16 - 1; i++)
2222 {
2223 /* Sort the entries */
2224 for (j = 0; j < 16 - 1; j++)
2225 {
2226 int i1 = j;
2227 int i2 = j + 1;
2228
2229 int p1 = r_info[what[i1]].level;
2230 int p2 = r_info[what[i2]].level;
2231
2232 /* Bubble */
2233 if (p1 > p2)
2234 {
2235 int tmp = what[i1];
2236 what[i1] = what[i2];
2237 what[i2] = tmp;
2238 }
2239 }
2240 }
2241
2242 /* Select the entries */
2243 for (i = 0; i < 8; i++)
2244 {
2245 /* Every other entry */
2246 what[i] = what[i * 2];
2247 }
2248
2249
2250 #if 0
2251 /* Message */
2252 if (cheat_room)
2253 {
2254 /* Room type */
2255 msg_format("Monster pit (%s)", name);
2256
2257 /* Contents */
2258 for (i = 0; i < 8; i++)
2259 {
2260 /* Message */
2261 msg_print(r_name + r_info[what[i]].name);
2262 }
2263 }
2264 #endif
2265
2266
2267 /* Increase the level rating */
2268 rating += 10;
2269
2270 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2271 if ((Depth <= 40) && (randint1(Depth*Depth + 1) < 300))
2272 {
2273 good_item_flag = TRUE;
2274 }
2275
2276
2277 /* Top and bottom rows */
2278 for (x = xval - 9; x <= xval + 9; x++)
2279 {
2280 place_monster_aux(Depth, yval - 2, x, what[0], FALSE, FALSE);
2281 place_monster_aux(Depth, yval + 2, x, what[0], FALSE, FALSE);
2282 }
2283
2284 /* Middle columns */
2285 for (y = yval - 1; y <= yval + 1; y++)
2286 {
2287 place_monster_aux(Depth, y, xval - 9, what[0], FALSE, FALSE);
2288 place_monster_aux(Depth, y, xval + 9, what[0], FALSE, FALSE);
2289
2290 place_monster_aux(Depth, y, xval - 8, what[1], FALSE, FALSE);
2291 place_monster_aux(Depth, y, xval + 8, what[1], FALSE, FALSE);
2292
2293 place_monster_aux(Depth, y, xval - 7, what[1], FALSE, FALSE);
2294 place_monster_aux(Depth, y, xval + 7, what[1], FALSE, FALSE);
2295
2296 place_monster_aux(Depth, y, xval - 6, what[2], FALSE, FALSE);
2297 place_monster_aux(Depth, y, xval + 6, what[2], FALSE, FALSE);
2298
2299 place_monster_aux(Depth, y, xval - 5, what[2], FALSE, FALSE);
2300 place_monster_aux(Depth, y, xval + 5, what[2], FALSE, FALSE);
2301
2302 place_monster_aux(Depth, y, xval - 4, what[3], FALSE, FALSE);
2303 place_monster_aux(Depth, y, xval + 4, what[3], FALSE, FALSE);
2304
2305 place_monster_aux(Depth, y, xval - 3, what[3], FALSE, FALSE);
2306 place_monster_aux(Depth, y, xval + 3, what[3], FALSE, FALSE);
2307
2308 place_monster_aux(Depth, y, xval - 2, what[4], FALSE, FALSE);
2309 place_monster_aux(Depth, y, xval + 2, what[4], FALSE, FALSE);
2310 }
2311
2312 /* Above/Below the center monster */
2313 for (x = xval - 1; x <= xval + 1; x++)
2314 {
2315 place_monster_aux(Depth, yval + 1, x, what[5], FALSE, FALSE);
2316 place_monster_aux(Depth, yval - 1, x, what[5], FALSE, FALSE);
2317 }
2318
2319 /* Next to the center monster */
2320 place_monster_aux(Depth, yval, xval + 1, what[6], FALSE, FALSE);
2321 place_monster_aux(Depth, yval, xval - 1, what[6], FALSE, FALSE);
2322
2323 /* Center monster */
2324 place_monster_aux(Depth, yval, xval, what[7], FALSE, FALSE);
2325 }
2326
2327
2328
2329 /*
2330 * Hack -- fill in "vault" rooms
2331 */
build_vault(int Depth,int yval,int xval,int ymax,int xmax,cptr data)2332 void build_vault(int Depth, int yval, int xval, int ymax, int xmax, cptr data)
2333 {
2334 int dx, dy, x, y;
2335
2336 cptr t;
2337
2338 cave_type *c_ptr;
2339
2340 /* The edge is defined by 0 0 MAX_WID-1 MAX_HGT-1 */
2341 if ((xval == 0) || /* At the left edge */
2342 (yval == 0) || /* At the top edge */
2343 (xmax == MAX_WID-1) || /* At the right edge */
2344 (ymax == MAX_HGT-1)) /* At the bottom edge */
2345 return; /* Abort if any side of the vault is at the edge of the dungeon */
2346
2347 /* Place dungeon features and objects */
2348 for (t = data, dy = 0; dy < ymax; dy++)
2349 {
2350 for (dx = 0; dx < xmax; dx++, t++)
2351 {
2352 /* Extract the location */
2353 x = xval - (xmax / 2) + dx;
2354 y = yval - (ymax / 2) + dy;
2355
2356 /* FIXME - find a better solution */
2357 if(!in_bounds(Depth,y,x))
2358 continue;
2359
2360 /* Hack -- skip "non-grids" */
2361 if (*t == ' ') continue;
2362
2363 /* Access the grid */
2364 c_ptr = &cave[Depth][y][x];
2365
2366 /* Lay down a floor */
2367 c_ptr->feat = FEAT_FLOOR;
2368
2369 /* Part of a vault */
2370 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2371
2372 /* Analyze the grid */
2373 switch (*t)
2374 {
2375 /* Granite wall (outer) */
2376 case '%':
2377 c_ptr->feat = FEAT_WALL_OUTER;
2378 break;
2379
2380 /* Granite wall (inner) */
2381 case '#':
2382 c_ptr->feat = FEAT_WALL_INNER;
2383 break;
2384
2385 /* Permanent wall (inner) */
2386 case 'X':
2387 c_ptr->feat = FEAT_PERM_INNER;
2388 break;
2389
2390 /* Treasure/trap */
2391 case '*':
2392 if (randint0(100) < 75)
2393 {
2394 place_object(Depth, y, x, FALSE, FALSE, ORIGIN_VAULT);
2395 }
2396 else
2397 {
2398 place_trap(Depth, y, x);
2399 }
2400 break;
2401
2402 /* Secret doors */
2403 case '+':
2404 place_secret_door(Depth, y, x);
2405 break;
2406
2407 /* Trap */
2408 case '^':
2409 place_trap(Depth, y, x);
2410 break;
2411 }
2412 }
2413 }
2414
2415
2416 /* Place dungeon monsters and objects */
2417 for (t = data, dy = 0; dy < ymax; dy++)
2418 {
2419 for (dx = 0; dx < xmax; dx++, t++)
2420 {
2421 /* Extract the grid */
2422 x = xval - (xmax/2) + dx;
2423 y = yval - (ymax/2) + dy;
2424
2425 /* FIXME - find a better solution */
2426 if(!in_bounds(Depth,y,x))
2427 continue;
2428
2429 /* Hack -- skip "non-grids" */
2430 if (*t == ' ') continue;
2431
2432 /* Analyze the symbol */
2433 switch (*t)
2434 {
2435 /* Monster */
2436 case '&':
2437 monster_level = Depth + 5;
2438 place_monster(Depth, y, x, TRUE, TRUE);
2439 monster_level = Depth;
2440 break;
2441
2442 /* Meaner monster */
2443 case '@':
2444 monster_level = Depth + 11;
2445 place_monster(Depth, y, x, TRUE, TRUE);
2446 monster_level = Depth;
2447 break;
2448
2449 /* Meaner monster, plus treasure */
2450 case '9':
2451 monster_level = Depth + 9;
2452 place_monster(Depth, y, x, TRUE, TRUE);
2453 monster_level = Depth;
2454 object_level = Depth + 7;
2455 place_object(Depth, y, x, TRUE, FALSE, ORIGIN_VAULT);
2456 object_level = Depth;
2457 break;
2458
2459 /* Nasty monster and treasure */
2460 case '8':
2461 monster_level = Depth + 40;
2462 place_monster(Depth, y, x, TRUE, TRUE);
2463 monster_level = Depth;
2464 object_level = Depth + 20;
2465 place_object(Depth, y, x, TRUE, TRUE, ORIGIN_VAULT);
2466 object_level = Depth;
2467 break;
2468
2469 /* Monster and/or object */
2470 case ',':
2471 if (randint0(100) < 50)
2472 {
2473 monster_level = Depth + 3;
2474 place_monster(Depth, y, x, TRUE, TRUE);
2475 monster_level = Depth;
2476 }
2477 if (randint0(100) < 50)
2478 {
2479 object_level = Depth + 7;
2480 place_object(Depth, y, x, FALSE, FALSE, 0);
2481 object_level = Depth;
2482 }
2483 break;
2484 }
2485 }
2486 }
2487 }
2488
2489
2490
2491 /*
2492 * Type 7 -- simple vaults (see "v_info.txt")
2493 */
build_type7(int Depth,int yval,int xval)2494 static void build_type7(int Depth, int yval, int xval)
2495 {
2496 vault_type *v_ptr;
2497
2498 /* Pick a lesser vault */
2499 while (TRUE)
2500 {
2501 /* Access a random vault record */
2502 v_ptr = &v_info[randint0(z_info->v_max)];
2503
2504 /* Accept the first lesser vault */
2505 if (v_ptr->typ == 7) break;
2506 }
2507
2508 /* Message */
2509 /*if (cheat_room) msg_print("Lesser Vault");*/
2510 #ifdef DEBUG
2511 /* Audit vault allocation */
2512 cheat(format("+v %s", v_name + v_ptr->name));
2513 #endif
2514
2515 /* Boost the rating */
2516 rating += v_ptr->rat;
2517
2518 /* (Sometimes) Cause a special feeling */
2519 if ((Depth <= 50) ||
2520 (randint1((Depth-40) * (Depth-40) + 1) < 400))
2521 {
2522 good_item_flag = TRUE;
2523 }
2524
2525 /* Hack -- Build the vault */
2526 build_vault(Depth, yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
2527 }
2528
2529
2530
2531 /*
2532 * Type 8 -- greater vaults (see "v_info.txt")
2533 */
build_type8(int Depth,int yval,int xval)2534 static void build_type8(int Depth, int yval, int xval)
2535 {
2536 vault_type *v_ptr;
2537
2538 /* Pick a lesser vault */
2539 while (TRUE)
2540 {
2541 /* Access a random vault record */
2542 v_ptr = &v_info[randint0(z_info->v_max)];
2543
2544 /* Accept the first greater vault */
2545 if (v_ptr->typ == 8) break;
2546 }
2547
2548 /* Message */
2549 /*if (cheat_room) msg_print("Greater Vault");*/
2550 #ifdef DEBUG
2551 /* Audit monster allocation */
2552 cheat(format("+v %s", v_name + v_ptr->name));
2553 #endif
2554
2555 /* Boost the rating */
2556 rating += v_ptr->rat;
2557
2558 /* (Sometimes) Cause a special feeling */
2559 if ((Depth <= 50) ||
2560 (randint1((Depth-40) * (Depth-40) + 1) < 400))
2561 {
2562 good_item_flag = TRUE;
2563 }
2564
2565 /* Hack -- Build the vault */
2566 build_vault(Depth, yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
2567 }
2568
2569
2570
2571 /*
2572 * Constructs a tunnel between two points
2573 *
2574 * This function must be called BEFORE any streamers are created,
2575 * since we use the special "granite wall" sub-types to keep track
2576 * of legal places for corridors to pierce rooms.
2577 *
2578 * We use "door_flag" to prevent excessive construction of doors
2579 * along overlapping corridors.
2580 *
2581 * We queue the tunnel grids to prevent door creation along a corridor
2582 * which intersects itself.
2583 *
2584 * We queue the wall piercing grids to prevent a corridor from leaving
2585 * a room and then coming back in through the same entrance.
2586 *
2587 * We "pierce" grids which are "outer" walls of rooms, and when we
2588 * do so, we change all adjacent "outer" walls of rooms into "solid"
2589 * walls so that no two corridors may use adjacent grids for exits.
2590 *
2591 * The "solid" wall check prevents corridors from "chopping" the
2592 * corners of rooms off, as well as "silly" door placement, and
2593 * "excessively wide" room entrances.
2594 *
2595 * Useful "feat" values:
2596 * FEAT_WALL_EXTRA -- granite walls
2597 * FEAT_WALL_INNER -- inner room walls
2598 * FEAT_WALL_OUTER -- outer room walls
2599 * FEAT_WALL_SOLID -- solid room walls
2600 * FEAT_PERM_EXTRA -- shop walls (perma)
2601 * FEAT_PERM_INNER -- inner room walls (perma)
2602 * FEAT_PERM_OUTER -- outer room walls (perma)
2603 * FEAT_PERM_SOLID -- dungeon border (perma)
2604 */
build_tunnel(int Depth,int row1,int col1,int row2,int col2)2605 static void build_tunnel(int Depth, int row1, int col1, int row2, int col2)
2606 {
2607 int i, y, x;
2608 int tmp_row, tmp_col;
2609 int row_dir, col_dir;
2610 int start_row, start_col;
2611 int main_loop_count = 0;
2612
2613 bool door_flag = FALSE;
2614
2615 cave_type *c_ptr;
2616
2617
2618 /* Reset the arrays */
2619 dun->tunn_n = 0;
2620 dun->wall_n = 0;
2621
2622 /* Save the starting location */
2623 start_row = row1;
2624 start_col = col1;
2625
2626 /* Start out in the correct direction */
2627 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
2628
2629 /* Keep going until done (or bored) */
2630 while ((row1 != row2) || (col1 != col2))
2631 {
2632 /* Mega-Hack -- Paranoia -- prevent infinite loops */
2633 if (main_loop_count++ > 2000) break;
2634
2635 /* Allow bends in the tunnel */
2636 if (randint0(100) < DUN_TUN_CHG)
2637 {
2638 /* Acquire the correct direction */
2639 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
2640
2641 /* Random direction */
2642 if (randint0(100) < DUN_TUN_RND)
2643 {
2644 rand_dir(&row_dir, &col_dir);
2645 }
2646 }
2647
2648 /* Get the next location */
2649 tmp_row = row1 + row_dir;
2650 tmp_col = col1 + col_dir;
2651
2652
2653 /* Extremely Important -- do not leave the dungeon */
2654 while (!in_bounds(Depth, tmp_row, tmp_col))
2655 {
2656 /* Acquire the correct direction */
2657 correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
2658
2659 /* Random direction */
2660 if (randint0(100) < DUN_TUN_RND)
2661 {
2662 rand_dir(&row_dir, &col_dir);
2663 }
2664
2665 /* Get the next location */
2666 tmp_row = row1 + row_dir;
2667 tmp_col = col1 + col_dir;
2668 }
2669
2670
2671 /* Access the location */
2672 c_ptr = &cave[Depth][tmp_row][tmp_col];
2673
2674
2675 /* Avoid the edge of the dungeon */
2676 if (c_ptr->feat == FEAT_PERM_SOLID) continue;
2677
2678 /* Avoid the edge of vaults */
2679 if (c_ptr->feat == FEAT_PERM_OUTER) continue;
2680
2681 /* Avoid "solid" granite walls */
2682 if (c_ptr->feat == FEAT_WALL_SOLID) continue;
2683
2684 /* Pierce "outer" walls of rooms */
2685 if (c_ptr->feat == FEAT_WALL_OUTER)
2686 {
2687 /* Acquire the "next" location */
2688 y = tmp_row + row_dir;
2689 x = tmp_col + col_dir;
2690
2691 /* Hack -- Avoid outer/solid permanent walls */
2692 if (cave[Depth][y][x].feat == FEAT_PERM_SOLID) continue;
2693 if (cave[Depth][y][x].feat == FEAT_PERM_OUTER) continue;
2694
2695 /* Hack -- Avoid outer/solid granite walls */
2696 if (cave[Depth][y][x].feat == FEAT_WALL_OUTER) continue;
2697 if (cave[Depth][y][x].feat == FEAT_WALL_SOLID) continue;
2698
2699 /* Accept this location */
2700 row1 = tmp_row;
2701 col1 = tmp_col;
2702
2703 /* Save the wall location */
2704 if (dun->wall_n < WALL_MAX)
2705 {
2706 dun->wall[dun->wall_n].y = row1;
2707 dun->wall[dun->wall_n].x = col1;
2708 dun->wall_n++;
2709 }
2710
2711 #ifdef WIDE_CORRIDORS
2712 /* Save the wall location */
2713 if (dun->wall_n < WALL_MAX)
2714 {
2715 if (cave[Depth][row1 + col_dir][col1 + row_dir].feat != FEAT_PERM_SOLID &&
2716 cave[Depth][row1 + col_dir][col1 + row_dir].feat != FEAT_PERM_SOLID)
2717 {
2718 dun->wall[dun->wall_n].y = row1 + col_dir;
2719 dun->wall[dun->wall_n].x = col1 + row_dir;
2720 dun->wall_n++;
2721 }
2722 else
2723 {
2724 dun->wall[dun->wall_n].y = row1;
2725 dun->wall[dun->wall_n].x = col1;
2726 dun->wall_n++;
2727 }
2728 }
2729 #endif
2730
2731 #ifdef WIDE_CORRIDORS
2732 /* Forbid re-entry near this piercing */
2733 for (y = row1 - 2; y <= row1 + 2; y++)
2734 {
2735 for (x = col1 - 2; x <= col1 + 2; x++)
2736 {
2737 /* Be sure we are "in bounds" */
2738 if (!in_bounds(Depth, y, x)) continue;
2739
2740 /* Convert adjacent "outer" walls as "solid" walls */
2741 if (cave[Depth][y][x].feat == FEAT_WALL_OUTER)
2742 {
2743 /* Change the wall to a "solid" wall */
2744 cave[Depth][y][x].feat = FEAT_WALL_SOLID;
2745 }
2746 }
2747 }
2748 #else
2749 /* Forbid re-entry near this piercing */
2750 for (y = row1 - 1; y <= row1 + 1; y++)
2751 {
2752 for (x = col1 - 1; x <= col1 + 1; x++)
2753 {
2754 /* Convert adjacent "outer" walls as "solid" walls */
2755 if (cave[Depth][y][x].feat == FEAT_WALL_OUTER)
2756 {
2757 /* Change the wall to a "solid" wall */
2758 cave[Depth][y][x].feat = FEAT_WALL_SOLID;
2759 }
2760 }
2761 }
2762 #endif
2763 }
2764
2765 /* Travel quickly through rooms */
2766 else if (c_ptr->info & CAVE_ROOM)
2767 {
2768 /* Accept the location */
2769 row1 = tmp_row;
2770 col1 = tmp_col;
2771 }
2772
2773 /* Tunnel through all other walls */
2774 else if (c_ptr->feat >= FEAT_WALL_EXTRA)
2775 {
2776 /* Accept this location */
2777 row1 = tmp_row;
2778 col1 = tmp_col;
2779
2780 /* Save the tunnel location */
2781 if (dun->tunn_n < TUNN_MAX)
2782 {
2783 dun->tunn[dun->tunn_n].y = row1;
2784 dun->tunn[dun->tunn_n].x = col1;
2785 dun->tunn_n++;
2786 }
2787
2788 #ifdef WIDE_CORRIDORS
2789 /* Note that this is incredibly hacked */
2790
2791 /* Make sure we're in bounds */
2792 if (in_bounds(Depth, row1 + col_dir, col1 + row_dir))
2793 {
2794 /* New spot to be hollowed out */
2795 c_ptr = &cave[Depth][row1 + col_dir][col1 + row_dir];
2796
2797 /* Make sure it's a wall we want to tunnel */
2798 if (c_ptr->feat == FEAT_WALL_EXTRA)
2799 {
2800 /* Save the tunnel location */
2801 if (dun->tunn_n < TUNN_MAX)
2802 {
2803 dun->tunn[dun->tunn_n].y = row1 + col_dir;
2804 dun->tunn[dun->tunn_n].x = col1 + row_dir;
2805 dun->tunn_n++;
2806 }
2807 }
2808 }
2809 #endif
2810
2811 /* Allow door in next grid */
2812 door_flag = FALSE;
2813 }
2814
2815 /* Handle corridor intersections or overlaps */
2816 else
2817 {
2818 /* Accept the location */
2819 row1 = tmp_row;
2820 col1 = tmp_col;
2821
2822 /* Collect legal door locations */
2823 if (!door_flag)
2824 {
2825 /* Save the door location */
2826 if (dun->door_n < DOOR_MAX)
2827 {
2828 dun->door[dun->door_n].y = row1;
2829 dun->door[dun->door_n].x = col1;
2830 dun->door_n++;
2831 }
2832
2833 #ifdef WIDE_CORRIDORS
2834 /* Save the next door location */
2835 if (dun->door_n < DOOR_MAX)
2836 {
2837 if (in_bounds(Depth, row1 + col_dir, col1 + row_dir))
2838 {
2839 dun->door[dun->door_n].y = row1 + col_dir;
2840 dun->door[dun->door_n].x = col1 + row_dir;
2841 dun->door_n++;
2842 }
2843
2844 /* Hack -- Duplicate the previous door */
2845 else
2846 {
2847 dun->door[dun->door_n].y = row1;
2848 dun->door[dun->door_n].x = col1;
2849 dun->door_n++;
2850 }
2851 }
2852 #endif
2853
2854 /* No door in next grid */
2855 door_flag = TRUE;
2856 }
2857
2858 /* Hack -- allow pre-emptive tunnel termination */
2859 if (randint0(100) >= DUN_TUN_CON)
2860 {
2861 /* Distance between row1 and start_row */
2862 tmp_row = row1 - start_row;
2863 if (tmp_row < 0) tmp_row = (-tmp_row);
2864
2865 /* Distance between col1 and start_col */
2866 tmp_col = col1 - start_col;
2867 if (tmp_col < 0) tmp_col = (-tmp_col);
2868
2869 /* Terminate the tunnel */
2870 if ((tmp_row > 10) || (tmp_col > 10)) break;
2871 }
2872 }
2873 }
2874
2875
2876 /* Turn the tunnel into corridor */
2877 for (i = 0; i < dun->tunn_n; i++)
2878 {
2879 /* Access the grid */
2880 y = dun->tunn[i].y;
2881 x = dun->tunn[i].x;
2882
2883 /* Access the grid */
2884 c_ptr = &cave[Depth][y][x];
2885
2886 /* Clear previous contents, add a floor */
2887 c_ptr->feat = FEAT_FLOOR;
2888 }
2889
2890
2891 /* Apply the piercings that we found */
2892 for (i = 0; i < dun->wall_n; i++)
2893 {
2894 int feat;
2895
2896 /* Access the grid */
2897 y = dun->wall[i].y;
2898 x = dun->wall[i].x;
2899
2900 /* Access the grid */
2901 c_ptr = &cave[Depth][y][x];
2902
2903 /* Clear previous contents, add up floor */
2904 c_ptr->feat = FEAT_FLOOR;
2905
2906 /* Occasional doorway */
2907 if (randint0(100) < DUN_TUN_PEN)
2908 {
2909 /* Place a random door */
2910 place_random_door(Depth, y, x);
2911
2912 /* Remember type of door */
2913 feat = cave[Depth][y][x].feat;
2914
2915 #ifdef WIDE_CORRIDORS
2916 /* Make sure both halves get a door */
2917 if (i % 2)
2918 {
2919 /* Access the grid */
2920 y = dun->wall[i - 1].y;
2921 x = dun->wall[i - 1].x;
2922 }
2923 else
2924 {
2925 /* Access the grid */
2926 y = dun->wall[i + 1].y;
2927 x = dun->wall[i + 1].x;
2928
2929 /* Increment counter */
2930 i++;
2931 }
2932
2933 /* Place the same type of door */
2934 cave[Depth][y][x].feat = feat;
2935 #endif
2936 }
2937 }
2938 }
2939
2940
2941
2942
2943 /*
2944 * Count the number of "corridor" grids adjacent to the given grid.
2945 *
2946 * Note -- Assumes "in_bounds(y1, x1)"
2947 *
2948 * XXX XXX This routine currently only counts actual "empty floor"
2949 * grids which are not in rooms. We might want to also count stairs,
2950 * open doors, closed doors, etc.
2951 */
next_to_corr(int Depth,int y1,int x1)2952 static int next_to_corr(int Depth, int y1, int x1)
2953 {
2954 int i, y, x, k = 0;
2955
2956 cave_type *c_ptr;
2957
2958 /* Scan adjacent grids */
2959 for (i = 0; i < 4; i++)
2960 {
2961 /* Extract the location */
2962 y = y1 + ddy_ddd[i];
2963 x = x1 + ddx_ddd[i];
2964
2965 /* Skip non floors */
2966 if (!cave_floor_bold(Depth, y, x)) continue;
2967
2968 /* Access the grid */
2969 c_ptr = &cave[Depth][y][x];
2970
2971 /* Skip non "empty floor" grids */
2972 if (c_ptr->feat != FEAT_FLOOR) continue;
2973
2974 /* Skip grids inside rooms */
2975 if (c_ptr->info & CAVE_ROOM) continue;
2976
2977 /* Count these grids */
2978 k++;
2979 }
2980
2981 /* Return the number of corridors */
2982 return (k);
2983 }
2984
2985
2986 /*
2987 * Determine if the given location is "between" two walls,
2988 * and "next to" two corridor spaces. XXX XXX XXX
2989 *
2990 * Assumes "in_bounds(y,x)"
2991 */
possible_doorway(int Depth,int y,int x)2992 static bool possible_doorway(int Depth, int y, int x)
2993 {
2994 /* Count the adjacent corridors */
2995 if (next_to_corr(Depth, y, x) >= 2)
2996 {
2997 /* Check Vertical */
2998 if ((cave[Depth][y-1][x].feat >= FEAT_MAGMA) &&
2999 (cave[Depth][y+1][x].feat >= FEAT_MAGMA))
3000 {
3001 return (TRUE);
3002 }
3003
3004 /* Check Horizontal */
3005 if ((cave[Depth][y][x-1].feat >= FEAT_MAGMA) &&
3006 (cave[Depth][y][x+1].feat >= FEAT_MAGMA))
3007 {
3008 return (TRUE);
3009 }
3010 }
3011
3012 /* No doorway */
3013 return (FALSE);
3014 }
3015
3016
3017 /*
3018 * Places door at y, x position if at least 2 walls found
3019 */
try_door(int Depth,int y,int x)3020 static void try_door(int Depth, int y, int x)
3021 {
3022 /* Paranoia */
3023 if (!in_bounds(Depth, y, x)) return;
3024
3025 /* Ignore walls */
3026 if (cave[Depth][y][x].feat >= FEAT_MAGMA) return;
3027
3028 /* Ignore room grids */
3029 if (cave[Depth][y][x].info & CAVE_ROOM) return;
3030
3031 /* Occasional door (if allowed) */
3032 if ((randint0(100) < DUN_TUN_JCT) && possible_doorway(Depth, y, x))
3033 {
3034 /* Place a door */
3035 place_random_door(Depth, y, x);
3036 }
3037 }
3038
3039
3040
3041
3042 /*
3043 * Attempt to build a room of the given type at the given block
3044 *
3045 * Note that we restrict the number of "crowded" rooms to reduce
3046 * the chance of overflowing the monster list during level creation.
3047 */
room_build(int Depth,int y0,int x0,int typ)3048 static bool room_build(int Depth, int y0, int x0, int typ)
3049 {
3050 int y, x, y1, x1, y2, x2;
3051
3052
3053 /* Restrict level */
3054 if (Depth < room[typ].level) return (FALSE);
3055
3056 /* Restrict "crowded" rooms */
3057 if (dun->crowded && ((typ == 5) || (typ == 6))) return (FALSE);
3058
3059 /* Extract blocks */
3060 y1 = y0 + room[typ].dy1;
3061 y2 = y0 + room[typ].dy2;
3062 x1 = x0 + room[typ].dx1;
3063 x2 = x0 + room[typ].dx2;
3064
3065 /* Never run off the screen */
3066 if ((y1 < 0) || (y2 >= dun->row_rooms)) return (FALSE);
3067 if ((x1 < 0) || (x2 >= dun->col_rooms)) return (FALSE);
3068
3069 /* Verify open space */
3070 for (y = y1; y <= y2; y++)
3071 {
3072 for (x = x1; x <= x2; x++)
3073 {
3074 if (dun->room_map[y][x]) return (FALSE);
3075 }
3076 }
3077
3078 /* XXX XXX XXX It is *extremely* important that the following */
3079 /* calculation is *exactly* correct to prevent memory errors */
3080
3081 /* Acquire the location of the room */
3082 y = ((y1 + y2 + 1) * BLOCK_HGT) / 2;
3083 x = ((x1 + x2 + 1) * BLOCK_WID) / 2;
3084
3085 /* Build a room */
3086 switch (typ)
3087 {
3088 /* Build an appropriate room */
3089 case 8: build_type8(Depth, y, x); break;
3090 case 7: build_type7(Depth, y, x); break;
3091 case 6: build_type6(Depth, y, x); break;
3092 case 5: build_type5(Depth, y, x); break;
3093 case 4: build_type4(Depth, y, x); break;
3094 case 3: build_type3(Depth, y, x); break;
3095 case 2: build_type2(Depth, y, x); break;
3096 case 1: build_type1(Depth, y, x); break;
3097
3098 /* Paranoia */
3099 default: return (FALSE);
3100 }
3101
3102 /* Save the room location */
3103 if (dun->cent_n < CENT_MAX)
3104 {
3105 dun->cent[dun->cent_n].y = y;
3106 dun->cent[dun->cent_n].x = x;
3107 dun->cent_n++;
3108 }
3109
3110 /* Reserve some blocks */
3111 for (y = y1; y <= y2; y++)
3112 {
3113 for (x = x1; x <= x2; x++)
3114 {
3115 dun->room_map[y][x] = TRUE;
3116 }
3117 }
3118
3119 /* Count "crowded" rooms */
3120 if ((typ == 5) || (typ == 6)) dun->crowded = TRUE;
3121
3122 /* Success */
3123 return (TRUE);
3124 }
3125
3126
3127 /*
3128 * Generate a new dungeon level
3129 *
3130 * Note that "dun_body" adds about 4000 bytes of memory to the stack.
3131 */
cave_gen(int Depth)3132 static void cave_gen(int Depth)
3133 {
3134 int i, k, y, x, y1, x1;
3135
3136 bool destroyed = FALSE;
3137
3138 dun_data dun_body;
3139
3140
3141 /* Global data */
3142 dun = &dun_body;
3143
3144
3145 /* Hack -- Start with basic granite */
3146 for (y = 0; y < MAX_HGT; y++)
3147 {
3148 for (x = 0; x < MAX_WID; x++)
3149 {
3150 cave_type *c_ptr = &cave[Depth][y][x];
3151
3152 /* Create granite wall */
3153 c_ptr->feat = FEAT_WALL_EXTRA;
3154 }
3155 }
3156
3157
3158 /* Possible "destroyed" level */
3159 if ((Depth > 10) && (randint0(DUN_DEST) == 0)) destroyed = TRUE;
3160
3161 /* Hack -- No destroyed "quest" levels */
3162 if (is_quest(Depth)) destroyed = FALSE;
3163
3164
3165 /* Actual maximum number of rooms on this level */
3166 dun->row_rooms = MAX_HGT / BLOCK_HGT;
3167 dun->col_rooms = MAX_WID / BLOCK_WID;
3168
3169 /* Initialize the room table */
3170 for (y = 0; y < dun->row_rooms; y++)
3171 {
3172 for (x = 0; x < dun->col_rooms; x++)
3173 {
3174 dun->room_map[y][x] = FALSE;
3175 }
3176 }
3177
3178
3179 /* No "crowded" rooms yet */
3180 dun->crowded = FALSE;
3181
3182
3183 /* No rooms yet */
3184 dun->cent_n = 0;
3185
3186 /* Build some rooms */
3187 for (i = 0; i < DUN_ROOMS; i++)
3188 {
3189 /* Pick a block for the room */
3190 y = randint0(dun->row_rooms);
3191 x = randint0(dun->col_rooms);
3192
3193 /* Align dungeon rooms */
3194 if (dungeon_align)
3195 {
3196 /* Slide some rooms right */
3197 if ((x % 3) == 0) x++;
3198
3199 /* Slide some rooms left */
3200 if ((x % 3) == 2) x--;
3201 }
3202
3203 /* Destroyed levels are boring */
3204 if (destroyed)
3205 {
3206 /* Attempt a "trivial" room */
3207 if (room_build(Depth, y, x, 1)) continue;
3208
3209 /* Never mind */
3210 continue;
3211 }
3212
3213 /* Attempt an "unusual" room */
3214 if (randint0(DUN_UNUSUAL) < Depth)
3215 {
3216 /* Roll for room type */
3217 k = randint0(100);
3218
3219 /* Attempt a very unusual room */
3220 if (randint0(DUN_UNUSUAL) < Depth)
3221 {
3222 /* Type 8 -- Greater vault (10%) */
3223 if ((k < 10) && room_build(Depth, y, x, 8)) continue;
3224
3225 /* Type 7 -- Lesser vault (15%) */
3226 if ((k < 25) && room_build(Depth, y, x, 7)) continue;
3227
3228 /* Type 6 -- Monster pit (15%) */
3229 if ((k < 40) && room_build(Depth, y, x, 6)) continue;
3230
3231 /* Type 5 -- Monster nest (10%) */
3232 if ((k < 50) && room_build(Depth, y, x, 5)) continue;
3233 }
3234
3235 /* Type 4 -- Large room (25%) */
3236 if ((k < 25) && room_build(Depth, y, x, 4)) continue;
3237
3238 /* Type 3 -- Cross room (25%) */
3239 if ((k < 50) && room_build(Depth, y, x, 3)) continue;
3240
3241 /* Type 2 -- Overlapping (50%) */
3242 if ((k < 100) && room_build(Depth, y, x, 2)) continue;
3243 }
3244
3245 /* Attempt a trivial room */
3246 if (room_build(Depth, y, x, 1)) continue;
3247 }
3248
3249
3250 /* Special boundary walls -- Top */
3251 for (x = 0; x < MAX_WID; x++)
3252 {
3253 cave_type *c_ptr = &cave[Depth][0][x];
3254
3255 /* Clear previous contents, add "solid" perma-wall */
3256 c_ptr->feat = FEAT_PERM_SOLID;
3257 }
3258
3259 /* Special boundary walls -- Bottom */
3260 for (x = 0; x < MAX_WID; x++)
3261 {
3262 cave_type *c_ptr = &cave[Depth][MAX_HGT-1][x];
3263
3264 /* Clear previous contents, add "solid" perma-wall */
3265 c_ptr->feat = FEAT_PERM_SOLID;
3266 }
3267
3268 /* Special boundary walls -- Left */
3269 for (y = 0; y < MAX_HGT; y++)
3270 {
3271 cave_type *c_ptr = &cave[Depth][y][0];
3272
3273 /* Clear previous contents, add "solid" perma-wall */
3274 c_ptr->feat = FEAT_PERM_SOLID;
3275 }
3276
3277 /* Special boundary walls -- Right */
3278 for (y = 0; y < MAX_HGT; y++)
3279 {
3280 cave_type *c_ptr = &cave[Depth][y][MAX_WID-1];
3281
3282 /* Clear previous contents, add "solid" perma-wall */
3283 c_ptr->feat = FEAT_PERM_SOLID;
3284 }
3285
3286
3287 /* Hack -- Scramble the room order */
3288 for (i = 0; i < dun->cent_n; i++)
3289 {
3290 int pick1 = randint0(dun->cent_n);
3291 int pick2 = randint0(dun->cent_n);
3292 y1 = dun->cent[pick1].y;
3293 x1 = dun->cent[pick1].x;
3294 dun->cent[pick1].y = dun->cent[pick2].y;
3295 dun->cent[pick1].x = dun->cent[pick2].x;
3296 dun->cent[pick2].y = y1;
3297 dun->cent[pick2].x = x1;
3298 }
3299
3300 /* Start with no tunnel doors */
3301 dun->door_n = 0;
3302
3303 /* Hack -- connect the first room to the last room */
3304 y = dun->cent[dun->cent_n-1].y;
3305 x = dun->cent[dun->cent_n-1].x;
3306
3307 /* Connect all the rooms together */
3308 for (i = 0; i < dun->cent_n; i++)
3309 {
3310 /* Connect the room to the previous room */
3311 build_tunnel(Depth, dun->cent[i].y, dun->cent[i].x, y, x);
3312
3313 /* Remember the "previous" room */
3314 y = dun->cent[i].y;
3315 x = dun->cent[i].x;
3316 }
3317
3318 /* Place intersection doors */
3319 for (i = 0; i < dun->door_n; i++)
3320 {
3321 /* Extract junction location */
3322 y = dun->door[i].y;
3323 x = dun->door[i].x;
3324
3325 /* Try placing doors */
3326 try_door(Depth, y, x - 1);
3327 try_door(Depth, y, x + 1);
3328 try_door(Depth, y - 1, x);
3329 try_door(Depth, y + 1, x);
3330 }
3331
3332
3333 /* Hack -- Add some magma streamers */
3334 for (i = 0; i < DUN_STR_MAG; i++)
3335 {
3336 build_streamer(Depth, FEAT_MAGMA, DUN_STR_MC);
3337 }
3338
3339 /* Hack -- Add some quartz streamers */
3340 for (i = 0; i < DUN_STR_QUA; i++)
3341 {
3342 build_streamer(Depth, FEAT_QUARTZ, DUN_STR_QC);
3343 }
3344
3345
3346 /* Destroy the level if necessary */
3347 if (destroyed) destroy_level(Depth);
3348
3349
3350 /* Place 3 or 4 down stairs near some walls */
3351 alloc_stairs(Depth, FEAT_MORE, rand_range(3, 4), 3);
3352
3353 /* Place 1 or 2 up stairs near some walls */
3354 alloc_stairs(Depth, FEAT_LESS, rand_range(1, 2), 3);
3355
3356
3357 /* Determine the character location */
3358 new_player_spot(Depth);
3359
3360
3361 /* Basic "amount" */
3362 k = (Depth / 3);
3363 if (k > 10) k = 10;
3364 if (k < 2) k = 2;
3365
3366
3367 /* Pick a base number of monsters */
3368 i = MIN_M_ALLOC_LEVEL + randint1(8);
3369
3370 /* Put some monsters in the dungeon */
3371 for (i = i + k; i > 0; i--)
3372 {
3373 (void)alloc_monster(Depth, 0, TRUE);
3374 }
3375
3376
3377 /* Place some traps in the dungeon */
3378 alloc_object(Depth, ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k));
3379
3380 /* Put some rubble in corridors */
3381 alloc_object(Depth, ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k));
3382
3383 /* Put some objects in rooms */
3384 alloc_object(Depth, ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3));
3385
3386 /* Put some objects/gold in the dungeon */
3387 alloc_object(Depth, ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3));
3388 alloc_object(Depth, ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3));
3389 }
3390
3391
3392
3393 /*
3394 * Builds a store at a given (row, column)
3395 *
3396 * Note that the solid perma-walls are at x=0/65 and y=0/21
3397 *
3398 * As of 2.7.4 (?) the stores are placed in a more "user friendly"
3399 * configuration, such that the four "center" buildings always
3400 * have at least four grids between them, to allow easy running,
3401 * and the store doors tend to face the middle of town.
3402 *
3403 * The stores now lie inside boxes from 3-9 and 12-18 vertically,
3404 * and from 7-17, 21-31, 35-45, 49-59. Note that there are thus
3405 * always at least 2 open grids between any disconnected walls.
3406 */
build_store(int n,int yy,int xx)3407 static void build_store(int n, int yy, int xx)
3408 {
3409 int i, y, x, y0, x0, y1, x1, y2, x2, tmp;
3410
3411 cave_type *c_ptr;
3412
3413 y0 = yy * 11 + 5;
3414 x0 = xx * 16 + 12;
3415
3416 /* Determine the store boundaries */
3417 y1 = y0 - randint1((yy == 0) ? 3 : 2);
3418 y2 = y0 + randint1((yy == 1) ? 3 : 2);
3419 x1 = x0 - randint1(5);
3420 x2 = x0 + randint1(5);
3421
3422 /* Hack -- make building's as large as possible */
3423 //if (n == 12)
3424 //{
3425 y1 = y0 - randint1(3);
3426 y2 = y0 + randint1(3);
3427 x1 = x0 - randint1(5);
3428 x2 = x0 + randint1(5);
3429 //}
3430
3431 /* Build an invulnerable rectangular building */
3432 for (y = y1; y <= y2; y++)
3433 {
3434 for (x = x1; x <= x2; x++)
3435 {
3436 /* Get the grid */
3437 c_ptr = &cave[0][y][x];
3438
3439 /* Clear previous contents, add "basic" perma-wall */
3440 c_ptr->feat = FEAT_PERM_EXTRA;
3441
3442 /* Hack -- The buildings are illuminated and known */
3443 /* c_ptr->info |= (CAVE_GLOW); */
3444 }
3445 }
3446
3447 /* Hack -- Make store "8" (the old home) empty */
3448 if (n == 7)
3449 {
3450 for (y = y1 + 1; y < y2; y++)
3451 {
3452 for (x = x1 + 1; x < x2; x++)
3453 {
3454 /* Get the grid */
3455 c_ptr = &cave[0][y][x];
3456
3457 /* Clear contents */
3458 c_ptr->feat = FEAT_FLOOR;
3459
3460 /* Declare this to be a room */
3461 c_ptr->info |= CAVE_ROOM | CAVE_GLOW | CAVE_ICKY;
3462 }
3463 }
3464
3465 /* Hack -- have everyone start in the tavern */
3466 level_down_y[0] = (y1 + y2) / 2;
3467 level_down_x[0] = (x1 + x2) / 2;
3468 }
3469
3470 /* Make doorways, fill with grass and trees */
3471 if (n == 9)
3472 {
3473 for (y = y1 + 1; y < y2; y++)
3474 {
3475 for (x = x1 + 1; x < x2; x++)
3476 {
3477 /* Get the grid */
3478 c_ptr = &cave[0][y][x];
3479
3480 /* Clear contents */
3481 c_ptr->feat = FEAT_GRASS;
3482 }
3483 }
3484
3485 y = (y1 + y2) / 2;
3486 x = (x1 + x2) / 2;
3487
3488 cave[0][y1][x].feat = FEAT_GRASS;
3489 cave[0][y2][x].feat = FEAT_GRASS;
3490 cave[0][y][x1].feat = FEAT_GRASS;
3491 cave[0][y][x2].feat = FEAT_GRASS;
3492
3493 for (i = 0; i < 5; i++)
3494 {
3495 if (trees_in_town == cfg_max_trees && cfg_max_trees != -1) break;
3496
3497 y = rand_range(y1 + 1, y2 - 1);
3498 x = rand_range(x1 + 1, x2 - 1);
3499
3500 c_ptr = &cave[0][y][x];
3501
3502 c_ptr->feat = FEAT_TREE;
3503 trees_in_town++;
3504 }
3505
3506 return;
3507 }
3508
3509 /* Pond */
3510 if (n == 10)
3511 {
3512 for (y = y1; y <= y2; y++)
3513 {
3514 for (x = x1; x <= x2; x++)
3515 {
3516 /* Get the grid */
3517 c_ptr = &cave[0][y][x];
3518
3519 /* Fill with water */
3520 c_ptr->feat = FEAT_WATER;
3521 }
3522 }
3523
3524 /* Make the pond not so "square" */
3525 cave[0][y1][x1].feat = FEAT_DIRT;
3526 cave[0][y1][x2].feat = FEAT_DIRT;
3527 cave[0][y2][x1].feat = FEAT_DIRT;
3528 cave[0][y2][x2].feat = FEAT_DIRT;
3529
3530 return;
3531 }
3532
3533 /* Building with stairs */
3534 if (n == 11)
3535 {
3536 for (y = y1; y <= y2; y++)
3537 {
3538 for (x = x1; x <= x2; x++)
3539 {
3540 /* Get the grid */
3541 c_ptr = &cave[0][y][x];
3542
3543 /* Empty it */
3544 c_ptr->feat = FEAT_FLOOR;
3545
3546 /* Put some grass */
3547 if (randint1(100) < 50)
3548 c_ptr->feat = FEAT_GRASS;
3549 }
3550 }
3551
3552 x = (x1 + x2) / 2;
3553 y = (y1 + y2) / 2;
3554
3555 /* Access the stair grid */
3556 c_ptr = &cave[0][y][x];
3557
3558 /* Clear previous contents, add down stairs */
3559 c_ptr->feat = FEAT_MORE;
3560
3561 /* Hack -- the players start on the stairs while coming up */
3562 level_up_y[0] = level_rand_y[0] = y;
3563 level_up_x[0] = level_rand_x[0] = x;
3564
3565 return;
3566 }
3567
3568 /* Forest */
3569 if (n == 12)
3570 {
3571 int xc, yc, max_dis;
3572 int size = (y2 - y1 + 1) * (x2 - x1 + 1);
3573 bool limit_trees = ((cfg_max_trees > 0) && (size > (cfg_max_trees / 4)));
3574 int max_chance = (limit_trees? (100 * (cfg_max_trees / 4)): (100 * size));
3575
3576 /* Find the center of the forested area */
3577 xc = (x1 + x2) / 2;
3578 yc = (y1 + y2) / 2;
3579
3580 /* Find the max distance from center */
3581 max_dis = distance(y2, x2, yc, xc);
3582
3583 for (y = y1; y <= y2; y++)
3584 {
3585 for (x = x1; x <= x2; x++)
3586 {
3587 int chance;
3588
3589 /* Get the grid */
3590 c_ptr = &cave[0][y][x];
3591
3592 /* Empty it */
3593 c_ptr->feat = FEAT_GRASS;
3594
3595 /* Calculate chance of a tree */
3596 chance = 100 * (distance(y, x, yc, xc));
3597 chance /= max_dis;
3598 chance = 80 - chance;
3599 chance *= size;
3600
3601 /* We want at most (cfg_max_trees / 4) trees */
3602 if (limit_trees && (chance > max_chance)) chance = max_chance;
3603
3604 /* Put some trees */
3605 if (randint1(100 * size) < chance && (trees_in_town < cfg_max_trees || cfg_max_trees == -1))
3606 {
3607 c_ptr->feat = FEAT_TREE;
3608 trees_in_town++;
3609 }
3610 }
3611 }
3612
3613 return;
3614 }
3615
3616
3617 /* House */
3618 if (n == 13)
3619 {
3620 int price;
3621
3622 for (y = y1 + 1; y < y2; y++)
3623 {
3624 for (x = x1 + 1; x < x2; x++)
3625 {
3626 /* Get the grid */
3627 c_ptr = &cave[0][y][x];
3628
3629 /* Fill with floor */
3630 c_ptr->feat = FEAT_FLOOR;
3631
3632 /* Make it "icky" */
3633 c_ptr->info |= CAVE_ICKY;
3634 }
3635 }
3636
3637 /* Setup some "house info" */
3638 price = (x2 - x1 - 1) * (y2 - y1 - 1);
3639 /*price *= 20 * price; -APD- price is now proportional to size*/
3640 price *= 20;
3641 price *= 80 + randint1(40);
3642
3643 /* Remember price */
3644 houses[num_houses].price = price;
3645 houses[num_houses].x_1 = x1+1;
3646 houses[num_houses].y_1 = y1+1;
3647 houses[num_houses].x_2 = x2-1;
3648 houses[num_houses].y_2 = y2-1;
3649 houses[num_houses].depth = 0;
3650 }
3651
3652
3653 /* Pick a door direction (S,N,E,W) */
3654 tmp = randint0(4);
3655
3656 /* Re-roll "annoying" doors */
3657 while (((tmp == 0) && ((yy % 2) == 1)) ||
3658 ((tmp == 1) && ((yy % 2) == 0)) ||
3659 ((tmp == 2) && ((xx % 2) == 1)) ||
3660 ((tmp == 3) && ((xx % 2) == 0)))
3661 {
3662 /* Pick a new direction */
3663 tmp = randint0(4);
3664 }
3665
3666 /* Extract a "door location" */
3667 switch (tmp)
3668 {
3669 /* Bottom side */
3670 case 0:
3671 y = y2;
3672 x = rand_range(x1, x2);
3673 break;
3674
3675 /* Top side */
3676 case 1:
3677 y = y1;
3678 x = rand_range(x1, x2);
3679 break;
3680
3681 /* Right side */
3682 case 2:
3683 y = rand_range(y1, y2);
3684 x = x2;
3685 break;
3686
3687 /* Left side */
3688 default:
3689 y = rand_range(y1, y2);
3690 x = x1;
3691 break;
3692 }
3693
3694 /* Access the grid */
3695 c_ptr = &cave[0][y][x];
3696
3697 /* Some buildings get special doors */
3698 if (n == 13)
3699 {
3700 c_ptr->feat = FEAT_HOME_HEAD + houses[num_houses].strength;
3701
3702 /* hack -- only create houses that aren't already loaded from disk */
3703 if ((tmp = pick_house(0, y, x)) == -1)
3704 {
3705 /* Store door location information */
3706 houses[num_houses].door_y = y;
3707 houses[num_houses].door_x = x;
3708 houses[num_houses].owned[0] = '\0';
3709
3710 /* One more house */
3711 num_houses++;
3712 }
3713 else
3714 {
3715 c_ptr->feat = FEAT_HOME_HEAD + houses[tmp].strength;
3716 }
3717 }
3718 else if (n == 14) // auctionhouse
3719 {
3720 c_ptr->feat = FEAT_PERM_EXTRA; // wants to work.
3721
3722 }
3723 else
3724 {
3725 /* Clear previous contents, add a store door */
3726 c_ptr->feat = FEAT_SHOP_HEAD + n;
3727
3728 /* If this is the Black Market add the "back room" */
3729 if (n == 6)
3730 {
3731 /* At the back :) */
3732 if (y == y2) y = y1; else if (y == y1) y = y2;
3733 if (x == x2) x = x1; else if (x == x1) x = x2;
3734 c_ptr = &cave[0][y][x];
3735 /* Disabled */
3736 /* c_ptr->feat = FEAT_SHOP_HEAD + 8; */
3737
3738 }
3739 }
3740 }
3741
3742 /*
3743 * Build a road.
3744 */
place_street(int vert,int place)3745 static void place_street(int vert, int place)
3746 {
3747 int y, x, y1, y2, x1, x2;
3748
3749 /* Vertical streets */
3750 if (vert)
3751 {
3752 x = place * 32 + 20;
3753 x1 = x - 2;
3754 x2 = x + 2;
3755
3756 y1 = 5;
3757 y2 = MAX_HGT - 5;
3758 }
3759 else
3760 {
3761 y = place * 22 + 10;
3762 y1 = y - 2;
3763 y2 = y + 2;
3764
3765 x1 = 5;
3766 x2 = MAX_WID - 5;
3767 }
3768
3769 for (y = y1; y <= y2; y++)
3770 {
3771 for (x = x1; x <= x2; x++)
3772 {
3773 if (cave[0][y][x].feat != FEAT_FLOOR)
3774 cave[0][y][x].feat = FEAT_GRASS;
3775 }
3776 }
3777
3778 if (vert)
3779 {
3780 x1++;
3781 x2--;
3782 }
3783 else
3784 {
3785 y1++;
3786 y2--;
3787 }
3788
3789 for (y = y1; y <= y2; y++)
3790 {
3791 for (x = x1; x <= x2; x++)
3792 {
3793 cave[0][y][x].feat = FEAT_FLOOR;
3794 }
3795 }
3796 }
3797
3798
3799
3800 /*
3801 * Generate the "consistent" town features, and place the player
3802 *
3803 * Hack -- play with the R.N.G. to always yield the same town
3804 * layout, including the size and shape of the buildings, the
3805 * locations of the doorways, and the location of the stairs.
3806 */
town_gen_hack(void)3807 static void town_gen_hack(void)
3808 {
3809 int y, x, k, n;
3810
3811 #ifdef DEVEL_TOWN_COMPATIBILITY
3812 /* -APD- the location of the auction house */
3813 int auction_x, auction_y;
3814 #endif
3815
3816 int rooms[72];
3817 /* int rooms[MAX_STORES]; */
3818
3819 /* Hack limit trees to max/4 */
3820 int size = (MAX_HGT - 2) * (MAX_WID - 2);
3821 bool limit_trees = ((cfg_max_trees > 0) && (size > (cfg_max_trees / 4)));
3822 int max_chance = (limit_trees? (100 * (cfg_max_trees / 4)): (100 * size));
3823 int chance;
3824 /* Reset counter */
3825 trees_in_town = 0;
3826 /* Calculate chance of a tree */
3827 chance = 4 * size;
3828 /* We want at most (cfg_max_trees / 4) trees */
3829 if (limit_trees && (chance > max_chance)) chance = max_chance;
3830
3831 /* Hack -- Use the "simple" RNG */
3832 Rand_quick = TRUE;
3833
3834 /* Hack -- Induce consistant town layout */
3835 Rand_value = seed_town;
3836
3837 /* Hack -- Start with basic floors */
3838 for (y = 1; y < MAX_HGT - 1; y++)
3839 {
3840 for (x = 1; x < MAX_WID - 1; x++)
3841 {
3842 cave_type *c_ptr = &cave[0][y][x];
3843
3844 /* Clear all features, set to "empty floor" */
3845 c_ptr->feat = FEAT_DIRT;
3846
3847 if (randint0(100 * size) < chance && (cfg_max_trees == -1 || trees_in_town < cfg_max_trees))
3848 {
3849 c_ptr->feat = FEAT_TREE;
3850 trees_in_town++;
3851 }
3852
3853 else if (randint0(100) < 75)
3854 {
3855 c_ptr->feat = FEAT_GRASS;
3856 }
3857 }
3858 }
3859
3860 /* Place horizontal "streets" */
3861 for (y = 0; y < 3; y++)
3862 {
3863 place_street(0, y);
3864 }
3865
3866 /* Place vertical "streets" */
3867 for (x = 0; x < 6; x++)
3868 {
3869 place_street(1, x);
3870 }
3871
3872 /* Prepare an Array of "remaining stores", and count them */
3873 for (n = 0; n < MAX_STORES-1; n++) rooms[n] = n;
3874 for (n = MAX_STORES-1; n < 16; n++) rooms[n] = 10;
3875 for (n = 16; n < 68; n++) rooms[n] = 13;
3876 for (n = 68; n < 71; n++) rooms[n] = 12; /* 3 forests */
3877 rooms[n++] = 11;
3878
3879 /* Place stores */
3880 for (y = 2; y < 4; y++)
3881 {
3882 for (x = 4; x < 8; x++)
3883 {
3884 /* Pick a random unplaced store */
3885 k = randint0(n - 64);
3886
3887 /* Build that store at the proper location */
3888 build_store(rooms[k], y, x);
3889
3890 /* One less store */
3891 n--;
3892
3893 /* Shift the stores down, remove one store */
3894 rooms[k] = rooms[n - 64];
3895 }
3896 }
3897
3898 /* Place two rows of stores */
3899 for (y = 0; y < 6; y++)
3900 {
3901 /* Place four stores per row */
3902 for (x = 0; x < 12; x++)
3903 {
3904 /* Make sure we haven't already placed this one */
3905 if (y >= 2 && y <= 3 && x >= 4 && x <= 7) continue;
3906
3907 /* Pick a random unplaced store */
3908 k = randint0(n) + 8;
3909
3910 build_store(rooms[k], y, x);
3911
3912 /* One less building */
3913 n--;
3914
3915 /* Shift the stores down, remove one store */
3916 rooms[k] = rooms[n + 8];
3917 }
3918 }
3919
3920 /* Hack -- use the "complex" RNG */
3921 Rand_quick = FALSE;
3922 }
3923
3924
3925
3926
3927 /*
3928 * Town logic flow for generation of new town
3929 *
3930 * We start with a fully wiped cave of normal floors.
3931 *
3932 * Note that town_gen_hack() plays games with the R.N.G.
3933 *
3934 * This function does NOT do anything about the owners of the stores,
3935 * nor the contents thereof. It only handles the physical layout.
3936 *
3937 * We place the player on the stairs at the same time we make them.
3938 *
3939 * Hack -- since the player always leaves the dungeon by the stairs,
3940 * he is always placed on the stairs, even if he left the dungeon via
3941 * word of recall or teleport level.
3942 */
3943
3944 /*
3945 Hack -- since boundary walls are a 'good thing' for many of the algorithms
3946 used, the feature FEAT_PERM_CLEAR was created. It is used to create an
3947 invisible boundary wall for town and wilderness levels, keeping the
3948 algorithms happy, and the players fooled.
3949
3950 */
3951
town_gen(void)3952 static void town_gen(void)
3953 {
3954 int y, x;
3955 cave_type *c_ptr;
3956
3957 byte wall_feat;
3958 if (!cfg_town_wall) wall_feat = FEAT_PERM_CLEAR;
3959 else wall_feat = FEAT_PERM_SOLID;
3960
3961 /* Perma-walls -- North/South*/
3962 for (x = 0; x < MAX_WID; x++)
3963 {
3964 /* North wall */
3965 c_ptr = &cave[0][0][x];
3966
3967 /* Clear previous contents, add "clear" perma-wall */
3968 c_ptr->feat = wall_feat;
3969
3970 /* Illuminate and memorize the walls
3971 c_ptr->info |= (CAVE_GLOW | CAVE_MARK);*/
3972
3973 /* South wall */
3974 c_ptr = &cave[0][MAX_HGT-1][x];
3975
3976 /* Clear previous contents, add "clear" perma-wall */
3977 c_ptr->feat = wall_feat;
3978
3979 /* Illuminate and memorize the walls
3980 c_ptr->info |= (CAVE_GLOW);*/
3981 }
3982
3983 /* Perma-walls -- West/East */
3984 for (y = 0; y < MAX_HGT; y++)
3985 {
3986 /* West wall */
3987 c_ptr = &cave[0][y][0];
3988
3989 /* Clear previous contents, add "clear" perma-wall */
3990 c_ptr->feat = wall_feat;
3991
3992 /* Illuminate and memorize the walls
3993 c_ptr->info |= (CAVE_GLOW);*/
3994
3995 /* East wall */
3996 c_ptr = &cave[0][y][MAX_WID-1];
3997
3998 /* Clear previous contents, add "clear" perma-wall */
3999 c_ptr->feat = wall_feat;
4000
4001 /* Illuminate and memorize the walls
4002 c_ptr->info |= (CAVE_GLOW);*/
4003 }
4004
4005
4006 /* Hack -- Build the buildings/stairs (from memory) */
4007 town_gen_hack();
4008
4009
4010 /* Day Light */
4011 if ((turn.turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2))
4012 {
4013 /* Lite up the town */
4014 for (y = 0; y < MAX_HGT; y++)
4015 {
4016 for (x = 0; x < MAX_WID; x++)
4017 {
4018 c_ptr = &cave[0][y][x];
4019
4020 /* Perma-Lite */
4021 c_ptr->info |= CAVE_GLOW;
4022
4023 /* Memorize
4024 if (view_perma_grids) c_ptr->info |= CAVE_MARK;
4025 */
4026 }
4027 }
4028
4029 /* This has been disabled, since the old monsters will now be saved when
4030 * the server goes down. -APD
4031 */
4032 /* Make some day-time residents
4033 for (i = 0; i < MIN_M_ALLOC_TD; i++) (void)alloc_monster(0, 3, TRUE);
4034 */
4035 }
4036 /* Night Time */
4037 else
4038 {
4039 /* Make some night-time residents
4040 for (i = 0; i < MIN_M_ALLOC_TN; i++) (void)alloc_monster(0, 3, TRUE);
4041 */
4042 }
4043 }
4044
4045
4046
4047
4048
4049 /*
4050 * Allocate the space needed for a dungeon level
4051 */
alloc_dungeon_level(int Depth)4052 void alloc_dungeon_level(int Depth)
4053 {
4054 int i;
4055
4056 /* Allocate the array of rows */
4057 C_MAKE(cave[Depth], MAX_HGT, cave_type *);
4058
4059 /* Allocate each row */
4060 for (i = 0; i < MAX_HGT; i++)
4061 {
4062 /* Allocate it */
4063 C_MAKE(cave[Depth][i], MAX_WID, cave_type);
4064 }
4065 }
4066
4067 /*
4068 * Deallocate the space needed for a dungeon level
4069 */
dealloc_dungeon_level(int Depth)4070 void dealloc_dungeon_level(int Depth)
4071 {
4072 int i;
4073
4074 /* Hack to compensate for the half baked hacks below! */
4075 /* Don't deallocate levels which contain houses owned by players */
4076 for (i = 0; i < num_houses; i++)
4077 {
4078 /* House on this depth and owned? */
4079 if (houses[i].depth == Depth && house_owned(i))
4080 {
4081 return;
4082 }
4083 }
4084
4085 /* Delete any monsters on that level */
4086 /* Hack -- don't wipe wilderness monsters */
4087 if (Depth > 0) wipe_m_list(Depth);
4088
4089 /* Delete any objects on that level */
4090 /* Hack -- don't wipe wilderness objects */
4091 if (Depth > 0) wipe_o_list(Depth);
4092
4093 /* Free up the space taken by each row */
4094 for (i = 0; i < MAX_HGT; i++)
4095 {
4096 /* Dealloc that row */
4097 FREE(cave[Depth][i]);
4098 }
4099
4100 /* Deallocate the array of rows */
4101 FREE(cave[Depth]);
4102
4103 /* Set that level to "ungenerated" */
4104 cave[Depth] = NULL;
4105 }
4106
4107
4108
4109
4110 /*
4111 * Generates a random dungeon level -RAK-
4112 *
4113 * Hack -- regenerate any "overflow" levels
4114 *
4115 * Hack -- allow auto-scumming via a gameplay option.
4116 */
4117
4118
generate_cave(player_type * p_ptr,int Depth,int auto_scum)4119 void generate_cave(player_type *p_ptr, int Depth, int auto_scum)
4120 {
4121 int i, num;
4122 int scum = auto_scum;
4123
4124 /* No dungeon yet */
4125 server_dungeon = FALSE;
4126
4127 /* Default room align */
4128 dungeon_align = TRUE;
4129
4130 /* get the player context, if any */
4131 if (p_ptr)
4132 {
4133 dungeon_align = option_p(p_ptr,DUNGEON_ALIGN);
4134 }
4135
4136 /* Generate */
4137 for (num = 0; TRUE; num++)
4138 {
4139 bool okay = TRUE;
4140
4141 cptr why = NULL;
4142
4143
4144 /* Hack -- Reset heaps */
4145 /*o_max = 1;
4146 m_max = 1;*/
4147
4148 /* Start with a blank cave */
4149 for (i = 0; i < MAX_HGT; i++)
4150 {
4151 /* Wipe a whole row at a time */
4152 C_WIPE(cave[Depth][i], MAX_WID, cave_type);
4153 }
4154
4155
4156 /* Mega-Hack -- no player yet */
4157 /*px = py = 0;*/
4158
4159
4160 /* Mega-Hack -- no panel yet */
4161 /*panel_row_min = 0;
4162 panel_row_max = 0;
4163 panel_col_min = 0;
4164 panel_col_max = 0;*/
4165
4166
4167 /* Reset the monster generation level */
4168 monster_level = Depth;
4169
4170 /* Reset the object generation level */
4171 object_level = Depth;
4172
4173 /* Nothing special here yet */
4174 good_item_flag = FALSE;
4175
4176 /* Nothing good here yet */
4177 rating = 0;
4178
4179
4180 /* Build the town */
4181 if (!Depth)
4182 {
4183 /* Small town */
4184 /*cur_hgt = SCREEN_HGT;
4185 cur_wid = SCREEN_WID;*/
4186
4187 /* Determine number of panels */
4188 /*max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
4189 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;*/
4190
4191 /* Try again */
4192 /* Assume illegal panel */
4193 /*panel_row = max_panel_rows;
4194 panel_col = max_panel_cols;*/
4195
4196 /* Make a town */
4197 town_gen();
4198 }
4199
4200 /* Build wilderness */
4201 else if (Depth < 0)
4202 {
4203 wilderness_gen(Depth);
4204 }
4205
4206 /* Build a real level */
4207 else
4208 {
4209 /* Big dungeon */
4210 /*cur_hgt = MAX_HGT;
4211 cur_wid = MAX_WID;*/
4212
4213 /* Determine number of panels */
4214 /*max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
4215 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;*/
4216
4217 /* Assume illegal panel */
4218 /*panel_row = max_panel_rows;
4219 panel_col = max_panel_cols;*/
4220
4221 /* Make a dungeon */
4222 cave_gen(Depth);
4223 }
4224
4225
4226 /* Extract the feeling */
4227 if (rating > 100) feeling = 2;
4228 else if (rating > 80) feeling = 3;
4229 else if (rating > 60) feeling = 4;
4230 else if (rating > 40) feeling = 5;
4231 else if (rating > 30) feeling = 6;
4232 else if (rating > 20) feeling = 7;
4233 else if (rating > 10) feeling = 8;
4234 else if (rating > 0) feeling = 9;
4235 else feeling = 10;
4236 /* fprintf(stderr," New Level %d Rating %d\n",Depth*50,rating); */
4237
4238 /* Hack -- Have a special feeling sometimes */
4239 if (good_item_flag) feeling = 1;
4240
4241 if (!cfg_ironman && p_ptr)
4242 {
4243 /* It takes 1000 game turns for "feelings" to recharge */
4244 if (!ht_passed(&turn, &p_ptr->old_turn, 1000))
4245 {
4246 feeling = 0;
4247 scum = FALSE;
4248 }
4249 }
4250
4251 /* Hack -- no feeling in the town */
4252 if (!Depth) feeling = 0;
4253
4254
4255 /* Prevent object over-flow */
4256 if (o_max >= MAX_O_IDX)
4257 {
4258 /* Message */
4259 why = "too many objects";
4260
4261 /* Message */
4262 okay = FALSE;
4263 }
4264
4265 /* Prevent monster over-flow */
4266 if (m_max >= MAX_M_IDX)
4267 {
4268 /* Message */
4269 why = "too many monsters";
4270
4271 /* Message */
4272 okay = FALSE;
4273 }
4274
4275 /* Mega-Hack -- "auto-scum" */
4276 /* Auto-scum only in the dungeon!!! */
4277 if ((Depth > 0) && scum && (num < 100))
4278 {
4279 /* fprintf(stderr,"auto_scum in on for this level\n"); */
4280 /* Require "goodness" */
4281 if ((feeling > 9) ||
4282 ((Depth >= 5) && (feeling > 8)) ||
4283 ((Depth >= 10) && (feeling > 7)) ||
4284 ((Depth >= 20) && (feeling > 6)) ||
4285 /* Try again */
4286 ((Depth >= 40) && (feeling > 5)))
4287 {
4288 #if 0
4289 /* Give message to cheaters */
4290 if (cheat_room || cheat_hear ||
4291 cheat_peek || cheat_xtra)
4292 {
4293 /* Message */
4294 why = "boring level";
4295 }
4296 #endif
4297 /* Try again */
4298 okay = FALSE;
4299 }
4300 }
4301
4302 /* Accept */
4303 if (okay) break;
4304
4305
4306 /* Message */
4307 if (why) plog(format("Generation restarted (%s)", why));
4308
4309 /* Wipe the objects */
4310 wipe_o_list(Depth);
4311
4312 /* Wipe the monsters */
4313 wipe_m_list(Depth);
4314
4315 /* Compact some objects, if necessary */
4316 if (o_max >= MAX_O_IDX * 3 / 4)
4317 compact_objects(32);
4318
4319 /* Compact some monsters, if necessary */
4320 if (m_max >= MAX_M_IDX * 3 / 4)
4321 compact_monsters(32);
4322 }
4323
4324 /* Remember when we had a level feeling if we are a player */
4325 if(p_ptr)
4326 {
4327 p_ptr->old_turn = turn;
4328 }
4329
4330 /* Remember when we generated this level */
4331 turn_cavegen[Depth] = turn;
4332
4333 /* Dungeon level ready */
4334 server_dungeon = TRUE;
4335 }
4336