1 /* NetHack 3.6 mklev.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
8 /* croom->lx etc are schar (width <= int), so % arith ensures that */
9 /* conversion of result to int is reasonable */
11 STATIC_DCL
void FDECL(mkfount
, (int, struct mkroom
*));
12 STATIC_DCL
void FDECL(mksink
, (struct mkroom
*));
13 STATIC_DCL
void FDECL(mkaltar
, (struct mkroom
*));
14 STATIC_DCL
void FDECL(mkgrave
, (struct mkroom
*));
15 STATIC_DCL
void NDECL(makevtele
);
16 STATIC_DCL
void NDECL(clear_level_structures
);
17 STATIC_DCL
void NDECL(makelevel
);
18 STATIC_DCL boolean
FDECL(bydoor
, (XCHAR_P
, XCHAR_P
));
19 STATIC_DCL
struct mkroom
*FDECL(find_branch_room
, (coord
*));
20 STATIC_DCL
struct mkroom
*FDECL(pos_to_room
, (XCHAR_P
, XCHAR_P
));
21 STATIC_DCL boolean
FDECL(place_niche
, (struct mkroom
*, int *, int *, int *));
22 STATIC_DCL
void FDECL(makeniche
, (int));
23 STATIC_DCL
void NDECL(make_niches
);
24 STATIC_PTR
int FDECL(CFDECLSPEC do_comp
, (const genericptr
,
26 STATIC_DCL
void FDECL(dosdoor
, (XCHAR_P
, XCHAR_P
, struct mkroom
*, int));
27 STATIC_DCL
void FDECL(join
, (int, int, BOOLEAN_P
));
28 STATIC_DCL
void FDECL(do_room_or_subroom
, (struct mkroom
*, int, int,
30 SCHAR_P
, BOOLEAN_P
, BOOLEAN_P
));
31 STATIC_DCL
void NDECL(makerooms
);
32 STATIC_DCL
void FDECL(finddpos
, (coord
*, XCHAR_P
, XCHAR_P
,
34 STATIC_DCL
void FDECL(mkinvpos
, (XCHAR_P
, XCHAR_P
, int));
35 STATIC_DCL
void FDECL(mk_knox_portal
, (XCHAR_P
, XCHAR_P
));
37 #define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
38 #define init_vault() vault_x = -1
39 #define do_vault() (vault_x != -1)
40 static xchar vault_x
, vault_y
;
41 static boolean made_branch
; /* used only during level creation */
43 /* Args must be (const genericptr) so that qsort will always be happy. */
45 STATIC_PTR
int CFDECLSPEC
51 /* lint complains about possible pointer alignment problems, but we know
52 that vx and vy are always properly aligned. Hence, the following
55 return (vx
== vy
) ? 0 : -1;
57 register const struct mkroom
*x
, *y
;
59 x
= (const struct mkroom
*) vx
;
60 y
= (const struct mkroom
*) vy
;
63 return (x
->lx
> y
->lx
);
68 finddpos(cc
, xl
, yl
, xh
, yh
)
74 x
= rn1(xh
- xl
+ 1, xl
);
75 y
= rn1(yh
- yl
+ 1, yl
);
79 for (x
= xl
; x
<= xh
; x
++)
80 for (y
= yl
; y
<= yh
; y
++)
84 for (x
= xl
; x
<= xh
; x
++)
85 for (y
= yl
; y
<= yh
; y
++)
86 if (IS_DOOR(levl
[x
][y
].typ
) || levl
[x
][y
].typ
== SDOOR
)
88 /* cannot find something reasonable -- strange */
100 #if defined(SYSV) || defined(DGUX)
101 qsort((genericptr_t
) rooms
, (unsigned) nroom
, sizeof(struct mkroom
),
104 qsort((genericptr_t
) rooms
, nroom
, sizeof(struct mkroom
), do_comp
);
109 do_room_or_subroom(croom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
, is_room
)
110 register struct mkroom
*croom
;
112 register int hix
, hiy
;
121 /* locations might bump level edges in wall-less rooms */
122 /* add/subtract 1 to allow for edge locations */
127 if (hix
>= COLNO
- 1)
129 if (hiy
>= ROWNO
- 1)
133 for (x
= lowx
- 1; x
<= hix
+ 1; x
++) {
134 lev
= &levl
[x
][max(lowy
- 1, 0)];
135 for (y
= lowy
- 1; y
<= hiy
+ 1; y
++)
146 croom
->rtype
= rtype
;
148 /* if we're not making a vault, doorindex will still be 0
149 * if we are, we'll have problems adding niches to the previous room
150 * unless fdoor is at least doorindex
152 croom
->fdoor
= doorindex
;
153 croom
->irregular
= FALSE
;
155 croom
->nsubrooms
= 0;
156 croom
->sbrooms
[0] = (struct mkroom
*) 0;
158 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
159 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
160 levl
[x
][y
].typ
= HWALL
;
161 levl
[x
][y
].horizontal
= 1; /* For open/secret doors. */
163 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
164 for (y
= lowy
; y
<= hiy
; y
++) {
165 levl
[x
][y
].typ
= VWALL
;
166 levl
[x
][y
].horizontal
= 0; /* For open/secret doors. */
168 for (x
= lowx
; x
<= hix
; x
++) {
169 lev
= &levl
[x
][lowy
];
170 for (y
= lowy
; y
<= hiy
; y
++)
174 levl
[lowx
- 1][lowy
- 1].typ
= TLCORNER
;
175 levl
[hix
+ 1][lowy
- 1].typ
= TRCORNER
;
176 levl
[lowx
- 1][hiy
+ 1].typ
= BLCORNER
;
177 levl
[hix
+ 1][hiy
+ 1].typ
= BRCORNER
;
178 } else { /* a subroom */
179 wallification(lowx
- 1, lowy
- 1, hix
+ 1, hiy
+ 1);
185 add_room(lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
)
186 int lowx
, lowy
, hix
, hiy
;
191 register struct mkroom
*croom
;
193 croom
= &rooms
[nroom
];
194 do_room_or_subroom(croom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
,
202 add_subroom(proom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
)
203 struct mkroom
*proom
;
204 int lowx
, lowy
, hix
, hiy
;
209 register struct mkroom
*croom
;
211 croom
= &subrooms
[nsubroom
];
212 do_room_or_subroom(croom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
,
214 proom
->sbrooms
[proom
->nsubrooms
++] = croom
;
223 boolean tried_vault
= FALSE
;
225 /* make rooms until satisfied */
226 /* rnd_rect() will returns 0 if no more rects are available... */
227 while (nroom
< MAXNROFROOMS
&& rnd_rect()) {
228 if (nroom
>= (MAXNROFROOMS
/ 6) && rn2(2) && !tried_vault
) {
230 if (create_vault()) {
231 vault_x
= rooms
[nroom
].lx
;
232 vault_y
= rooms
[nroom
].ly
;
233 rooms
[nroom
].hx
= -1;
235 } else if (!create_room(-1, -1, -1, -1, -1, -1, OROOM
, -1))
246 coord cc
, tt
, org
, dest
;
247 register xchar tx
, ty
, xx
, yy
;
248 register struct mkroom
*croom
, *troom
;
254 /* find positions cc and tt for doors in croom and troom
255 and direction for a corridor between them */
257 if (troom
->hx
< 0 || croom
->hx
< 0 || doorindex
>= DOORMAX
)
259 if (troom
->lx
> croom
->hx
) {
264 finddpos(&cc
, xx
, croom
->ly
, xx
, croom
->hy
);
265 finddpos(&tt
, tx
, troom
->ly
, tx
, troom
->hy
);
266 } else if (troom
->hy
< croom
->ly
) {
270 finddpos(&cc
, croom
->lx
, yy
, croom
->hx
, yy
);
272 finddpos(&tt
, troom
->lx
, ty
, troom
->hx
, ty
);
273 } else if (troom
->hx
< croom
->lx
) {
278 finddpos(&cc
, xx
, croom
->ly
, xx
, croom
->hy
);
279 finddpos(&tt
, tx
, troom
->ly
, tx
, troom
->hy
);
285 finddpos(&cc
, croom
->lx
, yy
, croom
->hx
, yy
);
286 finddpos(&tt
, troom
->lx
, ty
, troom
->hx
, ty
);
292 if (nxcor
&& levl
[xx
+ dx
][yy
+ dy
].typ
)
294 if (okdoor(xx
, yy
) || !nxcor
)
295 dodoor(xx
, yy
, croom
);
302 if (!dig_corridor(&org
, &dest
, nxcor
, level
.flags
.arboreal
? ROOM
: CORR
,
306 /* we succeeded in digging the corridor */
307 if (okdoor(tt
.x
, tt
.y
) || !nxcor
)
308 dodoor(tt
.x
, tt
.y
, troom
);
310 if (smeq
[a
] < smeq
[b
])
322 for (a
= 0; a
< nroom
- 1; a
++) {
323 join(a
, a
+ 1, FALSE
);
325 break; /* allow some randomness */
327 for (a
= 0; a
< nroom
- 2; a
++)
328 if (smeq
[a
] != smeq
[a
+ 2])
329 join(a
, a
+ 2, FALSE
);
330 for (a
= 0; any
&& a
< nroom
; a
++) {
332 for (b
= 0; b
< nroom
; b
++)
333 if (smeq
[a
] != smeq
[b
]) {
339 for (i
= rn2(nroom
) + 4; i
; i
--) {
349 add_door(x
, y
, aroom
)
351 register struct mkroom
*aroom
;
353 register struct mkroom
*broom
;
357 if (aroom
->doorct
== 0)
358 aroom
->fdoor
= doorindex
;
362 for (tmp
= doorindex
; tmp
> aroom
->fdoor
; tmp
--)
363 doors
[tmp
] = doors
[tmp
- 1];
365 for (i
= 0; i
< nroom
; i
++) {
367 if (broom
!= aroom
&& broom
->doorct
&& broom
->fdoor
>= aroom
->fdoor
)
370 for (i
= 0; i
< nsubroom
; i
++) {
371 broom
= &subrooms
[i
];
372 if (broom
!= aroom
&& broom
->doorct
&& broom
->fdoor
>= aroom
->fdoor
)
377 doors
[aroom
->fdoor
].x
= x
;
378 doors
[aroom
->fdoor
].y
= y
;
382 dosdoor(x
, y
, aroom
, type
)
384 struct mkroom
*aroom
;
387 boolean shdoor
= *in_rooms(x
, y
, SHOPBASE
) ? TRUE
: FALSE
;
389 if (!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs on already made doors */
391 levl
[x
][y
].typ
= type
;
393 if (!rn2(3)) { /* is it a locked door, closed, or a doorway? */
395 levl
[x
][y
].doormask
= D_ISOPEN
;
397 levl
[x
][y
].doormask
= D_LOCKED
;
399 levl
[x
][y
].doormask
= D_CLOSED
;
401 if (levl
[x
][y
].doormask
!= D_ISOPEN
&& !shdoor
402 && level_difficulty() >= 5 && !rn2(25))
403 levl
[x
][y
].doormask
|= D_TRAPPED
;
407 levl
[x
][y
].doormask
= D_ISOPEN
;
409 levl
[x
][y
].doormask
= D_NODOOR
;
411 levl
[x
][y
].doormask
= (shdoor
? D_ISOPEN
: D_NODOOR
);
415 /* also done in roguecorr(); doing it here first prevents
416 making mimics in place of trapped doors on rogue level */
417 if (Is_rogue_level(&u
.uz
))
418 levl
[x
][y
].doormask
= D_NODOOR
;
420 if (levl
[x
][y
].doormask
& D_TRAPPED
) {
423 if (level_difficulty() >= 9 && !rn2(5)
424 && !((mvitals
[PM_SMALL_MIMIC
].mvflags
& G_GONE
)
425 && (mvitals
[PM_LARGE_MIMIC
].mvflags
& G_GONE
)
426 && (mvitals
[PM_GIANT_MIMIC
].mvflags
& G_GONE
))) {
427 /* make a mimic instead */
428 levl
[x
][y
].doormask
= D_NODOOR
;
429 mtmp
= makemon(mkclass(S_MIMIC
, 0), x
, y
, NO_MM_FLAGS
);
436 if (shdoor
|| !rn2(5))
437 levl
[x
][y
].doormask
= D_LOCKED
;
439 levl
[x
][y
].doormask
= D_CLOSED
;
441 if (!shdoor
&& level_difficulty() >= 4 && !rn2(20))
442 levl
[x
][y
].doormask
|= D_TRAPPED
;
445 add_door(x
, y
, aroom
);
449 place_niche(aroom
, dy
, xx
, yy
)
450 register struct mkroom
*aroom
;
457 finddpos(&dd
, aroom
->lx
, aroom
->hy
+ 1, aroom
->hx
, aroom
->hy
+ 1);
460 finddpos(&dd
, aroom
->lx
, aroom
->ly
- 1, aroom
->hx
, aroom
->ly
- 1);
464 return (boolean
) ((isok(*xx
, *yy
+ *dy
)
465 && levl
[*xx
][*yy
+ *dy
].typ
== STONE
)
466 && (isok(*xx
, *yy
- *dy
)
467 && !IS_POOL(levl
[*xx
][*yy
- *dy
].typ
)
468 && !IS_FURNITURE(levl
[*xx
][*yy
- *dy
].typ
)));
471 /* there should be one of these per trap, in the same order as trap.h */
472 static NEARDATA
const char *trap_engravings
[TRAPNUM
] = {
473 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
474 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
475 (char *) 0, (char *) 0, (char *) 0, (char *) 0,
476 /* 14..16: trap door, teleport, level-teleport */
477 "Vlad was here", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
478 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
485 register struct mkroom
*aroom
;
491 if (doorindex
< DOORMAX
) {
493 aroom
= &rooms
[rn2(nroom
)];
494 if (aroom
->rtype
!= OROOM
)
495 continue; /* not an ordinary room */
496 if (aroom
->doorct
== 1 && rn2(5))
498 if (!place_niche(aroom
, &dy
, &xx
, &yy
))
501 rm
= &levl
[xx
][yy
+ dy
];
502 if (trap_type
|| !rn2(4)) {
505 if ((trap_type
== HOLE
|| trap_type
== TRAPDOOR
)
506 && !Can_fall_thru(&u
.uz
))
507 trap_type
= ROCKTRAP
;
508 ttmp
= maketrap(xx
, yy
+ dy
, trap_type
);
510 if (trap_type
!= ROCKTRAP
)
512 if (trap_engravings
[trap_type
]) {
513 make_engr_at(xx
, yy
- dy
,
514 trap_engravings
[trap_type
], 0L,
516 wipe_engr_at(xx
, yy
- dy
, 5,
517 FALSE
); /* age it a little */
521 dosdoor(xx
, yy
, aroom
, SDOOR
);
525 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
527 /* inaccessible niches occasionally have iron bars */
528 if (!rn2(5) && IS_WALL(levl
[xx
][yy
].typ
)) {
529 levl
[xx
][yy
].typ
= IRONBARS
;
531 (void) mkcorpstat(CORPSE
, (struct monst
*) 0,
532 mkclass(S_HUMAN
, 0), xx
,
535 if (!level
.flags
.noteleport
)
536 (void) mksobj_at(SCR_TELEPORTATION
, xx
, yy
+ dy
, TRUE
,
539 (void) mkobj_at(0, xx
, yy
+ dy
, TRUE
);
550 int ct
= rnd((nroom
>> 1) + 1), dep
= depth(&u
.uz
);
551 boolean ltptr
= (!level
.flags
.noteleport
&& dep
> 15),
552 vamp
= (dep
> 5 && dep
< 25);
555 if (ltptr
&& !rn2(6)) {
557 makeniche(LEVEL_TELEP
);
558 } else if (vamp
&& !rn2(6)) {
569 makeniche(TELEP_TRAP
);
572 /* clear out various globals that keep information on the current level.
573 * some of this is only necessary for some types of levels (maze, normal,
574 * special) but it's easier to put it all in one place than make sure
575 * each type initializes what it needs to separately.
578 clear_level_structures()
580 static struct rm zerorm
= { cmap_to_glyph(S_stone
),
581 0, 0, 0, 0, 0, 0, 0, 0, 0 };
583 register struct rm
*lev
;
585 for (x
= 0; x
< COLNO
; x
++) {
587 for (y
= 0; y
< ROWNO
; y
++) {
590 * These used to be '#if MICROPORT_BUG',
591 * with use of memset(0) for '#if !MICROPORT_BUG' below,
592 * but memset is not appropriate for initializing pointers,
593 * so do these level.objects[][] and level.monsters[][]
594 * initializations unconditionally.
596 level
.objects
[x
][y
] = (struct obj
*) 0;
597 level
.monsters
[x
][y
] = (struct monst
*) 0;
600 level
.objlist
= (struct obj
*) 0;
601 level
.buriedobjlist
= (struct obj
*) 0;
602 level
.monlist
= (struct monst
*) 0;
603 level
.damagelist
= (struct damage
*) 0;
604 level
.bonesinfo
= (struct cemetery
*) 0;
606 level
.flags
.nfountains
= 0;
607 level
.flags
.nsinks
= 0;
608 level
.flags
.has_shop
= 0;
609 level
.flags
.has_vault
= 0;
610 level
.flags
.has_zoo
= 0;
611 level
.flags
.has_court
= 0;
612 level
.flags
.has_morgue
= level
.flags
.graveyard
= 0;
613 level
.flags
.has_beehive
= 0;
614 level
.flags
.has_barracks
= 0;
615 level
.flags
.has_temple
= 0;
616 level
.flags
.has_swamp
= 0;
617 level
.flags
.noteleport
= 0;
618 level
.flags
.hardfloor
= 0;
619 level
.flags
.nommap
= 0;
620 level
.flags
.hero_memory
= 1;
621 level
.flags
.shortsighted
= 0;
622 level
.flags
.sokoban_rules
= 0;
623 level
.flags
.is_maze_lev
= 0;
624 level
.flags
.is_cavernous_lev
= 0;
625 level
.flags
.arboreal
= 0;
626 level
.flags
.wizard_bones
= 0;
627 level
.flags
.corrmaze
= 0;
636 xdnstair
= ydnstair
= xupstair
= yupstair
= 0;
637 sstairs
.sx
= sstairs
.sy
= 0;
638 xdnladder
= ydnladder
= xupladder
= yupladder
= 0;
646 register struct mkroom
*croom
, *troom
;
649 struct monst
*tmonst
; /* always put a web with a spider */
653 if (wiz1_level
.dlevel
== 0)
655 oinit(); /* assign level dependent obj probabilities */
656 clear_level_structures();
659 register s_level
*slev
= Is_special(&u
.uz
);
661 /* check for special levels */
662 if (slev
&& !Is_rogue_level(&u
.uz
)) {
663 makemaz(slev
->proto
);
665 } else if (dungeons
[u
.uz
.dnum
].proto
[0]) {
668 } else if (In_mines(&u
.uz
)) {
671 } else if (In_quest(&u
.uz
)) {
675 Sprintf(fillname
, "%s-loca", urole
.filecode
);
676 loc_lev
= find_level(fillname
);
678 Sprintf(fillname
, "%s-fil", urole
.filecode
);
680 (u
.uz
.dlevel
< loc_lev
->dlevel
.dlevel
) ? "a" : "b");
683 } else if (In_hell(&u
.uz
)
684 || (rn2(5) && u
.uz
.dnum
== medusa_level
.dnum
685 && depth(&u
.uz
) > depth(&medusa_level
))) {
691 /* otherwise, fall through - it's a "regular" level. */
693 if (Is_rogue_level(&u
.uz
)) {
700 /* construct stairs (up and down in different rooms if possible) */
701 croom
= &rooms
[rn2(nroom
)];
702 if (!Is_botlevel(&u
.uz
))
703 mkstairs(somex(croom
), somey(croom
), 0, croom
); /* down */
706 croom
= &rooms
[rn2(nroom
- 1)];
711 if (u
.uz
.dlevel
!= 1) {
716 } while (occupied(sx
, sy
));
717 mkstairs(sx
, sy
, 1, croom
); /* up */
720 branchp
= Is_branchlev(&u
.uz
); /* possible dungeon branch */
721 room_threshold
= branchp
? 4 : 3; /* minimum number of rooms needed
722 to allow a random special room */
723 if (Is_rogue_level(&u
.uz
))
728 /* make a secret treasure vault, not connected to the rest */
731 debugpline0("trying to make a vault...");
734 if (check_room(&vault_x
, &w
, &vault_y
, &h
, TRUE
)) {
736 add_room(vault_x
, vault_y
, vault_x
+ w
, vault_y
+ h
, TRUE
, VAULT
,
738 level
.flags
.has_vault
= 1;
740 fill_room(&rooms
[nroom
- 1], FALSE
);
741 mk_knox_portal(vault_x
+ w
, vault_y
+ h
);
742 if (!level
.flags
.noteleport
&& !rn2(3))
744 } else if (rnd_rect() && create_vault()) {
745 vault_x
= rooms
[nroom
].lx
;
746 vault_y
= rooms
[nroom
].ly
;
747 if (check_room(&vault_x
, &w
, &vault_y
, &h
, TRUE
))
750 rooms
[nroom
].hx
= -1;
755 register int u_depth
= depth(&u
.uz
);
757 if (wizard
&& nh_getenv("SHOPTYPE"))
759 else if (u_depth
> 1 && u_depth
< depth(&medusa_level
)
760 && nroom
>= room_threshold
&& rn2(u_depth
) < 3)
762 else if (u_depth
> 4 && !rn2(6))
764 else if (u_depth
> 5 && !rn2(8)
765 && !(mvitals
[PM_LEPRECHAUN
].mvflags
& G_GONE
))
767 else if (u_depth
> 6 && !rn2(7))
769 else if (u_depth
> 8 && !rn2(5))
771 else if (u_depth
> 9 && !rn2(5)
772 && !(mvitals
[PM_KILLER_BEE
].mvflags
& G_GONE
))
774 else if (u_depth
> 11 && !rn2(6))
776 else if (u_depth
> 12 && !rn2(8) && antholemon())
778 else if (u_depth
> 14 && !rn2(4)
779 && !(mvitals
[PM_SOLDIER
].mvflags
& G_GONE
))
781 else if (u_depth
> 15 && !rn2(6))
783 else if (u_depth
> 16 && !rn2(8)
784 && !(mvitals
[PM_COCKATRICE
].mvflags
& G_GONE
))
789 /* Place multi-dungeon branch. */
790 place_branch(branchp
, 0, 0);
792 /* for each room: put things inside */
793 for (croom
= rooms
; croom
->hx
> 0; croom
++) {
794 if (croom
->rtype
!= OROOM
)
797 /* put a sleeping monster inside */
798 /* Note: monster may be on the stairs. This cannot be
799 avoided: maybe the player fell through a trap door
800 while a monster was on the stairs. Conclusion:
801 we have to check for monsters on the stairs anyway. */
803 if (u
.uhave
.amulet
|| !rn2(3)) {
806 tmonst
= makemon((struct permonst
*) 0, x
, y
, NO_MM_FLAGS
);
807 if (tmonst
&& tmonst
->data
== &mons
[PM_GIANT_SPIDER
]
809 (void) maketrap(x
, y
, WEB
);
811 /* put traps and mimics inside */
812 x
= 8 - (level_difficulty() / 6);
816 mktrap(0, 0, croom
, (coord
*) 0);
818 (void) mkgold(0L, somex(croom
), somey(croom
));
819 if (Is_rogue_level(&u
.uz
))
827 x
= 80 - (depth(&u
.uz
) * 2);
833 /* put statues inside */
835 (void) mkcorpstat(STATUE
, (struct monst
*) 0,
836 (struct permonst
*) 0, somex(croom
),
837 somey(croom
), CORPSTAT_INIT
);
838 /* put box/chest inside;
839 * 40% chance for at least 1 box, regardless of number
840 * of rooms; about 5 - 7.5% for 2 boxes, least likely
841 * when few rooms; chance for 3 or more is negligible.
843 if (!rn2(nroom
* 5 / 2))
844 (void) mksobj_at((rn2(3)) ? LARGE_BOX
: CHEST
, somex(croom
),
845 somey(croom
), TRUE
, FALSE
);
847 /* maybe make some graffiti */
848 if (!rn2(27 + 3 * abs(depth(&u
.uz
)))) {
850 const char *mesg
= random_engraving(buf
);
855 } while (levl
[x
][y
].typ
!= ROOM
&& !rn2(40));
856 if (!(IS_POOL(levl
[x
][y
].typ
)
857 || IS_FURNITURE(levl
[x
][y
].typ
)))
858 make_engr_at(x
, y
, mesg
, 0L, MARK
);
864 (void) mkobj_at(0, somex(croom
), somey(croom
), TRUE
);
868 impossible("tryct overflow4");
871 (void) mkobj_at(0, somex(croom
), somey(croom
), TRUE
);
878 * Place deposits of minerals (gold and misc gems) in the stone
879 * surrounding the rooms on the map.
880 * Also place kelp in water.
881 * mineralize(-1, -1, -1, -1, FALSE); => "default" behaviour
884 mineralize(kelp_pool
, kelp_moat
, goldprob
, gemprob
, skip_lvl_checks
)
885 int kelp_pool
, kelp_moat
, goldprob
, gemprob
;
886 boolean skip_lvl_checks
;
897 /* Place kelp, except on the plane of water */
898 if (!skip_lvl_checks
&& In_endgame(&u
.uz
))
900 for (x
= 2; x
< (COLNO
- 2); x
++)
901 for (y
= 1; y
< (ROWNO
- 1); y
++)
902 if ((kelp_pool
&& levl
[x
][y
].typ
== POOL
&& !rn2(kelp_pool
))
903 || (kelp_moat
&& levl
[x
][y
].typ
== MOAT
&& !rn2(kelp_moat
)))
904 (void) mksobj_at(KELP_FROND
, x
, y
, TRUE
, FALSE
);
906 /* determine if it is even allowed;
907 almost all special levels are excluded */
909 && (In_hell(&u
.uz
) || In_V_tower(&u
.uz
) || Is_rogue_level(&u
.uz
)
910 || level
.flags
.arboreal
911 || ((sp
= Is_special(&u
.uz
)) != 0 && !Is_oracle_level(&u
.uz
)
912 && (!In_mines(&u
.uz
) || sp
->flags
.town
))))
915 /* basic level-related probabilities */
917 goldprob
= 20 + depth(&u
.uz
) / 3;
919 gemprob
= goldprob
/ 4;
921 /* mines have ***MORE*** goodies - otherwise why mine? */
922 if (!skip_lvl_checks
) {
923 if (In_mines(&u
.uz
)) {
926 } else if (In_quest(&u
.uz
)) {
933 * Seed rock areas with gold and/or gems.
934 * We use fairly low level object handling to avoid unnecessary
935 * overhead from placing things in the floor chain prior to burial.
937 for (x
= 2; x
< (COLNO
- 2); x
++)
938 for (y
= 1; y
< (ROWNO
- 1); y
++)
939 if (levl
[x
][y
+ 1].typ
!= STONE
) { /* <x,y> spot not eligible */
940 y
+= 2; /* next two spots aren't eligible either */
941 } else if (levl
[x
][y
].typ
!= STONE
) { /* this spot not eligible */
942 y
+= 1; /* next spot isn't eligible either */
943 } else if (!(levl
[x
][y
].wall_info
& W_NONDIGGABLE
)
944 && levl
[x
][y
- 1].typ
== STONE
945 && levl
[x
+ 1][y
- 1].typ
== STONE
946 && levl
[x
- 1][y
- 1].typ
== STONE
947 && levl
[x
+ 1][y
].typ
== STONE
948 && levl
[x
- 1][y
].typ
== STONE
949 && levl
[x
+ 1][y
+ 1].typ
== STONE
950 && levl
[x
- 1][y
+ 1].typ
== STONE
) {
951 if (rn2(1000) < goldprob
) {
952 if ((otmp
= mksobj(GOLD_PIECE
, FALSE
, FALSE
)) != 0) {
953 otmp
->ox
= x
, otmp
->oy
= y
;
954 otmp
->quan
= 1L + rnd(goldprob
* 3);
955 otmp
->owt
= weight(otmp
);
959 place_object(otmp
, x
, y
);
962 if (rn2(1000) < gemprob
) {
963 for (cnt
= rnd(2 + dunlev(&u
.uz
) / 3); cnt
> 0; cnt
--)
964 if ((otmp
= mkobj(GEM_CLASS
, FALSE
)) != 0) {
965 if (otmp
->otyp
== ROCK
) {
966 dealloc_obj(otmp
); /* discard it */
968 otmp
->ox
= x
, otmp
->oy
= y
;
972 place_object(otmp
, x
, y
);
982 struct mkroom
*croom
;
992 mineralize(-1, -1, -1, -1, FALSE
);
994 /* has_morgue gets cleared once morgue is entered; graveyard stays
995 set (graveyard might already be set even when has_morgue is clear
996 [see fixup_special()], so don't update it unconditionally) */
997 if (level
.flags
.has_morgue
)
998 level
.flags
.graveyard
= 1;
999 if (!level
.flags
.is_maze_lev
) {
1000 for (croom
= &rooms
[0]; croom
!= &rooms
[nroom
]; croom
++)
1001 #ifdef SPECIALIZATION
1002 topologize(croom
, FALSE
);
1008 /* for many room types, rooms[].rtype is zeroed once the room has been
1009 entered; rooms[].orig_rtype always retains original rtype value */
1010 for (ridx
= 0; ridx
< SIZE(rooms
); ridx
++)
1011 rooms
[ridx
].orig_rtype
= rooms
[ridx
].rtype
;
1015 #ifdef SPECIALIZATION
1016 topologize(croom
, do_ordinary
)
1017 struct mkroom
*croom
;
1018 boolean do_ordinary
;
1021 struct mkroom
*croom
;
1024 register int x
, y
, roomno
= (int) ((croom
- rooms
) + ROOMOFFSET
);
1025 int lowx
= croom
->lx
, lowy
= croom
->ly
;
1026 int hix
= croom
->hx
, hiy
= croom
->hy
;
1027 #ifdef SPECIALIZATION
1028 schar rtype
= croom
->rtype
;
1030 int subindex
, nsubrooms
= croom
->nsubrooms
;
1032 /* skip the room if already done; i.e. a shop handled out of order */
1033 /* also skip if this is non-rectangular (it _must_ be done already) */
1034 if ((int) levl
[lowx
][lowy
].roomno
== roomno
|| croom
->irregular
)
1036 #ifdef SPECIALIZATION
1037 if (Is_rogue_level(&u
.uz
))
1038 do_ordinary
= TRUE
; /* vision routine helper */
1039 if ((rtype
!= OROOM
) || do_ordinary
)
1042 /* do innards first */
1043 for (x
= lowx
; x
<= hix
; x
++)
1044 for (y
= lowy
; y
<= hiy
; y
++)
1045 #ifdef SPECIALIZATION
1047 levl
[x
][y
].roomno
= NO_ROOM
;
1050 levl
[x
][y
].roomno
= roomno
;
1051 /* top and bottom edges */
1052 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
1053 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
1054 levl
[x
][y
].edge
= 1;
1055 if (levl
[x
][y
].roomno
)
1056 levl
[x
][y
].roomno
= SHARED
;
1058 levl
[x
][y
].roomno
= roomno
;
1061 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
1062 for (y
= lowy
; y
<= hiy
; y
++) {
1063 levl
[x
][y
].edge
= 1;
1064 if (levl
[x
][y
].roomno
)
1065 levl
[x
][y
].roomno
= SHARED
;
1067 levl
[x
][y
].roomno
= roomno
;
1071 for (subindex
= 0; subindex
< nsubrooms
; subindex
++)
1072 #ifdef SPECIALIZATION
1073 topologize(croom
->sbrooms
[subindex
], (boolean
) (rtype
!= OROOM
));
1075 topologize(croom
->sbrooms
[subindex
]);
1079 /* Find an unused room for a branch location. */
1080 STATIC_OVL
struct mkroom
*
1081 find_branch_room(mp
)
1084 struct mkroom
*croom
= 0;
1087 mazexy(mp
); /* already verifies location */
1089 /* not perfect - there may be only one stairway */
1094 croom
= &rooms
[rn2(nroom
)];
1095 while ((croom
== dnstairs_room
|| croom
== upstairs_room
1096 || croom
->rtype
!= OROOM
) && (++tryct
< 100));
1098 croom
= &rooms
[rn2(nroom
)];
1101 if (!somexy(croom
, mp
))
1102 impossible("Can't place branch!");
1103 } while (occupied(mp
->x
, mp
->y
)
1104 || (levl
[mp
->x
][mp
->y
].typ
!= CORR
1105 && levl
[mp
->x
][mp
->y
].typ
!= ROOM
));
1110 /* Find the room for (x,y). Return null if not in a room. */
1111 STATIC_OVL
struct mkroom
*
1116 struct mkroom
*curr
;
1118 for (curr
= rooms
, i
= 0; i
< nroom
; curr
++, i
++)
1119 if (inside_room(curr
, x
, y
))
1122 return (struct mkroom
*) 0;
1125 /* If given a branch, randomly place a special stair or portal. */
1127 place_branch(br
, x
, y
)
1128 branch
*br
; /* branch to place */
1129 xchar x
, y
; /* location */
1133 boolean make_stairs
;
1134 struct mkroom
*br_room
;
1137 * Return immediately if there is no branch to make or we have
1138 * already made one. This routine can be called twice when
1139 * a special level is loaded that specifies an SSTAIR location
1140 * as a favored spot for a branch.
1142 if (!br
|| made_branch
)
1145 if (!x
) { /* find random coordinates for branch */
1146 br_room
= find_branch_room(&m
);
1150 br_room
= pos_to_room(x
, y
);
1153 if (on_level(&br
->end1
, &u
.uz
)) {
1155 make_stairs
= br
->type
!= BR_NO_END1
;
1159 make_stairs
= br
->type
!= BR_NO_END2
;
1163 if (br
->type
== BR_PORTAL
) {
1164 mkportal(x
, y
, dest
->dnum
, dest
->dlevel
);
1165 } else if (make_stairs
) {
1169 (char) on_level(&br
->end1
, &u
.uz
) ? br
->end1_up
: !br
->end1_up
;
1170 assign_level(&sstairs
.tolev
, dest
);
1171 sstairs_room
= br_room
;
1173 levl
[x
][y
].ladder
= sstairs
.up
? LA_UP
: LA_DOWN
;
1174 levl
[x
][y
].typ
= STAIRS
;
1177 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
1178 * make_stairs is false) since there is currently only one branch
1179 * per level, if we failed once, we're going to fail again on the
1187 register xchar x
, y
;
1191 if (isok(x
+ 1, y
)) {
1192 typ
= levl
[x
+ 1][y
].typ
;
1193 if (IS_DOOR(typ
) || typ
== SDOOR
)
1196 if (isok(x
- 1, y
)) {
1197 typ
= levl
[x
- 1][y
].typ
;
1198 if (IS_DOOR(typ
) || typ
== SDOOR
)
1201 if (isok(x
, y
+ 1)) {
1202 typ
= levl
[x
][y
+ 1].typ
;
1203 if (IS_DOOR(typ
) || typ
== SDOOR
)
1206 if (isok(x
, y
- 1)) {
1207 typ
= levl
[x
][y
- 1].typ
;
1208 if (IS_DOOR(typ
) || typ
== SDOOR
)
1214 /* see whether it is allowable to create a door at [x,y] */
1219 boolean near_door
= bydoor(x
, y
);
1221 return ((levl
[x
][y
].typ
== HWALL
|| levl
[x
][y
].typ
== VWALL
)
1222 && doorindex
< DOORMAX
&& !near_door
);
1228 struct mkroom
*aroom
;
1230 if (doorindex
>= DOORMAX
) {
1231 impossible("DOORMAX exceeded?");
1235 dosdoor(x
, y
, aroom
, rn2(8) ? DOOR
: SDOOR
);
1240 register xchar x
, y
;
1242 return (boolean
) (t_at(x
, y
) || IS_FURNITURE(levl
[x
][y
].typ
)
1243 || is_lava(x
, y
) || is_pool(x
, y
)
1244 || invocation_pos(x
, y
));
1247 /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
1248 /* if tm != null, make trap at that location */
1250 mktrap(num
, mazeflag
, croom
, tm
)
1252 struct mkroom
*croom
;
1258 /* no traps in pools */
1259 if (tm
&& is_pool(tm
->x
, tm
->y
))
1262 if (num
> 0 && num
< TRAPNUM
) {
1264 } else if (Is_rogue_level(&u
.uz
)) {
1282 kind
= SLP_GAS_TRAP
;
1288 } else if (Inhell
&& !rn2(5)) {
1289 /* bias the frequency of fire traps in Gehennom */
1292 unsigned lvl
= level_difficulty();
1295 kind
= rnd(TRAPNUM
- 1);
1296 /* reject "too hard" traps */
1299 case VIBRATING_SQUARE
:
1302 case ROLLING_BOULDER_TRAP
:
1308 if (lvl
< 5 || level
.flags
.noteleport
)
1333 if (level
.flags
.noteleport
)
1337 /* make these much less often than other traps */
1342 } while (kind
== NO_TRAP
);
1345 if ((kind
== TRAPDOOR
|| kind
== HOLE
) && !Can_fall_thru(&u
.uz
))
1351 register int tryct
= 0;
1352 boolean avoid_boulder
= (kind
== PIT
|| kind
== SPIKED_PIT
1353 || kind
== TRAPDOOR
|| kind
== HOLE
);
1360 else if (!somexy(croom
, &m
))
1362 } while (occupied(m
.x
, m
.y
)
1363 || (avoid_boulder
&& sobj_at(BOULDER
, m
.x
, m
.y
)));
1366 (void) maketrap(m
.x
, m
.y
, kind
);
1368 (void) makemon(&mons
[PM_GIANT_SPIDER
], m
.x
, m
.y
, NO_MM_FLAGS
);
1372 mkstairs(x
, y
, up
, croom
)
1375 struct mkroom
*croom
;
1378 impossible("mkstairs: bogus stair attempt at <%d,%d>", x
, y
);
1383 * We can't make a regular stair off an end of the dungeon. This
1384 * attempt can happen when a special level is placed at an end and
1385 * has an up or down stair specified in its description file.
1387 if ((dunlev(&u
.uz
) == 1 && up
)
1388 || (dunlev(&u
.uz
) == dunlevs_in_dungeon(&u
.uz
) && !up
))
1394 upstairs_room
= croom
;
1398 dnstairs_room
= croom
;
1401 levl
[x
][y
].typ
= STAIRS
;
1402 levl
[x
][y
].ladder
= up
? LA_UP
: LA_DOWN
;
1406 mkfount(mazeflag
, croom
)
1408 struct mkroom
*croom
;
1411 register int tryct
= 0;
1418 else if (!somexy(croom
, &m
))
1420 } while (occupied(m
.x
, m
.y
) || bydoor(m
.x
, m
.y
));
1422 /* Put a fountain at m.x, m.y */
1423 levl
[m
.x
][m
.y
].typ
= FOUNTAIN
;
1424 /* Is it a "blessed" fountain? (affects drinking from fountain) */
1426 levl
[m
.x
][m
.y
].blessedftn
= 1;
1428 level
.flags
.nfountains
++;
1433 struct mkroom
*croom
;
1436 register int tryct
= 0;
1441 if (!somexy(croom
, &m
))
1443 } while (occupied(m
.x
, m
.y
) || bydoor(m
.x
, m
.y
));
1445 /* Put a sink at m.x, m.y */
1446 levl
[m
.x
][m
.y
].typ
= SINK
;
1448 level
.flags
.nsinks
++;
1453 struct mkroom
*croom
;
1456 register int tryct
= 0;
1459 if (croom
->rtype
!= OROOM
)
1465 if (!somexy(croom
, &m
))
1467 } while (occupied(m
.x
, m
.y
) || bydoor(m
.x
, m
.y
));
1469 /* Put an altar at m.x, m.y */
1470 levl
[m
.x
][m
.y
].typ
= ALTAR
;
1472 /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
1473 al
= rn2((int) A_LAWFUL
+ 2) - 1;
1474 levl
[m
.x
][m
.y
].altarmask
= Align2amask(al
);
1479 struct mkroom
*croom
;
1482 register int tryct
= 0;
1483 register struct obj
*otmp
;
1484 boolean dobell
= !rn2(10);
1486 if (croom
->rtype
!= OROOM
)
1492 if (!somexy(croom
, &m
))
1494 } while (occupied(m
.x
, m
.y
) || bydoor(m
.x
, m
.y
));
1496 /* Put a grave at m.x, m.y */
1497 make_grave(m
.x
, m
.y
, dobell
? "Saved by the bell!" : (char *) 0);
1499 /* Possibly fill it with objects */
1501 (void) mkgold(0L, m
.x
, m
.y
);
1502 for (tryct
= rn2(5); tryct
; tryct
--) {
1503 otmp
= mkobj(RANDOM_CLASS
, TRUE
);
1509 add_to_buried(otmp
);
1512 /* Leave a bell, in case we accidentally buried someone alive */
1514 (void) mksobj_at(BELL
, m
.x
, m
.y
, TRUE
, FALSE
);
1518 /* maze levels have slightly different constraints from normal levels */
1519 #define x_maze_min 2
1520 #define y_maze_min 2
1523 * Major level transmutation: add a set of stairs (to the Sanctum) after
1524 * an earthquake that leaves behind a a new topology, centered at inv_pos.
1525 * Assumes there are no rooms within the invocation area and that inv_pos
1526 * is not too close to the edge of the map. Also assume the hero can see,
1527 * which is guaranteed for normal play due to the fact that sight is needed
1528 * to read the Book of the Dead.
1534 xchar xmin
= inv_pos
.x
, xmax
= inv_pos
.x
;
1535 xchar ymin
= inv_pos
.y
, ymax
= inv_pos
.y
;
1538 pline_The("floor shakes violently under you!");
1539 pline_The("walls around you begin to bend and crumble!");
1540 display_nhwindow(WIN_MESSAGE
, TRUE
);
1542 /* any trap hero is stuck in will be going away now */
1545 if (u
.utraptype
== TT_BURIEDBALL
)
1546 buried_ball_to_punishment();
1548 mkinvpos(xmin
, ymin
, 0); /* middle, before placing stairs */
1550 for (dist
= 1; dist
< 7; dist
++) {
1554 /* top and bottom */
1555 if (dist
!= 3) { /* the area is wider that it is high */
1558 for (i
= xmin
+ 1; i
< xmax
; i
++) {
1559 mkinvpos(i
, ymin
, dist
);
1560 mkinvpos(i
, ymax
, dist
);
1564 /* left and right */
1565 for (i
= ymin
; i
<= ymax
; i
++) {
1566 mkinvpos(xmin
, i
, dist
);
1567 mkinvpos(xmax
, i
, dist
);
1570 flush_screen(1); /* make sure the new glyphs shows up */
1574 You("are standing at the top of a stairwell leading down!");
1575 mkstairs(u
.ux
, u
.uy
, 0, (struct mkroom
*) 0); /* down */
1577 vision_full_recalc
= 1; /* everything changed */
1580 /* Change level topology. Boulders in the vicinity are eliminated.
1581 * Temporarily overrides vision in the name of a nice effect.
1584 mkinvpos(x
, y
, dist
)
1591 register struct rm
*lev
= &levl
[x
][y
];
1593 /* clip at existing map borders if necessary */
1594 if (!within_bounded_area(x
, y
, x_maze_min
+ 1, y_maze_min
+ 1,
1595 x_maze_max
- 1, y_maze_max
- 1)) {
1596 /* only outermost 2 columns and/or rows may be truncated due to edge
1599 panic("mkinvpos: <%d,%d> (%d) off map edge!", x
, y
, dist
);
1604 if ((ttmp
= t_at(x
, y
)) != 0)
1607 /* clear boulders; leave some rocks for non-{moat|trap} locations */
1608 make_rocks
= (dist
!= 1 && dist
!= 4 && dist
!= 5) ? TRUE
: FALSE
;
1609 while ((otmp
= sobj_at(BOULDER
, x
, y
)) != 0) {
1611 fracture_rock(otmp
);
1612 make_rocks
= FALSE
; /* don't bother with more rocks */
1614 obj_extract_self(otmp
);
1615 obfree(otmp
, (struct obj
*) 0);
1618 unblock_point(x
, y
); /* make sure vision knows this location is open */
1620 /* fake out saved state */
1626 lev
->horizontal
= FALSE
;
1627 /* short-circuit vision recalc */
1628 viz_array
[y
][x
] = (dist
< 6) ? (IN_SIGHT
| COULD_SEE
) : COULD_SEE
;
1631 case 1: /* fire traps */
1635 ttmp
= maketrap(x
, y
, FIRE_TRAP
);
1639 case 0: /* lit room locations */
1642 case 6: /* unlit room locations */
1645 case 4: /* pools (aka a wide moat) */
1651 impossible("mkinvpos called with dist %d", dist
);
1655 /* display new value of position; could have a monster/object on it */
1660 * The portal to Ludios is special. The entrance can only occur within a
1661 * vault in the main dungeon at a depth greater than 10. The Ludios branch
1662 * structure reflects this by having a bogus "source" dungeon: the value
1663 * of n_dgns (thus, Is_branchlev() will never find it).
1665 * Ludios will remain isolated until the branch is corrected by this function.
1668 mk_knox_portal(x
, y
)
1671 extern int n_dgns
; /* from dungeon.c */
1676 br
= dungeon_branch("Fort Ludios");
1677 if (on_level(&knox_level
, &br
->end1
)) {
1680 /* disallow Knox branch on a level with one branch already */
1681 if (Is_branchlev(&u
.uz
))
1686 /* Already set or 2/3 chance of deferring until a later level. */
1687 if (source
->dnum
< n_dgns
|| (rn2(3) && !wizard
))
1690 if (!(u
.uz
.dnum
== oracle_level
.dnum
/* in main dungeon */
1691 && !at_dgn_entrance("The Quest") /* but not Quest's entry */
1692 && (u_depth
= depth(&u
.uz
)) > 10 /* beneath 10 */
1693 && u_depth
< depth(&medusa_level
))) /* and above Medusa */
1696 /* Adjust source to be current level and re-insert branch. */
1698 insert_branch(br
, TRUE
);
1700 debugpline0("Made knox portal.");
1701 place_branch(br
, x
, y
);