1 /* NetHack 3.6 mklev.c $NHDT-Date: 1562455089 2019/07/06 23:18:09 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.63 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Alex Smith, 2017. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
14 /* croom->lx etc are schar (width <= int), so % arith ensures that */
15 /* conversion of result to int is reasonable */
17 STATIC_DCL void FDECL(mkfount, (int, struct mkroom *));
18 STATIC_DCL void FDECL(mksink, (struct mkroom *));
19 STATIC_DCL void FDECL(mkaltar, (struct mkroom *));
20 STATIC_DCL void FDECL(mkgrave, (struct mkroom *));
21 STATIC_DCL void NDECL(makevtele);
22 STATIC_DCL void NDECL(clear_level_structures);
23 STATIC_DCL void NDECL(makelevel);
24 STATIC_DCL boolean FDECL(bydoor, (XCHAR_P, XCHAR_P));
25 STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *));
26 STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
27 STATIC_DCL boolean FDECL(place_niche, (struct mkroom *, int *, int *, int *));
28 STATIC_DCL void FDECL(makeniche, (int));
29 STATIC_DCL void NDECL(make_niches);
30 STATIC_PTR int FDECL(CFDECLSPEC do_comp, (const genericptr,
32 STATIC_DCL void FDECL(dosdoor, (XCHAR_P, XCHAR_P, struct mkroom *, int));
33 STATIC_DCL void FDECL(join, (int, int, BOOLEAN_P));
34 STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *, int, int,
36 SCHAR_P, BOOLEAN_P, BOOLEAN_P));
37 STATIC_DCL void NDECL(makerooms);
38 STATIC_DCL void FDECL(finddpos, (coord *, XCHAR_P, XCHAR_P,
40 STATIC_DCL void FDECL(mkinvpos, (XCHAR_P, XCHAR_P, int));
41 STATIC_DCL void FDECL(mk_knox_portal, (XCHAR_P, XCHAR_P));
43 #define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
44 #define init_vault() vault_x = -1
45 #define do_vault() (vault_x != -1)
46 static xchar vault_x, vault_y;
47 static boolean made_branch; /* used only during level creation */
49 /* Args must be (const genericptr) so that qsort will always be happy. */
51 STATIC_PTR int CFDECLSPEC
57 /* lint complains about possible pointer alignment problems, but we know
58 that vx and vy are always properly aligned. Hence, the following
61 return (vx == vy) ? 0 : -1;
63 register const struct mkroom *x, *y;
65 x = (const struct mkroom *) vx;
66 y = (const struct mkroom *) vy;
69 return (x->lx > y->lx);
74 finddpos(cc, xl, yl, xh, yh)
80 x = rn1(xh - xl + 1, xl);
81 y = rn1(yh - yl + 1, yl);
85 for (x = xl; x <= xh; x++)
86 for (y = yl; y <= yh; y++)
90 for (x = xl; x <= xh; x++)
91 for (y = yl; y <= yh; y++)
92 if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
94 /* cannot find something reasonable -- strange */
106 #if defined(SYSV) || defined(DGUX)
107 #define CAST_nroom (unsigned) nroom
109 #define CAST_nroom nroom /*as-is*/
111 qsort((genericptr_t) rooms, CAST_nroom, sizeof (struct mkroom), do_comp);
116 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
117 register struct mkroom *croom;
119 register int hix, hiy;
128 /* locations might bump level edges in wall-less rooms */
129 /* add/subtract 1 to allow for edge locations */
134 if (hix >= COLNO - 1)
136 if (hiy >= ROWNO - 1)
140 for (x = lowx - 1; x <= hix + 1; x++) {
141 lev = &levl[x][max(lowy - 1, 0)];
142 for (y = lowy - 1; y <= hiy + 1; y++)
153 croom->rtype = rtype;
155 /* if we're not making a vault, doorindex will still be 0
156 * if we are, we'll have problems adding niches to the previous room
157 * unless fdoor is at least doorindex
159 croom->fdoor = doorindex;
160 croom->irregular = FALSE;
162 croom->nsubrooms = 0;
163 croom->sbrooms[0] = (struct mkroom *) 0;
165 for (x = lowx - 1; x <= hix + 1; x++)
166 for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
167 levl[x][y].typ = HWALL;
168 levl[x][y].horizontal = 1; /* For open/secret doors. */
170 for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
171 for (y = lowy; y <= hiy; y++) {
172 levl[x][y].typ = VWALL;
173 levl[x][y].horizontal = 0; /* For open/secret doors. */
175 for (x = lowx; x <= hix; x++) {
176 lev = &levl[x][lowy];
177 for (y = lowy; y <= hiy; y++)
181 levl[lowx - 1][lowy - 1].typ = TLCORNER;
182 levl[hix + 1][lowy - 1].typ = TRCORNER;
183 levl[lowx - 1][hiy + 1].typ = BLCORNER;
184 levl[hix + 1][hiy + 1].typ = BRCORNER;
185 } else { /* a subroom */
186 wallification(lowx - 1, lowy - 1, hix + 1, hiy + 1);
192 add_room(lowx, lowy, hix, hiy, lit, rtype, special)
193 int lowx, lowy, hix, hiy;
198 register struct mkroom *croom;
200 croom = &rooms[nroom];
201 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
209 add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
210 struct mkroom *proom;
211 int lowx, lowy, hix, hiy;
216 register struct mkroom *croom;
218 croom = &subrooms[nsubroom];
219 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
221 proom->sbrooms[proom->nsubrooms++] = croom;
230 boolean tried_vault = FALSE;
232 /* make rooms until satisfied */
233 /* rnd_rect() will returns 0 if no more rects are available... */
234 while (nroom < MAXNROFROOMS && rnd_rect()) {
235 if (nroom >= (MAXNROFROOMS / 6) && rn2(2) && !tried_vault) {
237 if (create_vault()) {
238 vault_x = rooms[nroom].lx;
239 vault_y = rooms[nroom].ly;
240 rooms[nroom].hx = -1;
242 } else if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
253 coord cc, tt, org, dest;
254 register xchar tx, ty, xx, yy;
255 register struct mkroom *croom, *troom;
261 /* find positions cc and tt for doors in croom and troom
262 and direction for a corridor between them */
264 if (troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX)
266 if (troom->lx > croom->hx) {
271 finddpos(&cc, xx, croom->ly, xx, croom->hy);
272 finddpos(&tt, tx, troom->ly, tx, troom->hy);
273 } else if (troom->hy < croom->ly) {
277 finddpos(&cc, croom->lx, yy, croom->hx, yy);
279 finddpos(&tt, troom->lx, ty, troom->hx, ty);
280 } else if (troom->hx < croom->lx) {
285 finddpos(&cc, xx, croom->ly, xx, croom->hy);
286 finddpos(&tt, tx, troom->ly, tx, troom->hy);
292 finddpos(&cc, croom->lx, yy, croom->hx, yy);
293 finddpos(&tt, troom->lx, ty, troom->hx, ty);
299 if (nxcor && levl[xx + dx][yy + dy].typ)
301 if (okdoor(xx, yy) || !nxcor)
302 dodoor(xx, yy, croom);
309 if (!dig_corridor(&org, &dest, nxcor, level.flags.arboreal ? ROOM : CORR,
313 /* we succeeded in digging the corridor */
314 if (okdoor(tt.x, tt.y) || !nxcor)
315 dodoor(tt.x, tt.y, troom);
317 if (smeq[a] < smeq[b])
329 for (a = 0; a < nroom - 1; a++) {
330 join(a, a + 1, FALSE);
332 break; /* allow some randomness */
334 for (a = 0; a < nroom - 2; a++)
335 if (smeq[a] != smeq[a + 2])
336 join(a, a + 2, FALSE);
337 for (a = 0; any && a < nroom; a++) {
339 for (b = 0; b < nroom; b++)
340 if (smeq[a] != smeq[b]) {
346 for (i = rn2(nroom) + 4; i; i--) {
356 add_door(x, y, aroom)
358 register struct mkroom *aroom;
360 register struct mkroom *broom;
364 if (aroom->doorct == 0)
365 aroom->fdoor = doorindex;
369 for (tmp = doorindex; tmp > aroom->fdoor; tmp--)
370 doors[tmp] = doors[tmp - 1];
372 for (i = 0; i < nroom; i++) {
374 if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
377 for (i = 0; i < nsubroom; i++) {
378 broom = &subrooms[i];
379 if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
384 doors[aroom->fdoor].x = x;
385 doors[aroom->fdoor].y = y;
389 dosdoor(x, y, aroom, type)
391 struct mkroom *aroom;
394 boolean shdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
396 if (!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
398 levl[x][y].typ = type;
400 if (!rn2(3)) { /* is it a locked door, closed, or a doorway? */
402 levl[x][y].doormask = D_ISOPEN;
404 levl[x][y].doormask = D_LOCKED;
406 levl[x][y].doormask = D_CLOSED;
408 if (levl[x][y].doormask != D_ISOPEN && !shdoor
409 && level_difficulty() >= 5 && !rn2(25))
410 levl[x][y].doormask |= D_TRAPPED;
414 levl[x][y].doormask = D_ISOPEN;
416 levl[x][y].doormask = D_NODOOR;
418 levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
422 /* also done in roguecorr(); doing it here first prevents
423 making mimics in place of trapped doors on rogue level */
424 if (Is_rogue_level(&u.uz))
425 levl[x][y].doormask = D_NODOOR;
427 if (levl[x][y].doormask & D_TRAPPED) {
430 if (level_difficulty() >= 9 && !rn2(5)
431 && !((mvitals[PM_SMALL_MIMIC].mvflags & G_GONE)
432 && (mvitals[PM_LARGE_MIMIC].mvflags & G_GONE)
433 && (mvitals[PM_GIANT_MIMIC].mvflags & G_GONE))) {
434 /* make a mimic instead */
435 levl[x][y].doormask = D_NODOOR;
436 mtmp = makemon(mkclass(S_MIMIC, 0), x, y, NO_MM_FLAGS);
443 if (shdoor || !rn2(5))
444 levl[x][y].doormask = D_LOCKED;
446 levl[x][y].doormask = D_CLOSED;
448 if (!shdoor && level_difficulty() >= 4 && !rn2(20))
449 levl[x][y].doormask |= D_TRAPPED;
452 add_door(x, y, aroom);
456 place_niche(aroom, dy, xx, yy)
457 register struct mkroom *aroom;
464 finddpos(&dd, aroom->lx, aroom->hy + 1, aroom->hx, aroom->hy + 1);
467 finddpos(&dd, aroom->lx, aroom->ly - 1, aroom->hx, aroom->ly - 1);
471 return (boolean) ((isok(*xx, *yy + *dy)
472 && levl[*xx][*yy + *dy].typ == STONE)
473 && (isok(*xx, *yy - *dy)
474 && !IS_POOL(levl[*xx][*yy - *dy].typ)
475 && !IS_FURNITURE(levl[*xx][*yy - *dy].typ)));
478 /* there should be one of these per trap, in the same order as trap.h */
479 static NEARDATA const char *trap_engravings[TRAPNUM] = {
480 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
481 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
482 (char *) 0, (char *) 0, (char *) 0, (char *) 0,
483 /* 14..16: trap door, teleport, level-teleport */
485 "Vlad was here", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
487 "
\83\94\83\89\83h
\82Í
\82±
\82±
\82É
\82¢
\82é", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
488 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
495 register struct mkroom *aroom;
501 if (doorindex < DOORMAX) {
503 aroom = &rooms[rn2(nroom)];
504 if (aroom->rtype != OROOM)
505 continue; /* not an ordinary room */
506 if (aroom->doorct == 1 && rn2(5))
508 if (!place_niche(aroom, &dy, &xx, &yy))
511 rm = &levl[xx][yy + dy];
512 if (trap_type || !rn2(4)) {
515 if (is_hole(trap_type) && !Can_fall_thru(&u.uz))
516 trap_type = ROCKTRAP;
517 ttmp = maketrap(xx, yy + dy, trap_type);
519 if (trap_type != ROCKTRAP)
521 if (trap_engravings[trap_type]) {
522 make_engr_at(xx, yy - dy,
523 trap_engravings[trap_type], 0L,
525 wipe_engr_at(xx, yy - dy, 5,
526 FALSE); /* age it a little */
530 dosdoor(xx, yy, aroom, SDOOR);
534 dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
536 /* inaccessible niches occasionally have iron bars */
537 if (!rn2(5) && IS_WALL(levl[xx][yy].typ)) {
538 levl[xx][yy].typ = IRONBARS;
540 (void) mkcorpstat(CORPSE, (struct monst *) 0,
541 mkclass(S_HUMAN, 0), xx,
544 if (!level.flags.noteleport)
545 (void) mksobj_at(SCR_TELEPORTATION, xx, yy + dy, TRUE,
548 (void) mkobj_at(0, xx, yy + dy, TRUE);
559 int ct = rnd((nroom >> 1) + 1), dep = depth(&u.uz);
560 boolean ltptr = (!level.flags.noteleport && dep > 15),
561 vamp = (dep > 5 && dep < 25);
564 if (ltptr && !rn2(6)) {
566 makeniche(LEVEL_TELEP);
567 } else if (vamp && !rn2(6)) {
578 makeniche(TELEP_TRAP);
581 /* clear out various globals that keep information on the current level.
582 * some of this is only necessary for some types of levels (maze, normal,
583 * special) but it's easier to put it all in one place than make sure
584 * each type initializes what it needs to separately.
587 clear_level_structures()
589 static struct rm zerorm = { cmap_to_glyph(S_stone),
590 0, 0, 0, 0, 0, 0, 0, 0, 0 };
592 register struct rm *lev;
594 /* note: normally we'd start at x=1 because map column #0 isn't used
595 (except for placing vault guard at <0,0> when removed from the map
596 but not from the level); explicitly reset column #0 along with the
597 rest so that we start the new level with a completely clean slate */
598 for (x = 0; x < COLNO; x++) {
600 for (y = 0; y < ROWNO; y++) {
603 * These used to be '#if MICROPORT_BUG',
604 * with use of memset(0) for '#if !MICROPORT_BUG' below,
605 * but memset is not appropriate for initializing pointers,
606 * so do these level.objects[][] and level.monsters[][]
607 * initializations unconditionally.
609 level.objects[x][y] = (struct obj *) 0;
610 level.monsters[x][y] = (struct monst *) 0;
613 level.objlist = (struct obj *) 0;
614 level.buriedobjlist = (struct obj *) 0;
615 level.monlist = (struct monst *) 0;
616 level.damagelist = (struct damage *) 0;
617 level.bonesinfo = (struct cemetery *) 0;
619 level.flags.nfountains = 0;
620 level.flags.nsinks = 0;
621 level.flags.has_shop = 0;
622 level.flags.has_vault = 0;
623 level.flags.has_zoo = 0;
624 level.flags.has_court = 0;
625 level.flags.has_morgue = level.flags.graveyard = 0;
626 level.flags.has_beehive = 0;
627 level.flags.has_barracks = 0;
628 level.flags.has_temple = 0;
629 level.flags.has_swamp = 0;
630 level.flags.noteleport = 0;
631 level.flags.hardfloor = 0;
632 level.flags.nommap = 0;
633 level.flags.hero_memory = 1;
634 level.flags.shortsighted = 0;
635 level.flags.sokoban_rules = 0;
636 level.flags.is_maze_lev = 0;
637 level.flags.is_cavernous_lev = 0;
638 level.flags.arboreal = 0;
639 level.flags.wizard_bones = 0;
640 level.flags.corrmaze = 0;
649 xdnstair = ydnstair = xupstair = yupstair = 0;
650 sstairs.sx = sstairs.sy = 0;
651 xdnladder = ydnladder = xupladder = yupladder = 0;
652 dnstairs_room = upstairs_room = sstairs_room = (struct mkroom *) 0;
660 register struct mkroom *croom, *troom;
663 struct monst *tmonst; /* always put a web with a spider */
667 if (wiz1_level.dlevel == 0)
669 oinit(); /* assign level dependent obj probabilities */
670 clear_level_structures();
673 register s_level *slev = Is_special(&u.uz);
675 /* check for special levels */
676 if (slev && !Is_rogue_level(&u.uz)) {
677 makemaz(slev->proto);
679 } else if (dungeons[u.uz.dnum].proto[0]) {
682 } else if (In_mines(&u.uz)) {
685 } else if (In_quest(&u.uz)) {
689 Sprintf(fillname, "%s-loca", urole.filecode);
690 loc_lev = find_level(fillname);
692 Sprintf(fillname, "%s-fil", urole.filecode);
694 (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
697 } else if (In_hell(&u.uz)
698 || (rn2(5) && u.uz.dnum == medusa_level.dnum
699 && depth(&u.uz) > depth(&medusa_level))) {
705 /* otherwise, fall through - it's a "regular" level. */
707 if (Is_rogue_level(&u.uz)) {
714 /* construct stairs (up and down in different rooms if possible) */
715 croom = &rooms[rn2(nroom)];
716 if (!Is_botlevel(&u.uz))
717 mkstairs(somex(croom), somey(croom), 0, croom); /* down */
720 croom = &rooms[rn2(nroom - 1)];
725 if (u.uz.dlevel != 1) {
730 } while (occupied(sx, sy));
731 mkstairs(sx, sy, 1, croom); /* up */
734 branchp = Is_branchlev(&u.uz); /* possible dungeon branch */
735 room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed
736 to allow a random special room */
737 if (Is_rogue_level(&u.uz))
742 /* make a secret treasure vault, not connected to the rest */
746 debugpline0("trying to make a vault...");
749 if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
751 add_room(vault_x, vault_y, vault_x + w, vault_y + h,
753 level.flags.has_vault = 1;
755 fill_room(&rooms[nroom - 1], FALSE);
756 mk_knox_portal(vault_x + w, vault_y + h);
757 if (!level.flags.noteleport && !rn2(3))
759 } else if (rnd_rect() && create_vault()) {
760 vault_x = rooms[nroom].lx;
761 vault_y = rooms[nroom].ly;
762 if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
765 rooms[nroom].hx = -1;
770 register int u_depth = depth(&u.uz);
772 if (wizard && nh_getenv("SHOPTYPE"))
774 else if (u_depth > 1 && u_depth < depth(&medusa_level)
775 && nroom >= room_threshold && rn2(u_depth) < 3)
777 else if (u_depth > 4 && !rn2(6))
779 else if (u_depth > 5 && !rn2(8)
780 && !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE))
782 else if (u_depth > 6 && !rn2(7))
784 else if (u_depth > 8 && !rn2(5))
786 else if (u_depth > 9 && !rn2(5)
787 && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE))
789 else if (u_depth > 11 && !rn2(6))
791 else if (u_depth > 12 && !rn2(8) && antholemon())
793 else if (u_depth > 14 && !rn2(4)
794 && !(mvitals[PM_SOLDIER].mvflags & G_GONE))
796 else if (u_depth > 15 && !rn2(6))
798 else if (u_depth > 16 && !rn2(8)
799 && !(mvitals[PM_COCKATRICE].mvflags & G_GONE))
804 /* Place multi-dungeon branch. */
805 place_branch(branchp, 0, 0);
807 /* for each room: put things inside */
808 for (croom = rooms; croom->hx > 0; croom++) {
809 if (croom->rtype != OROOM)
812 /* put a sleeping monster inside */
813 /* Note: monster may be on the stairs. This cannot be
814 avoided: maybe the player fell through a trap door
815 while a monster was on the stairs. Conclusion:
816 we have to check for monsters on the stairs anyway. */
818 if (u.uhave.amulet || !rn2(3)) {
821 tmonst = makemon((struct permonst *) 0, x, y, MM_NOGRP);
822 if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER]
824 (void) maketrap(x, y, WEB);
826 /* put traps and mimics inside */
827 x = 8 - (level_difficulty() / 6);
831 mktrap(0, 0, croom, (coord *) 0);
833 (void) mkgold(0L, somex(croom), somey(croom));
834 if (Is_rogue_level(&u.uz))
842 x = 80 - (depth(&u.uz) * 2);
848 /* put statues inside */
850 (void) mkcorpstat(STATUE, (struct monst *) 0,
851 (struct permonst *) 0, somex(croom),
852 somey(croom), CORPSTAT_INIT);
853 /* put box/chest inside;
854 * 40% chance for at least 1 box, regardless of number
855 * of rooms; about 5 - 7.5% for 2 boxes, least likely
856 * when few rooms; chance for 3 or more is negligible.
858 if (!rn2(nroom * 5 / 2))
859 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, somex(croom),
860 somey(croom), TRUE, FALSE);
862 /* maybe make some graffiti */
863 if (!rn2(27 + 3 * abs(depth(&u.uz)))) {
865 const char *mesg = random_engraving(buf);
871 } while (levl[x][y].typ != ROOM && !rn2(40));
872 if (!(IS_POOL(levl[x][y].typ)
873 || IS_FURNITURE(levl[x][y].typ)))
874 make_engr_at(x, y, mesg, 0L, MARK);
880 (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
884 impossible("tryct overflow4");
887 (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
894 * Place deposits of minerals (gold and misc gems) in the stone
895 * surrounding the rooms on the map.
896 * Also place kelp in water.
897 * mineralize(-1, -1, -1, -1, FALSE); => "default" behaviour
900 mineralize(kelp_pool, kelp_moat, goldprob, gemprob, skip_lvl_checks)
901 int kelp_pool, kelp_moat, goldprob, gemprob;
902 boolean skip_lvl_checks;
913 /* Place kelp, except on the plane of water */
914 if (!skip_lvl_checks && In_endgame(&u.uz))
916 for (x = 2; x < (COLNO - 2); x++)
917 for (y = 1; y < (ROWNO - 1); y++)
918 if ((kelp_pool && levl[x][y].typ == POOL && !rn2(kelp_pool))
919 || (kelp_moat && levl[x][y].typ == MOAT && !rn2(kelp_moat)))
920 (void) mksobj_at(KELP_FROND, x, y, TRUE, FALSE);
922 /* determine if it is even allowed;
923 almost all special levels are excluded */
925 && (In_hell(&u.uz) || In_V_tower(&u.uz) || Is_rogue_level(&u.uz)
926 || level.flags.arboreal
927 || ((sp = Is_special(&u.uz)) != 0 && !Is_oracle_level(&u.uz)
928 && (!In_mines(&u.uz) || sp->flags.town))))
931 /* basic level-related probabilities */
933 goldprob = 20 + depth(&u.uz) / 3;
935 gemprob = goldprob / 4;
937 /* mines have ***MORE*** goodies - otherwise why mine? */
938 if (!skip_lvl_checks) {
939 if (In_mines(&u.uz)) {
942 } else if (In_quest(&u.uz)) {
949 * Seed rock areas with gold and/or gems.
950 * We use fairly low level object handling to avoid unnecessary
951 * overhead from placing things in the floor chain prior to burial.
953 for (x = 2; x < (COLNO - 2); x++)
954 for (y = 1; y < (ROWNO - 1); y++)
955 if (levl[x][y + 1].typ != STONE) { /* <x,y> spot not eligible */
956 y += 2; /* next two spots aren't eligible either */
957 } else if (levl[x][y].typ != STONE) { /* this spot not eligible */
958 y += 1; /* next spot isn't eligible either */
959 } else if (!(levl[x][y].wall_info & W_NONDIGGABLE)
960 && levl[x][y - 1].typ == STONE
961 && levl[x + 1][y - 1].typ == STONE
962 && levl[x - 1][y - 1].typ == STONE
963 && levl[x + 1][y].typ == STONE
964 && levl[x - 1][y].typ == STONE
965 && levl[x + 1][y + 1].typ == STONE
966 && levl[x - 1][y + 1].typ == STONE) {
967 if (rn2(1000) < goldprob) {
968 if ((otmp = mksobj(GOLD_PIECE, FALSE, FALSE)) != 0) {
969 otmp->ox = x, otmp->oy = y;
970 otmp->quan = 1L + rnd(goldprob * 3);
971 otmp->owt = weight(otmp);
975 place_object(otmp, x, y);
978 if (rn2(1000) < gemprob) {
979 for (cnt = rnd(2 + dunlev(&u.uz) / 3); cnt > 0; cnt--)
980 if ((otmp = mkobj(GEM_CLASS, FALSE)) != 0) {
981 if (otmp->otyp == ROCK) {
982 dealloc_obj(otmp); /* discard it */
984 otmp->ox = x, otmp->oy = y;
988 place_object(otmp, x, y);
998 struct mkroom *croom;
1002 reseed_random(rn2_on_display_rng);
1004 init_mapseen(&u.uz);
1011 mineralize(-1, -1, -1, -1, FALSE);
1013 /* has_morgue gets cleared once morgue is entered; graveyard stays
1014 set (graveyard might already be set even when has_morgue is clear
1015 [see fixup_special()], so don't update it unconditionally) */
1016 if (level.flags.has_morgue)
1017 level.flags.graveyard = 1;
1018 if (!level.flags.is_maze_lev) {
1019 for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
1020 #ifdef SPECIALIZATION
1021 topologize(croom, FALSE);
1027 /* for many room types, rooms[].rtype is zeroed once the room has been
1028 entered; rooms[].orig_rtype always retains original rtype value */
1029 for (ridx = 0; ridx < SIZE(rooms); ridx++)
1030 rooms[ridx].orig_rtype = rooms[ridx].rtype;
1032 /* something like this usually belongs in clear_level_structures()
1033 but these aren't saved and restored so might not retain their
1034 values for the life of the current level; reset them to default
1035 now so that they never do and no one will be tempted to introduce
1036 a new use of them for anything on this level */
1037 dnstairs_room = upstairs_room = sstairs_room = (struct mkroom *) 0;
1040 reseed_random(rn2_on_display_rng);
1044 #ifdef SPECIALIZATION
1045 topologize(croom, do_ordinary)
1046 struct mkroom *croom;
1047 boolean do_ordinary;
1050 struct mkroom *croom;
1053 register int x, y, roomno = (int) ((croom - rooms) + ROOMOFFSET);
1054 int lowx = croom->lx, lowy = croom->ly;
1055 int hix = croom->hx, hiy = croom->hy;
1056 #ifdef SPECIALIZATION
1057 schar rtype = croom->rtype;
1059 int subindex, nsubrooms = croom->nsubrooms;
1061 /* skip the room if already done; i.e. a shop handled out of order */
1062 /* also skip if this is non-rectangular (it _must_ be done already) */
1063 if ((int) levl[lowx][lowy].roomno == roomno || croom->irregular)
1065 #ifdef SPECIALIZATION
1066 if (Is_rogue_level(&u.uz))
1067 do_ordinary = TRUE; /* vision routine helper */
1068 if ((rtype != OROOM) || do_ordinary)
1071 /* do innards first */
1072 for (x = lowx; x <= hix; x++)
1073 for (y = lowy; y <= hiy; y++)
1074 #ifdef SPECIALIZATION
1076 levl[x][y].roomno = NO_ROOM;
1079 levl[x][y].roomno = roomno;
1080 /* top and bottom edges */
1081 for (x = lowx - 1; x <= hix + 1; x++)
1082 for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
1083 levl[x][y].edge = 1;
1084 if (levl[x][y].roomno)
1085 levl[x][y].roomno = SHARED;
1087 levl[x][y].roomno = roomno;
1090 for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
1091 for (y = lowy; y <= hiy; y++) {
1092 levl[x][y].edge = 1;
1093 if (levl[x][y].roomno)
1094 levl[x][y].roomno = SHARED;
1096 levl[x][y].roomno = roomno;
1100 for (subindex = 0; subindex < nsubrooms; subindex++)
1101 #ifdef SPECIALIZATION
1102 topologize(croom->sbrooms[subindex], (boolean) (rtype != OROOM));
1104 topologize(croom->sbrooms[subindex]);
1108 /* Find an unused room for a branch location. */
1109 STATIC_OVL struct mkroom *
1110 find_branch_room(mp)
1113 struct mkroom *croom = 0;
1116 mazexy(mp); /* already verifies location */
1118 /* not perfect - there may be only one stairway */
1123 croom = &rooms[rn2(nroom)];
1124 while ((croom == dnstairs_room || croom == upstairs_room
1125 || croom->rtype != OROOM) && (++tryct < 100));
1127 croom = &rooms[rn2(nroom)];
1130 if (!somexy(croom, mp))
1131 impossible("Can't place branch!");
1132 } while (occupied(mp->x, mp->y)
1133 || (levl[mp->x][mp->y].typ != CORR
1134 && levl[mp->x][mp->y].typ != ROOM));
1139 /* Find the room for (x,y). Return null if not in a room. */
1140 STATIC_OVL struct mkroom *
1145 struct mkroom *curr;
1147 for (curr = rooms, i = 0; i < nroom; curr++, i++)
1148 if (inside_room(curr, x, y))
1151 return (struct mkroom *) 0;
1154 /* If given a branch, randomly place a special stair or portal. */
1156 place_branch(br, x, y)
1157 branch *br; /* branch to place */
1158 xchar x, y; /* location */
1162 boolean make_stairs;
1163 struct mkroom *br_room;
1166 * Return immediately if there is no branch to make or we have
1167 * already made one. This routine can be called twice when
1168 * a special level is loaded that specifies an SSTAIR location
1169 * as a favored spot for a branch.
1171 if (!br || made_branch)
1174 if (!x) { /* find random coordinates for branch */
1175 br_room = find_branch_room(&m);
1179 br_room = pos_to_room(x, y);
1182 if (on_level(&br->end1, &u.uz)) {
1184 make_stairs = br->type != BR_NO_END1;
1188 make_stairs = br->type != BR_NO_END2;
1192 if (br->type == BR_PORTAL) {
1193 mkportal(x, y, dest->dnum, dest->dlevel);
1194 } else if (make_stairs) {
1198 (char) on_level(&br->end1, &u.uz) ? br->end1_up : !br->end1_up;
1199 assign_level(&sstairs.tolev, dest);
1200 sstairs_room = br_room;
1202 levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
1203 levl[x][y].typ = STAIRS;
1206 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
1207 * make_stairs is false) since there is currently only one branch
1208 * per level, if we failed once, we're going to fail again on the
1216 register xchar x, y;
1220 if (isok(x + 1, y)) {
1221 typ = levl[x + 1][y].typ;
1222 if (IS_DOOR(typ) || typ == SDOOR)
1225 if (isok(x - 1, y)) {
1226 typ = levl[x - 1][y].typ;
1227 if (IS_DOOR(typ) || typ == SDOOR)
1230 if (isok(x, y + 1)) {
1231 typ = levl[x][y + 1].typ;
1232 if (IS_DOOR(typ) || typ == SDOOR)
1235 if (isok(x, y - 1)) {
1236 typ = levl[x][y - 1].typ;
1237 if (IS_DOOR(typ) || typ == SDOOR)
1243 /* see whether it is allowable to create a door at [x,y] */
1248 boolean near_door = bydoor(x, y);
1250 return ((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL)
1251 && doorindex < DOORMAX && !near_door);
1257 struct mkroom *aroom;
1259 if (doorindex >= DOORMAX) {
1260 impossible("DOORMAX exceeded?");
1264 dosdoor(x, y, aroom, rn2(8) ? DOOR : SDOOR);
1269 register xchar x, y;
1271 return (boolean) (t_at(x, y) || IS_FURNITURE(levl[x][y].typ)
1272 || is_lava(x, y) || is_pool(x, y)
1273 || invocation_pos(x, y));
1276 /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
1277 /* if tm != null, make trap at that location */
1279 mktrap(num, mazeflag, croom, tm)
1281 struct mkroom *croom;
1286 unsigned lvl = level_difficulty();
1289 /* no traps in pools */
1290 if (tm && is_pool(tm->x, tm->y))
1293 if (num > 0 && num < TRAPNUM) {
1295 } else if (Is_rogue_level(&u.uz)) {
1313 kind = SLP_GAS_TRAP;
1319 } else if (Inhell && !rn2(5)) {
1320 /* bias the frequency of fire traps in Gehennom */
1324 kind = rnd(TRAPNUM - 1);
1325 /* reject "too hard" traps */
1328 case VIBRATING_SQUARE:
1331 case ROLLING_BOULDER_TRAP:
1337 if (lvl < 5 || level.flags.noteleport)
1362 if (level.flags.noteleport)
1366 /* make these much less often than other traps */
1371 } while (kind == NO_TRAP);
1374 if (is_hole(kind) && !Can_fall_thru(&u.uz))
1380 register int tryct = 0;
1381 boolean avoid_boulder = (is_pit(kind) || is_hole(kind));
1388 else if (!somexy(croom, &m))
1390 } while (occupied(m.x, m.y)
1391 || (avoid_boulder && sobj_at(BOULDER, m.x, m.y)));
1394 t = maketrap(m.x, m.y, kind);
1395 /* we should always get type of trap we're asking for (occupied() test
1396 should prevent cases where that might not happen) but be paranoid */
1397 kind = t ? t->ttyp : NO_TRAP;
1400 (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
1402 /* The hero isn't the only person who's entered the dungeon in
1403 search of treasure. On the very shallowest levels, there's a
1404 chance that a created trap will have killed something already
1405 (and this is guaranteed on the first level).
1407 This isn't meant to give any meaningful treasure (in fact, any
1408 items we drop here are typically cursed, other than ammo fired
1409 by the trap). Rather, it's mostly just for flavour and to give
1410 players on very early levels a sufficient chance to avoid traps
1411 that may end up killing them before they have a fair chance to
1412 build max HP. Including cursed items gives the same fair chance
1413 to the starting pet, and fits the rule that possessions of the
1414 dead are normally cursed.
1416 Some types of traps are excluded because they're entirely
1417 nonlethal, even indirectly. We also exclude all of the
1418 later/fancier traps because they tend to have special
1419 considerations (e.g. webs, portals), often are indirectly
1420 lethal, and tend not to generate on shallower levels anyway.
1421 Finally, pits are excluded because it's weird to see an item
1422 in a pit and yet not be able to identify that the pit is there. */
1423 if (kind != NO_TRAP && lvl <= (unsigned) rnd(4)
1424 && kind != SQKY_BOARD && kind != RUST_TRAP
1425 /* rolling boulder trap might not have a boulder if there was no
1426 viable path (such as when placed in the corner of a room), in
1427 which case tx,ty==launch.x,y; no boulder => no dead predecessor */
1428 && !(kind == ROLLING_BOULDER_TRAP
1429 && t->launch.x == t->tx && t->launch.y == t->ty)
1430 && !is_pit(kind) && kind < HOLE) {
1431 /* Object generated by the trap; initially NULL, stays NULL if
1432 we fail to generate an object or if the trap doesn't
1433 generate objects. */
1434 struct obj *otmp = NULL;
1435 int victim_mnum; /* race of the victim */
1437 /* Not all trap types have special handling here; only the ones
1438 that kill in a specific way that's obvious after the fact. */
1441 otmp = mksobj(ARROW, TRUE, FALSE);
1442 otmp->opoisoned = 0;
1443 /* don't adjust the quantity; maybe the trap shot multiple
1444 times, there was an untrapping attempt, etc... */
1447 otmp = mksobj(DART, TRUE, FALSE);
1450 otmp = mksobj(ROCK, TRUE, FALSE);
1453 /* no item dropped by the trap */
1457 place_object(otmp, m.x, m.y);
1460 /* now otmp is reused for other items we're placing */
1462 /* Place a random possession. This could be a weapon, tool,
1463 food, or gem, i.e. the item classes that are typically
1464 nonmagical and not worthless. */
1466 int poss_class = RANDOM_CLASS; /* init => lint suppression */
1470 poss_class = WEAPON_CLASS;
1473 poss_class = TOOL_CLASS;
1476 poss_class = FOOD_CLASS;
1479 poss_class = GEM_CLASS;
1483 otmp = mkobj(poss_class, FALSE);
1484 /* these items are always cursed, both for flavour (owned
1485 by a dead adventurer, bones-pile-style) and for balance
1486 (less useful to use, and encourage pets to avoid the trap) */
1490 otmp->owt = weight(otmp);
1491 place_object(otmp, m.x, m.y);
1494 /* 20% chance of placing an additional item, recursively */
1497 /* Place a corpse. */
1500 /* elf corpses are the rarest as they're the most useful */
1501 victim_mnum = PM_ELF;
1502 /* elven adventurers get sleep resistance early; so don't
1503 generate elf corpses on sleeping gas traps unless a)
1504 we're on dlvl 2 (1 is impossible) and b) we pass a coin
1506 if (kind == SLP_GAS_TRAP && !(lvl <= 2 && rn2(2)))
1507 victim_mnum = PM_HUMAN;
1510 victim_mnum = PM_DWARF;
1512 case 3: case 4: case 5:
1513 victim_mnum = PM_ORC;
1515 case 6: case 7: case 8: case 9:
1516 /* more common as they could have come from the Mines */
1517 victim_mnum = PM_GNOME;
1518 /* 10% chance of a candle too */
1520 otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
1525 otmp->owt = weight(otmp);
1526 place_object(otmp, m.x, m.y);
1530 /* the most common race */
1531 victim_mnum = PM_HUMAN;
1534 otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
1537 otmp->age -= 51; /* died too long ago to eat */
1542 mkstairs(x, y, up, croom)
1545 struct mkroom *croom;
1548 impossible("mkstairs: bogus stair attempt at <%d,%d>", x, y);
1553 * We can't make a regular stair off an end of the dungeon. This
1554 * attempt can happen when a special level is placed at an end and
1555 * has an up or down stair specified in its description file.
1557 if ((dunlev(&u.uz) == 1 && up)
1558 || (dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
1564 upstairs_room = croom;
1568 dnstairs_room = croom;
1571 levl[x][y].typ = STAIRS;
1572 levl[x][y].ladder = up ? LA_UP : LA_DOWN;
1576 mkfount(mazeflag, croom)
1578 struct mkroom *croom;
1581 register int tryct = 0;
1588 else if (!somexy(croom, &m))
1590 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1592 /* Put a fountain at m.x, m.y */
1593 levl[m.x][m.y].typ = FOUNTAIN;
1594 /* Is it a "blessed" fountain? (affects drinking from fountain) */
1596 levl[m.x][m.y].blessedftn = 1;
1598 level.flags.nfountains++;
1603 struct mkroom *croom;
1606 register int tryct = 0;
1611 if (!somexy(croom, &m))
1613 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1615 /* Put a sink at m.x, m.y */
1616 levl[m.x][m.y].typ = SINK;
1618 level.flags.nsinks++;
1623 struct mkroom *croom;
1626 register int tryct = 0;
1629 if (croom->rtype != OROOM)
1635 if (!somexy(croom, &m))
1637 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1639 /* Put an altar at m.x, m.y */
1640 levl[m.x][m.y].typ = ALTAR;
1642 /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
1643 al = rn2((int) A_LAWFUL + 2) - 1;
1644 levl[m.x][m.y].altarmask = Align2amask(al);
1649 struct mkroom *croom;
1652 register int tryct = 0;
1653 register struct obj *otmp;
1654 boolean dobell = !rn2(10);
1656 if (croom->rtype != OROOM)
1662 if (!somexy(croom, &m))
1664 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1666 /* Put a grave at <m.x,m.y> */
1668 make_grave(m.x, m.y, dobell ? "Saved by the bell!" : (char *) 0);
1670 make_grave(m.x, m.y, dobell ? "
\83x
\83\8b\82É
\8b~
\82í
\82ê
\82½
\81I" : (char *) 0);
1672 /* Possibly fill it with objects */
1674 /* this used to use mkgold(), which puts a stack of gold on
1675 the ground (or merges it with an existing one there if
1676 present), and didn't bother burying it; now we create a
1677 loose, easily buriable, stack but we make no attempt to
1678 replicate mkgold()'s level-based formula for the amount */
1679 struct obj *gold = mksobj(GOLD_PIECE, TRUE, FALSE);
1681 gold->quan = (long) (rnd(20) + level_difficulty() * rnd(5));
1682 gold->owt = weight(gold);
1683 gold->ox = m.x, gold->oy = m.y;
1684 add_to_buried(gold);
1686 for (tryct = rn2(5); tryct; tryct--) {
1687 otmp = mkobj(RANDOM_CLASS, TRUE);
1693 add_to_buried(otmp);
1696 /* Leave a bell, in case we accidentally buried someone alive */
1698 (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE);
1702 /* maze levels have slightly different constraints from normal levels */
1703 #define x_maze_min 2
1704 #define y_maze_min 2
1707 * Major level transmutation: add a set of stairs (to the Sanctum) after
1708 * an earthquake that leaves behind a new topology, centered at inv_pos.
1709 * Assumes there are no rooms within the invocation area and that inv_pos
1710 * is not too close to the edge of the map. Also assume the hero can see,
1711 * which is guaranteed for normal play due to the fact that sight is needed
1712 * to read the Book of the Dead. [That assumption is not valid; it is
1713 * possible that "the Book reads the hero" rather than vice versa if
1714 * attempted while blind (in order to make blind-from-birth conduct viable).]
1720 xchar xmin = inv_pos.x, xmax = inv_pos.x,
1721 ymin = inv_pos.y, ymax = inv_pos.y;
1724 /* slightly odd if levitating, but not wrong */
1726 pline_The("floor shakes violently under you!");
1728 pline("
\82 \82È
\82½
\82Ì
\89º
\82Ì
\8f°
\82ª
\93Ë
\91R
\97h
\82ê
\82½
\81I");
1731 * Suppress this message if player has dug out all the walls
1732 * that would otherwise be affected.
1735 pline_The("walls around you begin to bend and crumble!");
1737 pline("
\82»
\82µ
\82Ä
\82Ü
\82í
\82è
\82Ì
\95Ç
\82ª
\82Ë
\82¶
\82ê
\81C
\8dÓ
\82¯
\82½
\81I");
1738 display_nhwindow(WIN_MESSAGE, TRUE);
1740 /* any trap hero is stuck in will be going away now */
1742 if (u.utraptype == TT_BURIEDBALL)
1743 buried_ball_to_punishment();
1746 mkinvpos(xmin, ymin, 0); /* middle, before placing stairs */
1748 for (dist = 1; dist < 7; dist++) {
1752 /* top and bottom */
1753 if (dist != 3) { /* the area is wider that it is high */
1756 for (i = xmin + 1; i < xmax; i++) {
1757 mkinvpos(i, ymin, dist);
1758 mkinvpos(i, ymax, dist);
1762 /* left and right */
1763 for (i = ymin; i <= ymax; i++) {
1764 mkinvpos(xmin, i, dist);
1765 mkinvpos(xmax, i, dist);
1768 flush_screen(1); /* make sure the new glyphs shows up */
1773 You("are standing at the top of a stairwell leading down!");
1775 You("
\89º
\82É
\91±
\82
\90\81\82«
\94²
\82¯
\8aK
\92i
\82Ì
\8fã
\82É
\97§
\82Á
\82Ä
\82¢
\82é
\81I");
1776 mkstairs(u.ux, u.uy, 0, (struct mkroom *) 0); /* down */
1778 vision_full_recalc = 1; /* everything changed */
1781 /* Change level topology. Boulders in the vicinity are eliminated.
1782 * Temporarily overrides vision in the name of a nice effect.
1785 mkinvpos(x, y, dist)
1792 register struct rm *lev = &levl[x][y];
1795 /* clip at existing map borders if necessary */
1796 if (!within_bounded_area(x, y, x_maze_min + 1, y_maze_min + 1,
1797 x_maze_max - 1, y_maze_max - 1)) {
1798 /* outermost 2 columns and/or rows may be truncated due to edge */
1800 panic("mkinvpos: <%d,%d> (%d) off map edge!", x, y, dist);
1805 if ((ttmp = t_at(x, y)) != 0)
1808 /* clear boulders; leave some rocks for non-{moat|trap} locations */
1809 make_rocks = (dist != 1 && dist != 4 && dist != 5) ? TRUE : FALSE;
1810 while ((otmp = sobj_at(BOULDER, x, y)) != 0) {
1812 fracture_rock(otmp);
1813 make_rocks = FALSE; /* don't bother with more rocks */
1815 obj_extract_self(otmp);
1816 obfree(otmp, (struct obj *) 0);
1820 /* fake out saved state */
1826 lev->horizontal = FALSE;
1827 /* short-circuit vision recalc */
1828 viz_array[y][x] = (dist < 6) ? (IN_SIGHT | COULD_SEE) : COULD_SEE;
1831 case 1: /* fire traps */
1835 ttmp = maketrap(x, y, FIRE_TRAP);
1839 case 0: /* lit room locations */
1842 case 6: /* unlit room locations */
1845 case 4: /* pools (aka a wide moat) */
1851 impossible("mkinvpos called with dist %d", dist);
1855 if ((mon = m_at(x, y)) != 0) {
1856 /* wake up mimics, don't want to deal with them blocking vision */
1860 if ((ttmp = t_at(x, y)) != 0)
1861 (void) mintrap(mon);
1863 (void) minliquid(mon);
1866 if (!does_block(x, y, lev))
1867 unblock_point(x, y); /* make sure vision knows this location is open */
1869 /* display new value of position; could have a monster/object on it */
1874 * The portal to Ludios is special. The entrance can only occur within a
1875 * vault in the main dungeon at a depth greater than 10. The Ludios branch
1876 * structure reflects this by having a bogus "source" dungeon: the value
1877 * of n_dgns (thus, Is_branchlev() will never find it).
1879 * Ludios will remain isolated until the branch is corrected by this function.
1882 mk_knox_portal(x, y)
1885 extern int n_dgns; /* from dungeon.c */
1891 br = dungeon_branch("Fort Ludios");
1893 br = dungeon_branch("
\83\8d\81[
\83f
\83B
\83I
\83X
\8dÔ");
1894 if (on_level(&knox_level, &br->end1)) {
1897 /* disallow Knox branch on a level with one branch already */
1898 if (Is_branchlev(&u.uz))
1903 /* Already set or 2/3 chance of deferring until a later level. */
1904 if (source->dnum < n_dgns || (rn2(3) && !wizard))
1907 if (!(u.uz.dnum == oracle_level.dnum /* in main dungeon */
1909 && !at_dgn_entrance("The Quest") /* but not Quest's entry */
1911 && !at_dgn_entrance("
\83N
\83G
\83X
\83g") /* but not Quest's entry */
1913 && (u_depth = depth(&u.uz)) > 10 /* beneath 10 */
1914 && u_depth < depth(&medusa_level))) /* and above Medusa */
1917 /* Adjust source to be current level and re-insert branch. */
1919 insert_branch(br, TRUE);
1921 debugpline0("Made knox portal.");
1922 place_branch(br, x, y);