Ticket #156: generate.c

File generate.c, 114.1 KB (added by takkaria, 12 years ago)

New generate.c for V 2.9.3

Line 
1
2/* File: generate.c */
3
4/*
5 * Dungeon generation
6 *
7 * Code for making, stocking, and populating levels when generated. 
8 * Includes rooms of every kind, pits, vaults (inc. interpretation of
9 * vault.txt), streamers, tunnelling, etc.  Level feelings and other
10 * messages, autoscummer behavior.  Creation of the town.
11 *
12 * Copyright (c) 2001 Ben Harrison, James E. Wilson, Robert A. Koeneke
13 *
14 * This software may be copied and distributed for educational, research,
15 * and not for profit purposes provided that this copyright and statement
16 * are included in all such copies.  Other copyrights may also apply.
17 */
18
19#include "angband.h"
20
21
22
23/*
24 * Level generation is not an important bottleneck, though it can be
25 * annoyingly slow on older machines...  Thus we emphasize simplicity
26 * and correctness over speed.  See individual functions for notes.
27 *
28 * This entire file is only needed for generating levels.
29 * This may allow smart compilers to only load it when needed.
30 *
31 * The "vault.txt" file is used to store vault generation info.
32 */
33
34
35/*
36 * Dungeon generation values
37 */
38#define DUN_ROOMS                       30      /* Number of rooms to attempt */
39#define DEST_LEVEL_CHANCE       30      /* 1/chance of being a destroyed level */
40
41
42/*
43 * Dungeon tunnel generation values
44 */
45#define DUN_TUN_RND     30      /* 1 in # chance of random direction */
46#define DUN_TUN_ADJ     10      /* 1 in # chance of adjusting direction */
47#define DUN_TUN_PEN     35      /* Chance of doors at room entrances */
48#define DUN_TUN_JCT     70     /* Chance of doors at tunnel junctions */
49
50/*
51 * Dungeon streamer generation values
52 */
53#define DUN_STR_WID     2       /* Width of streamers (can sometimes be higher) */
54#define DUN_STR_MAG     3       /* Number of magma streamers */
55#define DUN_STR_MC      70      /* 1/chance of treasure per magma */
56#define DUN_STR_QUA     2       /* Number of quartz streamers */
57#define DUN_STR_QC      35      /* 1/chance of treasure per quartz */
58#define DUN_STR_CHG     16      /* 1/(4 + chance) of altering direction */
59
60/*
61 * Dungeon treasure allocation values
62 */
63#define DUN_AMT_ROOM    9       /* Amount of objects for rooms */
64#define DUN_AMT_ITEM    3       /* Amount of objects for rooms/corridors */
65#define DUN_AMT_GOLD    3       /* Amount of treasure for rooms/corridors */
66
67/*
68 * Hack -- Dungeon allocation "places"
69 */
70#define ALLOC_SET_CORR          1       /* Hallway */
71#define ALLOC_SET_ROOM          2       /* Room */
72#define ALLOC_SET_BOTH          3       /* Anywhere */
73
74/*
75 * Hack -- Dungeon allocation "types"
76 */
77#define ALLOC_TYP_RUBBLE        1       /* Rubble */
78#define ALLOC_TYP_TRAP          3       /* Trap */
79#define ALLOC_TYP_GOLD          4       /* Gold */
80#define ALLOC_TYP_OBJECT        5       /* Object */
81
82
83/*
84 * Maximum numbers of rooms along each axis (currently 6x18)
85 */
86#define MAX_ROOMS_ROW   (DUNGEON_HGT / BLOCK_HGT)
87#define MAX_ROOMS_COL   (DUNGEON_WID / BLOCK_WID)
88
89/*
90 * Maximal number of room types
91 */
92#define ROOM_MAX        8
93
94/*
95 * Bounds on some arrays used in the "dun_data" structure.
96 * These bounds are checked, though usually this is a formality.
97 */
98#define CENT_MAX        DUN_ROOMS
99#define DOOR_MAX        100
100#define WALL_MAX        40
101#define TUNN_MAX        300
102#define STAIR_MAX       30
103
104/*
105 * Simple structure to hold a map location
106 */
107typedef struct coord coord;
108
109struct coord
110{
111        byte y;
112        byte x;
113};
114
115/*
116 * Structure to hold all dungeon generation data
117 */
118
119typedef struct dun_data dun_data;
120
121struct dun_data
122{
123        /* Array of centers of rooms */
124        int cent_n;
125        coord cent[CENT_MAX];
126
127        /* Array to store whether rooms are connected or not. */
128        bool connected[CENT_MAX];
129
130        /* Array of possible door locations */
131        int door_n;
132        coord door[DOOR_MAX];
133
134        /* Array of wall piercing locations */
135        int wall_n;
136        coord wall[WALL_MAX];
137
138        /* Array of tunnel grids */
139        int tunn_n;
140        coord tunn[TUNN_MAX];
141
142        /* Array of good potential stair grids */
143        int stair_n;
144        coord stair[STAIR_MAX];
145
146        /* Number of blocks along each axis */
147        int row_rooms;
148        int col_rooms;
149
150        /* Array to store block usage */
151        int room_map[MAX_ROOMS_ROW][MAX_ROOMS_COL];
152};
153
154/*
155 * Dungeon generation data -- see "cave_gen()"
156 */
157static dun_data *dun;
158
159
160/*
161 * Room type information
162 */
163typedef struct room_data room_data;
164
165struct room_data
166{
167        /* Allocation information. */
168        s16b room_gen_num[11];
169
170        /* Minimum level on which room can appear. */
171        byte min_level;
172};
173
174/*
175 * Table of values that control how many times each type of room will,
176 * on average, appear on 100 levels at various depths.  Each type of room
177 * has its own row, and each column corresponds to dungeon levels 0, 10,
178 * 20, and so on.  The final value is the minimum depth the room can appear
179 * at.  -LM-
180 *
181 * Level 101 and below use the values for level 100.
182 *
183 * Rooms with lots of monsters or loot may not be generated if the object or
184 * monster lists are already nearly full.  Rooms will not appear above their
185 * minimum depth.  No type of room (other than type 1) can appear more than
186 * DUN_ROOMS/2 times in any level.
187 *
188 * The entries for room type 1 are blank because these rooms are built once
189 * all other rooms are finished -- until the level fills up, or the room
190 * count reaches the limit (DUN_ROOMS).
191 */
192static room_data room[ROOM_MAX] =
193{
194   /* Depth:          0   10   20   30   40   50   60   70   80   90  100   min */
195
196   /* Nothing */  {{  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 },  0 },
197   /* Simple */   {{  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 },  0 },
198   /* Overlap */  {{ 60,  80, 100, 120, 140, 165, 180, 200, 220, 240, 260 },  1 },
199   /* Cross */    {{  0,  25,  50,  70,  85, 100, 110, 120, 130, 140, 150 },  3 },
200   /* Large */    {{  0,  25,  50,  70,  85, 100, 110, 120, 130, 140, 150 },  3 },
201   /* Pit      */ {{  0,   6,  13,  28,  35,  40,  45,  45,  45,  45,  45 },  5 },
202   /* L. Vault */ {{  0,   1,   4,   9,  16,  27,  40,  55,  70,  80,  90 },  5 },
203   /* G. Vault */ {{  0,   0,   1,   2,   3,   4,   6,   7,   8,  10,  12 }, 20 }
204};
205
206
207
208/*
209 * This table takes a depth, and returns a suitable monster symbol.  Depth
210 * input is assumed to be player depth.  It is also assumed that monsters
211 * can be generated slightly out of depth.  -LM-
212 *
213 * Depths greater than 60 should map to the row for level 60.
214 *
215 * - Symbol '*' is any creature of a randomly-chosen racial char.
216 * - Symbol '1' is any animal.
217 * - Symbol '2' is any insect ('a', 'c', 'l', 'F', 'I', 'K').
218 * - Symbol '3' is any naga, snake, hydra, or other reptile.
219 * - Symbol '4' is any jelly, mold, icky thing ('i', 'j', or 'm').
220 *
221 * - Symbol '%' is any orc, ogre, troll, or giant.
222 * - Symbol 'N' is any undead.  Upon occasion, deep in the dungeon, the
223 *   racial type may be forced to 'G', 'L', 'V', or 'W'.
224 * - Symbols 'p' and 'h' may sometimes be found in combination.  If they
225 *   are, they are usually all of a given class (magical, pious, natural,
226 *   assassination/thievery, or warrior)
227 * - Symbols 'E' and 'v' may be found in combination.  If they are, they
228 *   will always be of a given elemental type.
229 * - Symbols 'd' and 'D' both mean dragons of either char.  Dragons are
230 *   often of a particular type (blue, red, gold, shadow/ethereal etc.).
231 * - Symbols 'u' and 'U' may mean lesser demons, greater demons, or both,
232 *   depending on depth.
233 * - Symbol 'A' is angels.
234 *
235 * - Other symbols usually represent specific racial characters.
236 *
237 * 80% of the time, one of the first seven characters will be chosen. 
238 * 20% of the time, one of the last six will be.
239 */
240static char mon_symbol_at_depth[12][13] =
241{
242        /*      common pits                            rare pits         */
243
244        /* Levels 5, 10, 15, and 20 */
245        {'1', '1', '4', '4', '4', 'k', 'y',   '*', '*', '2', 'a', '3', 'S' },
246        {'1', '4', '4', 'o', 'o', 'N', '2',   '*', 'C', 'f', 'a', '3', 'S' },
247        {'1', '4', 'o', 'o', 'o', 'u', '*',   '#', '#', 'S', 'E', '3', 'Z' },
248        {'1', '4', '4', 'o', 'T', 'T', '#',   'p', 'h', 'f', '2', '*', 'Z' },
249
250        /* Levels 25, 30, 35, and 40 */
251        {'1', '4', 'T', 'T', 'u', 'P', 'P',   'p', 'v', 'd', '2', 'S', '3' },
252        {'1', '1', 'T', 'P', 'P', 'N', 'd',   'p', 'h', 'f', 'v', 'g', 'Z' },
253        {'1', '4', 'T', 'P', 'N', 'u', 'd',   'p', 'H', 'E', '2', '*', '3' },
254        {'1', '1', 'T', 'P', 'N', 'u', 'd',   'p', 'h', 'g', 'E', '*', 'Z' },
255
256        /* Levels 45, 50, 55, and 60 */
257        {'1', 'P', 'N', 'u', 'd', 'd', '*',   'p', 'h', 'v', 'E', '*', 'Z' },
258        {'N', 'N', 'U', 'U', 'D', 'D', '*',   'p', 'h', 'v', 'T', 'B', 'Z' },
259        {'1', 'N', 'U', 'U', 'D', 'D', '*',   'p', 'h', 'W', 'G', '*', 'Z' },
260        {'N', 'N', 'U', 'U', 'D', 'D', '*',   'p', 'h', 'v', '*', 'D', 'Z' }
261};
262
263/*
264 * Restrictions on monsters, used in pits, etc.
265 */
266static bool allow_unique;
267static char d_char_req[10];
268static byte d_attr_req[4];
269static u32b racial_flag_mask;
270static u32b breath_flag_mask;
271
272
273
274/*
275 * Table of monster descriptions.  Used to make descriptions for kinds
276 * of pits and rooms of chambers that have no special names.
277 */
278cptr d_char_req_desc[] =
279{
280        "B:bird",
281        "C:canine",
282        "D:dragon",
283        "E:elemental",
284        "F:dragon fly",
285        "G:ghost",
286        "H:hybrid",
287        "I:insect",
288        "J:snake",
289        "K:killer beetle",
290        "L:lich",
291        "M:multi-headed hydra",
292        "O:ogre",
293        "P:giant",
294        "Q:quylthulg",
295        "R:reptile",
296        "S:spider",
297        "T:troll",
298        "U:demon",
299        "V:vampire",
300        "W:wraith",
301        "Y:yeti",
302        "Z:zephyr hound",
303        "a:ant",
304        "b:bat",
305        "c:centipede",
306        "d:dragon",
307        "e:floating eye",
308        "f:feline",
309        "g:golem",
310        "h:humanoid",
311        "i:icky thing",
312        "j:jelly",
313        "k:kobold",
314        "l:louse",
315        "m:mold",
316        "n:naga",
317        "o:orc",
318        "p:human",
319        "q:quadruped",
320        "r:rodent",
321        "s:skeleton",
322        "t:townsperson",
323        "u:demon",
324        "v:vortex",
325        "w:worm",
326        "y:yeek",
327        "z:zombie",
328        ",:mushroom patch",
329        NULL
330};
331
332
333
334
335/**************************************************************/
336/*                                                            */
337/*                 The monster-selection code                 */
338/*                                                            */
339/**************************************************************/
340
341
342/*
343 * Use various selection criteria (set elsewhere) to restrict monster
344 * generation.
345 *
346 * This function is capable of selecting monsters by:
347 *   - racial symbol (may be any of the characters allowed)
348 *   - symbol color (may be any of up to four colors).
349 *   - racial flag(s) (monster may have any allowed flag)
350 *   - breath flag(s) (monster must have exactly the flags specified)
351 *
352 * Uniques may be forbidden, or allowed on rare occasions.
353 *
354 * Some situations (like the elemental war themed level) require special
355 * processing; this is done in helper functions called from this one.
356 */
357static bool mon_select(int r_idx)
358{
359        monster_race *r_ptr = &r_info[r_idx];
360        bool ok = FALSE;
361
362
363        /* Require that the monster symbol be correct. */
364        if (d_char_req[0] != '\0')
365        {
366                if (strchr(d_char_req, r_ptr->d_char) == 0) return (FALSE);
367        }
368
369        /* Require correct racial type. */
370        if (racial_flag_mask)
371        {
372                if (!(r_ptr->flags3 & (racial_flag_mask))) return (FALSE);
373
374                /* Hack -- no invisible undead until deep. */
375                if ((p_ptr->depth < 40) && (r_ptr->flags3 & (RF3_UNDEAD)) &&
376                        (r_ptr->flags2 & (RF2_INVISIBLE))) return (FALSE);
377        }
378
379        /* Require that monster breaths be exactly those specified. */
380        if (breath_flag_mask)
381        {
382                if (r_ptr->flags4 != breath_flag_mask) return (FALSE);
383        }
384
385        /* Require that the monster color be correct. */
386        if (d_attr_req[0])
387        {
388                /* Check all allowed colors, if given. */
389                if ((d_attr_req[0]) && (r_ptr->d_attr == d_attr_req[0])) ok = TRUE;
390                if ((d_attr_req[1]) && (r_ptr->d_attr == d_attr_req[1])) ok = TRUE;
391                if ((d_attr_req[2]) && (r_ptr->d_attr == d_attr_req[2])) ok = TRUE;
392                if ((d_attr_req[3]) && (r_ptr->d_attr == d_attr_req[3])) ok = TRUE;
393
394                /* Hack -- No multihued dragons allowed in the arcane dragon pit. */
395                if ((strchr(d_char_req, 'd') || strchr(d_char_req, 'D')) &&
396                        (d_attr_req[0] == TERM_VIOLET) &&
397                        (r_ptr->flags4 == (RF4_BR_ACID |
398                                RF4_BR_ELEC | RF4_BR_FIRE |
399                                RF4_BR_COLD | RF4_BR_POIS)))
400                {
401                        return (FALSE);
402                }
403
404                /* Doesn't match any of the given colors?  Not good. */
405                if (!ok) return (FALSE);
406        }
407
408        /* Usually decline unique monsters. */
409        if (r_ptr->flags1 & (RF1_UNIQUE))
410        {
411                if (!allow_unique) return (FALSE);
412                else if (rand_int(5) != 0) return (FALSE);
413        }
414
415        /* Okay */
416        return (TRUE);
417}
418
419
420/*
421 * Accept characters representing a race or group of monsters and
422 * an (adjusted) depth, and use these to set values for required racial
423 * type, monster symbol, monster symbol color, and breath type.  -LM-
424 *
425 * This function is called to set restrictions, point the monster
426 * allocation function to "mon_select()", and remake monster allocation. 
427 * It undoes all of this things when called with the symbol '\0'.
428 *
429 * Describe the monsters (used by cheat_room) and determine if they
430 * should be neatly ordered or randomly placed (used in monster pits).
431 */
432static char *mon_restrict(char symbol, byte depth, bool *ordered, bool unique_ok)
433{
434        int i, j;
435
436        /* Assume no definite name */
437        char name[80] = "misc";
438
439        /* Clear global monster restriction variables. */
440        allow_unique = unique_ok;
441        for (i = 0; i < 10; i++) d_char_req[i] = '\0';
442        for (i = 0; i < 4; i++) d_attr_req[i] = 0;
443        racial_flag_mask = 0; breath_flag_mask = 0;
444
445
446        /* No symbol, no restrictions. */
447        if (symbol == '\0')
448        {
449                get_mon_num_hook = NULL;
450                get_mon_num_prep();
451                return ("misc");
452        }
453
454        /* Handle the "wild card" symbol '*'  */
455        if (symbol == '*')
456        {
457                for (i = 0; i < 2500; i++)
458                {
459                        /* Get a random monster. */
460                        j = randint(z_info->r_max - 1);
461
462                        /* Must be a real monster */
463                        if (!r_info[j].rarity) continue;
464
465                        /* Try for close to depth, accept in-depth if necessary */
466                        if (i < 200)
467                        {
468                                if ((!(r_info[j].flags1 & RF1_UNIQUE)) &&
469                                      (r_info[j].level != 0) &&
470                                      (r_info[j].level <= depth) &&
471                                      (ABS(r_info[j].level - p_ptr->depth) <
472                                      1 + (p_ptr->depth / 4))) break;
473                        }
474                        else
475                        {
476                                if ((!(r_info[j].flags1 & RF1_UNIQUE)) &&
477                                      (r_info[j].level != 0) &&
478                                      (r_info[j].level <= depth)) break;
479                        }
480                }
481
482                /* We've found a monster. */
483                if (i < 2499)
484                {
485                        /* ...use that monster's symbol for all monsters. */
486                        symbol = r_info[j].d_char;
487                }
488                else
489                {
490                        /* Paranoia - pit stays empty if no monster is found */
491                        return (NULL);
492                }
493        }
494
495        /* Apply monster restrictions according to symbol. */
496        switch (symbol)
497        {
498                /* All animals */
499                case '1':
500                {
501                        strcpy(name, "animal");
502                        racial_flag_mask = RF3_ANIMAL;
503                        *ordered = FALSE;
504                        break;
505                }
506
507                /* Insects */
508                case '2':
509                {
510                        strcpy(name, "insect");
511                        strcpy(d_char_req, "aclFIK");
512                        *ordered = FALSE;
513                        break;
514                }
515
516                /* Reptiles */
517                case '3':
518                {
519                        strcpy(name, "reptile");
520                        strcpy(d_char_req, "nJRM");
521                        *ordered = FALSE;
522                        break;
523                }
524
525                /* Jellies, etc. */
526                case '4':
527                {
528                        strcpy(name, "jelly");
529                        strcpy(d_char_req, "ijm,");
530                        *ordered = FALSE;
531                        break;
532                }
533
534                /* Humans and humaniods */
535                case 'p':
536                case 'h':
537                {
538                        /* 'p's and 'h's can coexist. */
539                        if (rand_int(3) == 0)
540                        {
541                                strcpy(d_char_req, "ph");
542
543                                /* If so, they will usually all be of similar classes. */
544                                if (rand_int(4) != 0)
545                                {
546                                        /* Randomizer. */
547                                        i = rand_int(5);
548
549                                        /* Magicians and necromancers */
550                                        if (i == 0)
551                                        {
552                                                d_attr_req[0] = TERM_RED;
553                                                d_attr_req[1] = TERM_L_RED;
554                                                d_attr_req[2] = TERM_VIOLET;
555                                                strcpy(name, "school of sorcery");
556                                        }
557                                        /* Priests and paladins */
558                                        else if (i == 1)
559                                        {
560                                                d_attr_req[0] = TERM_GREEN;
561                                                d_attr_req[1] = TERM_L_GREEN;
562                                                d_attr_req[2] = TERM_WHITE;
563                                                d_attr_req[3] = TERM_L_WHITE;
564                                                strcpy(name, "temple of piety");
565                                        }
566                                        /* Druids and ninjas */
567                                        else if (i == 2)
568                                        {
569                                                d_attr_req[0] = TERM_ORANGE;
570                                                d_attr_req[1] = TERM_YELLOW;
571                                                strcpy(name, "gathering of nature");
572                                        }
573                                        /* Thieves and assassins */
574                                        else if (i == 3)
575                                        {
576                                                d_attr_req[0] = TERM_BLUE;
577                                                d_attr_req[1] = TERM_L_BLUE;
578                                                d_attr_req[2] = TERM_SLATE;
579                                                d_attr_req[3] = TERM_L_DARK;
580                                                strcpy(name, "den of thieves");
581                                        }
582                                        /* Warriors and rangers */
583                                        else
584                                        {
585                                                d_attr_req[0] = TERM_UMBER;
586                                                d_attr_req[1] = TERM_L_UMBER;
587                                                strcpy(name, "fighter's hall");
588                                        }
589                                }
590                                else
591                                {
592                                        strcpy(name, "humans and humaniods");
593                                }
594                        }
595
596                        /* Usually, just accept the symbol. */
597                        else
598                        {
599                                d_char_req[0] = symbol;
600
601                                if (symbol == 'p') strcpy(name, "human");
602                                else if (symbol == 'h') strcpy(name, "humanoid");
603                        }
604
605                        *ordered = FALSE;
606                        break;
607                }
608
609                /* Orcs */
610                case 'o':
611                {
612                        strcpy(name, "orc");
613                        strcpy(d_char_req, "o");
614                        *ordered = TRUE;
615                        break;
616                }
617
618                /* Trolls */
619                case 'T':
620                {
621                        strcpy(name, "troll");
622                        strcpy(d_char_req, "T");
623                        *ordered = TRUE;
624                        break;
625                }
626
627                /* Giants (sometimes ogres at low levels) */
628                case 'P':
629                {
630                        strcpy(name, "giant");
631                        if ((p_ptr->depth < 30) && (rand_int(3) == 0))
632                             strcpy(d_char_req, "O");
633                        else strcpy(d_char_req, "P");
634                        *ordered = TRUE;
635                        break;
636                }
637
638                /* Orcs, ogres, trolls, or giants */
639                case '%':
640                {
641                        strcpy(name, "moria");
642                        strcpy(d_char_req, "oOPT");
643                        *ordered = FALSE;
644                        break;
645                }
646
647                /* Monsters found in caves */
648                case '0':
649                {
650                        strcpy(name, "dungeon monsters");
651                        strcpy(d_char_req, "ykoOT");
652                        *ordered = FALSE;
653                        break;
654                }
655
656
657
658                /* Undead */
659                case 'N':
660                {
661                        /* Sometimes, restrict by symbol. */
662                        if ((depth > 40) && (rand_int(3) == 0))
663                        {
664                                for (i = 0; i < 500; i++)
665                                {
666                                        /* Find a suitable monster near depth. */
667                                        j = randint(z_info->r_max - 1);
668
669                                        /* Require a non-unique undead. */
670                                        if ((r_info[j].flags3 & RF3_UNDEAD) &&
671                                            (!(r_info[j].flags1 & RF1_UNIQUE)) &&
672                                            (strchr("GLWV", r_info[j].d_char)) &&
673                                            (ABS(r_info[j].level - p_ptr->depth) <
674                                            1 + (p_ptr->depth / 4)))
675                                        {
676                                                break;
677                                        }
678                                }
679
680                                /* If we find a monster, */
681                                if (i < 499)
682                                {
683                                        /* Use that monster's symbol for all monsters */
684                                        d_char_req[0] = r_info[j].d_char;
685
686                                        /* No pit name (yet) */
687
688                                        /* In this case, we do order the monsters */
689                                        *ordered = TRUE;
690                                }
691                                else
692                                {
693                                        /* Accept any undead. */
694                                        strcpy(name, "undead");
695                                        racial_flag_mask = RF3_UNDEAD;
696                                        *ordered = FALSE;
697                                }
698                        }
699                        else
700                        {
701                                /* No restrictions on symbol. */
702                                strcpy(name, "undead");
703                                racial_flag_mask = RF3_UNDEAD;
704                                *ordered = FALSE;
705                        }
706                        break;
707                }
708
709                /* Demons */
710                case 'u':
711                case 'U':
712                {
713                        strcpy(name, "demon");
714                        if (depth > 55)      strcpy(d_char_req, "U");
715                        else if (depth < 40) strcpy(d_char_req, "u");
716                        else                 strcpy(d_char_req, "uU");
717                        *ordered = TRUE;
718                        break;
719                }
720
721                /* Dragons */
722                case 'd':
723                case 'D':
724                {
725                        strcpy(d_char_req, "dD");
726
727                        /* Dragons usually associate with others of their kind. */
728                        if (rand_int(6) != 0)
729                        {
730                                /* Dragons of a single kind are ordered. */
731                                *ordered = TRUE;
732
733                                /* Some dragon types are not found everywhere */
734                                if (depth > 70) i = rand_int(35);
735                                else if (depth > 45) i = rand_int(32);
736                                else if (depth > 32) i = rand_int(30);
737                                else if (depth > 23) i = rand_int(28);
738                                else i = rand_int(24);
739
740                                if (i < 4)
741                                {
742                                        breath_flag_mask = (RF4_BR_ACID);
743                                        strcpy(name, "dragon - acid");
744                                }
745                                else if (i < 8)
746                                {
747                                        breath_flag_mask = (RF4_BR_ELEC);
748                                        strcpy(name, "dragon - electricity");
749                                }
750                                else if (i < 12)
751                                {
752                                        breath_flag_mask = (RF4_BR_FIRE);
753                                        strcpy(name, "dragon - fire");
754                                }
755                                else if (i < 16)
756                                {
757                                        breath_flag_mask = (RF4_BR_COLD);
758                                        strcpy(name, "dragon - cold");
759                                }
760                                else if (i < 20)
761                                {
762                                        breath_flag_mask = (RF4_BR_POIS);
763                                        strcpy(name, "dragon - poison");
764                                }
765                                else if (i < 24)
766                                {
767                                        breath_flag_mask = (RF4_BR_ACID |
768                                            RF4_BR_ELEC | RF4_BR_FIRE |
769                                            RF4_BR_COLD | RF4_BR_POIS);
770                                        strcpy(name, "dragon - multihued");
771                                }
772                                else if (i < 26)
773                                {
774                                        breath_flag_mask = (RF4_BR_CONF);
775                                        strcpy(name, "dragon - confusion");
776                                }
777                                else if (i < 28)
778                                {
779                                        breath_flag_mask = (RF4_BR_SOUN);
780                                        strcpy(name, "dragon - sound");
781                                }
782                                else if (i < 30)
783                                {
784                                        breath_flag_mask = (RF4_BR_LITE |
785                                                            RF4_BR_DARK);
786                                        strcpy(name, "dragon - ethereal");
787                                }
788
789                                /* Chaos, Law, Balance, Power, etc.) */
790                                else
791                                {
792                                        d_attr_req[0] = TERM_VIOLET;
793                                        d_attr_req[1] = TERM_L_BLUE;
794                                        d_attr_req[2] = TERM_L_GREEN;
795                                        strcpy(name, "dragon - arcane");
796                                }
797                        }
798                        else
799                        {
800                                strcpy(name, "dragon - mixed");
801
802                                /* Dragons of all kinds are not ordered. */
803                                *ordered = FALSE;
804                        }
805                        break;
806                }
807
808                /* Angels */
809                case 'A':
810                {
811                        strcpy(name, "angelic");
812                        strcpy(d_char_req, "A");
813                        *ordered = TRUE;
814                        break;
815                }
816
817                /* Vortexes and elementals */
818                case 'v':
819                case 'E':
820                {
821                        /* Usually, just have any kind of 'v' or 'E' */
822                        if (rand_int(3) != 0)
823                        {
824                                d_char_req[0] = symbol;
825
826                                if (symbol == 'v') strcpy(name, "vortex");
827                                if (symbol == 'E') strcpy(name, "elemental");
828                        }
829
830                        /* Sometimes, choose both 'v' and 'E's of one element */
831                        else
832                        {
833                                strcpy(d_char_req, "vE");
834
835                                i = rand_int(4);
836
837                                /* Fire */
838                                if (i == 0)
839                                {
840                                        d_attr_req[0] = TERM_RED;
841                                        strcpy(name, "fire");
842                                }
843                                /* Frost */
844                                if (i == 1)
845                                {
846                                        d_attr_req[0] = TERM_L_WHITE;
847                                        d_attr_req[1] = TERM_WHITE;
848                                        strcpy(name, "frost");
849                                }
850                                /* Air/electricity */
851                                if (i == 2)
852                                {
853                                        d_attr_req[0] = TERM_L_BLUE;
854                                        d_attr_req[1] = TERM_BLUE;
855                                        strcpy(name, "air");
856                                }
857                                /* Acid/water/earth */
858                                if (i == 3)
859                                {
860                                        d_attr_req[0] = TERM_GREEN;
861                                        d_attr_req[1] = TERM_L_UMBER;
862                                        d_attr_req[2] = TERM_UMBER;
863                                        d_attr_req[3] = TERM_SLATE;
864                                        strcpy(name, "earth & water");
865                                }
866                        }
867
868                        *ordered = FALSE;
869                        break;
870                }
871
872                /* Special case:  mimics and treasure */
873                case '!':
874                case '?':
875                case '=':
876                case '~':
877                case '|':
878                case '.':
879                case '$':
880                {
881                        if (symbol == '$')
882                        {
883                                strcpy(name, "treasure");
884
885                                /* Nothing but loot! */
886                                if (rand_int(3) == 0) strcpy(d_char_req, "$");
887
888                                /* Guard the money well. */
889                                else strcpy(d_char_req, "$!?=~|.");
890                        }
891                        else
892                        {
893                                /* No treasure. */
894                                strcpy(d_char_req, "!?=~|.");
895                                strcpy(name, "mimic");
896                        }
897
898                        *ordered = FALSE;
899                        break;
900                }
901
902                /* Special case:  creatures of earth. */
903                case 'X':
904                case '#':
905                {
906                        strcpy(d_char_req, "X#");
907                        strcpy(name, "creatures of earth");
908                        *ordered = FALSE;
909                        break;
910                }
911
912                /* Space for more monster types here. */
913
914
915                /* Any symbol not handled elsewhere. */
916                default:
917                {
918                        /* Accept the character. */
919                        d_char_req[0] = symbol;
920
921                        /* Some monsters should logically be ordered. */
922                        if (strchr("knosuyzGLMOPTUVW", symbol)) *ordered = TRUE;
923
924                        /* Most should not */
925                        else *ordered = FALSE;
926                       
927                        break;
928                }
929        }
930
931        /* If monster pit hasn't been named already, get a name. */
932        if (streq(name, "misc"))
933        {
934                /* Search a table for a description of the symbol */
935                for (i = 0; d_char_req_desc[i]; ++i)
936                {
937                        if (symbol == d_char_req_desc[i][0])
938                        {
939                                /* Get all but the 1st 2 characters of the text. */
940                                sprintf(name, "%s", d_char_req_desc[i] + 2);
941                                break;
942                        }
943                }
944        }
945
946        /* Apply our restrictions */
947        get_mon_num_hook = mon_select;
948
949        /* Prepare allocation table */
950        get_mon_num_prep();
951
952        /* Return the name. */
953        return (format("%s", name));
954}
955
956
957
958
959
960/**************************************************************/
961/*                                                            */
962/*            General dungeon-generation functions            */
963/*                                                            */
964/**************************************************************/
965
966
967/*
968 * Count the number of walls adjacent to the given grid.
969 *
970 * Note -- Assumes "in_bounds_fully(y, x)"
971 */
972static int next_to_walls(int y, int x)
973{
974        int k = 0;
975
976        if (cave_feat[y+1][x] >= FEAT_MAGMA) k++;
977        if (cave_feat[y-1][x] >= FEAT_MAGMA) k++;
978        if (cave_feat[y][x+1] >= FEAT_MAGMA) k++;
979        if (cave_feat[y][x-1] >= FEAT_MAGMA) k++;
980
981        return (k);
982}
983
984
985/*
986 * Returns co-ordinates for the player.  Player prefers to be near
987 * walls, because large open spaces are dangerous.
988 */
989static void new_player_spot(void)
990{
991        int i = 0;
992        int y, x;
993
994        /*
995         * Check stored stair locations, then search at random.
996         */
997        while (TRUE)
998        {
999                i++;
1000
1001                /* Scan stored locations first. */
1002                if (i < dun->stair_n)
1003                {
1004                        /* Get location */
1005                        y = dun->stair[i].y;
1006                        x = dun->stair[i].x;
1007
1008                        /* Require exactly three adjacent walls */
1009                        if (next_to_walls(y, x) != 3) continue;
1010
1011                        /* If character starts on stairs, ... */
1012                        if (dungeon_stair)
1013                        {
1014                                /* Accept stairs going the right way or floors. */
1015                                if (p_ptr->create_down_stair)
1016                                {
1017                                        /* Accept down stairs */
1018                                        if (cave_feat[y][x] == FEAT_MORE) break;
1019
1020                                        /* Accept floors, build down stairs. */
1021                                        if (cave_naked_bold(y, x))
1022                                        {
1023                                                cave_set_feat(y, x, FEAT_MORE);
1024                                                break;
1025                                        }
1026                                }
1027                                else
1028                                {
1029                                        /* Accept up stairs */
1030                                        if (cave_feat[y][x] == FEAT_LESS) break;
1031
1032                                        /* Accept floors, build up stairs. */
1033                                        if (cave_naked_bold(y, x))
1034                                        {
1035                                                cave_set_feat(y, x, FEAT_LESS);
1036                                                break;
1037                                        }
1038                                }
1039                        }
1040
1041                        /* If character doesn't start on stairs, ... */
1042                        else
1043                        {
1044                                /* Accept only "naked" floor grids */
1045                                if (cave_naked_bold(y, x)) break;
1046                        }
1047                }
1048
1049                /* Then, search at random */
1050                else
1051                {
1052                        /* Pick a random grid */
1053                        y = rand_int(DUNGEON_HGT);
1054                        x = rand_int(DUNGEON_WID);
1055
1056                        /* Refuse to start on anti-teleport (vault) grids */
1057                        if (cave_info[y][x] & (CAVE_ICKY)) continue;
1058
1059                        /* Must be a "naked" floor grid */
1060                        if (!cave_naked_bold(y, x)) continue;
1061
1062                        /* Player prefers to be near walls. */
1063                        if (i < 300 && (next_to_walls(y, x) < 2)) continue;
1064                        else if (i < 600 && (next_to_walls(y, x) < 1)) continue;
1065
1066                        /* Success */
1067                        break;
1068                }
1069        }
1070
1071        /* Place the player */
1072        player_place(y, x);
1073}
1074
1075
1076/*
1077 * Convert existing terrain type to rubble
1078 */
1079static void place_rubble(int y, int x)
1080{
1081        /* Create rubble */
1082        cave_set_feat(y, x, FEAT_RUBBLE);
1083}
1084
1085
1086/*
1087 * Convert existing terrain type to "up stairs"
1088 */
1089static void place_up_stairs(int y, int x)
1090{
1091        /* Create up stairs */
1092        cave_set_feat(y, x, FEAT_LESS);
1093}
1094
1095
1096/*
1097 * Convert existing terrain type to "down stairs"
1098 */
1099static void place_down_stairs(int y, int x)
1100{
1101        /* Create down stairs */
1102        cave_set_feat(y, x, FEAT_MORE);
1103}
1104
1105
1106/*
1107 * Place an up/down staircase at given location
1108 */
1109static void place_random_stairs(int y, int x)
1110{
1111        /* Paranoia */
1112        if (!cave_clean_bold(y, x)) return;
1113
1114        /* Choose a staircase */
1115        if (!p_ptr->depth)
1116        {
1117                place_down_stairs(y, x);
1118        }
1119        else if (is_quest(p_ptr->depth) || (p_ptr->depth >= MAX_DEPTH-1))
1120        {
1121                place_up_stairs(y, x);
1122        }
1123        else if (rand_int(100) < 50)
1124        {
1125                place_down_stairs(y, x);
1126        }
1127        else
1128        {
1129                place_up_stairs(y, x);
1130        }
1131}
1132
1133
1134/*
1135 * Places some staircases near walls
1136 */
1137static void alloc_stairs(int feat, int num, int walls)
1138{
1139        int y, x, i, j;
1140
1141        /* Place "num" stairs */
1142        for (i = 0; i < num; i++)
1143        {
1144                /* Try hard to place the stair */
1145                for (j = 0; j < 3000; j++)
1146                {
1147                        /* Cut some slack if necessary */
1148                        if ((j > dun->stair_n) && (walls > 2)) walls = 2;
1149                        if ((j > 1000) && (walls > 1)) walls = 1;
1150                        if (j > 2000) walls = 0;
1151
1152                        /* Use the stored stair locations first */
1153                        if (j < dun->stair_n)
1154                        {
1155                                y = dun->stair[j].y;
1156                                x = dun->stair[j].x;
1157                        }
1158
1159                        /* Then, search at random */
1160                        else
1161                        {
1162                                /* Pick a random grid */
1163                                y = rand_int(DUNGEON_HGT);
1164                                x = rand_int(DUNGEON_WID);
1165                        }
1166
1167                        /* Require "naked" floor grid */
1168                        if (!cave_naked_bold(y, x)) continue;
1169
1170                        /* Require a certain number of adjacent walls */
1171                        if (next_to_walls(y, x) < walls) continue;
1172
1173                        /* Town -- must go down */
1174                        if (!p_ptr->depth)
1175                        {
1176                                /* Clear previous contents, add down stairs */
1177                                cave_set_feat(y, x, FEAT_MORE);
1178                        }
1179
1180                        /* Quest -- must go up */
1181                        else if (is_quest(p_ptr->depth) || (p_ptr->depth >= MAX_DEPTH-1))
1182                        {
1183                                /* Clear previous contents, add up stairs */
1184                                cave_set_feat(y, x, FEAT_LESS);
1185                        }
1186
1187                        /* Requested type */
1188                        else
1189                        {
1190                                /* Clear previous contents, add stairs */
1191                                cave_set_feat(y, x, feat);
1192                        }
1193
1194                        /* Finished with this staircase. */
1195                        break;
1196                }
1197        }
1198}
1199
1200
1201/*
1202 * Allocates some objects (using "place" and "type")
1203 */
1204static void alloc_object(int set, int typ, int num)
1205{
1206        int y, x, k;
1207
1208        /* Place some objects */
1209        for (k = 0; k < num; k++)
1210        {
1211                /* Pick a "legal" spot */
1212                while (TRUE)
1213                {
1214                        bool room;
1215
1216                        /* Location */
1217                        y = rand_int(DUNGEON_HGT);
1218                        x = rand_int(DUNGEON_WID);
1219
1220                        /* Require "naked" floor grid */
1221                        if (!cave_naked_bold(y, x)) continue;
1222
1223                        /* Check for "room" */
1224                        room = (cave_info[y][x] & (CAVE_ROOM)) ? TRUE : FALSE;
1225
1226                        /* Require corridor? */
1227                        if ((set == ALLOC_SET_CORR) && room) continue;
1228
1229                        /* Require room? */
1230                        if ((set == ALLOC_SET_ROOM) && !room) continue;
1231
1232                        /* Accept it */
1233                        break;
1234                }
1235
1236                /* Place something */
1237                switch (typ)
1238                {
1239                        case ALLOC_TYP_RUBBLE:
1240                        {
1241                                place_rubble(y, x);
1242                                break;
1243                        }
1244
1245                        case ALLOC_TYP_TRAP:
1246                        {
1247                                place_trap(y, x);
1248                                break;
1249                        }
1250
1251                        case ALLOC_TYP_GOLD:
1252                        {
1253                                place_gold(y, x);
1254                                break;
1255                        }
1256
1257                        case ALLOC_TYP_OBJECT:
1258                        {
1259                                place_object(y, x, FALSE, FALSE);
1260                                break;
1261                        }
1262                }
1263        }
1264}
1265
1266
1267/*
1268 * Value "1" means the grid will be changed, value "0" means it won't.
1269 *
1270 * We have 47 entries because 47 is not divisible by any reasonable
1271 * figure for streamer width.
1272 */
1273static bool streamer_change_grid[47] =
1274{
1275        0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
1276        1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0
1277};
1278
1279
1280/*
1281 * Places "streamers" of rock through dungeon.
1282 *
1283 * Note that there are actually six different terrain features used
1284 * to represent streamers.  Three each of magma and quartz, one for
1285 * basic vein, one with hidden gold, and one with known gold.  The
1286 * hidden gold types are currently unused.
1287 */
1288static void build_streamer(int feat, int chance)
1289{
1290        int table_start;
1291        int i;
1292        int y, x, dy, dx;
1293        int start_dir, dir;
1294        int out1, out2;
1295        bool change;
1296
1297        /* Initialize time until next turn, and time until next treasure */
1298        int time_to_treas = randint(chance * 2);
1299        int time_to_turn = randint(DUN_STR_CHG * 2);
1300
1301
1302        /* Set standard width.  Vary width sometimes. */
1303        int width = 2 * DUN_STR_WID + 1;
1304        if (rand_int(6) == 0) width += randint(3);
1305        else if (rand_int(6) == 0) width -= randint(3);
1306        if (width < 1) width = 1;
1307
1308        /* Set expansion outward from centerline. */
1309        out1 = width / 2;
1310        out2 = (width + 1) / 2;
1311
1312
1313        /* Hack -- Choose starting point */
1314        y = rand_spread(DUNGEON_HGT / 2, DUNGEON_HGT / 4);
1315        x = rand_spread(DUNGEON_WID / 2, DUNGEON_WID / 4);
1316
1317        /* Choose a random compass direction */
1318        dir = start_dir = ddd[rand_int(8)];
1319
1320        /* Get an initial start position on the grid alteration table. */
1321        table_start = rand_int(47);
1322
1323        /* Place streamer into dungeon */
1324        while (TRUE)
1325        {
1326                /* Advance streamer width steps on the table. */
1327                table_start += width;
1328
1329                /*
1330                 * Change grids outwards along sides.  If moving diagonally,
1331                 * change a cross-shaped area.
1332                 */
1333                if (ddy[dir])
1334                {
1335                        for (dx = x - out1; dx <= x + out2; dx++)
1336                        {
1337                                /* Stay within dungeon. */
1338                                if (!in_bounds(y, dx)) continue;
1339
1340                                /* Only convert "granite" walls */
1341                                if (cave_feat[y][dx] < FEAT_WALL_EXTRA) continue;
1342                                if (cave_feat[y][dx] > FEAT_WALL_SOLID) continue;
1343
1344                                i = table_start + dx - x;
1345
1346                                if ((i < 47) && (i >= 0)) change = streamer_change_grid[i];
1347                                else change = streamer_change_grid[i % 47];
1348
1349                                /* No change to be made. */
1350                                if (!change) continue;
1351
1352                                /* Clear previous contents, add proper vein type */
1353                                cave_set_feat(y, dx, feat);
1354
1355                                /* Count down time to next treasure. */
1356                                time_to_treas--;
1357
1358                                /* Hack -- Add some (known) treasure */
1359                                if (time_to_treas == 0)
1360                                {
1361                                        time_to_treas = randint(chance * 2);
1362                                        cave_feat[y][dx] += 0x04;
1363                                }
1364                        }
1365                }
1366
1367                if (ddx[dir])
1368                {
1369                        for (dy = y - out1; dy <= y + out2; dy++)
1370                        {
1371                                /* Stay within dungeon. */
1372                                if (!in_bounds(dy, x)) continue;
1373
1374                                /* Only convert "granite" walls */
1375                                if (cave_feat[dy][x] < FEAT_WALL_EXTRA) continue;
1376                                if (cave_feat[dy][x] > FEAT_WALL_SOLID) continue;
1377
1378                                i = table_start + dy - y;
1379
1380                                if ((i < 47) && (i >= 0)) change = streamer_change_grid[i];
1381                                else change = streamer_change_grid[i % 47];
1382
1383                                /* No change to be made. */
1384                                if (!change) continue;
1385
1386                                /* Clear previous contents, add proper vein type */
1387                                cave_set_feat(dy, x, feat);
1388
1389                                /* Count down time to next treasure. */
1390                                time_to_treas--;
1391
1392                                /* Hack -- Add some (known) treasure */
1393                                if (time_to_treas == 0)
1394                                {
1395                                        time_to_treas = randint(chance * 2);
1396                                        cave_feat[dy][x] += 0x04;
1397                                }
1398                        }
1399                }
1400
1401                /* Count down to next direction change. */
1402                time_to_turn--;
1403
1404                /* Sometimes, vary direction slightly. */
1405                if (time_to_turn == 0)
1406                {
1407                        /* Get time until next turn. */
1408                        time_to_turn = randint(DUN_STR_CHG * 2);
1409
1410                        /* Randomizer. */
1411                        i = rand_int(3);
1412
1413                        /* New direction is always close to start direction. */
1414                        if (start_dir == 2)
1415                        {
1416                                if (i == 0) dir = 2;
1417                                if (i == 1) dir = 1;
1418                                else        dir = 3;
1419                        }
1420                        else if (start_dir == 8)
1421                        {
1422                                if (i == 0) dir = 8;
1423                                if (i == 1) dir = 9;
1424                                else        dir = 7;
1425                        }
1426                        else if (start_dir == 6)
1427                        {
1428                                if (i == 0) dir = 6;
1429                                if (i == 1) dir = 3;
1430                                else        dir = 9;
1431                        }
1432                        else if (start_dir == 4)
1433                        {
1434                                if (i == 0) dir = 4;
1435                                if (i == 1) dir = 7;
1436                                else        dir = 1;
1437                        }
1438                        else if (start_dir == 3)
1439                        {
1440                                if (i == 0) dir = 3;
1441                                if (i == 1) dir = 2;
1442                                else        dir = 6;
1443                        }
1444                        else if (start_dir == 1)
1445                        {
1446                                if (i == 0) dir = 1;
1447                                if (i == 1) dir = 4;
1448                                else        dir = 2;
1449                        }
1450                        else if (start_dir == 9)
1451                        {
1452                                if (i == 0) dir = 9;
1453                                if (i == 1) dir = 6;
1454                                else        dir = 8;
1455                        }
1456                        else if (start_dir == 7)
1457                        {
1458                                if (i == 0) dir = 7;
1459                                if (i == 1) dir = 8;
1460                                else        dir = 4;
1461                        }
1462                }
1463
1464                /* Advance the streamer */
1465                y += ddy[dir];
1466                x += ddx[dir];
1467
1468                /* Stop at dungeon edge */
1469                if (!in_bounds(y, x)) break;
1470        }
1471}
1472
1473
1474/*
1475 * Build a destroyed level
1476 */
1477static void destroy_level(void)
1478{
1479        int y1, x1, y, x, k, t, n;
1480
1481
1482        /* Note destroyed levels */
1483        if (cheat_room) msg_print("Destroyed Level");
1484
1485        /* Drop a few epi-centers (usually about two) */
1486        for (n = 0; n < randint(5); n++)
1487        {
1488                /* Pick an epi-center */
1489                x1 = rand_range(5, DUNGEON_WID-1 - 5);
1490                y1 = rand_range(5, DUNGEON_HGT-1 - 5);
1491
1492                /* Big area of affect */
1493                for (y = (y1 - 15); y <= (y1 + 15); y++)
1494                {
1495                        for (x = (x1 - 15); x <= (x1 + 15); x++)
1496                        {
1497                                /* Skip illegal grids */
1498                                if (!in_bounds_fully(y, x)) continue;
1499
1500                                /* Extract the distance */
1501                                k = distance(y1, x1, y, x);
1502
1503                                /* Stay in the circle of death */
1504                                if (k >= 16) continue;
1505
1506                                /* Delete the monster (if any) */
1507                                delete_monster(y, x);
1508
1509                                /* Destroy valid grids */
1510                                if (cave_valid_bold(y, x))
1511                                {
1512                                        /* Delete objects */
1513                                        delete_object(y, x);
1514
1515                                        /* Wall (or floor) type */
1516                                        t = rand_int(200);
1517
1518                                        /* Granite */
1519                                        if (t < 20)
1520                                        {
1521                                                /* Create granite wall */
1522                                                cave_set_feat(y, x, FEAT_WALL_EXTRA);
1523                                        }
1524
1525                                        /* Quartz */
1526                                        else if (t < 70)
1527                                        {
1528                                                /* Create quartz vein */
1529                                                cave_set_feat(y, x, FEAT_QUARTZ);
1530                                        }
1531
1532                                        /* Magma */
1533                                        else if (t < 100)
1534                                        {
1535                                                /* Create magma vein */
1536                                                cave_set_feat(y, x, FEAT_MAGMA);
1537                                        }
1538
1539                                        /* Floor */
1540                                        else
1541                                        {
1542                                                /* Create floor */
1543                                                cave_set_feat(y, x, FEAT_FLOOR);
1544                                        }
1545
1546                                        /* No longer part of a room or vault */
1547                                        cave_info[y][x] &= ~(CAVE_ROOM | CAVE_ICKY);
1548
1549                                        /* No longer illuminated */
1550                                        cave_info[y][x] &= ~(CAVE_GLOW);
1551                                }
1552                        }
1553                }
1554        }
1555}
1556
1557
1558
1559/**************************************************************/
1560/*                                                            */
1561/*                   The room-building code                   */
1562/*                                                            */
1563/**************************************************************/
1564
1565
1566/*
1567 * Place objects, up to the number asked for, in a rectangle centered on
1568 * y0, x0.  Accept values for maximum vertical and horizontal displacement.
1569 *
1570 * Return prematurely if the code starts looping too much (this may happen
1571 * if y0 or x0 are out of bounds, or the floor is already filled).
1572 */
1573static void spread_objects(int depth, int num, int y0, int x0, int dy, int dx)
1574{
1575        int i, j;       /* Limits on loops */
1576        int count;
1577        int y = y0, x = x0;
1578
1579
1580        /* Try to place objects within our rectangle of effect. */
1581        for (count = 0, i = 0; ((count < num) && (i < 50)); i++)
1582        {
1583                /* Get a location */
1584                if ((dy == 0) && (dx == 0))
1585                {
1586                        y = y0; x = x0;
1587                        if (!in_bounds(y, x)) return;
1588                }
1589                else
1590                {
1591                        for (j = 0; j < 10; j++)
1592                        {
1593                                y = rand_spread(y0, dy);
1594                                x = rand_spread(x0, dx);
1595                                if (!in_bounds(y, x))
1596                                {
1597                                        if (j < 9) continue;
1598                                        else return;
1599                                }
1600                                break;
1601                        }
1602                }
1603
1604                /* Require "clean" floor space */
1605                if (!cave_clean_bold(y, x)) continue;
1606
1607                /* Place an item */
1608                if (rand_int(100) < 67)
1609                {
1610                        place_object(y, x, FALSE, FALSE);
1611                }
1612
1613                /* Place gold */
1614                else
1615                {
1616                        place_gold(y, x);
1617                }
1618
1619                /* Count the object, reset the loop count */
1620                count++;
1621                i = 0;
1622        }
1623}
1624
1625
1626/*
1627 * Place traps, up to the number asked for, in a rectangle centered on
1628 * y0, x0.  Accept values for maximum vertical and horizontal displacement.
1629 *
1630 * Return prematurely if the code starts looping too much (this may happen
1631 * if y0 or x0 are out of bounds, or the floor is already filled).
1632 */
1633static void spread_traps(int num, int y0, int x0, int dy, int dx)
1634{
1635        int i, j;       /* Limits on loops */
1636        int count;
1637        int y = y0, x = x0;
1638
1639        /* Try to create traps within our rectangle of effect. */
1640        for (count = 0, i = 0; ((count < num) && (i < 50)); i++)
1641        {
1642                /* Get a location */
1643                if ((dy == 0) && (dx == 0))
1644                {
1645                        y = y0; x = x0;
1646                        if (!in_bounds(y, x)) return;
1647                }
1648                else
1649                {
1650                        for (j = 0; j < 10; j++)
1651                        {
1652                                y = rand_spread(y0, dy);
1653                                x = rand_spread(x0, dx);
1654                                if (!in_bounds(y, x))
1655                                {
1656                                        if (j < 9) continue;
1657                                        else return;
1658                                }
1659                                break;
1660                        }
1661                }
1662
1663                /* Require "naked" floor grids */
1664                if (!cave_naked_bold(y, x)) continue;
1665
1666                /* Place the trap */
1667                place_trap(y, x);
1668
1669                /* Count the trap, reset the loop count */
1670                count++;
1671                i = 0;
1672        }
1673}
1674
1675
1676/*
1677 * Place monsters, up to the number asked for, in a rectangle centered on
1678 * y0, x0.  Accept values for monster depth, symbol, and maximum vertical
1679 * and horizontal displacement.  Call monster restriction functions if
1680 * needed.
1681 *
1682 * Return prematurely if the code starts looping too much (this may happen
1683 * if y0 or x0 are out of bounds, or the area is already occupied).
1684 */
1685static void spread_monsters(char symbol, int depth, int num,
1686        int y0, int x0, int dy, int dx)
1687{
1688        int i, j;       /* Limits on loops */
1689        int count;
1690        int y = y0, x = x0;
1691        int start_mon_num = m_max;
1692        bool dummy;
1693
1694        /* Restrict monsters.  Allow uniques. */
1695        (void)mon_restrict(symbol, (byte)depth, &dummy, TRUE);
1696
1697        /* Set generation level */
1698        monster_level = depth;
1699
1700        /* Build the monster probability table. */
1701        if (!get_mon_num(depth)) return;
1702
1703
1704        /* Try to summon monsters within our rectangle of effect. */
1705        for (count = 0, i = 0; ((count < num) && (i < 50)); i++)
1706        {
1707                /* Get a location */
1708                if ((dy == 0) && (dx == 0))
1709                {
1710                        y = y0; x = x0;
1711                        if (!in_bounds(y, x)) return;
1712                }
1713                else
1714                {
1715                        for (j = 0; j < 10; j++)
1716                        {
1717                                y = rand_spread(y0, dy);
1718                                x = rand_spread(x0, dx);
1719                                if (!in_bounds(y, x))
1720                                {
1721                                        if (j < 9) continue;
1722                                        else return;
1723                                }
1724                                break;
1725                        }
1726                }
1727
1728                /* Require "empty" floor grids */
1729                if (!cave_empty_bold(y, x)) continue;
1730
1731                /* Place the monster (sleeping, allow groups) */
1732                (void)place_monster(y, x, TRUE, TRUE);
1733
1734                /* Rein in monster groups and escorts a little. */
1735                if (m_max - start_mon_num > num * 2) break;
1736
1737                /* Count the monster(s), reset the loop count */
1738                count++;
1739                i = 0;
1740        }
1741
1742        /* Remove monster restrictions. */
1743        (void)mon_restrict('\0', (byte)depth, &dummy, TRUE);
1744
1745        /* Reset monster generation level. */
1746        monster_level = p_ptr->depth;
1747}
1748
1749
1750
1751/*
1752 * Generate helper -- create a new room with optional light
1753 *
1754 * Return FALSE if the room is not fully within the dungeon.
1755 */
1756static bool generate_room(int y1, int x1, int y2, int x2, int light)
1757{
1758        int y, x;
1759
1760        /* Confirm that room is in bounds. */
1761        if ((!in_bounds(y1, x1)) || (!in_bounds(y2, x2))) return (FALSE);
1762
1763        for (y = y1; y <= y2; y++)
1764        {
1765                for (x = x1; x <= x2; x++)
1766                {
1767                        cave_info[y][x] |= (CAVE_ROOM);
1768                        if (light) cave_info[y][x] |= (CAVE_GLOW);
1769                }
1770        }
1771
1772        /* Success. */
1773        return (TRUE);
1774}
1775
1776
1777/*
1778 * Generate helper -- fill a rectangle with a feature
1779 */
1780static void generate_fill(int y1, int x1, int y2, int x2, int feat)
1781{
1782        int y, x;
1783
1784        for (y = y1; y <= y2; y++)
1785        {
1786                for (x = x1; x <= x2; x++)
1787                {
1788                        cave_set_feat(y, x, feat);
1789                }
1790        }
1791}
1792
1793
1794/*
1795 * Generate helper -- draw a rectangle with a feature
1796 */
1797static void generate_draw(int y1, int x1, int y2, int x2, int feat)
1798{
1799        int y, x;
1800
1801        for (y = y1; y <= y2; y++)
1802        {
1803                cave_set_feat(y, x1, feat);
1804                cave_set_feat(y, x2, feat);
1805        }
1806
1807        for (x = x1; x <= x2; x++)
1808        {
1809                cave_set_feat(y1, x, feat);
1810                cave_set_feat(y2, x, feat);
1811        }
1812}
1813
1814
1815/*
1816 * Generate helper -- split a rectangle with a feature
1817 */
1818static void generate_plus(int y1, int x1, int y2, int x2, int feat)
1819{
1820        int y, x;
1821        int y0, x0;
1822
1823        /* Center */
1824        y0 = (y1 + y2) / 2;
1825        x0 = (x1 + x2) / 2;
1826
1827        for (y = y1; y <= y2; y++)
1828        {
1829                cave_set_feat(y, x0, feat);
1830        }
1831
1832        for (x = x1; x <= x2; x++)
1833        {
1834                cave_set_feat(y0, x, feat);
1835        }
1836}
1837
1838
1839/*
1840 * Generate helper -- open all sides of a rectangle with a feature
1841 */
1842static void generate_open(int y1, int x1, int y2, int x2, int feat)
1843{
1844        int y0, x0;
1845
1846        /* Center */
1847        y0 = (y1 + y2) / 2;
1848        x0 = (x1 + x2) / 2;
1849
1850        /* Open all sides */
1851        cave_set_feat(y1, x0, feat);
1852        cave_set_feat(y0, x1, feat);
1853        cave_set_feat(y2, x0, feat);
1854        cave_set_feat(y0, x2, feat);
1855}
1856
1857
1858/*
1859 * Generate helper -- open one side of a rectangle with a feature
1860 */
1861static void generate_hole(int y1, int x1, int y2, int x2, int feat)
1862{
1863        int y0, x0;
1864
1865        /* Center */
1866        y0 = (y1 + y2) / 2;
1867        x0 = (x1 + x2) / 2;
1868
1869        /* Open random side */
1870        switch (rand_int(4))
1871        {
1872                case 0:
1873                {
1874                        cave_set_feat(y1, x0, feat);
1875                        break;
1876                }
1877                case 1:
1878                {
1879                        cave_set_feat(y0, x1, feat);
1880                        break;
1881                }
1882                case 2:
1883                {
1884                        cave_set_feat(y2, x0, feat);
1885                        break;
1886                }
1887                case 3:
1888                {
1889                        cave_set_feat(y0, x2, feat);
1890                        break;
1891                }
1892        }
1893}
1894
1895
1896/*
1897 * Find a good spot for the next room. 
1898 *
1899 * Find and allocate a free space in the dungeon large enough to hold
1900 * the room calling this function.
1901 *
1902 * We allocate space in 11x11 blocks, but want to make sure that rooms
1903 * align neatly on the standard screen.  Therefore, we make them use
1904 * blocks in few 11x33 rectangles as possible.
1905 *
1906 * Be careful to include the edges of the room in height and width!
1907 *
1908 * Return TRUE and values for the center of the room if all went well. 
1909 * Otherwise, return FALSE.
1910 */
1911static bool find_space(int *y, int *x, int height, int width)
1912{
1913        int i;
1914        int by, bx, by1, bx1, by2, bx2;
1915        int block_y, block_x;
1916
1917        bool filled;
1918
1919
1920        /* Find out how many blocks we need. */
1921        int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
1922        int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
1923
1924        /* Sometimes, little rooms like to have more space. */
1925        if ((blocks_wide == 2) && (rand_int(3) == 0)) blocks_wide = 3;
1926        else if ((blocks_wide == 1) && (rand_int(2) == 0))
1927                blocks_wide = 1 + randint(2);
1928
1929
1930        /* We'll allow twenty-five guesses. */
1931        for (i = 0; i < 25; i++)
1932        {
1933                filled = FALSE;
1934
1935                /* Pick a top left block at random */
1936                block_y = rand_int(dun->row_rooms + blocks_high);
1937                block_x = rand_int(dun->col_rooms + blocks_wide);
1938
1939
1940                /* Itty-bitty rooms can shift about within their rectangle */
1941                if (blocks_wide < 3)
1942                {
1943                        /* Rooms that straddle a border must shift. */
1944                        if ((blocks_wide == 2) && ((block_x % 3) == 2))
1945                        {
1946                                if (rand_int(2) == 0) block_x--;
1947                                else block_x++;
1948                        }
1949                }
1950
1951                /* Rooms with width divisible by 3 get fitted to a rectangle. */
1952                else if ((blocks_wide % 3) == 0)
1953                {
1954                        /* Align to the left edge of a 11x33 rectangle. */
1955                        if ((block_x % 3) == 2) block_x++;
1956                        if ((block_x % 3) == 1) block_x--;
1957                }
1958
1959                /*
1960                 * Big rooms that do not have a width divisible by 3 get
1961                 * aligned towards the edge of the dungeon closest to them.
1962                 */
1963                else
1964                {
1965                        /* Shift towards left edge of dungeon. */
1966                        if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
1967                        {
1968                                if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
1969                                        block_x--;
1970                                if ((block_x % 3) == 1) block_x--;
1971                        }
1972
1973                        /* Shift toward right edge of dungeon. */
1974                        else
1975                        {
1976                                if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
1977                                        block_x++;
1978                                if ((block_x % 3) == 1) block_x++;
1979                        }
1980                }
1981
1982                /* Extract blocks */
1983                by1 = block_y + 0;
1984                bx1 = block_x + 0;
1985                by2 = block_y + blocks_high;
1986                bx2 = block_x + blocks_wide;
1987
1988                /* Never run off the screen */
1989                if ((by1 < 0) || (by2 > dun->row_rooms)) continue;
1990                if ((bx1 < 0) || (bx2 > dun->col_rooms)) continue;
1991
1992                /* Verify available space */
1993                for (by = by1; by < by2; by++)
1994                {
1995                        for (bx = bx1; bx < bx2; bx++)
1996                        {
1997                                if (dun->room_map[by][bx])
1998                                {
1999                                        filled = TRUE;
2000                                }
2001                        }
2002                }
2003
2004                /* If space filled, try again. */
2005                if (filled) continue;
2006
2007
2008                /* It is *extremely* important that the following calculation */
2009                /* be *exactly* correct to prevent memory errors XXX XXX XXX */
2010
2011                /* Get the location of the room */
2012                (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
2013                (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
2014
2015
2016                /* Save the room location */
2017                if (dun->cent_n < CENT_MAX)
2018                {
2019                        dun->cent[dun->cent_n].y = *y;
2020                        dun->cent[dun->cent_n].x = *x;
2021                        dun->cent_n++;
2022                }
2023
2024                /* Reserve some blocks.  Mark each with the room index. */
2025                for (by = by1; by < by2; by++)
2026                {
2027                        for (bx = bx1; bx < bx2; bx++)
2028                        {
2029                                dun->room_map[by][bx] = dun->cent_n;
2030                        }
2031                }
2032
2033                /* Success. */
2034                return (TRUE);
2035        }
2036
2037        /* Failure. */
2038        return (FALSE);
2039}
2040
2041
2042
2043/*
2044 * Is a feature passable (with or without some work) by the character?
2045 */
2046static bool passable(int feat)
2047{
2048        /* Some kinds of terrain are passable. */
2049        if ((feat == FEAT_FLOOR ) ||
2050            (feat == FEAT_SECRET) ||
2051            (feat == FEAT_RUBBLE) ||
2052            (feat == FEAT_INVIS ) ||
2053            (feat == FEAT_OPEN  ) ||
2054            (feat == FEAT_BROKEN) ||
2055            (feat == FEAT_LESS  ) ||
2056            (feat == FEAT_MORE  )) return (TRUE);
2057
2058        /* Doors are passable. */
2059        if ((feat >= FEAT_DOOR_HEAD) &&
2060            (feat <= FEAT_DOOR_TAIL)) return (TRUE);
2061
2062        /* Everything else is not passable. */
2063        return (FALSE);
2064}
2065
2066
2067/*
2068 * Room building routines.
2069 *
2070 * Seven basic room types:
2071 *   1 -- normal
2072 *   2 -- overlapping
2073 *   3 -- cross shaped
2074 *   4 -- large room with features
2075 *   5 -- monster pits
2076 *   6 -- simple vaults
2077 *   7 -- greater vaults
2078 */
2079
2080
2081/*
2082 * Type 1 -- normal rectangular rooms
2083 *
2084 * These rooms have the lowest build priority (this means that they
2085 * should not be very large), and are by far the most common type.
2086 */
2087static bool build_type1(void)
2088{
2089        int y, x, rand;
2090        int y0, x0;
2091
2092        int y1, x1, y2, x2;
2093
2094        bool light = FALSE;
2095
2096        /* Occasional light */
2097        if (p_ptr->depth <= randint(35)) light = TRUE;
2098
2099
2100        /* Pick a room size (less border walls) */
2101        x = 1 + randint(11) + randint(11);
2102        y = 1 + randint(4) + randint(4);
2103
2104        /* Find and reserve some space in the dungeon.  Get center of room. */
2105        if (!find_space(&y0, &x0, y+2, x+2)) return (FALSE);
2106
2107        /* Locate the room */
2108        y1 = y0 - y / 2;
2109        x1 = x0 - x / 2;
2110        y2 =  y1 + y - 1;
2111        x2 =  x1 + x - 1;
2112
2113
2114        /* Generate new room.  Quit immediately if out of bounds. */
2115        if (!generate_room(y1-1, x1-1, y2+1, x2+1, light)) return (FALSE);
2116
2117
2118        /* Generate outer walls */
2119        generate_draw(y1-1, x1-1, y2+1, x2+1, FEAT_WALL_OUTER);
2120
2121        /* Make a standard room. */
2122        generate_fill(y1, x1, y2, x2, FEAT_FLOOR);
2123
2124        /* Sometimes, we get creative. */
2125        if (rand_int(36) == 0)
2126        {
2127                /* Choose a room type.  Some types require odd dimensions. */
2128                if ((y % 2 == 0) || (x % 2 == 0)) rand = 60 + rand_int(40);
2129                else rand = rand_int(100);
2130
2131                /* Pillar room (requires odd dimensions) */
2132                if (rand < 45)
2133                {
2134                        int offsety = 0;
2135                        int offsetx = 0;
2136                        if (rand_int(2) == 0) offsety = 1;
2137                        if (rand_int(2) == 0) offsetx = 1;
2138
2139                        for (y = y1 + offsety; y <= y2 - offsety; y += 2)
2140                        {
2141                                for (x = x1 + offsetx; x <= x2 - offsetx; x += 2)
2142                                {
2143                                        cave_set_feat(y, x, FEAT_WALL_INNER);
2144                                }
2145                        }
2146                }
2147
2148                /* Ragged-edge room (requires odd dimensions) */
2149                else if (rand < 90)
2150                {
2151                        int offset = 0;
2152                        if (rand_int(2) == 0) offset = 1;
2153
2154                        for (y = y1 + offset; y <= y2 - offset; y += 2)
2155                        {
2156                                cave_set_feat(y, x1, FEAT_WALL_INNER);
2157                                cave_set_feat(y, x2, FEAT_WALL_INNER);
2158                        }
2159
2160                        for (x = x1 + offset; x <= x2 - offset; x += 2)
2161                        {
2162                                cave_set_feat(y1, x, FEAT_WALL_INNER);
2163                                cave_set_feat(y2, x, FEAT_WALL_INNER);
2164                        }
2165                }
2166
2167                /* The ceiling has collapsed. */
2168                else
2169                {
2170                        for (y = y1; y <= y2; y++)
2171                        {
2172                                for (x = x1; x <= x2; x++)
2173                                {
2174                                        /* Wall (or floor) type */
2175                                        int t = rand_int(100);
2176
2177                                        /* Granite */
2178                                        if (t < 5)
2179                                        {
2180                                                /* Create granite wall */
2181                                                cave_set_feat(y, x, FEAT_WALL_EXTRA);
2182                                        }
2183
2184                                        /* Quartz */
2185                                        else if (t < 12)
2186                                        {
2187                                                /* Create quartz vein */
2188                                                cave_set_feat(y, x, FEAT_QUARTZ);
2189                                        }
2190
2191                                        /* Magma */
2192                                        else if (t < 20)
2193                                        {
2194                                                /* Create magma vein */
2195                                                cave_set_feat(y, x, FEAT_MAGMA);
2196                                        }
2197
2198                                        /* Rubble. */
2199                                        else if (t < 40)
2200                                        {
2201                                                /* Create rubble */
2202                                                cave_set_feat(y, x, FEAT_RUBBLE);
2203                                        }
2204
2205                                        /* Floor */
2206                                        else
2207                                        {
2208                                                /* Create floor */
2209                                                cave_set_feat(y, x, FEAT_FLOOR);
2210                                        }
2211                                }
2212                        }
2213
2214                        /* Here, creatures of Earth dwell. */
2215                        if ((p_ptr->depth > 35) && (rand_int(3) == 0))
2216                        {
2217                                spread_monsters('X', p_ptr->depth, 2 + randint(3),
2218                                        y0, x0, 3, 9);
2219                        }
2220                }
2221        }
2222
2223        /* Success */
2224        return (TRUE);
2225}
2226
2227
2228/*
2229 * Type 2 -- Overlapping rectangular rooms
2230 */
2231static bool build_type2(void)
2232{
2233        int y1a, x1a, y2a, x2a;
2234        int y1b, x1b, y2b, x2b;
2235        int y0, x0;
2236        int height, width;
2237
2238        int light = FALSE;
2239
2240        /* Occasional light */
2241        if (p_ptr->depth <= randint(35)) light = TRUE;
2242
2243
2244        /* Determine extents of room (a) */
2245        y1a = randint(4);
2246        x1a = randint(13);
2247        y2a = randint(3);
2248        x2a = randint(9);
2249
2250        /* Determine extents of room (b) */
2251        y1b = randint(3);
2252        x1b = randint(9);
2253        y2b = randint(4);
2254        x2b = randint(13);
2255
2256
2257        /* Calculate height */
2258        height = 11;
2259
2260        /* Calculate width */
2261        if ((x1a < 8) && (x2a < 9) && (x1b < 8) && (x2b < 9)) width = 22;
2262        else width = 33;
2263
2264        /* Find and reserve some space in the dungeon.  Get center of room. */
2265        if (!find_space(&y0, &x0, height, width)) return (FALSE);
2266
2267        /* locate room (a) */
2268        y1a = y0 - y1a;
2269        x1a = x0 - x1a;
2270        y2a = y0 + y2a;
2271        x2a = x0 + x2a;
2272
2273        /* locate room (b) */
2274        y1b = y0 - y1b;
2275        x1b = x0 - x1b;
2276        y2b = y0 + y2b;
2277        x2b = x0 + x2b;
2278
2279
2280        /* Generate new room (a).  Quit immediately if out of bounds. */
2281        if (!generate_room(y1a-1, x1a-1, y2a+1, x2a+1, light)) return (FALSE);
2282
2283        /* Generate new room (b).  Quit immediately if out of bounds. */
2284        if (!generate_room(y1b-1, x1b-1, y2b+1, x2b+1, light)) return (FALSE);
2285
2286
2287        /* Generate outer walls (a) */
2288        generate_draw(y1a-1, x1a-1, y2a+1, x2a+1, FEAT_WALL_OUTER);
2289
2290        /* Generate outer walls (b) */
2291        generate_draw(y1b-1, x1b-1, y2b+1, x2b+1, FEAT_WALL_OUTER);
2292
2293        /* Generate inner floors (a) */
2294        generate_fill(y1a, x1a, y2a, x2a, FEAT_FLOOR);
2295
2296        /* Generate inner floors (b) */
2297        generate_fill(y1b, x1b, y2b, x2b, FEAT_FLOOR);
2298
2299        /* Success */
2300        return (TRUE);
2301}
2302
2303
2304
2305/*
2306 * Type 3 -- Cross shaped rooms
2307 *
2308 * Room "a" runs north/south, and Room "b" runs east/east
2309 * So a "central pillar" would run from x1a,y1b to x2a,y2b.
2310 *
2311 * Note that currently, the "center" is always 3x3, but I think that
2312 * the code below will work for 5x5 (and perhaps even for asymmetric
2313 * values like 4x3 or 5x3 or 3x4 or 3x5).
2314 */
2315static bool build_type3(void)
2316{
2317        int y, x;
2318        int y0, x0;
2319        int height, width;
2320
2321        int y1a, x1a, y2a, x2a;
2322        int y1b, x1b, y2b, x2b;
2323
2324        int dy, dx, wy, wx;
2325
2326        int light = FALSE;
2327
2328        /* Occasional light */
2329        if (p_ptr->depth <= randint(35)) light = TRUE;
2330
2331
2332        /* Pick inner dimension */
2333        wy = 1;
2334        wx = 1;
2335
2336        /* Pick outer dimension */
2337        dy = rand_range(3, 4);
2338        dx = rand_range(3, 11);
2339
2340        /* Determine extents of room (a) */
2341        y1a = dy;
2342        x1a = wx;
2343        y2a = dy;
2344        x2a = wx;
2345
2346        /* Determine extents of room (b) */
2347        y1b = wy;
2348        x1b = dx;
2349        y2b = wy;
2350        x2b = dx;
2351
2352        /* Calculate height */
2353        if ((y1a + y2a + 1) > (y1b + y2b + 1)) height = y1a + y2a + 1;
2354        else height = y1b + y2b + 1;
2355
2356        /* Calculate width */
2357        if ((x1a + x2a + 1) > (x1b + x2b + 1)) width = x1a + x2a + 1;
2358        else width = x1b + x2b + 1;
2359
2360        /* Find and reserve some space in the dungeon.  Get center of room. */
2361        if (!find_space(&y0, &x0, height, width)) return (FALSE);
2362
2363        /* Locate room (a) */
2364        y1a = y0 - dy;
2365        x1a = x0 - wx;
2366        y2a = y0 + dy;
2367        x2a = x0 + wx;
2368
2369        /* Locate room (b) */
2370        y1b = y0 - wy;
2371        x1b = x0 - dx;
2372        y2b = y0 + wy;
2373        x2b = x0 + dx;
2374
2375
2376        /* Generate new room (a).  Quit immediately if out of bounds. */
2377        if (!generate_room(y1a-1, x1a-1, y2a+1, x2a+1, light)) return (FALSE);
2378
2379        /* Generate new room (b).  Quit immediately if out of bounds. */
2380        if (!generate_room(y1b-1, x1b-1, y2b+1, x2b+1, light)) return (FALSE);
2381
2382
2383        /* Generate outer walls (a) */
2384        generate_draw(y1a-1, x1a-1, y2a+1, x2a+1, FEAT_WALL_OUTER);
2385
2386        /* Generate outer walls (b) */
2387        generate_draw(y1b-1, x1b-1, y2b+1, x2b+1, FEAT_WALL_OUTER);
2388
2389        /* Generate inner floors (a) */
2390        generate_fill(y1a, x1a, y2a, x2a, FEAT_FLOOR);
2391
2392        /* Generate inner floors (b) */
2393        generate_fill(y1b, x1b, y2b, x2b, FEAT_FLOOR);
2394
2395
2396        /* Special features */
2397        switch (randint(4))
2398        {
2399                /* Nothing */
2400                case 1:
2401                {
2402                        break;
2403                }
2404
2405                /* Large solid middle pillar */
2406                case 2:
2407                {
2408                        /* Generate a small inner solid pillar */
2409                        generate_fill(y1b, x1a, y2b, x2a, FEAT_WALL_INNER);
2410
2411                        break;
2412                }
2413
2414                /* Inner treasure vault */
2415                case 3:
2416                {
2417                        /* Generate a small inner vault */
2418                        generate_draw(y1b, x1a, y2b, x2a, FEAT_WALL_INNER);
2419
2420                        /* Open the inner vault with a secret door */
2421                        generate_hole(y1b, x1a, y2b, x2a, FEAT_SECRET);
2422
2423                        /* Place a treasure in the vault */
2424                        object_level = p_ptr->depth + 2;
2425                        place_object(y0, x0, FALSE, FALSE);
2426                        object_level = p_ptr->depth;
2427
2428                        /* Let's guard the treasure well */
2429                        monster_level = p_ptr->depth + 4;
2430                        (void)place_monster(y0, x0, TRUE, TRUE);
2431                        monster_level = p_ptr->depth;
2432
2433                        /* Traps, naturally. */
2434                        spread_traps(randint(3), y0, x0, 4, 4);
2435
2436                        break;
2437                }
2438
2439                /* Something else */
2440                case 4:
2441                {
2442                        /* Occasionally pinch the center shut */
2443                        if (rand_int(3) == 0)
2444                        {
2445                                /* Pinch the east/west sides */
2446                                for (y = y1b; y <= y2b; y++)
2447                                {
2448                                        if (y == y0) continue;
2449                                        cave_set_feat(y, x1a - 1, FEAT_WALL_INNER);
2450                                        cave_set_feat(y, x2a + 1, FEAT_WALL_INNER);
2451                                }
2452
2453                                /* Pinch the north/south sides */
2454                                for (x = x1a; x <= x2a; x++)
2455                                {
2456                                        if (x == x0) continue;
2457                                        cave_set_feat(y1b - 1, x, FEAT_WALL_INNER);
2458                                        cave_set_feat(y2b + 1, x, FEAT_WALL_INNER);
2459                                }
2460
2461                                /* Open sides with secret doors */
2462                                if (rand_int(3) == 0)
2463                                {
2464                                        generate_open(y1b-1, x1a-1, y2b+1, x2a+1, FEAT_SECRET);
2465                                }
2466                        }
2467
2468                        /* Occasionally put a "plus" in the center */
2469                        else if (rand_int(3) == 0)
2470                        {
2471                                generate_plus(y1b, x1a, y2b, x2a, FEAT_WALL_INNER);
2472                        }
2473
2474                        /* Occasionally put a "pillar" in the center */
2475                        else if (rand_int(3) == 0)
2476                        {
2477                                cave_set_feat(y0, x0, FEAT_WALL_INNER);
2478                        }
2479
2480                        break;
2481                }
2482        }
2483
2484        /* Success */
2485        return (TRUE);
2486}
2487
2488
2489/*
2490 * Type 4 -- Large room with an inner room
2491 *
2492 * Possible sub-types:
2493 *      1 - An inner room with a small inner room
2494 *      2 - An inner room with a pillar or pillars
2495 *      3 - An inner room with a checkerboard
2496 *      4 - An inner room with four compartments
2497 */
2498static bool build_type4(void)
2499{
2500        int y, x, y1, x1, y2, x2;
2501        int y0, x0;
2502
2503        int light = FALSE;
2504
2505        /* Occasional light */
2506        if (p_ptr->depth <= randint(35)) light = TRUE;
2507
2508
2509        /* Pick a room size (less border walls) */
2510        y = 9;
2511        x = 23;
2512
2513        /* Find and reserve some space in the dungeon.  Get center of room. */
2514        if (!find_space(&y0, &x0, y+2, x+2)) return (FALSE);
2515
2516        /* Locate the room */
2517        y1 = y0 - y / 2;
2518        x1 = x0 - x / 2;
2519        y2 =  y1 + y - 1;
2520        x2 =  x1 + x - 1;
2521
2522
2523        /* Generate new room.  Quit immediately if out of bounds. */
2524        if (!generate_room(y1-1, x1-1, y2+1, x2+1, light)) return (FALSE);
2525
2526
2527        /* Generate outer walls */
2528        generate_draw(y1-1, x1-1, y2+1, x2+1, FEAT_WALL_OUTER);
2529
2530        /* Generate inner floors */
2531        generate_fill(y1, x1, y2, x2, FEAT_FLOOR);
2532
2533
2534        /* The inner room */
2535        y1 = y1 + 2;
2536        y2 = y2 - 2;
2537        x1 = x1 + 2;
2538        x2 = x2 - 2;
2539
2540        /* Generate inner walls */
2541        generate_draw(y1-1, x1-1, y2+1, x2+1, FEAT_WALL_INNER);
2542
2543        /* Inner room variations */
2544        switch (randint(4))
2545        {
2546                /* An inner room with a small inner room */
2547                case 1:
2548                {
2549                        /* Open the inner room with a secret door */
2550                        generate_hole(y1-1, x1-1, y2+1, x2+1, FEAT_SECRET);
2551
2552                        /* Place another inner room */
2553                        generate_draw(y0-1, x0-1, y0+1, x0+1, FEAT_WALL_INNER);
2554
2555                        /* Open the inner room with a locked door */
2556                        generate_hole(y0-1, x0-1, y0+1, x0+1, FEAT_DOOR_HEAD + randint(7));
2557
2558                        /* Monsters on guard */
2559                        spread_monsters('\0', p_ptr->depth + 2, 4, y0, x0, 2, 6);
2560
2561                        /* Object (80%) */
2562                        if (rand_int(100) < 80)
2563                        {
2564                                object_level = p_ptr->depth + 2;
2565                                place_object(y0, x0, FALSE, FALSE);
2566                                object_level = p_ptr->depth;
2567                        }
2568
2569                        /* Stairs (20%) */
2570                        else
2571                        {
2572                                place_random_stairs(y0, x0);
2573                        }
2574
2575                        /* Traps */
2576                        spread_traps(rand_int(3) + 1, y0, x0, 2, 4);
2577
2578                        break;
2579                }
2580
2581
2582                /* An inner room with an inner pillar or pillars */
2583                case 2:
2584                {
2585                        /* Open the inner room with a secret door */
2586                        generate_hole(y1-1, x1-1, y2+1, x2+1, FEAT_SECRET);
2587
2588                        /* Inner pillar */
2589                        generate_fill(y0-1, x0-1, y0+1, x0+1, FEAT_WALL_INNER);
2590
2591                        /* Occasionally, two more large inner pillars */
2592                        if (rand_int(2) == 0)
2593                        {
2594                                /* Three spaces */
2595                                if (rand_int(100) < 50)
2596                                {
2597                                        /* Inner pillar */
2598                                        generate_fill(y0-1, x0-7, y0+1, x0-5, FEAT_WALL_INNER);
2599
2600                                        /* Inner pillar */
2601                                        generate_fill(y0-1, x0+5, y0+1, x0+7, FEAT_WALL_INNER);
2602                                }
2603
2604                                /* Two spaces */
2605                                else
2606                                {
2607                                        /* Inner pillar */
2608                                        generate_fill(y0-1, x0-6, y0+1, x0-4, FEAT_WALL_INNER);
2609
2610                                        /* Inner pillar */
2611                                        generate_fill(y0-1, x0+4, y0+1, x0+6, FEAT_WALL_INNER);
2612                                }
2613                        }
2614
2615                        /* Occasionally, some inner rooms */
2616                        if (rand_int(3) == 0)
2617                        {
2618                                /* Inner rectangle */
2619                                generate_draw(y0-1, x0-5, y0+1, x0+5, FEAT_WALL_INNER);
2620
2621                                /* Secret doors (random top/bottom) */
2622                                place_secret_door(y0 - 3 + (randint(2) * 2), x0 - 3);
2623                                place_secret_door(y0 - 3 + (randint(2) * 2), x0 + 3);
2624
2625                                /* Monsters */
2626                                spread_monsters('\0', p_ptr->depth, randint(4), y0, x0, 2, 7);
2627
2628                                /* Objects */
2629                                if (rand_int(3) == 0) place_object(y0, x0 - 2, FALSE, FALSE);
2630                                if (rand_int(3) == 0) place_object(y0, x0 + 2, FALSE, FALSE);
2631                        }
2632
2633                        break;
2634                }
2635
2636                /* An inner room with a checkerboard */
2637                case 3:
2638                {
2639                        /* Open the inner room with a secret door */
2640                        generate_hole(y1-1, x1-1, y2+1, x2+1, FEAT_SECRET);
2641
2642                        /* Checkerboard */
2643                        for (y = y1; y <= y2; y++)
2644                        {
2645                                for (x = x1; x <= x2; x++)
2646                                {
2647                                        if ((x + y) & 0x01)
2648                                        {
2649                                                cave_set_feat(y, x, FEAT_WALL_INNER);
2650                                        }
2651                                }
2652                        }
2653
2654                        /* Monsters (especially undead) just love mazes. */
2655                        if (rand_int(3) == 0)
2656                                spread_monsters('N', p_ptr->depth, randint(6), y0, x0, 2, 9);
2657                        else if (rand_int(3) == 0)
2658                                spread_monsters('*', p_ptr->depth, randint(6), y0, x0, 2, 9);
2659                        else
2660                                spread_monsters('\0', p_ptr->depth, randint(6), y0, x0, 2, 9);
2661
2662
2663                        /* Traps make them entertaining. */
2664                        spread_traps(2 + rand_int(4), y0, x0, 2, 9);
2665
2666                        /* Mazes should have some pretty good treasure too. */
2667                        spread_objects(p_ptr->depth, 2 + rand_int(4), y0, x0, 2, 9);
2668
2669                        break;
2670                }
2671
2672                /* Four small rooms. */
2673                case 4:
2674                {
2675                        /* Inner "cross" */
2676                        generate_plus(y1, x1, y2, x2, FEAT_WALL_INNER);
2677
2678                        /* Doors into the rooms */
2679                        if (rand_int(100) < 50)
2680                        {
2681                                int i = randint(10);
2682                                place_secret_door(y1 - 1, x0 - i);
2683                                place_secret_door(y1 - 1, x0 + i);
2684                                place_secret_door(y2 + 1, x0 - i);
2685                                place_secret_door(y2 + 1, x0 + i);
2686                        }
2687                        else
2688                        {
2689                                int i = randint(3);
2690                                place_secret_door(y0 + i, x1 - 1);
2691                                place_secret_door(y0 - i, x1 - 1);
2692                                place_secret_door(y0 + i, x2 + 1);
2693                                place_secret_door(y0 - i, x2 + 1);
2694                        }
2695
2696                        /* Treasure, centered at the center of the cross */
2697                        spread_objects(p_ptr->depth, 2 + randint(2), y0, x0, 1, 1);
2698
2699                        /* Gotta have some monsters */
2700                        spread_monsters('\0', p_ptr->depth, 6 + rand_int(11), y0, x0, 2, 9);
2701
2702                        break;
2703                }
2704        }
2705
2706        /* Success */
2707        return (TRUE);
2708}
2709
2710
2711/*
2712 * Type 5 -- Monster pits
2713 *
2714 * A monster pit is a 11x33 room, with an inner room filled with monsters.
2715 *
2716 * The type of monsters is determined by inputing the current dungeon
2717 * level into "mon_symbol_at_depth", and accepting the character returned.
2718 * After translating this into a set of selection criteria, monsters are
2719 * chosen and arranged in the inner room.
2720 *
2721 * Monster pits will never contain unique monsters.
2722 *
2723 */
2724static bool build_type5(void)
2725{
2726        int y, x, y0, x0, y1, x1, y2, x2;
2727        int i, j;
2728        int depth;
2729        int choice;
2730
2731        char *name;
2732        char symbol;
2733
2734        bool ordered = FALSE;
2735        bool dummy;
2736        int light = FALSE;
2737
2738
2739        /* Pick a room size (less border walls) */
2740        y = 9;
2741        x = 23;
2742
2743        /* Find and reserve some space in the dungeon.  Get center of room. */
2744        if (!find_space(&y0, &x0, y+2, x+2)) return (FALSE);
2745
2746        /* Locate the room */
2747        y1 = y0 - y / 2;
2748        x1 = x0 - x / 2;
2749        y2 =  y1 + y - 1;
2750        x2 =  x1 + x - 1;
2751
2752
2753        /* Generate new room.  Quit immediately if out of bounds. */
2754        if (!generate_room(y1-1, x1-1, y2+1, x2+1, light)) return (FALSE);
2755
2756
2757        /* Generate outer walls */
2758        generate_draw(y1-1, x1-1, y2+1, x2+1, FEAT_WALL_OUTER);
2759
2760        /* Generate inner floors */
2761        generate_fill(y1, x1, y2, x2, FEAT_FLOOR);
2762
2763        /* Advance to the center room */
2764        y1 = y1 + 2;
2765        y2 = y2 - 2;
2766        x1 = x1 + 2;
2767        x2 = x2 - 2;
2768
2769        /* Generate inner walls */
2770        generate_draw(y1-1, x1-1, y2+1, x2+1, FEAT_WALL_INNER);
2771
2772        /* Open the inner room with a secret door */
2773        generate_hole(y1-1, x1-1, y2+1, x2+1, FEAT_SECRET);
2774
2775
2776        /* Get a legal depth. */
2777        depth = p_ptr->depth + rand_int(11) - 5;
2778        if (depth > 60) depth = 60;
2779        if (depth <  5) depth =  5;
2780
2781        /* Pick a table position at random, favoring the first seven. */
2782        if (rand_int(5) == 0) choice = 7 + rand_int(6);
2783        else                  choice = rand_int(7);
2784
2785        /* Choose a monster type, using that depth and table position. */
2786        symbol = mon_symbol_at_depth[depth / 5 - 1][choice];
2787
2788
2789        /* Allow tougher monsters. */
2790        depth = p_ptr->depth + 3 + (p_ptr->depth < 70 ? p_ptr->depth/7 : 10);
2791
2792
2793        /*
2794         * Set monster generation restrictions.  Decide how to order
2795         * monsters.  Get a description of the monsters.
2796         */
2797        name = mon_restrict(symbol, (byte)depth, &ordered, FALSE);
2798
2799        /* A default description probably means trouble, so stop. */
2800        if (streq(name, "misc") || !name[0]) return (TRUE);
2801
2802        /* Build the monster probability table.  Leave the room empty on failure. */
2803        if (!get_mon_num(depth)) return (TRUE);
2804
2805
2806        /* Arrange the monsters in the room randomly. */
2807        if (!ordered)
2808        {
2809                int r_idx = 0;
2810
2811                /* Place some monsters */
2812                for (y = y0 - 2; y <= y0 + 2; y++)
2813                {
2814                        for (x = x0 - 9; x <= x0 + 9; x++)
2815                        {
2816                                /* Get a monster index */
2817                                r_idx = get_mon_num(depth);
2818
2819                                /* Place a single monster */
2820                                (void)place_monster_aux(y, x, r_idx, FALSE, FALSE);
2821                        }
2822                }
2823        }
2824
2825        /* Arrange the monsters in the room in an orderly fashion. */
2826        else
2827        {
2828                s16b what[16];
2829
2830                /* Pick some monster types */
2831                for (i = 0; i < 16; i++)
2832                {
2833                        /* Get a monster index */
2834                        what[i] = get_mon_num(depth);
2835                }
2836
2837                /* Sort the monsters */
2838                for (i = 0; i < 16 - 1; i++)
2839                {
2840                        for (j = 0; j < 16 - 1; j++)
2841                        {
2842                                int i1 = j;
2843                                int i2 = j + 1;
2844
2845                                int p1 = r_info[what[i1]].level;
2846                                int p2 = r_info[what[i2]].level;
2847
2848                                /* Bubble sort */
2849                                if (p1 > p2)
2850                                {
2851                                        int tmp = what[i1];
2852                                        what[i1] = what[i2];
2853                                        what[i2] = tmp;
2854                                }
2855                        }
2856                }
2857
2858
2859                /* Top and bottom rows (outer) */
2860                for (x = x0 - 9; x <= x0 - 4; x++)
2861                {
2862                        place_monster_aux(y0 - 2, x, what[2], FALSE, FALSE);
2863                        place_monster_aux(y0 + 2, x, what[2], FALSE, FALSE);
2864                }
2865                for (x = x0 + 4; x <= x0 + 9; x++)
2866                {
2867                        place_monster_aux(y0 - 2, x, what[2], FALSE, FALSE);
2868                        place_monster_aux(y0 + 2, x, what[2], FALSE, FALSE);
2869                }
2870
2871                /* Top and bottom rows (inner) */
2872                for (x = x0 - 3; x <= x0 + 3; x++)
2873                {
2874                        place_monster_aux(y0 - 2, x, what[3], FALSE, FALSE);
2875                        place_monster_aux(y0 + 2, x, what[3], FALSE, FALSE);
2876                }
2877
2878                /* Middle columns */
2879                for (y = y0 - 1; y <= y0 + 1; y++)
2880                {
2881                        place_monster_aux(y, x0 - 9, what[2], FALSE, FALSE);
2882                        place_monster_aux(y, x0 + 9, what[2], FALSE, FALSE);
2883
2884                        place_monster_aux(y, x0 - 8, what[4], FALSE, FALSE);
2885                        place_monster_aux(y, x0 + 8, what[4], FALSE, FALSE);
2886
2887                        place_monster_aux(y, x0 - 7, what[5], FALSE, FALSE);
2888                        place_monster_aux(y, x0 + 7, what[5], FALSE, FALSE);
2889
2890                        place_monster_aux(y, x0 - 6, what[6], FALSE, FALSE);
2891                        place_monster_aux(y, x0 + 6, what[6], FALSE, FALSE);
2892
2893                        place_monster_aux(y, x0 - 5, what[7], FALSE, FALSE);
2894                        place_monster_aux(y, x0 + 5, what[7], FALSE, FALSE);
2895
2896                        place_monster_aux(y, x0 - 4, what[8], FALSE, FALSE);
2897                        place_monster_aux(y, x0 + 4, what[8], FALSE, FALSE);
2898
2899                        place_monster_aux(y, x0 - 3, what[9], FALSE, FALSE);
2900                        place_monster_aux(y, x0 + 3, what[9], FALSE, FALSE);
2901
2902                        place_monster_aux(y, x0 - 2, what[11], FALSE, FALSE);
2903                        place_monster_aux(y, x0 + 2, what[11], FALSE, FALSE);
2904                }
2905
2906                /* Above/Below the center monster */
2907                for (x = x0 - 1; x <= x0 + 1; x++)
2908                {
2909                        place_monster_aux(y0 + 1, x, what[12], FALSE, FALSE);
2910                        place_monster_aux(y0 - 1, x, what[12], FALSE, FALSE);
2911                }
2912
2913                /* Next to the center monster */
2914                place_monster_aux(y0, x0 + 1, what[14], FALSE, FALSE);
2915                place_monster_aux(y0, x0 - 1, what[14], FALSE, FALSE);
2916
2917                /* Center monster */
2918                place_monster_aux(y0, x0, what[15], FALSE, FALSE);
2919        }
2920
2921        /* Remove restrictions */
2922        (void)mon_restrict('\0', (byte)depth, &dummy, FALSE);
2923
2924
2925        /* Describe */
2926        if (cheat_room)
2927        {
2928                /* Room type */
2929                msg_format("Monster pit (%s)", name);
2930        }
2931
2932        /* Increase the level rating */
2933        rating += 10;
2934
2935        /* Sometimes cause a special feeling */
2936        if ((randint(50) >= p_ptr->depth) && (rand_int(2) == 0))
2937        {
2938                good_item_flag = TRUE;
2939        }
2940
2941
2942        /* Success */
2943        return (TRUE);
2944}
2945
2946
2947
2948/*
2949 * Use information from the "v_info" array to fill in vault rooms.
2950 *
2951 * We mark grids "icky" to indicate the presence of a vault.
2952 */
2953static bool build_vault(int y0, int x0, int ymax, int xmax, cptr data,
2954        byte vault_type)
2955{
2956        int x, y;
2957        int y1, x1, y2, x2;
2958
2959        cptr t;
2960
2961
2962        /* Calculate the borders of the vault */
2963        y1 = y0 - (ymax / 2);
2964        x1 = x0 - (xmax / 2);
2965        y2 = y1 + ymax - 1;
2966        x2 = x1 + xmax - 1;
2967
2968        /* Make certain that the vault does not cross the dungeon edge */
2969        if ((!in_bounds(y1, x1)) || (!in_bounds(y2, x2))) return (FALSE);
2970
2971
2972        /* Place dungeon features and objects */
2973        for (t = data, y = y1; y <= y2; y++)
2974        {
2975                for (x = x1; x <= x2; x++, t++)
2976                {
2977                        /* Hack -- skip "non-grids" */
2978                        if (*t == ' ')
2979                        {
2980                                continue;
2981                        }
2982
2983                        /* Lay down a floor */
2984                        cave_set_feat(y, x, FEAT_FLOOR);
2985
2986                        /* Part of a vault */
2987                        cave_info[y][x] |= (CAVE_ROOM | CAVE_ICKY);
2988
2989                        /* Analyze the grid */
2990                        switch (*t)
2991                        {
2992                                /* Granite wall (outer) */
2993                                case '%':
2994                                {
2995                                        cave_set_feat(y, x, FEAT_WALL_OUTER);
2996                                        break;
2997                                }
2998
2999                                /* Granite wall (inner) */
3000                                case '#':
3001                                {
3002                                        cave_set_feat(y, x, FEAT_WALL_INNER);
3003                                        break;
3004                                }
3005                                /* Permanent wall (inner) */
3006                                case 'X':
3007                                {
3008                                        cave_set_feat(y, x, FEAT_PERM_INNER);
3009                                        break;
3010                                }
3011
3012                                /* Treasure/trap */
3013                                case '*':
3014                                {
3015                                        if (rand_int(100) < 75)
3016                                        {
3017                                                place_object(y, x, FALSE, FALSE);
3018                                        }
3019                                        else
3020                                        {
3021                                                place_trap(y, x);
3022                                        }
3023                                        break;
3024                                }
3025
3026                                /* Secret doors */
3027                                case '+':
3028                                {
3029                                        place_secret_door(y, x);
3030                                        break;
3031                                }
3032
3033                                /* Trap */
3034                                case '^':
3035                                {
3036                                        place_trap(y, x);
3037                                        break;
3038                                }
3039                        }
3040                }
3041        }
3042
3043        /* Place dungeon monsters and objects */
3044        for (t = data, y = y1; y <= y2; y++)
3045        {
3046                for (x = x1; x <= x2; x++, t++)
3047                {
3048                        /* Hack -- skip "non-grids" */
3049                        if (*t == ' ') continue;
3050
3051                        /* Analyze the grid */
3052                        switch (*t)
3053                        {
3054                                /* Monster */
3055                                case '&':
3056                                {
3057                                        monster_level = p_ptr->depth + 5;
3058                                        place_monster(y, x, TRUE, TRUE);
3059                                        monster_level = p_ptr->depth;
3060                                        break;
3061                                }
3062
3063                                /* Meaner monster */
3064                                case '@':
3065                                {
3066                                        monster_level = p_ptr->depth + 11;
3067                                        place_monster(y, x, TRUE, TRUE);
3068                                        monster_level = p_ptr->depth;
3069                                        break;
3070                                }
3071
3072                                /* Meaner monster, plus treasure */
3073                                case '9':
3074                                {
3075                                        monster_level = p_ptr->depth + 9;
3076                                        place_monster(y, x, TRUE, TRUE);
3077                                        monster_level = p_ptr->depth;
3078                                        object_level = p_ptr->depth + 7;
3079                                        place_object(y, x, TRUE, FALSE);
3080                                        object_level = p_ptr->depth;
3081                                        break;
3082                                }
3083
3084                                /* Nasty monster and treasure */
3085                                case '8':
3086                                {
3087                                        monster_level = p_ptr->depth + 40;
3088                                        place_monster(y, x, TRUE, TRUE);
3089                                        monster_level = p_ptr->depth;
3090                                        object_level = p_ptr->depth + 20;
3091                                        place_object(y, x, TRUE, TRUE);
3092                                        object_level = p_ptr->depth;
3093                                        break;
3094                                }
3095
3096                                /* Monster and/or object */
3097                                case ',':
3098                                {
3099                                        if (rand_int(100) < 50)
3100                                        {
3101                                                monster_level = p_ptr->depth + 3;
3102                                                place_monster(y, x, TRUE, TRUE);
3103                                                monster_level = p_ptr->depth;
3104                                        }
3105                                        if (rand_int(100) < 50)
3106                                        {
3107                                                object_level = p_ptr->depth + 7;
3108                                                place_object(y, x, FALSE, FALSE);
3109                                                object_level = p_ptr->depth;
3110                                        }
3111                                        break;
3112                                }
3113                        }
3114                }
3115        }
3116
3117        /* Success. */
3118        return (TRUE);
3119}
3120
3121/*
3122 * Type 6 -- lesser vaults.
3123 */
3124static bool build_type6(void)
3125{
3126        vault_type *v_ptr;
3127        int y, x;
3128
3129        /* Pick a lesser vault */
3130        while (TRUE)
3131        {
3132                /* Get a random vault record */
3133                v_ptr = &v_info[rand_int(z_info->v_max)];
3134
3135                /* Accept the first lesser vault */
3136                if (v_ptr->typ == 6) break;
3137        }
3138
3139        /* Find and reserve some space in the dungeon.  Get center of room. */
3140        if (!find_space(&y, &x, v_ptr->hgt, v_ptr->wid)) return (FALSE);
3141
3142
3143        /* Message */
3144        if (cheat_room) msg_format("Lesser vault (%s)", v_name + v_ptr->name);
3145
3146        /* Boost the rating */
3147        rating += v_ptr->rat;
3148
3149        /* (Sometimes) Cause a special feeling */
3150        if ((p_ptr->depth <= 50) ||
3151            (randint((p_ptr->depth - 40) * (p_ptr->depth - 40) + 1) < 400))
3152        {
3153                good_item_flag = TRUE;
3154        }
3155
3156
3157        /* Build the vault */
3158        if (!build_vault(y, x, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text,
3159                6)) return (FALSE);
3160
3161        /* Success */
3162        return (TRUE);
3163}
3164
3165
3166
3167/*
3168 * Type 7 -- greater vaults.
3169 */
3170static bool build_type7(void)
3171{
3172        vault_type *v_ptr;
3173        int y, x;
3174
3175        /* Pick a lesser vault */
3176        while (TRUE)
3177        {
3178                /* Get a random vault record */
3179                v_ptr = &v_info[rand_int(z_info->v_max)];
3180
3181                /* Accept the first greater vault */
3182                if (v_ptr->typ == 7) break;
3183        }
3184
3185        /* Find and reserve some space in the dungeon.  Get center of room. */
3186        if (!find_space(&y, &x, v_ptr->hgt, v_ptr->wid)) return (FALSE);
3187
3188
3189        /* Message */
3190        if (cheat_room) msg_format("Greater vault (%s)", v_name + v_ptr->name);
3191
3192        /* Boost the rating */
3193        rating += v_ptr->rat;
3194
3195        /* Greater vaults are special */
3196        good_item_flag = TRUE;
3197
3198
3199        /* Build the vault (never lit, icky, type 7) */
3200        if (!build_vault(y, x, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text,
3201                7)) return (FALSE);
3202
3203        /* Success */
3204        return (TRUE);
3205}
3206
3207
3208/*
3209 * Helper function that reads the room data table and returns the number
3210 * of rooms, of a given type, we should build on this level.
3211 */
3212static int num_rooms_allowed(int room_type)
3213{
3214        int allowed = 0;
3215        int base_num, num_tries, mod, i;
3216
3217        /* Point to the room information. */
3218        room_data *rm_ptr = &room[room_type];
3219
3220
3221        /* No rooms allowed above their minimum depth. */
3222        if (p_ptr->depth < rm_ptr->min_level) return (0);
3223
3224        /* No "nothing" rooms. */
3225        if (room_type == 0) return (0);
3226
3227        /* No special limit on ordinary rooms. */
3228        if (room_type == 1) return (DUN_ROOMS);
3229
3230
3231        /* If below level 100, use the rarity value for level 100. */
3232        if (p_ptr->depth > 100)
3233        {
3234                base_num = rm_ptr->room_gen_num[10];
3235        }
3236        else
3237        {
3238                mod = p_ptr->depth % 10;
3239
3240                /* If depth is divisable by 10, use the appropriate table value. */
3241                if (mod == 0)
3242                {
3243                        base_num = rm_ptr->room_gen_num[p_ptr->depth / 10];
3244                }
3245                /* Otherwise, use a weighted average of the nearest values. */
3246                else
3247                {
3248                        base_num = ((mod * rm_ptr->room_gen_num[(p_ptr->depth + 9) / 10]) +
3249                                ((10 - mod) * rm_ptr->room_gen_num[p_ptr->depth / 10])) / 10;
3250                }
3251        }
3252
3253        /* Find out how many times we'll try to boost the room count. */
3254        num_tries = 3 * base_num / 100;
3255        if (num_tries < 2) num_tries = (base_num < 12 ? 1 : 2);
3256        if (num_tries > DUN_ROOMS / 2) num_tries = DUN_ROOMS / 2;
3257
3258
3259        /* Try several times to increase the number of rooms to build. */
3260        for (i = 0; i < num_tries; i++)
3261        {
3262                if (rand_int(1000) < 10 * base_num / num_tries)
3263                {
3264                        allowed++;
3265                }
3266        }
3267
3268        /* Return the number of rooms of that type we should build. */
3269        return (allowed);
3270}
3271
3272
3273/*
3274 * Build a room of the given type.
3275 *
3276 * Check to see if there will probably be enough space in the monster
3277 * and object arrays.
3278 */
3279static bool room_build(int room_type)
3280{
3281        /* If trying to build a special room, check some limits first. */
3282        if (room_type > 4)
3283        {
3284                /* Help prevent object over-flow */
3285                if (o_max > 3 * z_info->o_max / 4)
3286                {
3287                        return (FALSE);
3288                }
3289
3290                /* Help prevent monster over-flow */
3291                if (m_max > 3 * z_info->m_max / 4)
3292                {
3293                        return (FALSE);
3294                }
3295        }
3296
3297
3298        /* Build a room */
3299        switch (room_type)
3300        {
3301                /* Find space for, position, and build the room asked for */
3302                case  7: if (!build_type7())  return (FALSE); break;
3303                case  6: if (!build_type6())  return (FALSE); break;
3304                case  5: if (!build_type5())  return (FALSE); break;
3305                case  4: if (!build_type4())  return (FALSE); break;
3306                case  3: if (!build_type3())  return (FALSE); break;
3307                case  2: if (!build_type2())  return (FALSE); break;
3308                case  1: if (!build_type1())  return (FALSE); break;
3309
3310                /* Paranoia */
3311                default: return (FALSE);
3312        }
3313
3314        /* Success */
3315        return (TRUE);
3316}
3317
3318
3319
3320/**************************************************************/
3321/*                                                            */
3322/*                     The tunnelling code                    */
3323/*                                                            */
3324/**************************************************************/
3325
3326
3327/*
3328 * Given a current position (y1, x1), move towards the target grid
3329 * (y2, x2) either vertically or horizontally.
3330 *
3331 * If both vertical and horizontal directions seem equally good,
3332 * prefer to move horizontally.
3333 */
3334static void correct_dir(int *row_dir, int *col_dir, int y1, int x1, int y2, int x2)
3335{
3336        /* Move vertically if vertical distance to target is greater. */
3337        if (ABS(y1 - y2) > ABS(x1 - x2))
3338        {
3339                *row_dir = ((y1 < y2) ? 1 : -1);
3340                *col_dir = 0;
3341        }
3342
3343        /* Prefer to move horizontally. */
3344        else
3345        {
3346                *row_dir = 0;
3347                *col_dir = ((x1 < x2) ? 1 : -1);
3348        }
3349}
3350
3351
3352/*
3353 * Go in a semi-random direction from current location to target location. 
3354 * Do not actually head away from the target grid.  Always make a turn.
3355 */
3356static void adjust_dir(int *row_dir, int *col_dir, int y1, int x1, int y2, int x2)
3357{
3358        /* Always turn 90 degrees. */
3359        if (*row_dir == 0)
3360        {
3361                *col_dir = 0;
3362
3363                /* On the y-axis of target - freely choose a side to turn to. */
3364                if (y1 == y2) *row_dir = ((rand_int(2) == 0) ? - 1 : 1);
3365
3366                /* Never turn away from target. */
3367                else *row_dir = ((y1 < y2) ? 1 : -1);
3368        }
3369        else
3370        {
3371                *row_dir = 0;
3372
3373                /* On the x-axis of target - freely choose a side to turn to. */
3374                if (x1 == x2) *col_dir = ((rand_int(2) == 0) ? - 1 : 1);
3375
3376                /* Never turn away from target. */
3377                else *col_dir = ((x1 < x2) ? 1 : -1);
3378        }
3379}
3380
3381
3382/*
3383 * Go in a completely random orthongonal direction.  If we turn around
3384 * 180 degrees, save the grid; it may be a good place to place stairs
3385 * and/or the player.
3386 */
3387static void rand_dir(int *row_dir, int *col_dir, int y, int x)
3388{
3389        /* Pick a random direction */
3390        int i = rand_int(4);
3391
3392        /* Extract the dy/dx components */
3393        int row_dir_tmp = ddy_ddd[i];
3394        int col_dir_tmp = ddx_ddd[i];
3395
3396        /* Save useful grids. */
3397        if ((-(*row_dir) == row_dir_tmp) && (-(*col_dir) == col_dir_tmp))
3398        {
3399                /* Save the current tunnel location if surrounded by walls. */
3400                if ((in_bounds_fully(y, x)) && (dun->stair_n < STAIR_MAX) &&
3401                        (next_to_walls(y, x) == 4))
3402                {
3403                        dun->stair[dun->stair_n].y = y;
3404                        dun->stair[dun->stair_n].x = x;
3405                        dun->stair_n++;
3406                }
3407        }
3408
3409        /* Save the new direction. */
3410        *row_dir = row_dir_tmp;
3411        *col_dir = col_dir_tmp;
3412}
3413
3414
3415/* Terrain type is unalterable and impassable. */
3416static bool unalterable(feat)
3417{
3418        /* A few features are unalterable. */
3419        if ((feat == FEAT_PERM_EXTRA) ||
3420            (feat == FEAT_PERM_INNER) ||
3421            (feat == FEAT_PERM_OUTER) ||
3422            (feat == FEAT_PERM_SOLID))
3423        {
3424                return (TRUE);
3425        }
3426
3427        /* Assume alterable */
3428        return (FALSE);
3429}
3430
3431/*
3432 * Given a set of coordinates, return the index number of the room occupying
3433 * the dungeon block this location is in.
3434 */
3435static int get_room_index(int y, int x)
3436{
3437        /* Which block are we in? */
3438        int by = y / BLOCK_HGT;
3439        int bx = x / BLOCK_WID;
3440
3441        /* Paranoia -- confirm that block is in the dungeon. */
3442        if ((by > MAX_ROOMS_ROW) || (by > MAX_ROOMS_ROW)) return (-1);
3443
3444        /* Get the room index. */
3445        return (dun->room_map[by][bx] - 1);
3446}
3447
3448
3449
3450/*
3451 * Search for a vault entrance.
3452 *
3453 * Notes:
3454 * - This function looks in both directions, and chooses the nearest
3455 *   entrance (if it has a choice).
3456 * - We assume rooms will have outer walls surrounding them.
3457 * - We assume the vault designer hasn't designed false entrances, or
3458 *   done something else really sneaky.
3459 */
3460static bool find_entrance(int row_dir, int col_dir, int *row1, int *col1)
3461{
3462        int i, j;
3463        int y;
3464        int x;
3465        int dy, dx;
3466
3467        /*
3468         * Initialize entrances found while looking in both directions, and
3469         * the distances to them.
3470         */
3471        int target_y[2] = {0, 0};
3472        int target_x[2] = {0, 0};
3473        int grids[2]    = {0, 0};
3474
3475
3476        /* Search in both directions. */
3477        for (i = 0; i < 2; i++)
3478        {
3479                bool stop_loop = FALSE;
3480
3481                y = *row1;
3482                x = *col1;
3483
3484                dy = row_dir;
3485                dx = col_dir;
3486
3487                /* Keep running through the steps. */
3488                while (TRUE)
3489                {
3490                        int dy_tmp = dy;
3491
3492                        /* Search grids on both sides for more impassable walls. */
3493                        for (j = i; j < 2 + i; j++)
3494                        {
3495                                if (dy_tmp == 0)
3496                                {
3497                                        dy = ((j == 1) ? - 1 : 1);
3498                                        dx = 0;
3499                                }
3500                                else
3501                                {
3502                                        dy = 0;
3503                                        dx = ((j == 1) ? - 1 : 1);
3504                                }
3505
3506                                /* Look in chosen direction. */
3507                                if ((!unalterable(cave_feat[y + dy][x + dx])) &&
3508                                        (cave_feat[y + dy][x + dx] != FEAT_WALL_OUTER))
3509                                {
3510                                        /*
3511                                         * Check the grid after this one.  If it belongs
3512                                         * to the same room, we've found an entrance.
3513                                         */
3514                                        if (get_room_index(y + dy, x + dx) ==
3515                                                get_room_index(y + dy + dy, x + dx + dx))
3516                                        {
3517                                                target_y[i] = y + dy;
3518                                                target_x[i] = x + dx;
3519                                                break;
3520                                        }
3521                                }
3522
3523                                /* Look again. */
3524                                else if (unalterable(cave_feat[y + dy][x + dx]))
3525                                {
3526                                        break;
3527                                }
3528
3529                                /* We're out on some kind of weird spur. */
3530                                else if (j == (1 + i))
3531                                {
3532                                        /* Stop travelling in this direction. */
3533                                        stop_loop = TRUE;
3534                                        break;
3535                                }
3536                        }
3537
3538                        /* Success or (known) failure. */
3539                        if (target_y[i] && target_x[i]) break;
3540                        if (stop_loop) break;
3541
3542                        /* Keep heading in the same direction. */
3543                        while (TRUE)
3544                        {
3545                                /* Advance to new grid in our direction of travel. */
3546                                y += dy;
3547                                x += dx;
3548
3549                                /* Count the number of grids we've travelled */
3550                                grids[i]++;
3551
3552                                /*
3553                                 * We're back where we started.  Room either has no
3554                                 * entrances, or we can't find them.
3555                                 */
3556                                if ((y == *row1) && (x == *col1))
3557                                {
3558                                        stop_loop = TRUE;
3559                                        break;
3560                                }
3561
3562                                /* We have hit the dungeon edge. */
3563                                if (!in_bounds_fully(y + dy, x + dx))
3564                                {
3565                                        stop_loop = TRUE;
3566                                        break;
3567                                }
3568
3569                                /* Next grid is outer wall. */
3570                                if (cave_feat[y + dy][x + dx] == FEAT_WALL_OUTER)
3571                                {
3572                                        /* We need to make another turn. */
3573                                        break;
3574                                }
3575
3576                                /* Next grid is alterable, and not outer wall. */
3577                                else if (!unalterable(cave_feat[y + dy][x + dx]))
3578                                {
3579                                        /*
3580                                         * Check the grid after this one.  If it belongs
3581                                         * to the same room, we've found an entrance.
3582                                         */
3583                                        if (get_room_index(y + dy, x + dx) ==
3584                                                get_room_index(y + dy + dy, x + dx + dx))
3585                                        {
3586                                                target_y[i] = y + dy;
3587                                                target_x[i] = x + dx;
3588                                                break;
3589                                        }
3590
3591                                        /*
3592                                         * If we're in the same room, our likely best move
3593                                         * is to keep moving along the permanent walls.
3594                                         */
3595                                        else
3596                                        {
3597                                                break;
3598                                        }
3599                                }
3600                        }
3601
3602                        /* Success. */
3603                        if (target_y[i] && target_x[i]) break;
3604
3605                        /* Failure. */
3606                        if (stop_loop) break;
3607                }
3608        }
3609
3610        /*
3611         * Compare reports.  Pick the only target available, or choose
3612         * the target that took less travelling to get to.
3613         */
3614        if ((target_y[0] && target_x[0]) && (target_y[1] && target_x[1]))
3615        {
3616                if (grids[0] < grids[1])
3617                {
3618                        *row1 = target_y[0];
3619                        *col1 = target_x[0];
3620                }
3621                else
3622                {
3623                        *row1 = target_y[1];
3624                        *col1 = target_x[1];
3625                }
3626
3627                return (TRUE);
3628        }
3629
3630        else if (target_y[0] && target_x[0])
3631        {
3632                *row1 = target_y[0];
3633                *col1 = target_x[0];
3634                return (TRUE);
3635        }
3636        else if (target_y[1] && target_x[1])
3637        {
3638                *row1 = target_y[1];
3639                *col1 = target_x[1];
3640                return (TRUE);
3641        }
3642
3643        /* No entrances found. */
3644        else return (FALSE);
3645}
3646
3647/*
3648 * Tests suitability of potential entranceways, and places doors if appropriate.
3649 */
3650static void try_entrance(int y0, int x0)
3651{
3652        int i, k;
3653
3654        /* Require walls on at least two sides. */
3655        for (k = 0, i = 0; i < 4; i++)
3656        {
3657                /* Extract the location */
3658                int y = y0 + ddy_ddd[i];
3659                int x = x0 + ddx_ddd[i];
3660
3661                /* Ignore non-walls. */
3662                if (cave_feat[y][x] < FEAT_MAGMA) continue;
3663
3664                /* We require at least two walls. */
3665                if ((k++) == 2) place_random_door(y0, x0);
3666        }
3667}
3668
3669/*
3670 * Places door at y, x position if at least 2 walls and two corridor spaces found
3671 */
3672static void try_door(int y0, int x0)
3673{
3674        int i, y, x;
3675        int k = 0;
3676
3677
3678        /* Ignore walls */
3679        if (cave_info[y0][x0] & (CAVE_WALL)) return;
3680
3681        /* Ignore room grids */
3682        if (cave_info[y0][x0] & (CAVE_ROOM)) return;
3683
3684        /* Occasional door (if allowed) */
3685        if (rand_int(100) < DUN_TUN_JCT)
3686        {
3687                /* Count the adjacent non-wall grids */
3688                for (i = 0; i < 4; i++)
3689                {
3690                        /* Extract the location */
3691                        y = y0 + ddy_ddd[i];
3692                        x = x0 + ddx_ddd[i];
3693
3694                        /* Skip impassable grids (or trees) */
3695                        if (cave_info[y][x] & (CAVE_WALL)) continue;
3696
3697                        /* Skip grids inside rooms */
3698                        if (cave_info[y][x] & (CAVE_ROOM)) continue;
3699
3700                        /* We require at least two walls outside of rooms. */
3701                        if ((k++) == 2) break;
3702                }
3703
3704                if (k == 2)
3705                {
3706                        /* Check Vertical */
3707                        if ((cave_feat[y0-1][x0] >= FEAT_MAGMA) &&
3708                            (cave_feat[y0+1][x0] >= FEAT_MAGMA))
3709                        {
3710                                place_random_door(y0, x0);
3711                        }
3712
3713                        /* Check Horizontal */
3714                        else if ((cave_feat[y0][x0-1] >= FEAT_MAGMA) &&
3715                            (cave_feat[y0][x0+1] >= FEAT_MAGMA))
3716                        {
3717                                place_random_door(y0, x0);
3718                        }
3719                }
3720        }
3721}
3722
3723
3724
3725
3726/*
3727 * Constructs a tunnel between two points.
3728 *
3729 * The tunnelling code connects room centers together.  It is the respon-
3730 * sibility of rooms to ensure all grids in them are accessable from the
3731 * center, or from a passable grid nearby if the center is a wall.
3732 *
3733 * (warnings)
3734 * This code is still beta-quality.  Use with care.  Known areas of
3735 * weakness include:
3736 * - A group of rooms may be connected to each other, and not to the rest
3737 *   of the dungeon.  This problem is rare.
3738 * - While the entrance-finding code is very useful, sometimes the tunnel
3739 *   gets lost on the way.
3740 * - On occasion, a tunnel will travel far too long.  It can even (rarely)
3741 *   happen that it would lock up the game if not artifically stopped.
3742 * - There are number of minor but annoying problems, both old and new,
3743 *   like excessive usage of tunnel grids, tunnels turning areas of the
3744 *   dungeon into Swiss cheese, and so on.
3745 * - This code is awfully, awfully long.
3746 *
3747 * (Handling the outer walls of rooms)
3748 * In order to place doors correctly, know when a room is connected, and
3749 * keep entances and exits to rooms neat, we set and use several different
3750 * kinds of granite.  Because of this, we must call this function before
3751 * making streamers.
3752 * - "Outer" walls must surround rooms.  The code can handle outer walls
3753 * up to two grids thick (which is common in non-rectangular rooms).
3754 * - When outer wall is pierced, "solid" walls are created along the axis
3755 * perpendicular to the direction of movement for three grids in each
3756 * direction.  This makes entrances tidy.
3757 *
3758 * (Handling difficult terrain)
3759 * When an unalterable (permanent) wall is encountered, this code is
3760 * capable of finding entrances and of using waypoints.  It is anticipated
3761 * that this will make vaults behave better than they did.
3762 *
3763 * Useful terrain values:
3764 *   FEAT_WALL_EXTRA -- granite walls
3765 *   FEAT_WALL_INNER -- inner room walls
3766 *   FEAT_WALL_OUTER -- outer room walls
3767 *   FEAT_WALL_SOLID -- solid room walls
3768 *   FEAT_PERM_INNER -- inner room walls (perma)
3769 *   FEAT_PERM_OUTER -- outer room walls (perma)
3770 *   FEAT_PERM_SOLID -- dungeon border (perma)
3771 */
3772void build_tunnel(int start_room, int end_room)
3773{
3774        int i = 0, j = 0, tmp, y, x;
3775        int y0, x0, y1, x1;
3776        int dy, dx;
3777
3778        int row_dir, col_dir;
3779
3780
3781        /* Get start and target grids. */
3782        int row1 = dun->cent[start_room].y;
3783        int col1 = dun->cent[start_room].x;
3784        int row2 = dun->cent[end_room].y;
3785        int col2 = dun->cent[end_room].x;
3786        int tmp_row = row1, tmp_col = col1;
3787
3788
3789        /* Store initial target, because we may have to use waypoints. */
3790        int initial_row2 = row2;
3791        int initial_col2 = col2;
3792
3793        /* Not yet worried about our progress */
3794        int desperation = 0;
3795
3796        /* Start out not allowing the placement of doors */
3797        bool door_flag = FALSE;
3798
3799        /* Don't leave just yet */
3800        bool leave = FALSE;
3801
3802        /* Not heading for a known entrance. */
3803        bool head_for_entrance = FALSE;
3804
3805        /* Initialize some movement counters */
3806        int adjust_dir_timer = randint(DUN_TUN_ADJ * 2);
3807        int rand_dir_timer   = randint(DUN_TUN_RND * 2);
3808        int correct_dir_timer = 0;
3809
3810
3811        /* Set number of tunnel grids and room entrances to zero. */
3812        dun->tunn_n = 0;
3813        dun->wall_n = 0;
3814
3815        /* Start out heading in the correct direction */
3816        correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3817
3818        /* Keep going until done (or look like we're getting nowhere). */
3819        while ((row1 != initial_row2) || (col1 != initial_col2))
3820        {
3821                /* Stop when tunnel is too long, or we want to stop. */
3822                if ((leave) || (dun->tunn_n == TUNN_MAX) || (j++ == 400)) break;
3823
3824                /*
3825                 * If we've reached a waypoint, the source and destination rooms
3826                 * should be connected to each other now, but they may not be to
3827                 * the rest of the network.  Get another room center at random,
3828                 * and move towards it.
3829                 */
3830                if ((row1 == row2) && (col1 == col2))
3831                {
3832                        while (TRUE)
3833                        {
3834                                i = rand_int(dun->cent_n);
3835                                if ((i != start_room) && (i != end_room)) break;
3836                        }
3837
3838                        row2 = initial_row2 = dun->cent[i].y;
3839                        col2 = initial_col2 = dun->cent[i].x;
3840
3841                        head_for_entrance = FALSE;
3842                }
3843
3844                /* Try moving randomly if we seem stuck. */
3845                else if ((row1 != tmp_row) && (col1 != tmp_col))
3846                {
3847                        desperation++;
3848
3849                        /* Try a 90 degree turn. */
3850                        if (desperation == 1)
3851                        {
3852                                adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3853                                adjust_dir_timer = 3;
3854                        }
3855
3856                        /* Try turning randomly. */
3857                        else if (desperation < 4)
3858                        {
3859                                rand_dir(&row_dir, &col_dir, row1, col1);
3860                                correct_dir_timer = 2;
3861                        }
3862                        else
3863                        {
3864                                /* We've run out of ideas.  Stop wasting time. */
3865                                break;
3866                        }
3867                }
3868
3869                /* We're making progress. */
3870                else
3871                {
3872                        /* No worries. */
3873                        desperation = 0;
3874
3875                        /* Check room. */
3876                        tmp = get_room_index(row1, col1);
3877
3878                        /* We're in our destination room - head straight for target. */
3879                        if ((tmp == end_room) && (cave_info[row1][col1] & (CAVE_ROOM)))
3880                        {
3881                                correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3882                        }
3883
3884                        else
3885                        {
3886                                /* Count down times until next movement changes. */
3887                                if (adjust_dir_timer > 0) adjust_dir_timer--;
3888                                if (rand_dir_timer > 0) rand_dir_timer--;
3889                                if (correct_dir_timer > 0) correct_dir_timer--;
3890
3891                                /* Make a random turn, set timer. */
3892                                if (rand_dir_timer == 0)
3893                                {
3894                                        rand_dir(&row_dir, &col_dir, row1, col1);
3895
3896                                        rand_dir_timer = randint(DUN_TUN_RND * 2);
3897                                        correct_dir_timer = randint(4);
3898                                }
3899
3900                                /* Adjust direction, set timer. */
3901                                else if (adjust_dir_timer == 0)
3902                                {
3903                                        adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3904
3905                                        adjust_dir_timer = randint(DUN_TUN_ADJ * 2);
3906                                }
3907
3908
3909                                /* Go in correct direction. */
3910                                else if (correct_dir_timer == 0)
3911                                {
3912                                        correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3913
3914                                        /* Don't use again unless needed. */
3915                                        correct_dir_timer = -1;
3916                                }
3917                        }
3918                }
3919
3920
3921                /* Get the next location */
3922                tmp_row = row1 + row_dir;
3923                tmp_col = col1 + col_dir;
3924
3925                /* Do not leave the dungeon */
3926                if (!in_bounds_fully(tmp_row, tmp_col))
3927                {
3928                        /* Adjust direction */
3929                        adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3930
3931                        /* Get the next location */
3932                        tmp_row = row1 + row_dir;
3933                        tmp_col = col1 + col_dir;
3934
3935                        /* Our destination is illegal - stop. */
3936                        if (!in_bounds_fully(tmp_row, tmp_col)) break;
3937                }
3938
3939                /* Tunnel through dungeon granite. */
3940                if (cave_feat[tmp_row][tmp_col] == FEAT_WALL_EXTRA)
3941                {
3942                        /* Accept this location */
3943                        row1 = tmp_row;
3944                        col1 = tmp_col;
3945
3946                        /* Save the current tunnel location */
3947                        if (dun->tunn_n < TUNN_MAX)
3948                        {
3949                                dun->tunn[dun->tunn_n].y = row1;
3950                                dun->tunn[dun->tunn_n].x = col1;
3951                                dun->tunn_n++;
3952                        }
3953
3954                        /* Allow door in next grid */
3955                        door_flag = TRUE;
3956
3957                        continue;
3958                }
3959
3960
3961                /* Pierce outer walls of rooms. */
3962                else if (cave_feat[tmp_row][tmp_col] == FEAT_WALL_OUTER)
3963                {
3964                        /* Look ahead */
3965                        y0 = tmp_row + row_dir;
3966                        x0 = tmp_col + col_dir;
3967
3968                        /* No annoying little alcoves near edge. */
3969                        if (!in_bounds_fully(y0, x0)) continue;
3970
3971
3972                        /* Disallow door in next grid */
3973                        door_flag = FALSE;
3974
3975                        /* Hack -- delay turns */
3976                        adjust_dir_timer++;  rand_dir_timer++;
3977
3978                        /* Navigate around various kinds of walls */
3979                        if ((cave_feat[y0][x0] == FEAT_WALL_SOLID) ||
3980                            (cave_feat[y0][x0] == FEAT_WALL_INNER) ||
3981                            (unalterable(cave_feat[y0][x0])))
3982                        {
3983                                for (i = 0; i < 2; i++)
3984                                {
3985                                        if (i == 0)
3986                                        {
3987                                                /* Check the more direct route first. */
3988                                                adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
3989
3990                                                /* Verify that we haven't just been here. */
3991                                                if ((dun->tunn_n == 0) || !(dun->tunn[dun->tunn_n - 1].y == row1 + row_dir) ||
3992                                                    !(dun->tunn[dun->tunn_n - 1].x == col1 + col_dir))
3993                                                {
3994                                                        tmp_row = row1 + row_dir;
3995                                                        tmp_col = col1 + col_dir;
3996                                                }
3997
3998                                                else continue;
3999                                        }
4000
4001                                        else
4002                                        {
4003                                                /* If that didn't work, try the other side. */
4004                                                tmp_row = row1 - row_dir;
4005                                                tmp_col = col1 - col_dir;
4006                                        }
4007
4008                                        if ((!unalterable(cave_feat[tmp_row][tmp_col])) &&
4009                                            (cave_feat[tmp_row][tmp_col] != FEAT_WALL_SOLID) &&
4010                                            (cave_feat[tmp_row][tmp_col] != FEAT_WALL_OUTER) &&
4011                                            (cave_feat[tmp_row][tmp_col] != FEAT_WALL_INNER))
4012                                        {
4013                                                /* Accept the location */
4014                                                row1 = tmp_row;
4015                                                col1 = tmp_col;
4016
4017                                                /* Save the current tunnel location */
4018                                                if (dun->tunn_n < TUNN_MAX)
4019                                                {
4020                                                        dun->tunn[dun->tunn_n].y = row1;
4021                                                        dun->tunn[dun->tunn_n].x = col1;
4022                                                        dun->tunn_n++;
4023                                                }
4024
4025                                                /* Continue */
4026                                                break;
4027                                        }
4028
4029                                        /* No luck. */
4030                                        if (i == 1) continue;
4031                                }
4032                        }
4033
4034                        /* Handle a double line of outer walls robustly. */
4035                        else if (cave_feat[y0][x0] == FEAT_WALL_OUTER)
4036                        {
4037                                /* Look ahead (again). */
4038                                y1 = y0 + row_dir;
4039                                x1 = x0 + col_dir;
4040
4041                                /* We've found something passable. */
4042                                if (passable(cave_feat[y1][x1]))
4043                                {
4044                                        /* Turn both outer wall grids into floor. */
4045                                        cave_set_feat(tmp_row, tmp_col, FEAT_FLOOR);
4046                                        cave_set_feat(y0, x0, FEAT_FLOOR);
4047
4048                                        /* Save the wall location */
4049                                        if (dun->wall_n < WALL_MAX)
4050                                        {
4051                                                dun->wall[dun->wall_n].y = tmp_row;
4052                                                dun->wall[dun->wall_n].x = tmp_col;
4053                                                dun->wall_n++;
4054                                        }
4055
4056                                        /* Accept this location */
4057                                        row1 = tmp_row = y0;
4058                                        col1 = tmp_col = x0;
4059                                }
4060
4061                                /* No luck - look at the sides. */
4062                                else
4063                                {
4064                                        for (i = 0; i < 2; i++)
4065                                        {
4066                                                if (i == 0)
4067                                                {
4068                                                        /* Check the more direct route first. */
4069                                                        adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
4070
4071                                                        tmp_row = row1 + row_dir;
4072                                                        tmp_col = col1 + col_dir;
4073                                                }
4074                                                else
4075                                                {
4076                                                        /* If that didn't work, try the other side. */
4077                                                        tmp_row = row1 - row_dir;
4078                                                        tmp_col = col1 - col_dir;
4079                                                }
4080
4081                                                if ((!unalterable(cave_feat[tmp_row][tmp_col])) &&
4082                                                    (cave_feat[tmp_row][tmp_col] != FEAT_WALL_SOLID) &&
4083                                                    (cave_feat[tmp_row][tmp_col] != FEAT_WALL_OUTER) &&
4084                                                    (cave_feat[tmp_row][tmp_col] != FEAT_WALL_INNER))
4085                                                {
4086                                                        /* Accept the location */
4087                                                        row1 = tmp_row;
4088                                                        col1 = tmp_col;
4089
4090                                                        /* Save the current tunnel location */
4091                                                        if (dun->tunn_n < TUNN_MAX)
4092                                                        {
4093                                                                dun->tunn[dun->tunn_n].y = row1;
4094                                                                dun->tunn[dun->tunn_n].x = col1;
4095                                                                dun->tunn_n++;
4096                                                        }
4097
4098                                                        /* Continue */
4099                                                        break;
4100                                                }
4101                                        }
4102                                }
4103                        }
4104
4105                        /* Second grid contains any other kind of terrain. */
4106                        else
4107                        {
4108                                /* Accept this location */
4109                                row1 = tmp_row;
4110                                col1 = tmp_col;
4111
4112                                /* Convert to floor grid */
4113                                cave_set_feat(row1, col1, FEAT_FLOOR);
4114
4115                                /* Save the wall location */
4116                                if (dun->wall_n < WALL_MAX)
4117                                {
4118                                        dun->wall[dun->wall_n].y = row1;
4119                                        dun->wall[dun->wall_n].x = col1;
4120                                        dun->wall_n++;
4121                                }
4122                        }
4123
4124                        /* Forbid re-entry near this piercing. */
4125                        if ((!unalterable(cave_feat[row1 + row_dir][col1 + col_dir])) &&
4126                                (cave_info[row1][col1] & (CAVE_ROOM)))
4127                        {
4128                                if (row_dir)
4129                                {
4130                                        for (x = col1 - 3; x <= col1 + 3; x++)
4131                                        {
4132                                                /* Convert adjacent "outer" walls */
4133                                                if ((in_bounds(row1, x)) &&
4134                                                    (cave_feat[row1][x] == FEAT_WALL_OUTER))
4135                                                {
4136                                                        /* Change the wall to a "solid" wall */
4137                                                        cave_set_feat(row1, x, FEAT_WALL_SOLID);
4138                                                }
4139                                        }
4140                                }
4141                                else
4142                                {
4143                                        for (y = row1 - 3; y <= row1 + 3; y++)
4144                                        {
4145                                                /* Convert adjacent "outer" walls */
4146                                                if ((in_bounds(y, col1)) &&
4147                                                    (cave_feat[y][col1] == FEAT_WALL_OUTER))
4148                                                {
4149                                                        /* Change the wall to a "solid" wall */
4150                                                        cave_set_feat(y, col1, FEAT_WALL_SOLID);
4151                                                }
4152                                        }
4153                                }
4154
4155                                /* Get current room. */
4156                                tmp = get_room_index(row1, col1);
4157
4158                                /* Record our success. */
4159                                if ((tmp != start_room) && (tmp != -1))
4160                                {
4161                                        /* If this room is connected, now our start room is too. */
4162                                        if (dun->connected[tmp])
4163                                        {
4164                                                dun->connected[start_room] = TRUE;
4165
4166                                                /* If our destination room is connected, we're done. */
4167                                                if (dun->connected[end_room]) leave = TRUE;
4168                                        }
4169
4170                                        /* If our start room was connected, this one is too. */
4171                                        else if (dun->connected[start_room])
4172                                                dun->connected[tmp] = TRUE;
4173                                }
4174
4175                                continue;
4176                        }
4177                }
4178
4179
4180                /*
4181                 * We've hit a feature that can't be altered.
4182                 */
4183                else if (unalterable(cave_feat[tmp_row][tmp_col]))
4184                {
4185                        /* We don't know what to do. */
4186                        if (!head_for_entrance)
4187                        {
4188                                /* Get the room that occupies this block. */
4189                                tmp = get_room_index(tmp_row, tmp_col);
4190
4191                                /* We're in our starting room. */
4192                                if (tmp == start_room)
4193                                {
4194                                        /* Look at next grid. */
4195                                        y = tmp_row + row_dir;
4196                                        x = tmp_col + col_dir;
4197
4198                                        /* If the next grid is outer wall, we know we need
4199                                         * to find an entrance.  Otherwise, travel through
4200                                         * the wall.
4201                                         */
4202                                        if (cave_feat[y][x] != FEAT_WALL_OUTER)
4203                                        {
4204                                                row1 = tmp_row;
4205                                                col1 = tmp_col;
4206                                                continue;
4207                                        }
4208                                }
4209
4210                                y = tmp_row;
4211                                x = tmp_col;
4212
4213                                /* We need to find an entrance to this room. */
4214                                if (!find_entrance(row_dir, col_dir, &y, &x))
4215                                {
4216                                        /* No entrance means insoluable trouble. */
4217                                        leave = TRUE;
4218                                        continue;
4219                                }
4220
4221                                /* We're in our starting room. */
4222                                if (tmp == start_room)
4223                                {
4224                                        /* Jump immediately to entrance. */
4225                                        row1 = tmp_row = y;
4226                                        col1 = tmp_col = x;
4227
4228                                        /* Look for outer wall to head for. */
4229                                        for (i = 0; i < 4; i++)
4230                                        {
4231                                                y = row1 + ddy_ddd[i];
4232                                                x = col1 + ddx_ddd[i];
4233
4234                                                if (cave_feat[y][x] == FEAT_WALL_OUTER)
4235                                                {
4236                                                        /* Aim for outer wall. */
4237                                                        row_dir = ddy_ddd[i];
4238                                                        col_dir = ddx_ddd[i];
4239
4240                                                        adjust_dir_timer = 2;
4241                                                }
4242                                        }
4243                                }
4244
4245                                /* We're anywhere else. */
4246                                else
4247                                {
4248                                        /* Aim for given waypoint. */
4249                                        row2 = y;
4250                                        col2 = x;
4251
4252                                        /* Reset the final target. */
4253                                        initial_row2 = y;
4254                                        initial_col2 = x;
4255
4256                                        /* Enter "head for entrance" mode. */
4257                                        head_for_entrance = TRUE;
4258                                }
4259                        }
4260
4261                        /* We're heading for an entrance to a vault. */
4262                        if (head_for_entrance)
4263                        {
4264                                /* Check both sides. */
4265                                for (i = 0; i < 2; i++)
4266                                {
4267                                        /*
4268                                         * Try going in the direction that best approches
4269                                         * the target first.  On the 2nd try, check the
4270                                         * opposite side.
4271                                         */
4272                                        if (col_dir == 0)
4273                                        {
4274                                                dy = 0;
4275                                                if (i == 0) dx = ((col1 < col2) ?  1 : -1);
4276                                                else        dx = ((col1 < col2) ? -1 :  1);
4277                                        }
4278                                        else
4279                                        {
4280                                                dx = 0;
4281                                                if (i == 0) dy = ((row1 < row2) ?  1 : -1);
4282                                                else        dy = ((row1 < row2) ? -1 :  1);
4283                                        }
4284
4285                                        /* Do not accept floor unless necessary. */
4286                                        /* if ((cave_feat[row1 + dy][col1 + dx] == FEAT_FLOOR)
4287                                                && (i == 0)) continue; */
4288
4289
4290                                        /* Check to see if grid to this side is alterable. */
4291                                        if (!unalterable(cave_feat[row1 + dy][col1 + dx]))
4292                                        {
4293                                                /* Change direction. */
4294                                                row_dir = dy;
4295                                                col_dir = dx;
4296
4297                                                /* Accept this location */
4298                                                row1 += row_dir;
4299                                                col1 += col_dir;
4300
4301                                                /* Clear previous contents, add a floor */
4302                                                cave_set_feat(row1, col1, FEAT_FLOOR);
4303
4304                                                /* Return to main loop. */
4305                                                break;
4306                                        }
4307
4308                                        /* We seem to be in trouble. */
4309                                        else if (i == 1)
4310                                        {
4311                                                /* If we previously found floor, accept the floor. */
4312                                                if (cave_feat[row1 -(dy)][col1 -(dx)] == FEAT_FLOOR)
4313                                                {
4314                                                        /* Change direction. */
4315                                                        row_dir = -(dy);
4316                                                        col_dir = -(dx);
4317
4318                                                        /* Accept this location */
4319                                                        row1 += row_dir;
4320                                                        col1 += col_dir;
4321
4322                                                        break;
4323                                                }
4324
4325                                                /* Otherwise, go backwards. */
4326                                                {
4327                                                        /* Change direction. */
4328                                                        row_dir = -(row_dir);
4329                                                        col_dir = -(col_dir);
4330
4331                                                        /* Accept this location */
4332                                                        row1 += row_dir;
4333                                                        col1 += col_dir;
4334
4335                                                        break;
4336                                                }
4337                                        }
4338                                }
4339                        }
4340                }
4341
4342                /* We've hit a solid wall. */
4343                else if (cave_feat[tmp_row][tmp_col] == FEAT_WALL_SOLID)
4344                {
4345                        /* check both sides, most direct route first. */
4346                        for (i = 0; i < 2; i++)
4347                        {
4348                                if (i == 0)
4349                                {
4350                                        /* Check the more direct route first. */
4351                                        adjust_dir(&row_dir, &col_dir, row1, col1, row2, col2);
4352
4353                                        tmp_row = row1 + row_dir;
4354                                        tmp_col = col1 + col_dir;
4355                                }
4356                                else
4357                                {
4358                                        /* If that didn't work, try the other side. */
4359                                        tmp_row = row1 - row_dir;
4360                                        tmp_col = col1 - col_dir;
4361                                }
4362
4363                                if ((!unalterable(cave_feat[tmp_row][tmp_col])) &&
4364                                        (cave_feat[tmp_row][tmp_col] != FEAT_WALL_SOLID))
4365                                {
4366                                        /* Accept the location */
4367                                        row1 = tmp_row;
4368                                        col1 = tmp_col;
4369
4370                                        /* Save the current tunnel location */
4371                                        if (dun->tunn_n < TUNN_MAX)
4372                                        {
4373                                                dun->tunn[dun->tunn_n].y = row1;
4374                                                dun->tunn[dun->tunn_n].x = col1;
4375                                                dun->tunn_n++;
4376                                        }
4377
4378                                        /* Move on. */
4379                                        i = 2;
4380                                }
4381                        }
4382
4383                        continue;
4384                }
4385
4386                /* Travel quickly through rooms. */
4387                else if (cave_info[tmp_row][tmp_col] & (CAVE_ROOM))
4388                {
4389                        /* Accept the location */
4390                        row1 = tmp_row;
4391                        col1 = tmp_col;
4392
4393                        continue;
4394                }
4395
4396                /*
4397                 * Handle all passable terrain outside of rooms (this is
4398                 * usually another corridor).
4399                 */
4400                else if (passable(cave_feat[tmp_row][tmp_col]))
4401                {
4402                        /* We've hit another tunnel. */
4403                        if (cave_feat[tmp_row][tmp_col] == FEAT_FLOOR)
4404                        {
4405                                /* Collect legal door locations */
4406                                if (door_flag)
4407                                {
4408                                        /* Save the door location */
4409                                        if (dun->door_n < DOOR_MAX)
4410                                        {
4411                                                dun->door[dun->door_n].y = tmp_row;
4412                                                dun->door[dun->door_n].x = tmp_col;
4413                                                dun->door_n++;
4414                                        }
4415
4416                                        /* No door in next grid */
4417                                        door_flag = FALSE;
4418                                }
4419
4420                                /* Mark start room connected. */
4421                                dun->connected[start_room] = TRUE;
4422
4423                                /*
4424                                 * If our destination room isn't connected, jump to
4425                                 * its center, and head towards the start room.
4426                                 */
4427                                if (dun->connected[end_room] == FALSE)
4428                                {
4429                                        /* Swap rooms. */
4430                                        tmp = end_room;
4431                                        end_room = start_room;
4432                                        start_room = tmp;
4433
4434                                        /* Re-initialize */
4435                                        row1 = dun->cent[start_room].y;
4436                                        col1 = dun->cent[start_room].x;
4437                                        row2 = dun->cent[end_room].y;
4438                                        col2 = dun->cent[end_room].x;
4439                                        initial_row2 = row2;
4440                                        initial_col2 = col2;
4441                                        tmp_row = row1, tmp_col = col1;
4442                                }
4443                                else
4444                                {
4445                                        /* All done. */
4446                                        leave = TRUE;
4447                                }
4448
4449                                continue;
4450                        }
4451
4452                        /* Grid is not another tunnel.  Advance, make no changes. */
4453                        row1 = tmp_row;
4454                        col1 = tmp_col;
4455
4456                        continue;
4457                }
4458        }
4459
4460        /* Turn the tunnel into corridor */
4461        for (i = 0; i < dun->tunn_n; i++)
4462        {
4463                /* Access the grid */
4464                y = dun->tunn[i].y;
4465                x = dun->tunn[i].x;
4466
4467                /* Clear previous contents, add a floor */
4468                cave_set_feat(y, x, FEAT_FLOOR);
4469        }
4470
4471        /* Make doors in entranceways. */
4472        for (i = 0; i < dun->wall_n; i++)
4473        {
4474                /* Access the grid */
4475                y = dun->wall[i].y;
4476                x = dun->wall[i].x;
4477
4478                /* Sometimes, make a door in the entranceway */
4479                if (rand_int(100) < DUN_TUN_PEN) try_entrance(y, x);
4480        }
4481
4482
4483        /* We've reached the target.  If one room was connected, now both are. */
4484        if ((row1 == initial_row2) && (col1 == initial_col2))
4485        {
4486                if (dun->connected[start_room])
4487                        dun->connected[end_room] = TRUE;
4488                else if (dun->connected[end_room])
4489                        dun->connected[start_room] = TRUE;
4490        }
4491}
4492
4493
4494/*
4495 * Generate a new dungeon level.  Determine if the level is destroyed. 
4496 * Build up to DUN_ROOMS rooms, type by type, in descending order of size
4497 * and  difficulty.
4498 *
4499 * Build the dungeon borders, scramble and connect the rooms.  Place stairs,
4500 * doors, and random monsters, objects, and traps.  Place any quest monsters.
4501 *
4502 * We mark grids "icky" to indicate the presence of a vault.
4503 *
4504 * Note that "dun_body" adds about 1100 bytes of memory to the stack.
4505 */
4506static void cave_gen(void)
4507{
4508        int i, j, k, y, x, y1, x1;
4509        int by, bx;
4510        int num_to_build;
4511        int room_type;
4512        int rooms_built = 0;
4513
4514        /* Build rooms in descending order of difficulty. */
4515        byte room_build_order[ROOM_MAX] = {7, 6, 5, 4, 3, 2, 1, 0};
4516
4517        bool destroyed = FALSE;
4518        bool dummy;
4519
4520        dun_data dun_body;
4521
4522        /* Global data */
4523        dun = &dun_body;
4524
4525
4526        /* It is possible for levels to be destroyed */
4527        if ((p_ptr->depth > 10) && (!is_quest(p_ptr->depth)) &&
4528                (rand_int(DEST_LEVEL_CHANCE) == 0))
4529        {
4530                destroyed = TRUE;
4531
4532                /* Destroyed levels do not have certain kinds of rooms. */
4533                for (i = 0; i < ROOM_MAX; i++)
4534                {
4535                        if (room_build_order[i] > 5) room_build_order[i] = 0;
4536                }
4537        }
4538
4539
4540        /* Hack -- Start with basic granite (or floor, if empty) */
4541        for (y = 0; y < DUNGEON_HGT; y++)
4542        {
4543                for (x = 0; x < DUNGEON_WID; x++)
4544                {
4545                        /* Create granite wall */
4546                        cave_info[y][x] |= (CAVE_WALL);
4547                        cave_feat[y][x] = FEAT_WALL_EXTRA;
4548                }
4549        }
4550
4551        /* Actual maximum number of rooms on this level */
4552        dun->row_rooms = DUNGEON_HGT / BLOCK_HGT;
4553        dun->col_rooms = DUNGEON_WID / BLOCK_WID;
4554
4555        /* No stair locations yet */
4556        dun->stair_n = 0;
4557
4558        /* Initialize the room table */
4559        for (by = 0; by < dun->row_rooms; by++)
4560        {
4561                for (bx = 0; bx < dun->col_rooms; bx++)
4562                {
4563                        dun->room_map[by][bx] = 0;
4564                }
4565        }
4566
4567        /* No rooms are connected yet */
4568        for (i = 0; i < CENT_MAX; i++)
4569        {
4570                dun->connected[i] = FALSE;
4571        }
4572
4573        /* No rooms yet */
4574        dun->cent_n = 0;
4575
4576
4577        /*
4578         * Build each type of room in turn until we cannot build any more.
4579         */
4580        for (i = 0; i < ROOM_MAX; i++)
4581        {
4582                /* What type of room are we building now? */
4583                room_type = room_build_order[i];
4584
4585                /* Find out how many rooms of this type we can build. */
4586                num_to_build = num_rooms_allowed(room_type);
4587
4588                /* No vaults on Quest levels (for now) -BR- */
4589                if (is_quest(p_ptr->depth) && ((room_type == 6) || (room_type == 7)))
4590                        num_to_build = 0;
4591
4592                /* Try to build all we are allowed. */
4593                for (j = 0; j < num_to_build; j++)
4594                {
4595                        /* Stop building rooms when we hit the maximum. */
4596                        if (rooms_built >= DUN_ROOMS) break;
4597
4598                        /* Build the room. */
4599                        if (room_build(room_type))
4600                        {
4601                                /* Increase the room built count. */
4602                                if (room_type == 10) rooms_built += 5;
4603                                else if ((room_type == 6) || (room_type == 9))
4604                                        rooms_built += 3;
4605                                else if (room_type == 8) rooms_built += 2;
4606                                else rooms_built++;
4607                        }
4608
4609                        /* Go to next type of room on failure. */
4610                        else break;
4611                }
4612        }
4613
4614        /* Special boundary walls -- Top */
4615        for (x = 0; x < DUNGEON_WID; x++)
4616        {
4617                y = 0;
4618
4619                /* Clear previous contents, add "solid" perma-wall */
4620                cave_set_feat(y, x, FEAT_PERM_SOLID);
4621        }
4622
4623        /* Special boundary walls -- Bottom */
4624        for (x = 0; x < DUNGEON_WID; x++)
4625        {
4626                y = DUNGEON_HGT - 1;
4627
4628                /* Clear previous contents, add "solid" perma-wall */
4629                cave_set_feat(y, x, FEAT_PERM_SOLID);
4630        }
4631
4632        /* Special boundary walls -- Left */
4633        for (y = 0; y < DUNGEON_HGT; y++)
4634        {
4635                x = 0;
4636
4637                /* Clear previous contents, add "solid" perma-wall */
4638                cave_set_feat(y, x, FEAT_PERM_SOLID);
4639        }
4640
4641        /* Special boundary walls -- Right */
4642        for (y = 0; y < DUNGEON_HGT; y++)
4643        {
4644                x = DUNGEON_WID - 1;
4645
4646                /* Clear previous contents, add "solid" perma-wall */
4647                cave_set_feat(y, x, FEAT_PERM_SOLID);
4648        }
4649
4650        /* Hack -- Scramble the room order */
4651        for (i = 0; i < dun->cent_n; i++)
4652        {
4653                int pick1 = i;
4654                int pick2 = rand_int(dun->cent_n);
4655                y1 = dun->cent[pick1].y;
4656                x1 = dun->cent[pick1].x;
4657                dun->cent[pick1].y = dun->cent[pick2].y;
4658                dun->cent[pick1].x = dun->cent[pick2].x;
4659                dun->cent[pick2].y = y1;
4660                dun->cent[pick2].x = x1;
4661
4662                /* XXX XXX - swap around room index numbers. */
4663                for (by = 0; by < 6; by++)
4664                {
4665                        for (bx = 0; bx < 18; bx++)
4666                        {
4667                                if      (dun->room_map[by][bx] == pick2 + 1)
4668                                         dun->room_map[by][bx] =  pick1 + 1;
4669                                else if (dun->room_map[by][bx] == pick1 + 1)
4670                                         dun->room_map[by][bx] =  pick2 + 1;
4671                        }
4672                }
4673        }
4674
4675        /* Start with no tunnel doors */
4676        dun->door_n = 0;
4677
4678        /* Mark the first room as being connected. */
4679        dun->connected[0] = TRUE;
4680
4681        /* Connect all the rooms together (and locate grids for tunnel doors) */
4682        for (i = 0; i < dun->cent_n; i++)
4683        {
4684                /* Connect the room to the next room. */
4685                if (i == dun->cent_n - 1) build_tunnel(dun->cent_n - 1, 0);
4686                else build_tunnel(i, i + 1);
4687        }
4688
4689        /* Place tunnel doors */
4690        for (i = 0; i < dun->door_n; i++)
4691        {
4692                /* Extract junction location */
4693                y = dun->door[i].y;
4694                x = dun->door[i].x;
4695
4696                /* Try placing doors */
4697                try_door(y, x - 1);
4698                try_door(y, x + 1);
4699                try_door(y - 1, x);
4700                try_door(y + 1, x);
4701        }
4702
4703
4704        /* Add some magma streamers */
4705        for (i = 0; i < DUN_STR_MAG; i++)
4706        {
4707                build_streamer(FEAT_MAGMA, DUN_STR_MC);
4708        }
4709
4710        /* Add some quartz streamers */
4711        for (i = 0; i < DUN_STR_QUA; i++)
4712        {
4713                build_streamer(FEAT_QUARTZ, DUN_STR_QC);
4714        }
4715
4716
4717        /* Destroy the level if necessary */
4718        if (destroyed) destroy_level();
4719
4720
4721        /* Basic "amount" */
4722        k = (p_ptr->depth / 3);
4723        if (k > 10) k = 10;
4724        if (k < 2) k = 2;
4725
4726
4727        /* Place 3 or 4 down stairs near some walls */
4728        alloc_stairs(FEAT_MORE, rand_range(3, 4), 3);
4729
4730        /* Place 1 or 2 up stairs near some walls */
4731        alloc_stairs(FEAT_LESS, rand_range(1, 2), 3);
4732
4733        /* Put some rubble in corridors */
4734        alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k));
4735
4736        /* Place some traps in the dungeon */
4737        alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint(k));
4738
4739
4740        /* Determine the character location */
4741        new_player_spot();
4742
4743
4744        /* Paranoia -- Remove all monster restrictions. */
4745        mon_restrict('\0', (byte)p_ptr->depth, &dummy, TRUE);
4746
4747        /* Paranoia -- Reset the monster generation depth. */
4748        monster_level = p_ptr->depth;
4749
4750
4751        /* Pick a base number of monsters */
4752        i = MIN_M_ALLOC_LEVEL + randint(8);
4753
4754        /* Put some monsters in the dungeon */
4755        for (j = i + k; j > 0; j--)
4756        {
4757                /* Place a random monster */
4758                (void)alloc_monster(0, TRUE);
4759        }
4760
4761
4762        /* Ensure quest monsters */
4763        if (is_quest(p_ptr->depth))
4764        {
4765                /* Ensure quest monsters */
4766                for (i = 1; i < z_info->r_max; i++)
4767                {
4768                        monster_race *r_ptr = &r_info[i];
4769
4770                        /* Ensure quest monsters */
4771                        if ((r_ptr->flags1 & (RF1_QUESTOR)) &&
4772                            (r_ptr->level == p_ptr->depth) &&
4773                            (r_ptr->cur_num <= 0))
4774                        {
4775                                int y, x;
4776
4777                                /* Pick a location */
4778                                while (1)
4779                                {
4780                                        y = rand_int(DUNGEON_HGT);
4781                                        x = rand_int(DUNGEON_WID);
4782
4783                                        if (cave_naked_bold(y, x)) break;
4784                                }
4785
4786                                /* Place the questor */
4787                                place_monster_aux(y, x, i, TRUE, TRUE);
4788                        }
4789                }
4790        }
4791
4792        /* Put some objects in rooms */
4793        alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, Rand_normal(DUN_AMT_ROOM, 3));
4794
4795        /* Put some objects/gold in the dungeon */
4796        alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, Rand_normal(DUN_AMT_ITEM, 3));
4797        alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, Rand_normal(DUN_AMT_GOLD, 3));
4798}
4799
4800
4801
4802/*
4803 * Builds a store at a given pseudo-location
4804 *
4805 * As of 2.8.1 (?) the town is actually centered in the middle of a
4806 * complete level, and thus the top left corner of the town itself
4807 * is no longer at (0,0), but rather, at (qy,qx), so the constants
4808 * in the comments below should be mentally modified accordingly.
4809 *
4810 * As of 2.7.4 (?) the stores are placed in a more "user friendly"
4811 * configuration, such that the four "center" buildings always
4812 * have at least four grids between them, to allow easy running,
4813 * and the store doors tend to face the middle of town.
4814 *
4815 * The stores now lie inside boxes from 3-9 and 12-18 vertically,
4816 * and from 7-17, 21-31, 35-45, 49-59.  Note that there are thus
4817 * always at least 2 open grids between any disconnected walls.
4818 *
4819 * Note the use of "town_illuminate()" to handle all "illumination"
4820 * and "memorization" issues.
4821 */
4822static void build_store(int n, int yy, int xx)
4823{
4824        int y, x, y0, x0, y1, x1, y2, x2, tmp;
4825
4826        int qy = SCREEN_HGT;
4827        int qx = SCREEN_WID;
4828
4829
4830        /* Find the "center" of the store */
4831        y0 = qy + yy * 9 + 6;
4832        x0 = qx + xx * 14 + 12;
4833
4834        /* Determine the store boundaries */
4835        y1 = y0 - randint((yy == 0) ? 3 : 2);
4836        y2 = y0 + randint((yy == 1) ? 3 : 2);
4837        x1 = x0 - randint(5);
4838        x2 = x0 + randint(5);
4839
4840        /* Build an invulnerable rectangular building */
4841        for (y = y1; y <= y2; y++)
4842        {
4843                for (x = x1; x <= x2; x++)
4844                {
4845                        /* Create the building */
4846                        cave_set_feat(y, x, FEAT_PERM_EXTRA);
4847                }
4848        }
4849
4850        /* Pick a door direction (S,N,E,W) */
4851        tmp = rand_int(4);
4852
4853        /* Re-roll "annoying" doors */
4854        if (((tmp == 0) && (yy == 1)) ||
4855            ((tmp == 1) && (yy == 0)) ||
4856            ((tmp == 2) && (xx == 3)) ||
4857            ((tmp == 3) && (xx == 0)))
4858        {
4859                /* Pick a new direction */
4860                tmp = rand_int(4);
4861        }
4862
4863        /* Extract a "door location" */
4864        switch (tmp)
4865        {
4866                /* Bottom side */
4867                case 0:
4868                {
4869                        y = y2;
4870                        x = rand_range(x1, x2);
4871                        break;
4872                }
4873
4874                /* Top side */
4875                case 1:
4876                {
4877                        y = y1;
4878                        x = rand_range(x1, x2);
4879                        break;
4880                }
4881
4882                /* Right side */
4883                case 2:
4884                {
4885                        y = rand_range(y1, y2);
4886                        x = x2;
4887                        break;
4888                }
4889
4890                /* Left side */
4891                default:
4892                {
4893                        y = rand_range(y1, y2);
4894                        x = x1;
4895                        break;
4896                }
4897        }
4898
4899        /* Clear previous contents, add a store door */
4900        cave_set_feat(y, x, FEAT_SHOP_HEAD + n);
4901}
4902
4903
4904
4905
4906/*
4907 * Generate the "consistent" town features, and place the player
4908 *
4909 * Hack -- play with the R.N.G. to always yield the same town
4910 * layout, including the size and shape of the buildings, the
4911 * locations of the doorways, and the location of the stairs.
4912 */
4913static void town_gen_hack(void)
4914{
4915        int y, x, k, n;
4916
4917        int qy = SCREEN_HGT;
4918        int qx = SCREEN_WID;
4919
4920        int rooms[MAX_STORES];
4921
4922
4923        /* Hack -- Use the "simple" RNG */
4924        Rand_quick = TRUE;
4925
4926        /* Hack -- Induce consistant town layout */
4927        Rand_value = seed_town;
4928
4929
4930        /* Prepare an Array of "remaining stores", and count them */
4931        for (n = 0; n < MAX_STORES; n++) rooms[n] = n;
4932
4933        /* Place two rows of stores */
4934        for (y = 0; y < 2; y++)
4935        {
4936                /* Place four stores per row */
4937                for (x = 0; x < 4; x++)
4938                {
4939                        /* Pick a random unplaced store */
4940                        k = ((n <= 1) ? 0 : rand_int(n));
4941
4942                        /* Build that store at the proper location */
4943                        build_store(rooms[k], y, x);
4944
4945                        /* Shift the stores down, remove one store */
4946                        rooms[k] = rooms[--n];
4947                }
4948        }
4949
4950
4951        /* Place the stairs */
4952        while (TRUE)
4953        {
4954                /* Pick a location at least "three" from the outer walls */
4955                y = qy + rand_range(3, SCREEN_HGT - 4);
4956                x = qx + rand_range(3, SCREEN_WID - 4);
4957
4958                /* Require a "naked" floor grid */
4959                if (cave_naked_bold(y, x)) break;
4960        }
4961
4962        /* Clear previous contents, add down stairs */
4963        cave_set_feat(y, x, FEAT_MORE);
4964
4965
4966        /* Place the player */
4967        player_place(y, x);
4968
4969
4970        /* Hack -- use the "complex" RNG */
4971        Rand_quick = FALSE;
4972}
4973
4974
4975
4976
4977/*
4978 * Town logic flow for generation of new town
4979 *
4980 * We start with a fully wiped cave of normal floors.
4981 *
4982 * Note that town_gen_hack() plays games with the R.N.G.
4983 *
4984 * This function does NOT do anything about the owners of the stores,
4985 * nor the contents thereof.  It only handles the physical layout.
4986 *
4987 * We place the player on the stairs at the same time we make them.
4988 *
4989 * Hack -- since the player always leaves the dungeon by the stairs,
4990 * he is always placed on the stairs, even if he left the dungeon via
4991 * word of recall or teleport level.
4992 */
4993static void town_gen(void)
4994{
4995        int i, y, x;
4996
4997        int residents;
4998
4999        int qy = SCREEN_HGT;
5000        int qx = SCREEN_WID;
5001
5002        bool daytime;
5003
5004
5005        /* Day time */
5006        if ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2))
5007        {
5008                /* Day time */
5009                daytime = TRUE;
5010
5011                /* Number of residents */
5012                residents = MIN_M_ALLOC_TD;
5013        }
5014
5015        /* Night time */
5016        else
5017        {
5018                /* Night time */
5019                daytime = FALSE;
5020
5021                /* Number of residents */
5022                residents = MIN_M_ALLOC_TN;
5023        }
5024
5025        /* Start with solid walls */
5026        for (y = 0; y < DUNGEON_HGT; y++)
5027        {
5028                for (x = 0; x < DUNGEON_WID; x++)
5029                {
5030                        /* Create "solid" perma-wall */
5031                        cave_set_feat(y, x, FEAT_PERM_SOLID);
5032                }
5033        }
5034
5035        /* Then place some floors */
5036        for (y = qy+1; y < qy+SCREEN_HGT-1; y++)
5037        {
5038                for (x = qx+1; x < qx+SCREEN_WID-1; x++)
5039                {
5040                        /* Create empty floor */
5041                        cave_set_feat(y, x, FEAT_FLOOR);
5042                }
5043        }
5044
5045        /* Build stuff */
5046        town_gen_hack();
5047
5048        /* Apply illumination */
5049        town_illuminate(daytime);
5050
5051        /* Make some residents */
5052        for (i = 0; i < residents; i++)
5053        {
5054                /* Make a resident */
5055                (void)alloc_monster(3, TRUE);
5056        }
5057}
5058
5059
5060/*
5061 * Generate a random dungeon level
5062 *
5063 * Hack -- regenerate any "overflow" levels
5064 *
5065 * Hack -- allow auto-scumming via a gameplay option.
5066 *
5067 * Note that this function resets flow data and grid flags directly.
5068 * Note that this function does not reset features, monsters, or objects. 
5069 * Features are left to the town and dungeon generation functions, and
5070 * "wipe_m_list()" and "wipe_o_list()" handle monsters and objects.
5071 */
5072void generate_cave(void)
5073{
5074        int y, x, num;
5075
5076        /* The dungeon is not ready */
5077        character_dungeon = FALSE;
5078
5079        /* Generate */
5080        for (num = 0; TRUE; num++)
5081        {
5082                bool okay = TRUE;
5083                cptr why = NULL;
5084
5085                /* Reset monsters and objects */
5086                o_max = 1;
5087                m_max = 1;
5088
5089
5090                /* Clear flags and flow information. */
5091                for (y = 0; y < DUNGEON_HGT; y++)
5092                {
5093                        for (x = 0; x < DUNGEON_WID; x++)
5094                        {
5095                                /* No flags */
5096                                cave_info[y][x] = 0;
5097
5098#ifdef MONSTER_FLOW
5099                                /* No flow */
5100                                cave_cost[y][x] = 0;
5101                                cave_when[y][x] = 0;
5102#endif /* MONSTER_FLOW */
5103
5104                        }
5105                }
5106
5107
5108                /* Mega-Hack -- no player in dungeon yet */
5109                cave_m_idx[p_ptr->py][p_ptr->px] = 0;
5110                p_ptr->px = p_ptr->py = 0;
5111
5112
5113                /* Reset the monster generation level */
5114                monster_level = p_ptr->depth;
5115
5116                /* Reset the object generation level */
5117                object_level = p_ptr->depth;
5118
5119                /* Nothing special here yet */
5120                good_item_flag = FALSE;
5121
5122                /* Nothing good here yet */
5123                rating = 0;
5124
5125                /* Build the town */
5126                if (!p_ptr->depth)
5127                {
5128                        /* Make a town */
5129                        town_gen();
5130                }
5131
5132                /* Build a real level */
5133                else
5134                {
5135                        /* Make a dungeon */
5136                        cave_gen();
5137                }
5138
5139                okay = TRUE;
5140
5141
5142                /* Extract the feeling */
5143                if      (rating > 50 +     p_ptr->depth    ) feeling = 2;
5144                else if (rating > 40 + 4 * p_ptr->depth / 5) feeling = 3;
5145                else if (rating > 30 + 3 * p_ptr->depth / 5) feeling = 4;
5146                else if (rating > 20 + 2 * p_ptr->depth / 5) feeling = 5;
5147                else if (rating > 15 + 1 * p_ptr->depth / 3) feeling = 6;
5148                else if (rating > 10 + 1 * p_ptr->depth / 5) feeling = 7;
5149                else if (rating >  5 + 1 * p_ptr->depth /10) feeling = 8;
5150                else if (rating >  0) feeling = 9;
5151                else feeling = 10;
5152
5153                /* Hack -- Have a special feeling sometimes */
5154                if (good_item_flag && !adult_preserve) feeling = 1;
5155
5156                /* It takes 1000 game turns for "feelings" to recharge */
5157                if ((turn - old_turn) < 1000) feeling = 0;
5158
5159                /* Hack -- no feeling in the town */
5160                if (!p_ptr->depth) feeling = 0;
5161
5162
5163                /* Prevent object over-flow */
5164                if (o_max >= z_info->o_max)
5165                {
5166                        /* Message */
5167                        why = "too many objects";
5168
5169                        /* Message */
5170                        okay = FALSE;
5171                }
5172
5173                /* Prevent monster over-flow */
5174                if (m_max >= z_info->m_max)
5175                {
5176                        /* Message */
5177                        why = "too many monsters";
5178
5179                        /* Message */
5180                        okay = FALSE;
5181                }
5182
5183                /* Mega-Hack -- "auto-scum" */
5184                if (auto_scum && (num < 100))
5185                {
5186                        /* Require "goodness" */
5187                        if ((feeling > 9) ||
5188                            ((p_ptr->depth >= 5) && (feeling > 8)) ||
5189                            ((p_ptr->depth >= 10) && (feeling > 7)) ||
5190                            ((p_ptr->depth >= 20) && (feeling > 6)) ||
5191                            ((p_ptr->depth >= 40) && (feeling > 5)))
5192                        {
5193                                /* Give message to cheaters */
5194                                if (cheat_room || cheat_hear ||
5195                                    cheat_peek || cheat_xtra)
5196                                {
5197                                        /* Message */
5198                                        why = "boring level";
5199                                }
5200
5201                                /* Try again */
5202                                okay = FALSE;
5203                        }
5204                }
5205
5206                /* Message */
5207                if ((cheat_room) && (why))
5208                        msg_format("Generation restarted (%s)", why);
5209
5210                /* Accept */
5211                if (okay) break;
5212
5213                /* Wipe the objects */
5214                wipe_o_list();
5215
5216                /* Wipe the monsters */
5217                wipe_m_list();
5218        }
5219
5220
5221        /* The dungeon is ready */
5222        character_dungeon = TRUE;
5223
5224
5225        /* Remember when this level was "created" */
5226        old_turn = turn;
5227}