1 /* NetHack 3.7 mklev.c $NHDT-Date: 1737387068 2025/01/20 07:31:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.194 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Alex Smith, 2017. */
4 /* NetHack may be freely redistributed. See license for details. */
8 /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
9 /* croom->lx etc are schar (width <= int), so % arith ensures that */
10 /* conversion of result to int is reasonable */
12 staticfn boolean
generate_stairs_room_good(struct mkroom
*, int);
13 staticfn
struct mkroom
*generate_stairs_find_room(void);
14 staticfn
void generate_stairs(void);
15 staticfn
void mkfount(struct mkroom
*);
16 staticfn boolean
find_okay_roompos(struct mkroom
*, coord
*) NONNULLARG12
;
17 staticfn
void mksink(struct mkroom
*);
18 staticfn
void mkaltar(struct mkroom
*);
19 staticfn
void mkgrave(struct mkroom
*);
20 staticfn
void mkinvpos(coordxy
, coordxy
, int);
21 staticfn
int mkinvk_check_wall(coordxy x
, coordxy y
);
22 staticfn
void mk_knox_portal(coordxy
, coordxy
);
23 staticfn
void makevtele(void);
24 staticfn
void fill_ordinary_room(struct mkroom
*, boolean
) NONNULLARG1
;
25 staticfn
void themerooms_post_level_generate(void);
26 staticfn
void makelevel(void);
27 staticfn boolean
bydoor(coordxy
, coordxy
);
28 staticfn
void mktrap_victim(struct trap
*);
29 staticfn
int traptype_rnd(unsigned);
30 staticfn
int traptype_roguelvl(void);
31 staticfn
struct mkroom
*find_branch_room(coord
*) NONNULLARG1
;
32 staticfn
struct mkroom
*pos_to_room(coordxy
, coordxy
);
33 staticfn boolean
cardinal_nextto_room(struct mkroom
*, coordxy
, coordxy
);
34 staticfn boolean
place_niche(struct mkroom
*, int *, coordxy
*, coordxy
*);
35 staticfn
void makeniche(int);
36 staticfn
void make_niches(void);
37 staticfn
int QSORTCALLBACK
mkroom_cmp(const genericptr
, const genericptr
);
38 staticfn
void dosdoor(coordxy
, coordxy
, struct mkroom
*, int);
39 staticfn
void join(int, int, boolean
);
40 staticfn
void alloc_doors(void);
41 staticfn
void do_room_or_subroom(struct mkroom
*,
42 coordxy
, coordxy
, coordxy
, coordxy
,
43 boolean
, schar
, boolean
, boolean
);
44 staticfn
void makerooms(void);
45 staticfn boolean
door_into_nonjoined(coordxy
, coordxy
);
46 staticfn boolean
finddpos(coord
*, coordxy
, coordxy
, coordxy
, coordxy
);
48 #define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
49 #define init_vault() gv.vault_x = -1
50 #define do_vault() (gv.vault_x != -1)
52 /* Args must be (const genericptr) so that qsort will always be happy. */
54 staticfn
int QSORTCALLBACK
55 mkroom_cmp(const genericptr vx
, const genericptr vy
)
57 const struct mkroom
*x
, *y
;
59 x
= (const struct mkroom
*) vx
;
60 y
= (const struct mkroom
*) vy
;
63 return (x
->lx
> y
->lx
);
66 /* Return TRUE if a door placed at (x, y) which otherwise passes okdoor()
67 * checks would be connecting into an area that was declared as joined=false.
68 * Checking for this in finddpos() enables us to have rooms with sub-areas
69 * (such as shops) that will never randomly generate unwanted doors in order
70 * to connect them up to other areas.
73 door_into_nonjoined(coordxy x
, coordxy y
)
77 for (i
= 0; i
< 4; i
++) {
78 tx
= x
+ xdir
[dirs_ord
[i
]];
79 ty
= y
+ ydir
[dirs_ord
[i
]];
80 if (!isok(tx
, ty
) || IS_OBSTRUCTED(levl
[tx
][ty
].typ
))
83 /* Is this connecting to a room that doesn't want joining? */
84 if (levl
[tx
][ty
].roomno
>= ROOMOFFSET
85 && !svr
.rooms
[levl
[tx
][ty
].roomno
- ROOMOFFSET
].needjoining
) {
95 coordxy xl
, coordxy yl
,
96 coordxy xh
, coordxy yh
)
100 x
= rn1(xh
- xl
+ 1, xl
);
101 y
= rn1(yh
- yl
+ 1, yl
);
102 if (okdoor(x
, y
) && !door_into_nonjoined(x
, y
))
105 for (x
= xl
; x
<= xh
; x
++)
106 for (y
= yl
; y
<= yh
; y
++)
107 if (okdoor(x
, y
) && !door_into_nonjoined(x
, y
))
110 for (x
= xl
; x
<= xh
; x
++)
111 for (y
= yl
; y
<= yh
; y
++)
112 if (IS_DOOR(levl
[x
][y
].typ
) || levl
[x
][y
].typ
== SDOOR
)
114 /* cannot find something reasonable -- strange */
124 /* Sort rooms on the level so they're ordered from left to right on the map.
125 makecorridors() by default links rooms N and N+1 */
130 unsigned i
, ri
[MAXNROFROOMS
+ 1] = { 0U }, n
= (unsigned) svn
.nroom
;
132 qsort((genericptr_t
) svr
.rooms
, n
, sizeof (struct mkroom
), mkroom_cmp
);
134 /* Update the roomnos on the map */
135 for (i
= 0; i
< n
; i
++)
136 ri
[svr
.rooms
[i
].roomnoidx
] = i
;
138 for (x
= 1; x
< COLNO
; x
++)
139 for (y
= 0; y
< ROWNO
; y
++) {
140 unsigned rno
= levl
[x
][y
].roomno
;
142 if (rno
>= ROOMOFFSET
&& rno
< MAXNROFROOMS
+ 1)
143 levl
[x
][y
].roomno
= ri
[rno
- ROOMOFFSET
] + ROOMOFFSET
;
148 do_room_or_subroom(struct mkroom
*croom
,
149 coordxy lowx
, coordxy lowy
, coordxy hix
, coordxy hiy
,
150 boolean lit
, schar rtype
, boolean special
, boolean is_room
)
155 /* locations might bump level edges in wall-less rooms */
156 /* add/subtract 1 to allow for edge locations */
161 if (hix
>= COLNO
- 1)
163 if (hiy
>= ROWNO
- 1)
167 for (x
= lowx
- 1; x
<= hix
+ 1; x
++) {
168 lev
= &levl
[x
][max(lowy
- 1, 0)];
169 for (y
= lowy
- 1; y
<= hiy
+ 1; y
++)
176 croom
->roomnoidx
= (croom
- svr
.rooms
);
181 croom
->rtype
= rtype
;
183 /* if we're not making a vault, gd.doorindex will still be 0
184 * if we are, we'll have problems adding niches to the previous room
185 * unless fdoor is at least gd.doorindex
187 croom
->fdoor
= gd
.doorindex
;
188 croom
->irregular
= FALSE
;
190 croom
->nsubrooms
= 0;
191 croom
->sbrooms
[0] = (struct mkroom
*) 0;
193 croom
->needjoining
= TRUE
;
194 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
195 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
196 levl
[x
][y
].typ
= HWALL
;
197 levl
[x
][y
].horizontal
= 1; /* For open/secret doors. */
199 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
200 for (y
= lowy
; y
<= hiy
; y
++) {
201 levl
[x
][y
].typ
= VWALL
;
202 levl
[x
][y
].horizontal
= 0; /* For open/secret doors. */
204 for (x
= lowx
; x
<= hix
; x
++) {
205 lev
= &levl
[x
][lowy
];
206 for (y
= lowy
; y
<= hiy
; y
++)
210 levl
[lowx
- 1][lowy
- 1].typ
= TLCORNER
;
211 levl
[hix
+ 1][lowy
- 1].typ
= TRCORNER
;
212 levl
[lowx
- 1][hiy
+ 1].typ
= BLCORNER
;
213 levl
[hix
+ 1][hiy
+ 1].typ
= BRCORNER
;
214 } else { /* a subroom */
215 wallification(lowx
- 1, lowy
- 1, hix
+ 1, hiy
+ 1);
221 add_room(coordxy lowx
, coordxy lowy
, coordxy hix
, coordxy hiy
,
222 boolean lit
, schar rtype
, boolean special
)
224 struct mkroom
*croom
;
226 croom
= &svr
.rooms
[svn
.nroom
];
227 do_room_or_subroom(croom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
,
235 add_subroom(struct mkroom
*proom
,
236 coordxy lowx
, coordxy lowy
,
237 coordxy hix
, coordxy hiy
,
238 boolean lit
, schar rtype
, boolean special
)
240 struct mkroom
*croom
;
242 croom
= &gs
.subrooms
[gn
.nsubroom
];
243 do_room_or_subroom(croom
, lowx
, lowy
, hix
, hiy
, lit
, rtype
, special
,
245 proom
->sbrooms
[proom
->nsubrooms
++] = croom
;
252 free_luathemes(enum lua_theme_group theme_group
)
257 * Release which group(s)?
258 * tut_themes => leaving tutorial, free tutorial themes only;
259 * most_themes => entering endgame, free non-endgame themes;
260 * all_themes => end of game, free all themes.
262 for (i
= 0; i
< svn
.n_dgns
; ++i
) {
263 if ((theme_group
== tut_themes
&& i
!= tutorial_dnum
)
264 || (theme_group
== most_themes
&& i
== astral_level
.dnum
))
266 if (gl
.luathemes
[i
]) {
267 nhl_done((lua_State
*) gl
.luathemes
[i
]);
268 gl
.luathemes
[i
] = (lua_State
*) 0;
276 boolean tried_vault
= FALSE
;
277 int themeroom_tries
= 0;
279 nhl_sandbox_info sbi
= {NHL_SB_SAFE
, 1*1024*1024, 0, 1*1024*1024};
280 lua_State
*themes
= (lua_State
*) gl
.luathemes
[u
.uz
.dnum
];
282 if (!themes
&& *(fname
= svd
.dungeons
[u
.uz
.dnum
].themerms
)) {
283 if ((themes
= nhl_init(&sbi
)) != 0) {
284 if (!nhl_loadlua(themes
, fname
)) {
285 /* loading lua failed, don't use themed rooms */
287 themes
= (lua_State
*) 0;
289 /* success; save state for this dungeon branch */
290 gl
.luathemes
[u
.uz
.dnum
] = (genericptr_t
) themes
;
291 /* keep themes context, so not 'nhl_done(themes);' */
292 iflags
.in_lua
= FALSE
; /* can affect error messages */
295 if (!themes
) /* don't try again when making next level */
296 *fname
= '\0'; /* svd.dungeons[u.uz.dnum].themerms */
301 iflags
.in_lua
= gi
.in_mk_themerooms
= TRUE
;
302 gt
.themeroom_failed
= FALSE
;
303 lua_getglobal(themes
, "pre_themerooms_generate");
304 nhl_pcall_handle(themes
, 0, 0, "makerooms-1", NHLpa_impossible
);
305 iflags
.in_lua
= gi
.in_mk_themerooms
= FALSE
;
308 /* make rooms until satisfied */
309 /* rnd_rect() will returns 0 if no more rects are available... */
310 while (svn
.nroom
< (MAXNROFROOMS
- 1) && rnd_rect()) {
311 if (svn
.nroom
>= (MAXNROFROOMS
/ 6) && rn2(2) && !tried_vault
) {
313 if (create_vault()) {
314 gv
.vault_x
= svr
.rooms
[svn
.nroom
].lx
;
315 gv
.vault_y
= svr
.rooms
[svn
.nroom
].ly
;
316 svr
.rooms
[svn
.nroom
].hx
= -1;
320 iflags
.in_lua
= gi
.in_mk_themerooms
= TRUE
;
321 gt
.themeroom_failed
= FALSE
;
322 lua_getglobal(themes
, "themerooms_generate");
323 nhl_pcall_handle(themes
, 0, 0, "makerooms-2", NHLpa_panic
);
324 iflags
.in_lua
= gi
.in_mk_themerooms
= FALSE
;
325 if (gt
.themeroom_failed
326 && ((themeroom_tries
++ > 10)
327 || (svn
.nroom
>= (MAXNROFROOMS
/ 6))))
330 if (!create_room(-1, -1, -1, -1, -1, -1, OROOM
, -1))
336 reset_xystart_size();
337 iflags
.in_lua
= gi
.in_mk_themerooms
= TRUE
;
338 gt
.themeroom_failed
= FALSE
;
339 lua_getglobal(themes
, "post_themerooms_generate");
340 nhl_pcall_handle(themes
, 0, 0, "makerooms-3", NHLpa_panic
);
341 iflags
.in_lua
= gi
.in_mk_themerooms
= FALSE
;
346 join(int a
, int b
, boolean nxcor
)
348 coord cc
, tt
, org
, dest
;
349 coordxy tx
, ty
, xx
, yy
;
350 struct mkroom
*croom
, *troom
;
353 croom
= &svr
.rooms
[a
];
354 troom
= &svr
.rooms
[b
];
356 if (!croom
->needjoining
|| !troom
->needjoining
)
359 /* find positions cc and tt for doors in croom and troom
360 and direction for a corridor between them */
362 if (troom
->hx
< 0 || croom
->hx
< 0)
364 if (troom
->lx
> croom
->hx
) {
369 if (!finddpos(&cc
, xx
, croom
->ly
, xx
, croom
->hy
))
371 if (!finddpos(&tt
, tx
, troom
->ly
, tx
, troom
->hy
))
373 } else if (troom
->hy
< croom
->ly
) {
378 if (!finddpos(&cc
, croom
->lx
, yy
, croom
->hx
, yy
))
380 if (!finddpos(&tt
, troom
->lx
, ty
, troom
->hx
, ty
))
382 } else if (troom
->hx
< croom
->lx
) {
387 if (!finddpos(&cc
, xx
, croom
->ly
, xx
, croom
->hy
))
389 if (!finddpos(&tt
, tx
, troom
->ly
, tx
, troom
->hy
))
396 if (!finddpos(&cc
, croom
->lx
, yy
, croom
->hx
, yy
))
398 if (!finddpos(&tt
, troom
->lx
, ty
, troom
->hx
, ty
))
405 if (nxcor
&& levl
[xx
+ dx
][yy
+ dy
].typ
!= STONE
)
407 if (okdoor(xx
, yy
) || !nxcor
)
408 dodoor(xx
, yy
, croom
);
415 if (!dig_corridor(&org
, &dest
, nxcor
,
416 svl
.level
.flags
.arboreal
? ROOM
: CORR
, STONE
))
419 /* we succeeded in digging the corridor */
420 if (okdoor(tt
.x
, tt
.y
) || !nxcor
)
421 dodoor(tt
.x
, tt
.y
, troom
);
423 if (gs
.smeq
[a
] < gs
.smeq
[b
])
424 gs
.smeq
[b
] = gs
.smeq
[a
];
426 gs
.smeq
[a
] = gs
.smeq
[b
];
429 /* create random corridors between rooms */
436 for (a
= 0; a
< svn
.nroom
- 1; a
++) {
437 join(a
, a
+ 1, FALSE
);
439 break; /* allow some randomness */
441 for (a
= 0; a
< svn
.nroom
- 2; a
++)
442 if (gs
.smeq
[a
] != gs
.smeq
[a
+ 2])
443 join(a
, a
+ 2, FALSE
);
444 for (a
= 0; any
&& a
< svn
.nroom
; a
++) {
446 for (b
= 0; b
< svn
.nroom
; b
++)
447 if (gs
.smeq
[a
] != gs
.smeq
[b
]) {
452 /* add some extra corridors which may be blocked off */
454 for (i
= rn2(svn
.nroom
) + 4; i
; i
--) {
456 b
= rn2(svn
.nroom
- 2);
463 /* (re)allocate space for svd.doors array */
467 if (!svd
.doors
|| gd
.doorindex
>= svd
.doors_alloc
) {
468 int c
= svd
.doors_alloc
+ DOORINC
;
469 coord
*doortmp
= (coord
*) alloc(c
* sizeof (coord
));
471 (void) memset((genericptr_t
) doortmp
, 0, c
* sizeof (coord
));
473 (void) memcpy(doortmp
, svd
.doors
,
474 svd
.doors_alloc
* sizeof (coord
));
483 add_door(coordxy x
, coordxy y
, struct mkroom
*aroom
)
485 struct mkroom
*broom
;
492 for (i
= 0; i
< aroom
->doorct
; i
++) {
493 tmp
= aroom
->fdoor
+ i
;
494 if (svd
.doors
[tmp
].x
== x
&& svd
.doors
[tmp
].y
== y
)
499 if (aroom
->doorct
== 0)
500 aroom
->fdoor
= gd
.doorindex
;
504 for (tmp
= gd
.doorindex
; tmp
> aroom
->fdoor
; tmp
--)
505 svd
.doors
[tmp
] = svd
.doors
[tmp
- 1];
507 for (i
= 0; i
< svn
.nroom
; i
++) {
508 broom
= &svr
.rooms
[i
];
509 if (broom
!= aroom
&& broom
->doorct
&& broom
->fdoor
>= aroom
->fdoor
)
512 for (i
= 0; i
< gn
.nsubroom
; i
++) {
513 broom
= &gs
.subrooms
[i
];
514 if (broom
!= aroom
&& broom
->doorct
&& broom
->fdoor
>= aroom
->fdoor
)
519 svd
.doors
[aroom
->fdoor
].x
= x
;
520 svd
.doors
[aroom
->fdoor
].y
= y
;
524 dosdoor(coordxy x
, coordxy y
, struct mkroom
*aroom
, int type
)
526 boolean shdoor
= *in_rooms(x
, y
, SHOPBASE
) ? TRUE
: FALSE
;
528 if (!IS_WALL(levl
[x
][y
].typ
)) /* avoid S.doors on already made doors */
530 levl
[x
][y
].typ
= type
;
532 if (!rn2(3)) { /* is it a locked door, closed, or a doorway? */
534 levl
[x
][y
].doormask
= D_ISOPEN
;
536 levl
[x
][y
].doormask
= D_LOCKED
;
538 levl
[x
][y
].doormask
= D_CLOSED
;
540 if (levl
[x
][y
].doormask
!= D_ISOPEN
&& !shdoor
541 && level_difficulty() >= 5 && !rn2(25))
542 levl
[x
][y
].doormask
|= D_TRAPPED
;
546 levl
[x
][y
].doormask
= D_ISOPEN
;
548 levl
[x
][y
].doormask
= D_NODOOR
;
550 levl
[x
][y
].doormask
= (shdoor
? D_ISOPEN
: D_NODOOR
);
554 /* also done in roguecorr(); doing it here first prevents
555 making mimics in place of trapped doors on rogue svl.level */
556 if (Is_rogue_level(&u
.uz
))
557 levl
[x
][y
].doormask
= D_NODOOR
;
559 if (levl
[x
][y
].doormask
& D_TRAPPED
) {
562 if (level_difficulty() >= 9 && !rn2(5)
563 && !((svm
.mvitals
[PM_SMALL_MIMIC
].mvflags
& G_GONE
)
564 && (svm
.mvitals
[PM_LARGE_MIMIC
].mvflags
& G_GONE
)
565 && (svm
.mvitals
[PM_GIANT_MIMIC
].mvflags
& G_GONE
))) {
566 /* make a mimic instead */
567 levl
[x
][y
].doormask
= D_NODOOR
;
568 mtmp
= makemon(mkclass(S_MIMIC
, 0), x
, y
, NO_MM_FLAGS
);
575 if (shdoor
|| !rn2(5))
576 levl
[x
][y
].doormask
= D_LOCKED
;
578 levl
[x
][y
].doormask
= D_CLOSED
;
580 if (!shdoor
&& level_difficulty() >= 4 && !rn2(20))
581 levl
[x
][y
].doormask
|= D_TRAPPED
;
584 add_door(x
, y
, aroom
);
587 /* is x,y location such that NEWS direction from it is inside aroom,
588 excluding subrooms */
590 cardinal_nextto_room(struct mkroom
*aroom
, coordxy x
, coordxy y
)
592 int rmno
= (int) ((aroom
- svr
.rooms
) + ROOMOFFSET
);
594 if (isok(x
- 1, y
) && !levl
[x
- 1][y
].edge
595 && (int) levl
[x
- 1][y
].roomno
== rmno
)
597 if (isok(x
+ 1, y
) && !levl
[x
+ 1][y
].edge
598 && (int) levl
[x
+ 1][y
].roomno
== rmno
)
600 if (isok(x
, y
- 1) && !levl
[x
][y
- 1].edge
601 && (int) levl
[x
][y
- 1].roomno
== rmno
)
603 if (isok(x
, y
+ 1) && !levl
[x
][y
+ 1].edge
604 && (int) levl
[x
][y
+ 1].roomno
== rmno
)
611 struct mkroom
*aroom
,
613 coordxy
*xx
, coordxy
*yy
)
619 if (!finddpos(&dd
, aroom
->lx
, aroom
->hy
+ 1,
620 aroom
->hx
, aroom
->hy
+ 1))
624 if (!finddpos(&dd
, aroom
->lx
, aroom
->ly
- 1,
625 aroom
->hx
, aroom
->ly
- 1))
630 return (boolean
) ((isok(*xx
, *yy
+ *dy
)
631 && levl
[*xx
][*yy
+ *dy
].typ
== STONE
)
632 && (isok(*xx
, *yy
- *dy
)
633 && !IS_POOL(levl
[*xx
][*yy
- *dy
].typ
)
634 && !IS_FURNITURE(levl
[*xx
][*yy
- *dy
].typ
))
635 && cardinal_nextto_room(aroom
, *xx
, *yy
));
638 /* there should be one of these per trap, in the same order as trap.h */
639 static NEARDATA
const char *trap_engravings
[TRAPNUM
] = {
640 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
641 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
642 (char *) 0, (char *) 0, (char *) 0, (char *) 0,
643 /* 14..16: trap door, teleport, level-teleport */
644 "Vlad was here", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
645 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
647 (char *) 0, (char *) 0,
651 makeniche(int trap_type
)
653 struct mkroom
*aroom
;
660 aroom
= &svr
.rooms
[rn2(svn
.nroom
)];
661 if (aroom
->rtype
!= OROOM
)
662 continue; /* not an ordinary room */
663 if (aroom
->doorct
== 1 && rn2(5))
665 if (!place_niche(aroom
, &dy
, &xx
, &yy
))
668 rm
= &levl
[xx
][yy
+ dy
];
669 if (trap_type
|| !rn2(4)) {
672 if (is_hole(trap_type
) && !Can_fall_thru(&u
.uz
))
673 trap_type
= ROCKTRAP
;
674 ttmp
= maketrap(xx
, yy
+ dy
, trap_type
);
676 if (trap_type
!= ROCKTRAP
)
678 if (trap_engravings
[trap_type
]) {
679 make_engr_at(xx
, yy
- dy
,
680 trap_engravings
[trap_type
], 0L,
682 wipe_engr_at(xx
, yy
- dy
, 5,
683 FALSE
); /* age it a little */
687 dosdoor(xx
, yy
, aroom
, SDOOR
);
691 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
693 /* inaccessible niches occasionally have iron bars */
694 if (!rn2(5) && IS_WALL(levl
[xx
][yy
].typ
)) {
695 (void) set_levltyp(xx
, yy
, IRONBARS
);
697 (void) mkcorpstat(CORPSE
, (struct monst
*) 0,
698 mkclass(S_HUMAN
, 0), xx
,
701 if (!svl
.level
.flags
.noteleport
)
702 (void) mksobj_at(SCR_TELEPORTATION
, xx
, yy
+ dy
, TRUE
,
705 (void) mkobj_at(RANDOM_CLASS
, xx
, yy
+ dy
, TRUE
);
715 int ct
= rnd((svn
.nroom
>> 1) + 1), dep
= depth(&u
.uz
);
716 boolean ltptr
= (!svl
.level
.flags
.noteleport
&& dep
> 15),
717 vamp
= (dep
> 5 && dep
< 25);
720 if (ltptr
&& !rn2(6)) {
722 makeniche(LEVEL_TELEP
);
723 } else if (vamp
&& !rn2(6)) {
734 makeniche(TELEP_TRAP
);
737 /* count the tracked features (sinks, fountains) present on the level */
739 count_level_features(void)
743 svl
.level
.flags
.nfountains
= svl
.level
.flags
.nsinks
= 0;
744 for (y
= 0; y
< ROWNO
; y
++)
745 for (x
= 1; x
< COLNO
; x
++) {
746 int typ
= levl
[x
][y
].typ
;
749 svl
.level
.flags
.nfountains
++;
750 else if (typ
== SINK
)
751 svl
.level
.flags
.nsinks
++;
755 /* clear out various globals that keep information on the current level.
756 * some of this is only necessary for some types of levels (maze, normal,
757 * special) but it's easier to put it all in one place than make sure
758 * each type initializes what it needs to separately.
761 clear_level_structures(void)
763 static struct rm zerorm
= { GLYPH_UNEXPLORED
,
764 0, 0, 0, 0, 0, 0, 0, 0, 0 };
768 /* note: normally we'd start at x=1 because map column #0 isn't used
769 (except for placing vault guard at <0,0> when removed from the map
770 but not from the level); explicitly reset column #0 along with the
771 rest so that we start the new level with a completely clean slate */
772 for (x
= 0; x
< COLNO
; x
++) {
774 for (y
= 0; y
< ROWNO
; y
++) {
776 svl
.level
.objects
[x
][y
] = (struct obj
*) 0;
777 svl
.level
.monsters
[x
][y
] = (struct monst
*) 0;
780 svl
.level
.objlist
= (struct obj
*) 0;
781 svl
.level
.buriedobjlist
= (struct obj
*) 0;
782 svl
.level
.monlist
= (struct monst
*) 0;
783 svl
.level
.damagelist
= (struct damage
*) 0;
784 svl
.level
.bonesinfo
= (struct cemetery
*) 0;
786 svl
.level
.flags
.nfountains
= 0;
787 svl
.level
.flags
.nsinks
= 0;
788 svl
.level
.flags
.has_shop
= 0;
789 svl
.level
.flags
.has_vault
= 0;
790 svl
.level
.flags
.has_zoo
= 0;
791 svl
.level
.flags
.has_court
= 0;
792 svl
.level
.flags
.has_morgue
= svl
.level
.flags
.graveyard
= 0;
793 svl
.level
.flags
.has_beehive
= 0;
794 svl
.level
.flags
.has_barracks
= 0;
795 svl
.level
.flags
.has_temple
= 0;
796 svl
.level
.flags
.has_swamp
= 0;
797 svl
.level
.flags
.noteleport
= 0;
798 svl
.level
.flags
.hardfloor
= 0;
799 svl
.level
.flags
.nommap
= 0;
800 svl
.level
.flags
.hero_memory
= 1;
801 svl
.level
.flags
.shortsighted
= 0;
802 svl
.level
.flags
.sokoban_rules
= 0;
803 svl
.level
.flags
.is_maze_lev
= 0;
804 svl
.level
.flags
.is_cavernous_lev
= 0;
805 svl
.level
.flags
.arboreal
= 0;
806 svl
.level
.flags
.has_town
= 0;
807 svl
.level
.flags
.wizard_bones
= 0;
808 svl
.level
.flags
.corrmaze
= 0;
809 svl
.level
.flags
.temperature
= In_hell(&u
.uz
) ? 1 : 0;
810 svl
.level
.flags
.rndmongen
= 1;
811 svl
.level
.flags
.deathdrops
= 1;
812 svl
.level
.flags
.noautosearch
= 0;
813 svl
.level
.flags
.fumaroles
= 0;
814 svl
.level
.flags
.stormy
= 0;
817 svr
.rooms
[0].hx
= -1;
819 gs
.subrooms
[0].hx
= -1;
821 if (svd
.doors_alloc
) {
822 free((genericptr_t
) svd
.doors
);
823 svd
.doors
= (coord
*) 0;
829 gm
.made_branch
= FALSE
;
832 reset_xystart_size();
833 if (gl
.lev_message
) {
834 free(gl
.lev_message
);
835 gl
.lev_message
= (char *) 0;
839 #define ROOM_IS_FILLABLE(croom) \
840 ((croom->rtype == OROOM || croom->rtype == THEMEROOM) \
841 && croom->needfill == FILL_NORMAL)
843 /* Fill a "random" room (i.e. a typical non-special room in the Dungeons of
844 Doom) with random monsters, objects, and dungeon features.
846 If bonus_items is TRUE, there may be an additional special item
847 generated, depending on depth. */
850 struct mkroom
*croom
,
855 struct monst
*tmonst
; /* always put a web with a spider */
857 boolean skip_chests
= FALSE
;
859 if (croom
->rtype
!= OROOM
&& croom
->rtype
!= THEMEROOM
)
862 /* If there are subrooms, fill them now - we don't want an outer room
863 * that's specified to be unfilled to block an inner subroom that's
864 * specified to be filled. */
865 for (x
= 0; x
< croom
->nsubrooms
; ++x
) {
866 struct mkroom
*subroom
= croom
->sbrooms
[x
];
869 impossible("fill_ordinary_room: Null subroom");
872 fill_ordinary_room(subroom
, FALSE
);
875 if (croom
->needfill
!= FILL_NORMAL
)
878 /* put a sleeping monster inside */
879 /* Note: monster may be on the stairs. This cannot be
880 avoided: maybe the player fell through a trap door
881 while a monster was on the stairs. Conclusion:
882 we have to check for monsters on the stairs anyway. */
884 if ((u
.uhave
.amulet
|| !rn2(3)) && somexyspace(croom
, &pos
)) {
885 tmonst
= makemon((struct permonst
*) 0, pos
.x
, pos
.y
, MM_NOGRP
);
886 if (tmonst
&& tmonst
->data
== &mons
[PM_GIANT_SPIDER
]
887 && !occupied(pos
.x
, pos
.y
))
888 (void) maketrap(pos
.x
, pos
.y
, WEB
);
890 /* put traps and mimics inside */
891 x
= 8 - (level_difficulty() / 6);
894 while (!rn2(x
) && (++trycnt
< 1000))
895 mktrap(0, MKTRAP_NOFLAGS
, croom
, (coord
*) 0);
896 if (!rn2(3) && somexyspace(croom
, &pos
))
897 (void) mkgold(0L, pos
.x
, pos
.y
);
898 if (Is_rogue_level(&u
.uz
))
906 x
= 80 - (depth(&u
.uz
) * 2);
912 /* put statues inside */
913 if (!rn2(20) && somexyspace(croom
, &pos
))
914 (void) mkcorpstat(STATUE
, (struct monst
*) 0,
915 (struct permonst
*) 0, pos
.x
,
916 pos
.y
, CORPSTAT_INIT
);
919 * bonus_items means that this is the room where the bonus item
920 * should be placed, if there is one; but there might not be a
921 * bonus item on any given level.
923 * Bonus items are currently as follows:
924 * a) on the Mines branch level, 100% chance of a fairly filling
926 * b) on other levels above the Oracle, 2/3 chance of a "supply
927 * chest" that contains an early-game survivability item
928 * (there are therefore more of these when Sokoban is deep,
929 * which is intentional as those games are harder).
930 * This mechanism could be expanded in the future to place
931 * near-guaranteed items on particular levels (but, it is possible
932 * that no room will be given a bonus item if there is no suitable
933 * room to place it in, so it should not be used for plot-critical
936 if (bonus_items
&& somexyspace(croom
, &pos
)) {
937 branch
*uz_branch
= Is_branchlev(&u
.uz
);
939 if (uz_branch
&& u
.uz
.dnum
!= mines_dnum
940 && (uz_branch
->end1
.dnum
== mines_dnum
941 || uz_branch
->end2
.dnum
== mines_dnum
)) {
942 (void) mksobj_at((rn2(5) < 3) ? FOOD_RATION
943 : rn2(2) ? CRAM_RATION
945 pos
.x
, pos
.y
, TRUE
, FALSE
);
946 } else if (u
.uz
.dnum
== oracle_level
.dnum
947 && u
.uz
.dlevel
< oracle_level
.dlevel
&& rn2(3)) {
951 /* reverse probabilities compared to non-supply chests;
952 these are twice as likely to be chests than large
953 boxes, rather than vice versa */
954 struct obj
*supply_chest
= mksobj_at(rn2(3) ? CHEST
: LARGE_BOX
,
955 pos
.x
, pos
.y
, FALSE
, FALSE
);
957 supply_chest
->olocked
= !!(rn2(6));
960 static const int supply_items
[] = {
972 /* 50% this is a potion of healing */
973 otyp
= rn2(2) ? POT_HEALING
: ROLL_FROM(supply_items
);
974 otmp
= mksobj(otyp
, TRUE
, FALSE
);
975 if (otyp
== POT_HEALING
&& rn2(2)) {
977 otmp
->owt
= weight(otmp
);
979 cursed
= otmp
->cursed
;
980 add_to_container(supply_chest
, otmp
); /* owt updated below */
984 impossible("couldn't generate supply chest item");
987 /* guarantee at least one noncursed item, with a small
988 probability of more; if we generate a cursed item, it's
989 added to the supply chest but we reroll for a noncursed
990 item and add that too */
991 } while (cursed
|| !rn2(5));
993 /* maybe put a random item into the supply chest, biased
994 slightly towards low-level spellbooks; avoid tools
995 because chests don't fit into other chests */
997 static const int extra_classes
[] = {
1009 int oclass
= ROLL_FROM(extra_classes
);
1011 otmp
= mkobj(oclass
, FALSE
);
1012 if (oclass
== SPBOOK_no_NOVEL
) {
1013 int pass
, maxpass
= (depth(&u
.uz
) > 2) ? 2 : 3;
1015 /* bias towards lower level by generating again
1016 and taking the lower-level book; do that three
1017 times if on level 1 or 2, twice when deeper */
1018 for (pass
= 1; pass
<= maxpass
; ++pass
) {
1019 struct obj
*otmp2
= mkobj(oclass
, FALSE
);
1021 if (objects
[otmp
->otyp
].oc_level
1022 <= objects
[otmp2
->otyp
].oc_level
) {
1030 add_to_container(supply_chest
, otmp
); /* owt updated below */
1033 /* add_to_container() doesn't update the container's weight */
1034 supply_chest
->owt
= weight(supply_chest
);
1036 skip_chests
= TRUE
; /* don't want a second chest in this room */
1041 /* put box/chest inside;
1042 * 40% chance for at least 1 box, regardless of number
1043 * of rooms; about 5 - 7.5% for 2 boxes, least likely
1044 * when few rooms; chance for 3 or more is negligible.
1046 /*assert(svn.nroom > 0); // must be true because we're filling a room*/
1047 if (!skip_chests
&& !rn2(svn
.nroom
* 5 / 2) && somexyspace(croom
, &pos
))
1048 (void) mksobj_at(rn2(3) ? LARGE_BOX
: CHEST
,
1049 pos
.x
, pos
.y
, TRUE
, FALSE
);
1051 /* maybe make some graffiti */
1052 if (!rn2(27 + 3 * abs(depth(&u
.uz
)))) {
1054 const char *mesg
= random_engraving(buf
);
1058 (void) somexyspace(croom
, &pos
);
1061 } while (levl
[x
][y
].typ
!= ROOM
&& !rn2(40));
1062 if (levl
[x
][y
].typ
== ROOM
)
1063 make_engr_at(x
, y
, mesg
, 0L, MARK
);
1068 if (!rn2(3) && somexyspace(croom
, &pos
)) {
1069 (void) mkobj_at(RANDOM_CLASS
, pos
.x
, pos
.y
, TRUE
);
1072 if (++trycnt
> 100) {
1073 impossible("trycnt overflow4");
1076 if (somexyspace(croom
, &pos
)) {
1077 (void) mkobj_at(RANDOM_CLASS
, pos
.x
, pos
.y
, TRUE
);
1084 themerooms_post_level_generate(void)
1086 lua_State
*themes
= (lua_State
*) gl
.luathemes
[u
.uz
.dnum
];
1088 /* themes should already be loaded by makerooms();
1089 * if not, we don't run this either */
1093 reset_xystart_size();
1094 iflags
.in_lua
= gi
.in_mk_themerooms
= TRUE
;
1095 gt
.themeroom_failed
= FALSE
;
1096 lua_getglobal(themes
, "post_level_generate");
1097 nhl_pcall_handle(themes
, 0, 0, "post_level_generate", NHLpa_panic
);
1098 iflags
.in_lua
= gi
.in_mk_themerooms
= FALSE
;
1100 wallification(1, 0, COLNO
- 1, ROWNO
- 1);
1103 lua_gc(themes
, LUA_GCCOLLECT
);
1109 struct mkroom
*croom
;
1111 stairway
*prevstairs
;
1116 if (wiz1_level
.dlevel
== 0) {
1117 impossible("makelevel() called when dungeon not yet initialized.");
1120 oinit(); /* assign level dependent obj probabilities */
1121 clear_level_structures();
1123 slev
= Is_special(&u
.uz
);
1124 /* check for special levels */
1125 if (slev
&& !Is_rogue_level(&u
.uz
)) {
1126 makemaz(slev
->proto
);
1127 } else if (svd
.dungeons
[u
.uz
.dnum
].proto
[0]) {
1129 } else if (svd
.dungeons
[u
.uz
.dnum
].fill_lvl
[0]) {
1130 makemaz(svd
.dungeons
[u
.uz
.dnum
].fill_lvl
);
1131 } else if (In_quest(&u
.uz
)) {
1135 Sprintf(fillname
, "%s-loca", gu
.urole
.filecode
);
1136 loc_lev
= find_level(fillname
);
1138 Sprintf(fillname
, "%s-fil", gu
.urole
.filecode
);
1140 (u
.uz
.dlevel
< loc_lev
->dlevel
.dlevel
) ? "a" : "b");
1142 } else if (In_hell(&u
.uz
)
1143 || (rn2(5) && u
.uz
.dnum
== medusa_level
.dnum
1144 && depth(&u
.uz
) > depth(&medusa_level
))) {
1147 /* otherwise, fall through - it's a "regular" level. */
1148 int u_depth
= depth(&u
.uz
);
1150 if (Is_rogue_level(&u
.uz
)) {
1156 assert(svn
.nroom
> 0);
1159 generate_stairs(); /* up and down stairs */
1161 branchp
= Is_branchlev(&u
.uz
); /* possible dungeon branch */
1162 room_threshold
= branchp
? 4 : 3; /* minimum number of rooms needed
1163 to allow a random special room */
1164 if (Is_rogue_level(&u
.uz
))
1169 /* make a secret treasure vault, not connected to the rest */
1173 debugpline0("trying to make a vault...");
1176 if (check_room(&gv
.vault_x
, &w
, &gv
.vault_y
, &h
, TRUE
)) {
1178 add_room(gv
.vault_x
, gv
.vault_y
,
1179 gv
.vault_x
+ w
, gv
.vault_y
+ h
,
1180 TRUE
, VAULT
, FALSE
);
1181 svl
.level
.flags
.has_vault
= 1;
1183 svr
.rooms
[svn
.nroom
- 1].needfill
= FILL_NORMAL
;
1184 fill_special_room(&svr
.rooms
[svn
.nroom
- 1]);
1185 mk_knox_portal(gv
.vault_x
+ w
, gv
.vault_y
+ h
);
1186 if (!svl
.level
.flags
.noteleport
&& !rn2(3))
1188 } else if (rnd_rect() && create_vault()) {
1189 gv
.vault_x
= svr
.rooms
[svn
.nroom
].lx
;
1190 gv
.vault_y
= svr
.rooms
[svn
.nroom
].ly
;
1191 if (check_room(&gv
.vault_x
, &w
, &gv
.vault_y
, &h
, TRUE
))
1194 svr
.rooms
[svn
.nroom
].hx
= -1;
1198 /* make up to 1 special room, with type dependent on depth;
1199 note that mkroom doesn't guarantee a room gets created, and that
1200 this step only sets the room's rtype - it doesn't fill it yet. */
1201 if (wizard
&& nh_getenv("SHOPTYPE"))
1202 do_mkroom(SHOPBASE
);
1203 else if (u_depth
> 1 && u_depth
< depth(&medusa_level
)
1204 && svn
.nroom
>= room_threshold
&& rn2(u_depth
) < 3)
1205 do_mkroom(SHOPBASE
);
1206 else if (u_depth
> 4 && !rn2(6))
1208 else if (u_depth
> 5 && !rn2(8)
1209 && !(svm
.mvitals
[PM_LEPRECHAUN
].mvflags
& G_GONE
))
1210 do_mkroom(LEPREHALL
);
1211 else if (u_depth
> 6 && !rn2(7))
1213 else if (u_depth
> 8 && !rn2(5))
1215 else if (u_depth
> 9 && !rn2(5)
1216 && !(svm
.mvitals
[PM_KILLER_BEE
].mvflags
& G_GONE
))
1218 else if (u_depth
> 11 && !rn2(6))
1220 else if (u_depth
> 12 && !rn2(8) && antholemon())
1222 else if (u_depth
> 14 && !rn2(4)
1223 && !(svm
.mvitals
[PM_SOLDIER
].mvflags
& G_GONE
))
1224 do_mkroom(BARRACKS
);
1225 else if (u_depth
> 15 && !rn2(6))
1227 else if (u_depth
> 16 && !rn2(8)
1228 && !(svm
.mvitals
[PM_COCKATRICE
].mvflags
& G_GONE
))
1229 do_mkroom(COCKNEST
);
1232 prevstairs
= gs
.stairs
; /* used to test for place_branch() success */
1233 /* Place multi-dungeon branch. */
1234 place_branch(branchp
, 0, 0);
1236 /* for main dungeon level 1, the stairs up where the hero starts
1237 are branch stairs; treat them as if hero had just come down
1238 them by marking them as having been traversed; most recently
1239 created stairway is held in 'gs.stairs' */
1240 if (u
.uz
.dnum
== 0 && u
.uz
.dlevel
== 1 && gs
.stairs
!= prevstairs
)
1241 gs
.stairs
->u_traversed
= TRUE
;
1243 /* some levels have specially generated items in ordinary
1244 rooms (intended to be indistinguishable from the normally
1245 generated items); work out which room these will be placed in */
1246 int fillable_room_count
= 0;
1247 for (croom
= svr
.rooms
; croom
->hx
> 0; croom
++) {
1248 if (ROOM_IS_FILLABLE(croom
))
1249 fillable_room_count
++;
1251 /* choose a random fillable room to be the one that gets the
1252 bonus items, if there are any; if there aren't any we don't
1253 generate the bonus items (but levels with no fillable rooms
1254 typically don't have any bonus items to generate anyway) */
1255 int bonus_item_room_countdown
= fillable_room_count
1256 ? rn2(fillable_room_count
) : -1;
1258 /* for each room: put things inside */
1259 for (croom
= svr
.rooms
; croom
->hx
> 0; croom
++) {
1260 boolean fillable
= ROOM_IS_FILLABLE(croom
);
1262 fill_ordinary_room(croom
,
1263 fillable
&& bonus_item_room_countdown
== 0);
1265 --bonus_item_room_countdown
;
1268 /* Fill all special rooms now, regardless of whether this is a special
1269 * level, proto level, or ordinary level. */
1270 for (i
= 0; i
< svn
.nroom
; ++i
) {
1271 fill_special_room(&svr
.rooms
[i
]);
1274 themerooms_post_level_generate();
1276 if (gl
.luacore
&& nhcb_counts
[NHCB_LVL_ENTER
]) {
1277 lua_getglobal(gl
.luacore
, "nh_callback_run");
1278 lua_pushstring(gl
.luacore
, nhcb_name
[NHCB_LVL_ENTER
]);
1279 nhl_pcall_handle(gl
.luacore
, 1, 0, "makelevel", NHLpa_panic
);
1280 lua_settop(gl
.luacore
, 0);
1285 * Place deposits of minerals (gold and misc gems) in the stone
1286 * surrounding the rooms on the map.
1287 * Also place kelp in water.
1288 * mineralize(-1, -1, -1, -1, FALSE); => "default" behavior
1291 mineralize(int kelp_pool
, int kelp_moat
, int goldprob
, int gemprob
,
1292 boolean skip_lvl_checks
)
1304 /* Place kelp, except on the plane of water */
1305 if (!skip_lvl_checks
&& In_endgame(&u
.uz
))
1307 for (x
= 2; x
< (COLNO
- 2); x
++)
1308 for (y
= 1; y
< (ROWNO
- 1); y
++)
1309 if ((kelp_pool
&& levl
[x
][y
].typ
== POOL
&& !rn2(kelp_pool
))
1310 || (kelp_moat
&& levl
[x
][y
].typ
== MOAT
&& !rn2(kelp_moat
)))
1311 (void) mksobj_at(KELP_FROND
, x
, y
, TRUE
, FALSE
);
1313 /* determine if it is even allowed;
1314 almost all special levels are excluded */
1315 if (!skip_lvl_checks
1316 && (In_hell(&u
.uz
) || In_V_tower(&u
.uz
) || Is_rogue_level(&u
.uz
)
1317 || svl
.level
.flags
.arboreal
1318 || ((sp
= Is_special(&u
.uz
)) != 0 && !Is_oracle_level(&u
.uz
)
1319 && (!In_mines(&u
.uz
) || sp
->flags
.town
))))
1322 /* basic level-related probabilities */
1324 goldprob
= 20 + depth(&u
.uz
) / 3;
1326 gemprob
= goldprob
/ 4;
1328 /* mines have ***MORE*** goodies - otherwise why mine? */
1329 if (!skip_lvl_checks
) {
1330 if (In_mines(&u
.uz
)) {
1333 } else if (In_quest(&u
.uz
)) {
1340 * Seed rock areas with gold and/or gems.
1341 * We use fairly low level object handling to avoid unnecessary
1342 * overhead from placing things in the floor chain prior to burial.
1344 for (x
= 2; x
< (COLNO
- 2); x
++)
1345 for (y
= 1; y
< (ROWNO
- 1); y
++)
1346 if (levl
[x
][y
+ 1].typ
!= STONE
) { /* <x,y> spot not eligible */
1347 y
+= 2; /* next two spots aren't eligible either */
1348 } else if (levl
[x
][y
].typ
!= STONE
) { /* this spot not eligible */
1349 y
+= 1; /* next spot isn't eligible either */
1350 } else if (!(levl
[x
][y
].wall_info
& W_NONDIGGABLE
)
1351 && levl
[x
][y
- 1].typ
== STONE
1352 && levl
[x
+ 1][y
- 1].typ
== STONE
1353 && levl
[x
- 1][y
- 1].typ
== STONE
1354 && levl
[x
+ 1][y
].typ
== STONE
1355 && levl
[x
- 1][y
].typ
== STONE
1356 && levl
[x
+ 1][y
+ 1].typ
== STONE
1357 && levl
[x
- 1][y
+ 1].typ
== STONE
) {
1358 if (rn2(1000) < goldprob
) {
1359 if ((otmp
= mksobj(GOLD_PIECE
, FALSE
, FALSE
)) != 0) {
1360 otmp
->ox
= x
, otmp
->oy
= y
;
1361 otmp
->quan
= 1L + rnd(goldprob
* 3);
1362 otmp
->owt
= weight(otmp
);
1364 add_to_buried(otmp
);
1366 place_object(otmp
, x
, y
);
1369 if (rn2(1000) < gemprob
) {
1370 for (cnt
= rnd(2 + dunlev(&u
.uz
) / 3); cnt
> 0; cnt
--)
1371 if ((otmp
= mkobj(GEM_CLASS
, FALSE
)) != 0) {
1372 if (otmp
->otyp
== ROCK
) {
1373 dealloc_obj(otmp
); /* discard it */
1375 otmp
->ox
= x
, otmp
->oy
= y
;
1377 add_to_buried(otmp
);
1379 place_object(otmp
, x
, y
);
1387 level_finalize_topology(void)
1389 struct mkroom
*croom
;
1393 mineralize(-1, -1, -1, -1, FALSE
);
1394 gi
.in_mklev
= FALSE
;
1395 /* avoid coordinates in future lua-loads for this level being thrown off
1396 * because xstart and ystart aren't saved with the level and will be 0
1397 * after leaving and returning */
1398 gx
.xstart
= gy
.ystart
= 0;
1399 /* has_morgue gets cleared once morgue is entered; graveyard stays
1400 set (graveyard might already be set even when has_morgue is clear
1401 [see fixup_special()], so don't update it unconditionally) */
1402 if (svl
.level
.flags
.has_morgue
)
1403 svl
.level
.flags
.graveyard
= 1;
1404 if (!svl
.level
.flags
.is_maze_lev
) {
1405 for (croom
= &svr
.rooms
[0]; croom
!= &svr
.rooms
[svn
.nroom
]; croom
++)
1406 #ifdef SPECIALIZATION
1407 topologize(croom
, FALSE
);
1413 /* for many room types, svr.rooms[].rtype is zeroed once the room has been
1414 entered; svr.rooms[].orig_rtype always retains original rtype value */
1415 for (ridx
= 0; ridx
< SIZE(svr
.rooms
); ridx
++)
1416 svr
.rooms
[ridx
].orig_rtype
= svr
.rooms
[ridx
].rtype
;
1423 reseed_random(rn2_on_display_rng
);
1425 init_mapseen(&u
.uz
);
1432 level_finalize_topology();
1435 reseed_random(rn2_on_display_rng
);
1439 #ifdef SPECIALIZATION
1440 topologize(struct mkroom
*croom
, boolean do_ordinary
)
1442 topologize(struct mkroom
*croom
)
1446 int roomno
= (int) ((croom
- svr
.rooms
) + ROOMOFFSET
);
1447 coordxy lowx
= croom
->lx
, lowy
= croom
->ly
;
1448 coordxy hix
= croom
->hx
, hiy
= croom
->hy
;
1449 #ifdef SPECIALIZATION
1450 schar rtype
= croom
->rtype
;
1452 int subindex
, nsubrooms
= croom
->nsubrooms
;
1454 /* skip the room if already done; i.e. a shop handled out of order */
1455 /* also skip if this is non-rectangular (it _must_ be done already) */
1456 if ((int) levl
[lowx
][lowy
].roomno
== roomno
|| croom
->irregular
)
1458 #ifdef SPECIALIZATION
1459 if (Is_rogue_level(&u
.uz
))
1460 do_ordinary
= TRUE
; /* vision routine helper */
1461 if ((rtype
!= OROOM
) || do_ordinary
)
1464 /* do innards first */
1465 for (x
= lowx
; x
<= hix
; x
++)
1466 for (y
= lowy
; y
<= hiy
; y
++)
1467 #ifdef SPECIALIZATION
1469 levl
[x
][y
].roomno
= NO_ROOM
;
1472 levl
[x
][y
].roomno
= roomno
;
1473 /* top and bottom edges */
1474 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
1475 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
1476 levl
[x
][y
].edge
= 1;
1477 if (levl
[x
][y
].roomno
)
1478 levl
[x
][y
].roomno
= SHARED
;
1480 levl
[x
][y
].roomno
= roomno
;
1483 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
1484 for (y
= lowy
; y
<= hiy
; y
++) {
1485 levl
[x
][y
].edge
= 1;
1486 if (levl
[x
][y
].roomno
)
1487 levl
[x
][y
].roomno
= SHARED
;
1489 levl
[x
][y
].roomno
= roomno
;
1493 for (subindex
= 0; subindex
< nsubrooms
; subindex
++)
1494 #ifdef SPECIALIZATION
1495 topologize(croom
->sbrooms
[subindex
], (boolean
) (rtype
!= OROOM
));
1497 topologize(croom
->sbrooms
[subindex
]);
1501 /* Find an unused room for a branch location. */
1502 staticfn
struct mkroom
*
1503 find_branch_room(coord
*mp
)
1505 struct mkroom
*croom
= 0;
1507 if (svn
.nroom
== 0) {
1508 mazexy(mp
); /* already verifies location */
1510 croom
= generate_stairs_find_room();
1511 assert(croom
!= NULL
); /* Null iff nroom==0 which won't get here */
1512 if (!somexyspace(croom
, mp
))
1513 impossible("Can't place branch!");
1518 /* Find the room for (x,y). Return null if not in a room. */
1519 staticfn
struct mkroom
*
1520 pos_to_room(coordxy x
, coordxy y
)
1523 struct mkroom
*curr
;
1525 for (curr
= svr
.rooms
, i
= 0; i
< svn
.nroom
; curr
++, i
++)
1526 if (inside_room(curr
, x
, y
))
1529 return (struct mkroom
*) 0;
1532 /* If given a branch, randomly place a special stair or portal. */
1535 branch
*br
, /* branch to place */
1536 coordxy x
, coordxy y
) /* location */
1540 boolean make_stairs
;
1543 * Return immediately if there is no branch to make or we have
1544 * already made one. This routine can be called twice when
1545 * a special level is loaded that specifies an SSTAIR location
1546 * as a favored spot for a branch.
1548 if (!br
|| gm
.made_branch
)
1551 if (!x
) { /* find random coordinates for branch */
1552 /* br_room = find_branch_room(&m); */
1553 (void) find_branch_room(&m
); /* sets m via mazexy() or somexy() */
1557 (void) pos_to_room(x
, y
);
1560 if (on_level(&br
->end1
, &u
.uz
)) {
1562 make_stairs
= br
->type
!= BR_NO_END1
;
1566 make_stairs
= br
->type
!= BR_NO_END2
;
1570 if (br
->type
== BR_PORTAL
) {
1571 if (iflags
.debug_fuzzer
&& (u
.ucamefrom
.dnum
|| u
.ucamefrom
.dlevel
))
1572 mkportal(x
, y
, u
.ucamefrom
.dnum
, u
.ucamefrom
.dlevel
);
1574 mkportal(x
, y
, dest
->dnum
, dest
->dlevel
);
1575 } else if (make_stairs
) {
1576 boolean goes_up
= on_level(&br
->end1
, &u
.uz
) ? br
->end1_up
1579 stairway_add(x
, y
, goes_up
, FALSE
, dest
);
1580 (void) set_levltyp(x
, y
, STAIRS
);
1581 levl
[x
][y
].ladder
= goes_up
? LA_UP
: LA_DOWN
;
1584 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
1585 * make_stairs is false) since there is currently only one branch
1586 * per level, if we failed once, we're going to fail again on the
1589 gm
.made_branch
= TRUE
;
1593 bydoor(coordxy x
, coordxy y
)
1597 if (isok(x
+ 1, y
)) {
1598 typ
= levl
[x
+ 1][y
].typ
;
1599 if (IS_DOOR(typ
) || typ
== SDOOR
)
1602 if (isok(x
- 1, y
)) {
1603 typ
= levl
[x
- 1][y
].typ
;
1604 if (IS_DOOR(typ
) || typ
== SDOOR
)
1607 if (isok(x
, y
+ 1)) {
1608 typ
= levl
[x
][y
+ 1].typ
;
1609 if (IS_DOOR(typ
) || typ
== SDOOR
)
1612 if (isok(x
, y
- 1)) {
1613 typ
= levl
[x
][y
- 1].typ
;
1614 if (IS_DOOR(typ
) || typ
== SDOOR
)
1620 /* see whether it is allowable to create a door at [x,y] */
1622 okdoor(coordxy x
, coordxy y
)
1624 boolean near_door
= bydoor(x
, y
);
1626 return ((levl
[x
][y
].typ
== HWALL
|| levl
[x
][y
].typ
== VWALL
)
1627 && ((isok(x
- 1, y
) && !IS_OBSTRUCTED(levl
[x
- 1][y
].typ
))
1628 || (isok(x
+ 1, y
) && !IS_OBSTRUCTED(levl
[x
+ 1][y
].typ
))
1629 || (isok(x
, y
- 1) && !IS_OBSTRUCTED(levl
[x
][y
- 1].typ
))
1630 || (isok(x
, y
+ 1) && !IS_OBSTRUCTED(levl
[x
][y
+ 1].typ
)))
1634 /* do we want a secret door/corridor? */
1636 maybe_sdoor(int chance
)
1638 return (depth(&u
.uz
) > 2) && !rn2(max(2, chance
));
1641 /* create a door at x,y in room aroom */
1643 dodoor(coordxy x
, coordxy y
, struct mkroom
*aroom
)
1645 dosdoor(x
, y
, aroom
, maybe_sdoor(8) ? SDOOR
: DOOR
);
1649 occupied(coordxy x
, coordxy y
)
1651 return (boolean
) (t_at(x
, y
) || IS_FURNITURE(levl
[x
][y
].typ
)
1652 || is_lava(x
, y
) || is_pool(x
, y
)
1653 || invocation_pos(x
, y
));
1656 /* generate a corpse and some items on top of a trap */
1658 mktrap_victim(struct trap
*ttmp
)
1660 /* Object generated by the trap; initially NULL, stays NULL if
1661 we fail to generate an object or if the trap doesn't
1662 generate objects. */
1663 struct obj
*otmp
= NULL
;
1664 int victim_mnum
; /* race of the victim */
1665 unsigned lvl
= level_difficulty();
1666 int kind
= ttmp
->ttyp
;
1667 coordxy x
= ttmp
->tx
, y
= ttmp
->ty
;
1669 assert(x
> 0 && x
< COLNO
&& y
>= 0 && y
< ROWNO
);
1670 /* Not all trap types have special handling here; only the ones
1671 that kill in a specific way that's obvious after the fact. */
1674 otmp
= mksobj(ARROW
, TRUE
, FALSE
);
1675 otmp
->opoisoned
= 0;
1676 /* don't adjust the quantity; maybe the trap shot multiple
1677 times, there was an untrapping attempt, etc... */
1680 otmp
= mksobj(DART
, TRUE
, FALSE
);
1683 otmp
= mksobj(ROCK
, TRUE
, FALSE
);
1686 /* no item dropped by the trap */
1690 place_object(otmp
, x
, y
);
1693 /* now otmp is reused for other items we're placing */
1695 /* Place a random possession. This could be a weapon, tool,
1696 food, or gem, i.e. the item classes that are typically
1697 nonmagical and not worthless. */
1699 int poss_class
= RANDOM_CLASS
; /* init => lint suppression */
1703 poss_class
= WEAPON_CLASS
;
1706 poss_class
= TOOL_CLASS
;
1709 poss_class
= FOOD_CLASS
;
1712 poss_class
= GEM_CLASS
;
1716 otmp
= mkobj(poss_class
, FALSE
);
1717 /* these items are always cursed, both for flavour (owned
1718 by a dead adventurer, bones-pile-style) and for balance
1719 (less useful to use, and encourage pets to avoid the trap) */
1723 otmp
->owt
= weight(otmp
);
1724 place_object(otmp
, x
, y
);
1727 /* 20% chance of placing an additional item, recursively */
1730 /* Place a corpse. */
1733 /* elf corpses are the rarest as they're the most useful */
1734 victim_mnum
= PM_ELF
;
1735 /* elven adventurers get sleep resistance early; so don't
1736 generate elf corpses on sleeping gas traps unless a)
1737 we're on dlvl 2 (1 is impossible) and b) we pass a coin
1739 if (kind
== SLP_GAS_TRAP
&& !(lvl
<= 2 && rn2(2)))
1740 victim_mnum
= PM_HUMAN
;
1743 victim_mnum
= PM_DWARF
;
1745 case 3: case 4: case 5:
1746 victim_mnum
= PM_ORC
;
1748 case 6: case 7: case 8: case 9:
1749 /* more common as they could have come from the Mines */
1750 victim_mnum
= PM_GNOME
;
1751 /* 10% chance of a candle too */
1753 otmp
= mksobj(rn2(4) ? TALLOW_CANDLE
: WAX_CANDLE
, TRUE
, FALSE
);
1755 otmp
->owt
= weight(otmp
);
1757 place_object(otmp
, x
, y
);
1758 if (!levl
[x
][y
].lit
)
1759 begin_burn(otmp
, FALSE
);
1763 /* human is the most common result */
1764 victim_mnum
= PM_HUMAN
;
1767 /* PM_HUMAN is a placeholder monster primarily used for zombie, mummy,
1768 and vampire corpses; usually change it into a fake player monster
1769 instead (always human); no role-specific equipment is provided */
1770 if (victim_mnum
== PM_HUMAN
&& rn2(25))
1771 victim_mnum
= rn1(PM_WIZARD
- PM_ARCHEOLOGIST
, PM_ARCHEOLOGIST
);
1772 otmp
= mkcorpstat(CORPSE
, NULL
, &mons
[victim_mnum
], x
, y
, CORPSTAT_INIT
);
1773 otmp
->age
-= (TAINT_AGE
+ 1); /* died too long ago to safely eat */
1776 /* pick a random trap type, return NO_TRAP if "too hard" */
1778 traptype_rnd(unsigned mktrapflags
)
1780 unsigned lvl
= level_difficulty();
1781 int kind
= rnd(TRAPNUM
- 1);
1784 /* these are controlled by the feature or object they guard,
1785 not by the map so mustn't be created on it */
1790 /* these can have a random location but can't be generated
1793 case VIBRATING_SQUARE
:
1796 case ROLLING_BOULDER_TRAP
:
1802 if (lvl
< 5 || svl
.level
.flags
.noteleport
1803 || single_level_branch(&u
.uz
))
1815 if (lvl
< 7 && !(mktrapflags
& MKTRAP_NOSPIDERONWEB
))
1828 if (svl
.level
.flags
.noteleport
)
1832 /* make these much less often than other traps */
1840 /* random trap type for the Rogue level */
1842 traptype_roguelvl(void)
1863 kind
= SLP_GAS_TRAP
;
1872 /* mktrap(): select trap type and location, then use maketrap() to create it;
1873 make it at location 'tm' when that isn't Null, otherwise in 'croom'
1874 if mktrapflags doesn't have MKTRAP_MAZEFLAG set, else in maze corridor */
1877 int num
, /* if non-zero, specific type of trap to make */
1878 unsigned mktrapflags
, /* MKTRAP_{SEEN,MAZEFLAG,NOSPIDERONWEB,NOVICTIM} */
1879 struct mkroom
*croom
, /* room to hold trap */
1880 coord
*tm
) /* specific location for trap */
1882 static int mktrap_err
= 0; /* move to struct g? */
1886 unsigned lvl
= level_difficulty();
1888 if (!tm
&& !croom
&& !(mktrapflags
& MKTRAP_MAZEFLAG
)) {
1889 /* complain when the combination of arguments will never set 'm' */
1890 if (!mktrap_err
++) {
1893 Snprintf(errbuf
, sizeof errbuf
,
1894 "args (%d,%d,%s,%s) are invalid",
1895 num
, mktrapflags
, "null room", "null location");
1896 paniclog("mktrap", errbuf
);
1902 /* no traps in pools */
1903 if (tm
&& is_pool(tm
->x
, tm
->y
))
1906 if (num
> NO_TRAP
&& num
< TRAPNUM
) {
1908 } else if (Is_rogue_level(&u
.uz
)) {
1909 kind
= traptype_roguelvl();
1910 } else if (Inhell
&& !rn2(5)) {
1911 /* bias the frequency of fire traps in Gehennom */
1915 kind
= traptype_rnd(mktrapflags
);
1916 } while (kind
== NO_TRAP
);
1919 if (is_hole(kind
) && !Can_fall_thru(&u
.uz
))
1926 boolean avoid_boulder
= (is_pit(kind
) || is_hole(kind
));
1931 if ((mktrapflags
& MKTRAP_MAZEFLAG
) != 0)
1933 else if (croom
&& !somexyspace(croom
, &m
))
1935 } while (occupied(m
.x
, m
.y
)
1936 || (avoid_boulder
&& sobj_at(BOULDER
, m
.x
, m
.y
)));
1939 t
= maketrap(m
.x
, m
.y
, kind
);
1940 /* we should always get type of trap we're asking for (occupied() test
1941 should prevent cases where that might not happen) but be paranoid */
1942 kind
= t
? t
->ttyp
: NO_TRAP
;
1944 if (kind
== WEB
&& !(mktrapflags
& MKTRAP_NOSPIDERONWEB
))
1945 (void) makemon(&mons
[PM_GIANT_SPIDER
], m
.x
, m
.y
, NO_MM_FLAGS
);
1946 if (t
&& (mktrapflags
& MKTRAP_SEEN
))
1948 if (kind
== MAGIC_PORTAL
&& (u
.ucamefrom
.dnum
|| u
.ucamefrom
.dlevel
)) {
1949 assign_level(&t
->dst
, &u
.ucamefrom
);
1952 /* The hero isn't the only person who's entered the dungeon in
1953 search of treasure. On the very shallowest levels, there's a
1954 chance that a created trap will have killed something already
1955 (and this is guaranteed on the first level).
1957 This isn't meant to give any meaningful treasure (in fact, any
1958 items we drop here are typically cursed, other than ammo fired
1959 by the trap). Rather, it's mostly just for flavour and to give
1960 players on very early levels a sufficient chance to avoid traps
1961 that may end up killing them before they have a fair chance to
1962 build max HP. Including cursed items gives the same fair chance
1963 to the starting pet, and fits the rule that possessions of the
1964 dead are normally cursed.
1966 Some types of traps are excluded because they're entirely
1967 nonlethal, even indirectly. We also exclude all of the
1968 later/fancier traps because they tend to have special
1969 considerations (e.g. webs, portals), often are indirectly
1970 lethal, and tend not to generate on shallower levels anyway
1971 (exception: magic traps can generate on dlvl 1 and be
1972 immediately lethal). Finally, pits are excluded because it's
1973 weird to see an item in a pit and yet not be able to identify
1974 that the pit is there. */
1975 if (kind
!= NO_TRAP
&& !(mktrapflags
& MKTRAP_NOVICTIM
)
1976 && lvl
<= (unsigned) rnd(4)
1977 && kind
!= SQKY_BOARD
&& kind
!= RUST_TRAP
1978 /* rolling boulder trap might not have a boulder if there was no
1979 viable path (such as when placed in the corner of a room), in
1980 which case tx,ty==launch.x,y; no boulder => no dead predecessor */
1981 && !(kind
== ROLLING_BOULDER_TRAP
1982 && t
->launch
.x
== t
->tx
&& t
->launch
.y
== t
->ty
)
1983 && !is_pit(kind
) && (kind
< HOLE
|| kind
== MAGIC_TRAP
)) {
1988 /* Create stairs up or down at x,y.
1989 If force is TRUE, change the terrain to ROOM first */
1992 coordxy x
, coordxy y
,
1993 char up
, /* [why 'char' when usage is boolean?] */
1994 struct mkroom
*croom UNUSED
,
2000 if (!x
|| !isok(x
, y
)) {
2001 impossible("mkstairs: bogus stair attempt at <%d,%d>", x
, y
);
2005 levl
[x
][y
].typ
= ROOM
;
2006 ltyp
= levl
[x
][y
].typ
; /* somexyspace() allows ice */
2007 if (ltyp
!= ROOM
&& ltyp
!= CORR
&& ltyp
!= ICE
) {
2008 int glyph
= back_to_glyph(x
, y
),
2009 sidx
= glyph_to_cmap(glyph
);
2011 impossible("mkstairs: placing stairs %s on %s at <%d,%d>",
2012 up
? "up" : "down", defsyms
[sidx
].explanation
, x
, y
);
2016 * We can't make a regular stair off an end of the dungeon. This
2017 * attempt can happen when a special level is placed at an end and
2018 * has an up or down stair specified in its description file.
2020 if (dunlev(&u
.uz
) == (up
? 1 : dunlevs_in_dungeon(&u
.uz
)))
2023 dest
.dnum
= u
.uz
.dnum
;
2024 dest
.dlevel
= u
.uz
.dlevel
+ (up
? -1 : 1);
2025 stairway_add(x
, y
, up
? TRUE
: FALSE
, FALSE
, &dest
);
2027 (void) set_levltyp(x
, y
, STAIRS
);
2028 levl
[x
][y
].ladder
= up
? LA_UP
: LA_DOWN
;
2031 /* is room a good one to generate up or down stairs in? */
2033 generate_stairs_room_good(struct mkroom
*croom
, int phase
)
2036 * phase values, smaller allows for more relaxed criteria:
2037 * 2 == no relaxed criteria;
2038 * 1 == allow a themed room;
2039 * 0 == allow same room as existing up/downstairs;
2040 * -1 == allow an unjoined room.
2042 return (croom
&& (croom
->needjoining
|| (phase
< 0))
2043 && ((!has_dnstairs(croom
) && !has_upstairs(croom
))
2045 && (croom
->rtype
== OROOM
2046 || ((phase
< 2) && croom
->rtype
== THEMEROOM
)));
2049 /* find a good room to generate an up or down stairs in */
2050 staticfn
struct mkroom
*
2051 generate_stairs_find_room(void)
2053 struct mkroom
*croom
;
2058 return (struct mkroom
*) 0;
2060 rmarr
= (int *) alloc(sizeof(int) * svn
.nroom
);
2062 for (phase
= 2; phase
> -1; phase
--) {
2064 for (i
= 0; i
< svn
.nroom
; i
++)
2065 if (generate_stairs_room_good(&svr
.rooms
[i
], phase
))
2070 return &svr
.rooms
[i
];
2075 croom
= &svr
.rooms
[rn2(svn
.nroom
)];
2079 /* construct stairs up and down within the same branch,
2080 up and down in different rooms if possible */
2082 generate_stairs(void)
2084 /* generate_stairs_find_room() returns Null if nroom == 0, but that
2085 should never happen for a rooms+corridors style level */
2087 gen_stairs_panic
[] = "generate_stairs: failed to find a room! (%d)";
2088 struct mkroom
*croom
;
2091 if (!Is_botlevel(&u
.uz
)) {
2092 if ((croom
= generate_stairs_find_room()) == NULL
)
2093 panic(gen_stairs_panic
, svn
.nroom
);
2095 if (!somexyspace(croom
, &pos
)) {
2096 pos
.x
= somex(croom
);
2097 pos
.y
= somey(croom
);
2099 mkstairs(pos
.x
, pos
.y
, 0, croom
, FALSE
); /* down */
2102 if (u
.uz
.dlevel
!= 1) {
2103 /* if there is only 1 room and we found it above, this will find
2105 if ((croom
= generate_stairs_find_room()) == NULL
)
2106 panic(gen_stairs_panic
, svn
.nroom
);
2108 if (!somexyspace(croom
, &pos
)) {
2109 pos
.x
= somex(croom
);
2110 pos
.y
= somey(croom
);
2112 mkstairs(pos
.x
, pos
.y
, 1, croom
, FALSE
); /* up */
2117 mkfount(struct mkroom
*croom
)
2121 if (!find_okay_roompos(croom
, &m
))
2124 /* Put a fountain at m.x, m.y */
2125 if (!set_levltyp(m
.x
, m
.y
, FOUNTAIN
))
2127 /* Is it a "blessed" fountain? (affects drinking from fountain) */
2129 levl
[m
.x
][m
.y
].blessedftn
= 1;
2131 svl
.level
.flags
.nfountains
++;
2135 find_okay_roompos(struct mkroom
*croom
, coord
*crd
)
2142 if (!somexyspace(croom
, crd
))
2144 } while (occupied(crd
->x
, crd
->y
) || bydoor(crd
->x
, crd
->y
));
2149 mksink(struct mkroom
*croom
)
2153 if (!find_okay_roompos(croom
, &m
))
2156 /* Put a sink at m.x, m.y */
2157 if (!set_levltyp(m
.x
, m
.y
, SINK
))
2160 svl
.level
.flags
.nsinks
++;
2164 mkaltar(struct mkroom
*croom
)
2169 if (croom
->rtype
!= OROOM
)
2172 if (!find_okay_roompos(croom
, &m
))
2175 /* Put an altar at m.x, m.y */
2176 if (!set_levltyp(m
.x
, m
.y
, ALTAR
))
2179 /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
2180 al
= rn2((int) A_LAWFUL
+ 2) - 1;
2181 levl
[m
.x
][m
.y
].altarmask
= Align2amask(al
);
2185 mkgrave(struct mkroom
*croom
)
2190 boolean dobell
= !rn2(10);
2192 if (croom
->rtype
!= OROOM
)
2195 if (!find_okay_roompos(croom
, &m
))
2198 /* Put a grave at <m.x,m.y> */
2199 make_grave(m
.x
, m
.y
, dobell
? "Saved by the bell!" : (char *) 0);
2201 /* Possibly fill it with objects */
2203 /* this used to use mkgold(), which puts a stack of gold on
2204 the ground (or merges it with an existing one there if
2205 present), and didn't bother burying it; now we create a
2206 loose, easily buriable, stack but we make no attempt to
2207 replicate mkgold()'s level-based formula for the amount */
2208 struct obj
*gold
= mksobj(GOLD_PIECE
, TRUE
, FALSE
);
2210 gold
->quan
= (long) (rnd(20) + level_difficulty() * rnd(5));
2211 gold
->owt
= weight(gold
);
2212 gold
->ox
= m
.x
, gold
->oy
= m
.y
;
2213 add_to_buried(gold
);
2215 for (tryct
= rn2(5); tryct
; tryct
--) {
2216 otmp
= mkobj(RANDOM_CLASS
, TRUE
);
2222 add_to_buried(otmp
);
2225 /* Leave a bell, in case we accidentally buried someone alive */
2227 (void) mksobj_at(BELL
, m
.x
, m
.y
, TRUE
, FALSE
);
2232 * Major level transmutation: add a set of stairs (to the Sanctum) after
2233 * an earthquake that leaves behind a new topology, centered at inv_pos.
2234 * Assumes there are no rooms within the invocation area and that svi.inv_pos
2235 * is not too close to the edge of the map. Also assume the hero can see,
2236 * which is guaranteed for normal play due to the fact that sight is needed
2237 * to read the Book of the Dead. [That assumption is not valid; it is
2238 * possible that "the Book reads the hero" rather than vice versa if
2239 * attempted while blind (in order to make blind-from-birth conduct viable).]
2245 coordxy xmin
, xmax
, ymin
, ymax
;
2248 /* slightly odd if levitating, but not wrong */
2249 pline_The("floor shakes violently under you!");
2250 /* decide whether to issue the crumbling walls message */
2252 xmin
= xmax
= svi
.inv_pos
.x
;
2253 ymin
= ymax
= svi
.inv_pos
.y
;
2254 wallct
= mkinvk_check_wall(xmin
, ymin
);
2255 /* this replicates the somewhat convoluted loop below, working
2256 out from the stair position, except for stopping early when
2258 for (dist
= 1; !wallct
&& dist
< 7; ++dist
) {
2260 /* top and bottom */
2261 if (dist
!= 3) { /* the area is wider that it is high */
2263 for (i
= xmin
+ 1; i
< xmax
; i
++) {
2264 if (mkinvk_check_wall(i
, ymin
))
2265 ++wallct
; /* we could break after finding first wall
2266 * but it isn't a significant optimization
2267 * for code which only executes once */
2268 if (mkinvk_check_wall(i
, ymax
))
2272 /* left and right */
2273 if (!wallct
) { /* skip y loop if x loop found any walls */
2274 for (i
= ymin
; i
<= ymax
; i
++) {
2275 if (mkinvk_check_wall(xmin
, i
))
2277 if (mkinvk_check_wall(xmax
, i
))
2282 /* message won't appear if the maze 'walls' on this level are lava
2283 or if all the walls within range have been dug away; when it does
2284 appear, it will describe iron bars as "walls" (which is ok) */
2286 pline_The("walls around you begin to bend and crumble!");
2288 display_nhwindow(WIN_MESSAGE
, TRUE
);
2290 /* any trap hero is stuck in will be going away now */
2292 if (u
.utraptype
== TT_BURIEDBALL
)
2293 buried_ball_to_punishment();
2297 xmin
= xmax
= svi
.inv_pos
.x
; /* reset after the check for walls */
2298 ymin
= ymax
= svi
.inv_pos
.y
;
2299 mkinvpos(xmin
, ymin
, 0); /* middle, before placing stairs */
2301 for (dist
= 1; dist
< 7; dist
++) {
2305 /* top and bottom */
2306 if (dist
!= 3) { /* the area is wider that it is high */
2309 for (i
= xmin
+ 1; i
< xmax
; i
++) {
2310 mkinvpos(i
, ymin
, dist
);
2311 mkinvpos(i
, ymax
, dist
);
2315 /* left and right */
2316 for (i
= ymin
; i
<= ymax
; i
++) {
2317 mkinvpos(xmin
, i
, dist
);
2318 mkinvpos(xmax
, i
, dist
);
2321 flush_screen(1); /* make sure the new glyphs shows up */
2325 You("are standing at the top of a stairwell leading down!");
2326 mkstairs(u
.ux
, u
.uy
, 0, (struct mkroom
*) 0, FALSE
); /* down */
2328 gv
.vision_full_recalc
= 1; /* everything changed */
2331 /* Change level topology. Boulders in the vicinity are eliminated.
2332 * Temporarily overrides vision in the name of a nice effect.
2335 mkinvpos(coordxy x
, coordxy y
, int dist
)
2340 struct rm
*lev
= &levl
[x
][y
];
2342 /* maze levels have slightly different constraints from normal levels;
2343 these are also defined in mkmaze.c and may not be appropriate for
2344 mazes with corridors wider than 1 or for cavernous levels */
2345 #define x_maze_min 2
2346 #define y_maze_min 2
2348 /* clip at existing map borders if necessary */
2349 if (!within_bounded_area(x
, y
, x_maze_min
, y_maze_min
,
2350 gx
.x_maze_max
, gy
.y_maze_max
)) {
2351 /* outermost 2 columns and/or rows may be truncated due to edge */
2352 if (dist
< (7 - 2)) { /* panic() or impossible() */
2353 void (*errfunc
)(const char *, ...) PRINTF_F(1, 2);
2355 errfunc
= !isok(x
, y
) ? panic
: impossible
;
2356 (*errfunc
)("mkinvpos: <%d,%d> (%d) off map edge!", x
, y
, dist
);
2362 if ((ttmp
= t_at(x
, y
)) != 0)
2365 /* clear boulders; leave some rocks for non-{moat|trap} locations */
2366 make_rocks
= (dist
!= 1 && dist
!= 4 && dist
!= 5) ? TRUE
: FALSE
;
2367 while ((otmp
= sobj_at(BOULDER
, x
, y
)) != 0) {
2369 fracture_rock(otmp
);
2370 make_rocks
= FALSE
; /* don't bother with more rocks */
2372 obj_extract_self(otmp
);
2373 obfree(otmp
, (struct obj
*) 0);
2377 /* fake out saved state */
2383 lev
->horizontal
= FALSE
;
2384 /* short-circuit vision recalc */
2385 gv
.viz_array
[y
][x
] = (dist
< 6) ? (IN_SIGHT
| COULD_SEE
) : COULD_SEE
;
2388 case 1: /* fire traps */
2392 ttmp
= maketrap(x
, y
, FIRE_TRAP
);
2396 case 0: /* lit room locations */
2399 case 6: /* unlit room locations */
2402 case 4: /* pools (aka a wide moat) */
2408 impossible("mkinvpos called with dist %d", dist
);
2412 if ((mon
= m_at(x
, y
)) != 0) {
2413 /* wake up mimics, don't want to deal with them blocking vision */
2417 if ((ttmp
= t_at(x
, y
)) != 0)
2418 (void) mintrap(mon
, NO_TRAP_FLAGS
);
2420 (void) minliquid(mon
);
2423 if (!does_block(x
, y
, lev
))
2424 unblock_point(x
, y
); /* make sure vision knows location is open */
2426 /* display new value of position; could have a monster/object on it */
2432 /* reduces clutter in mkinvokearea() while avoiding potential static analyzer
2433 confusion about using isok(x,y) to control access to levl[x][y] */
2435 mkinvk_check_wall(coordxy x
, coordxy y
)
2441 assert(x
> 0 && x
< COLNO
);
2442 assert(y
>= 0 && y
< ROWNO
);
2443 ltyp
= levl
[x
][y
].typ
;
2444 return (IS_STWALL(ltyp
) || ltyp
== IRONBARS
) ? 1 : 0;
2448 * The portal to Ludios is special. The entrance can only occur within a
2449 * vault in the main dungeon at a depth greater than 10. The Ludios branch
2450 * structure reflects this by having a bogus "source" dungeon: the value
2451 * of n_dgns (thus, Is_branchlev() will never find it).
2453 * Ludios will remain isolated until the branch is corrected by this function.
2456 mk_knox_portal(coordxy x
, coordxy y
)
2462 br
= dungeon_branch("Fort Ludios");
2463 /* dungeon_branch() panics (so never returns) if result would be Null */
2466 if (on_level(&knox_level
, &br
->end1
)) {
2469 /* disallow Knox branch on a level with one branch already */
2470 if (Is_branchlev(&u
.uz
))
2475 /* Already set or 2/3 chance of deferring until a later level. */
2476 if (source
->dnum
< svn
.n_dgns
|| (rn2(3) && !wizard
))
2479 if (!(u
.uz
.dnum
== oracle_level
.dnum
/* in main dungeon */
2480 && !at_dgn_entrance("The Quest") /* but not Quest's entry */
2481 && (u_depth
= depth(&u
.uz
)) > 10 /* beneath 10 */
2482 && u_depth
< depth(&medusa_level
))) /* and above Medusa */
2485 /* Adjust source to be current level and re-insert branch. */
2487 insert_branch(br
, TRUE
);
2489 debugpline0("Made knox portal.");
2490 place_branch(br
, x
, y
);