1 /* NetHack 3.6 mklev.c $NHDT-Date: 1562455089 2019/07/06 23:18:09 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.63 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Alex Smith, 2017. */
4 /* NetHack may be freely redistributed. See license for details. */
5
6 #include "hack.h"
7
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 */
11
12 STATIC_DCL void FDECL(mkfount, (int, struct mkroom *));
13 STATIC_DCL void FDECL(mksink, (struct mkroom *));
14 STATIC_DCL void FDECL(mkaltar, (struct mkroom *));
15 STATIC_DCL void FDECL(mkgrave, (struct mkroom *));
16 STATIC_DCL void NDECL(makevtele);
17 STATIC_DCL void NDECL(clear_level_structures);
18 STATIC_DCL void NDECL(makelevel);
19 STATIC_DCL boolean FDECL(bydoor, (XCHAR_P, XCHAR_P));
20 STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *));
21 STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
22 STATIC_DCL boolean FDECL(place_niche, (struct mkroom *, int *, int *, int *));
23 STATIC_DCL void FDECL(makeniche, (int));
24 STATIC_DCL void NDECL(make_niches);
25 STATIC_PTR int FDECL(CFDECLSPEC do_comp, (const genericptr,
26 const genericptr));
27 STATIC_DCL void FDECL(dosdoor, (XCHAR_P, XCHAR_P, struct mkroom *, int));
28 STATIC_DCL void FDECL(join, (int, int, BOOLEAN_P));
29 STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *, int, int,
30 int, int, BOOLEAN_P,
31 SCHAR_P, BOOLEAN_P, BOOLEAN_P));
32 STATIC_DCL void NDECL(makerooms);
33 STATIC_DCL void FDECL(finddpos, (coord *, XCHAR_P, XCHAR_P,
34 XCHAR_P, XCHAR_P));
35 STATIC_DCL void FDECL(mkinvpos, (XCHAR_P, XCHAR_P, int));
36 STATIC_DCL void FDECL(mk_knox_portal, (XCHAR_P, XCHAR_P));
37
38 #define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
39 #define init_vault() vault_x = -1
40 #define do_vault() (vault_x != -1)
41 static xchar vault_x, vault_y;
42 static boolean made_branch; /* used only during level creation */
43
44 /* Args must be (const genericptr) so that qsort will always be happy. */
45
46 STATIC_PTR int CFDECLSPEC
do_comp(vx,vy)47 do_comp(vx, vy)
48 const genericptr vx;
49 const genericptr vy;
50 {
51 #ifdef LINT
52 /* lint complains about possible pointer alignment problems, but we know
53 that vx and vy are always properly aligned. Hence, the following
54 bogus definition:
55 */
56 return (vx == vy) ? 0 : -1;
57 #else
58 register const struct mkroom *x, *y;
59
60 x = (const struct mkroom *) vx;
61 y = (const struct mkroom *) vy;
62 if (x->lx < y->lx)
63 return -1;
64 return (x->lx > y->lx);
65 #endif /* LINT */
66 }
67
68 STATIC_OVL void
finddpos(cc,xl,yl,xh,yh)69 finddpos(cc, xl, yl, xh, yh)
70 coord *cc;
71 xchar xl, yl, xh, yh;
72 {
73 register xchar x, y;
74
75 x = rn1(xh - xl + 1, xl);
76 y = rn1(yh - yl + 1, yl);
77 if (okdoor(x, y))
78 goto gotit;
79
80 for (x = xl; x <= xh; x++)
81 for (y = yl; y <= yh; y++)
82 if (okdoor(x, y))
83 goto gotit;
84
85 for (x = xl; x <= xh; x++)
86 for (y = yl; y <= yh; y++)
87 if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
88 goto gotit;
89 /* cannot find something reasonable -- strange */
90 x = xl;
91 y = yh;
92 gotit:
93 cc->x = x;
94 cc->y = y;
95 return;
96 }
97
98 void
sort_rooms()99 sort_rooms()
100 {
101 #if defined(SYSV) || defined(DGUX)
102 #define CAST_nroom (unsigned) nroom
103 #else
104 #define CAST_nroom nroom /*as-is*/
105 #endif
106 qsort((genericptr_t) rooms, CAST_nroom, sizeof (struct mkroom), do_comp);
107 #undef CAST_nroom
108 }
109
110 STATIC_OVL void
do_room_or_subroom(croom,lowx,lowy,hix,hiy,lit,rtype,special,is_room)111 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
112 register struct mkroom *croom;
113 int lowx, lowy;
114 register int hix, hiy;
115 boolean lit;
116 schar rtype;
117 boolean special;
118 boolean is_room;
119 {
120 register int x, y;
121 struct rm *lev;
122
123 /* locations might bump level edges in wall-less rooms */
124 /* add/subtract 1 to allow for edge locations */
125 if (!lowx)
126 lowx++;
127 if (!lowy)
128 lowy++;
129 if (hix >= COLNO - 1)
130 hix = COLNO - 2;
131 if (hiy >= ROWNO - 1)
132 hiy = ROWNO - 2;
133
134 if (lit) {
135 for (x = lowx - 1; x <= hix + 1; x++) {
136 lev = &levl[x][max(lowy - 1, 0)];
137 for (y = lowy - 1; y <= hiy + 1; y++)
138 lev++->lit = 1;
139 }
140 croom->rlit = 1;
141 } else
142 croom->rlit = 0;
143
144 croom->lx = lowx;
145 croom->hx = hix;
146 croom->ly = lowy;
147 croom->hy = hiy;
148 croom->rtype = rtype;
149 croom->doorct = 0;
150 /* if we're not making a vault, doorindex will still be 0
151 * if we are, we'll have problems adding niches to the previous room
152 * unless fdoor is at least doorindex
153 */
154 croom->fdoor = doorindex;
155 croom->irregular = FALSE;
156
157 croom->nsubrooms = 0;
158 croom->sbrooms[0] = (struct mkroom *) 0;
159 if (!special) {
160 for (x = lowx - 1; x <= hix + 1; x++)
161 for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
162 levl[x][y].typ = HWALL;
163 levl[x][y].horizontal = 1; /* For open/secret doors. */
164 }
165 for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
166 for (y = lowy; y <= hiy; y++) {
167 levl[x][y].typ = VWALL;
168 levl[x][y].horizontal = 0; /* For open/secret doors. */
169 }
170 for (x = lowx; x <= hix; x++) {
171 lev = &levl[x][lowy];
172 for (y = lowy; y <= hiy; y++)
173 lev++->typ = ROOM;
174 }
175 if (is_room) {
176 levl[lowx - 1][lowy - 1].typ = TLCORNER;
177 levl[hix + 1][lowy - 1].typ = TRCORNER;
178 levl[lowx - 1][hiy + 1].typ = BLCORNER;
179 levl[hix + 1][hiy + 1].typ = BRCORNER;
180 } else { /* a subroom */
181 wallification(lowx - 1, lowy - 1, hix + 1, hiy + 1);
182 }
183 }
184 }
185
186 void
add_room(lowx,lowy,hix,hiy,lit,rtype,special)187 add_room(lowx, lowy, hix, hiy, lit, rtype, special)
188 int lowx, lowy, hix, hiy;
189 boolean lit;
190 schar rtype;
191 boolean special;
192 {
193 register struct mkroom *croom;
194
195 croom = &rooms[nroom];
196 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
197 (boolean) TRUE);
198 croom++;
199 croom->hx = -1;
200 nroom++;
201 }
202
203 void
add_subroom(proom,lowx,lowy,hix,hiy,lit,rtype,special)204 add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
205 struct mkroom *proom;
206 int lowx, lowy, hix, hiy;
207 boolean lit;
208 schar rtype;
209 boolean special;
210 {
211 register struct mkroom *croom;
212
213 croom = &subrooms[nsubroom];
214 do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
215 (boolean) FALSE);
216 proom->sbrooms[proom->nsubrooms++] = croom;
217 croom++;
218 croom->hx = -1;
219 nsubroom++;
220 }
221
222 STATIC_OVL void
makerooms()223 makerooms()
224 {
225 boolean tried_vault = FALSE;
226
227 /* make rooms until satisfied */
228 /* rnd_rect() will returns 0 if no more rects are available... */
229 while (nroom < MAXNROFROOMS && rnd_rect()) {
230 if (nroom >= (MAXNROFROOMS / 6) && rn2(2) && !tried_vault) {
231 tried_vault = TRUE;
232 if (create_vault()) {
233 vault_x = rooms[nroom].lx;
234 vault_y = rooms[nroom].ly;
235 rooms[nroom].hx = -1;
236 }
237 } else if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
238 return;
239 }
240 return;
241 }
242
243 STATIC_OVL void
join(a,b,nxcor)244 join(a, b, nxcor)
245 register int a, b;
246 boolean nxcor;
247 {
248 coord cc, tt, org, dest;
249 register xchar tx, ty, xx, yy;
250 register struct mkroom *croom, *troom;
251 register int dx, dy;
252
253 croom = &rooms[a];
254 troom = &rooms[b];
255
256 /* find positions cc and tt for doors in croom and troom
257 and direction for a corridor between them */
258
259 if (troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX)
260 return;
261 if (troom->lx > croom->hx) {
262 dx = 1;
263 dy = 0;
264 xx = croom->hx + 1;
265 tx = troom->lx - 1;
266 finddpos(&cc, xx, croom->ly, xx, croom->hy);
267 finddpos(&tt, tx, troom->ly, tx, troom->hy);
268 } else if (troom->hy < croom->ly) {
269 dy = -1;
270 dx = 0;
271 yy = croom->ly - 1;
272 finddpos(&cc, croom->lx, yy, croom->hx, yy);
273 ty = troom->hy + 1;
274 finddpos(&tt, troom->lx, ty, troom->hx, ty);
275 } else if (troom->hx < croom->lx) {
276 dx = -1;
277 dy = 0;
278 xx = croom->lx - 1;
279 tx = troom->hx + 1;
280 finddpos(&cc, xx, croom->ly, xx, croom->hy);
281 finddpos(&tt, tx, troom->ly, tx, troom->hy);
282 } else {
283 dy = 1;
284 dx = 0;
285 yy = croom->hy + 1;
286 ty = troom->ly - 1;
287 finddpos(&cc, croom->lx, yy, croom->hx, yy);
288 finddpos(&tt, troom->lx, ty, troom->hx, ty);
289 }
290 xx = cc.x;
291 yy = cc.y;
292 tx = tt.x - dx;
293 ty = tt.y - dy;
294 if (nxcor && levl[xx + dx][yy + dy].typ)
295 return;
296 if (okdoor(xx, yy) || !nxcor)
297 dodoor(xx, yy, croom);
298
299 org.x = xx + dx;
300 org.y = yy + dy;
301 dest.x = tx;
302 dest.y = ty;
303
304 if (!dig_corridor(&org, &dest, nxcor, level.flags.arboreal ? ROOM : CORR,
305 STONE))
306 return;
307
308 /* we succeeded in digging the corridor */
309 if (okdoor(tt.x, tt.y) || !nxcor)
310 dodoor(tt.x, tt.y, troom);
311
312 if (smeq[a] < smeq[b])
313 smeq[b] = smeq[a];
314 else
315 smeq[a] = smeq[b];
316 }
317
318 void
makecorridors()319 makecorridors()
320 {
321 int a, b, i;
322 boolean any = TRUE;
323
324 for (a = 0; a < nroom - 1; a++) {
325 join(a, a + 1, FALSE);
326 if (!rn2(50))
327 break; /* allow some randomness */
328 }
329 for (a = 0; a < nroom - 2; a++)
330 if (smeq[a] != smeq[a + 2])
331 join(a, a + 2, FALSE);
332 for (a = 0; any && a < nroom; a++) {
333 any = FALSE;
334 for (b = 0; b < nroom; b++)
335 if (smeq[a] != smeq[b]) {
336 join(a, b, FALSE);
337 any = TRUE;
338 }
339 }
340 if (nroom > 2)
341 for (i = rn2(nroom) + 4; i; i--) {
342 a = rn2(nroom);
343 b = rn2(nroom - 2);
344 if (b >= a)
345 b += 2;
346 join(a, b, TRUE);
347 }
348 }
349
350 void
add_door(x,y,aroom)351 add_door(x, y, aroom)
352 register int x, y;
353 register struct mkroom *aroom;
354 {
355 register struct mkroom *broom;
356 register int tmp;
357 int i;
358
359 if (aroom->doorct == 0)
360 aroom->fdoor = doorindex;
361
362 aroom->doorct++;
363
364 for (tmp = doorindex; tmp > aroom->fdoor; tmp--)
365 doors[tmp] = doors[tmp - 1];
366
367 for (i = 0; i < nroom; i++) {
368 broom = &rooms[i];
369 if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
370 broom->fdoor++;
371 }
372 for (i = 0; i < nsubroom; i++) {
373 broom = &subrooms[i];
374 if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
375 broom->fdoor++;
376 }
377
378 doorindex++;
379 doors[aroom->fdoor].x = x;
380 doors[aroom->fdoor].y = y;
381 }
382
383 STATIC_OVL void
dosdoor(x,y,aroom,type)384 dosdoor(x, y, aroom, type)
385 register xchar x, y;
386 struct mkroom *aroom;
387 int type;
388 {
389 boolean shdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
390
391 if (!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
392 type = DOOR;
393 levl[x][y].typ = type;
394 if (type == DOOR) {
395 if (!rn2(3)) { /* is it a locked door, closed, or a doorway? */
396 if (!rn2(5))
397 levl[x][y].doormask = D_ISOPEN;
398 else if (!rn2(6))
399 levl[x][y].doormask = D_LOCKED;
400 else
401 levl[x][y].doormask = D_CLOSED;
402
403 if (levl[x][y].doormask != D_ISOPEN && !shdoor
404 && level_difficulty() >= 5 && !rn2(25))
405 levl[x][y].doormask |= D_TRAPPED;
406 } else {
407 #ifdef STUPID
408 if (shdoor)
409 levl[x][y].doormask = D_ISOPEN;
410 else
411 levl[x][y].doormask = D_NODOOR;
412 #else
413 levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
414 #endif
415 }
416
417 /* also done in roguecorr(); doing it here first prevents
418 making mimics in place of trapped doors on rogue level */
419 if (Is_rogue_level(&u.uz))
420 levl[x][y].doormask = D_NODOOR;
421
422 if (levl[x][y].doormask & D_TRAPPED) {
423 struct monst *mtmp;
424
425 if (level_difficulty() >= 9 && !rn2(5)
426 && !((mvitals[PM_SMALL_MIMIC].mvflags & G_GONE)
427 && (mvitals[PM_LARGE_MIMIC].mvflags & G_GONE)
428 && (mvitals[PM_GIANT_MIMIC].mvflags & G_GONE))) {
429 /* make a mimic instead */
430 levl[x][y].doormask = D_NODOOR;
431 mtmp = makemon(mkclass(S_MIMIC, 0), x, y, NO_MM_FLAGS);
432 if (mtmp)
433 set_mimic_sym(mtmp);
434 }
435 }
436 /* newsym(x,y); */
437 } else { /* SDOOR */
438 if (shdoor || !rn2(5))
439 levl[x][y].doormask = D_LOCKED;
440 else
441 levl[x][y].doormask = D_CLOSED;
442
443 if (!shdoor && level_difficulty() >= 4 && !rn2(20))
444 levl[x][y].doormask |= D_TRAPPED;
445 }
446
447 add_door(x, y, aroom);
448 }
449
450 STATIC_OVL boolean
place_niche(aroom,dy,xx,yy)451 place_niche(aroom, dy, xx, yy)
452 register struct mkroom *aroom;
453 int *dy, *xx, *yy;
454 {
455 coord dd;
456
457 if (rn2(2)) {
458 *dy = 1;
459 finddpos(&dd, aroom->lx, aroom->hy + 1, aroom->hx, aroom->hy + 1);
460 } else {
461 *dy = -1;
462 finddpos(&dd, aroom->lx, aroom->ly - 1, aroom->hx, aroom->ly - 1);
463 }
464 *xx = dd.x;
465 *yy = dd.y;
466 return (boolean) ((isok(*xx, *yy + *dy)
467 && levl[*xx][*yy + *dy].typ == STONE)
468 && (isok(*xx, *yy - *dy)
469 && !IS_POOL(levl[*xx][*yy - *dy].typ)
470 && !IS_FURNITURE(levl[*xx][*yy - *dy].typ)));
471 }
472
473 /* there should be one of these per trap, in the same order as trap.h */
474 static NEARDATA const char *trap_engravings[TRAPNUM] = {
475 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
476 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
477 (char *) 0, (char *) 0, (char *) 0, (char *) 0,
478 /* 14..16: trap door, teleport, level-teleport */
479 "Vlad was here", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
480 (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
481 };
482
483 STATIC_OVL void
makeniche(trap_type)484 makeniche(trap_type)
485 int trap_type;
486 {
487 register struct mkroom *aroom;
488 struct rm *rm;
489 int vct = 8;
490 int dy, xx, yy;
491 struct trap *ttmp;
492
493 if (doorindex < DOORMAX) {
494 while (vct--) {
495 aroom = &rooms[rn2(nroom)];
496 if (aroom->rtype != OROOM)
497 continue; /* not an ordinary room */
498 if (aroom->doorct == 1 && rn2(5))
499 continue;
500 if (!place_niche(aroom, &dy, &xx, &yy))
501 continue;
502
503 rm = &levl[xx][yy + dy];
504 if (trap_type || !rn2(4)) {
505 rm->typ = SCORR;
506 if (trap_type) {
507 if (is_hole(trap_type) && !Can_fall_thru(&u.uz))
508 trap_type = ROCKTRAP;
509 ttmp = maketrap(xx, yy + dy, trap_type);
510 if (ttmp) {
511 if (trap_type != ROCKTRAP)
512 ttmp->once = 1;
513 if (trap_engravings[trap_type]) {
514 make_engr_at(xx, yy - dy,
515 trap_engravings[trap_type], 0L,
516 DUST);
517 wipe_engr_at(xx, yy - dy, 5,
518 FALSE); /* age it a little */
519 }
520 }
521 }
522 dosdoor(xx, yy, aroom, SDOOR);
523 } else {
524 rm->typ = CORR;
525 if (rn2(7))
526 dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
527 else {
528 /* inaccessible niches occasionally have iron bars */
529 if (!rn2(5) && IS_WALL(levl[xx][yy].typ)) {
530 levl[xx][yy].typ = IRONBARS;
531 if (rn2(3))
532 (void) mkcorpstat(CORPSE, (struct monst *) 0,
533 mkclass(S_HUMAN, 0), xx,
534 yy + dy, TRUE);
535 }
536 if (!level.flags.noteleport)
537 (void) mksobj_at(SCR_TELEPORTATION, xx, yy + dy, TRUE,
538 FALSE);
539 if (!rn2(3))
540 (void) mkobj_at(0, xx, yy + dy, TRUE);
541 }
542 }
543 return;
544 }
545 }
546 }
547
548 STATIC_OVL void
make_niches()549 make_niches()
550 {
551 int ct = rnd((nroom >> 1) + 1), dep = depth(&u.uz);
552 boolean ltptr = (!level.flags.noteleport && dep > 15),
553 vamp = (dep > 5 && dep < 25);
554
555 while (ct--) {
556 if (ltptr && !rn2(6)) {
557 ltptr = FALSE;
558 makeniche(LEVEL_TELEP);
559 } else if (vamp && !rn2(6)) {
560 vamp = FALSE;
561 makeniche(TRAPDOOR);
562 } else
563 makeniche(NO_TRAP);
564 }
565 }
566
567 STATIC_OVL void
makevtele()568 makevtele()
569 {
570 makeniche(TELEP_TRAP);
571 }
572
573 /* clear out various globals that keep information on the current level.
574 * some of this is only necessary for some types of levels (maze, normal,
575 * special) but it's easier to put it all in one place than make sure
576 * each type initializes what it needs to separately.
577 */
578 STATIC_OVL void
clear_level_structures()579 clear_level_structures()
580 {
581 static struct rm zerorm = { cmap_to_glyph(S_stone),
582 0, 0, 0, 0, 0, 0, 0, 0, 0 };
583 register int x, y;
584 register struct rm *lev;
585
586 /* note: normally we'd start at x=1 because map column #0 isn't used
587 (except for placing vault guard at <0,0> when removed from the map
588 but not from the level); explicitly reset column #0 along with the
589 rest so that we start the new level with a completely clean slate */
590 for (x = 0; x < COLNO; x++) {
591 lev = &levl[x][0];
592 for (y = 0; y < ROWNO; y++) {
593 *lev++ = zerorm;
594 /*
595 * These used to be '#if MICROPORT_BUG',
596 * with use of memset(0) for '#if !MICROPORT_BUG' below,
597 * but memset is not appropriate for initializing pointers,
598 * so do these level.objects[][] and level.monsters[][]
599 * initializations unconditionally.
600 */
601 level.objects[x][y] = (struct obj *) 0;
602 level.monsters[x][y] = (struct monst *) 0;
603 }
604 }
605 level.objlist = (struct obj *) 0;
606 level.buriedobjlist = (struct obj *) 0;
607 level.monlist = (struct monst *) 0;
608 level.damagelist = (struct damage *) 0;
609 level.bonesinfo = (struct cemetery *) 0;
610
611 level.flags.nfountains = 0;
612 level.flags.nsinks = 0;
613 level.flags.has_shop = 0;
614 level.flags.has_vault = 0;
615 level.flags.has_zoo = 0;
616 level.flags.has_court = 0;
617 level.flags.has_morgue = level.flags.graveyard = 0;
618 level.flags.has_beehive = 0;
619 level.flags.has_barracks = 0;
620 level.flags.has_temple = 0;
621 level.flags.has_swamp = 0;
622 level.flags.noteleport = 0;
623 level.flags.hardfloor = 0;
624 level.flags.nommap = 0;
625 level.flags.hero_memory = 1;
626 level.flags.shortsighted = 0;
627 level.flags.sokoban_rules = 0;
628 level.flags.is_maze_lev = 0;
629 level.flags.is_cavernous_lev = 0;
630 level.flags.arboreal = 0;
631 level.flags.wizard_bones = 0;
632 level.flags.corrmaze = 0;
633
634 nroom = 0;
635 rooms[0].hx = -1;
636 nsubroom = 0;
637 subrooms[0].hx = -1;
638 doorindex = 0;
639 init_rect();
640 init_vault();
641 xdnstair = ydnstair = xupstair = yupstair = 0;
642 sstairs.sx = sstairs.sy = 0;
643 xdnladder = ydnladder = xupladder = yupladder = 0;
644 dnstairs_room = upstairs_room = sstairs_room = (struct mkroom *) 0;
645 made_branch = FALSE;
646 clear_regions();
647 }
648
649 STATIC_OVL void
makelevel()650 makelevel()
651 {
652 register struct mkroom *croom, *troom;
653 register int tryct;
654 register int x, y;
655 struct monst *tmonst; /* always put a web with a spider */
656 branch *branchp;
657 int room_threshold;
658
659 if (wiz1_level.dlevel == 0)
660 init_dungeons();
661 oinit(); /* assign level dependent obj probabilities */
662 clear_level_structures();
663
664 {
665 register s_level *slev = Is_special(&u.uz);
666
667 /* check for special levels */
668 if (slev && !Is_rogue_level(&u.uz)) {
669 makemaz(slev->proto);
670 return;
671 } else if (dungeons[u.uz.dnum].proto[0]) {
672 makemaz("");
673 return;
674 } else if (In_mines(&u.uz)) {
675 makemaz("minefill");
676 return;
677 } else if (In_quest(&u.uz)) {
678 char fillname[9];
679 s_level *loc_lev;
680
681 Sprintf(fillname, "%s-loca", urole.filecode);
682 loc_lev = find_level(fillname);
683
684 Sprintf(fillname, "%s-fil", urole.filecode);
685 Strcat(fillname,
686 (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
687 makemaz(fillname);
688 return;
689 } else if (In_hell(&u.uz)
690 || (rn2(5) && u.uz.dnum == medusa_level.dnum
691 && depth(&u.uz) > depth(&medusa_level))) {
692 makemaz("");
693 return;
694 }
695 }
696
697 /* otherwise, fall through - it's a "regular" level. */
698
699 if (Is_rogue_level(&u.uz)) {
700 makeroguerooms();
701 makerogueghost();
702 } else
703 makerooms();
704 sort_rooms();
705
706 /* construct stairs (up and down in different rooms if possible) */
707 croom = &rooms[rn2(nroom)];
708 if (!Is_botlevel(&u.uz))
709 mkstairs(somex(croom), somey(croom), 0, croom); /* down */
710 if (nroom > 1) {
711 troom = croom;
712 croom = &rooms[rn2(nroom - 1)];
713 if (croom == troom)
714 croom++;
715 }
716
717 if (u.uz.dlevel != 1) {
718 xchar sx, sy;
719 do {
720 sx = somex(croom);
721 sy = somey(croom);
722 } while (occupied(sx, sy));
723 mkstairs(sx, sy, 1, croom); /* up */
724 }
725
726 branchp = Is_branchlev(&u.uz); /* possible dungeon branch */
727 room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed
728 to allow a random special room */
729 if (Is_rogue_level(&u.uz))
730 goto skip0;
731 makecorridors();
732 make_niches();
733
734 /* make a secret treasure vault, not connected to the rest */
735 if (do_vault()) {
736 xchar w, h;
737
738 debugpline0("trying to make a vault...");
739 w = 1;
740 h = 1;
741 if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
742 fill_vault:
743 add_room(vault_x, vault_y, vault_x + w, vault_y + h,
744 TRUE, VAULT, FALSE);
745 level.flags.has_vault = 1;
746 ++room_threshold;
747 fill_room(&rooms[nroom - 1], FALSE);
748 mk_knox_portal(vault_x + w, vault_y + h);
749 if (!level.flags.noteleport && !rn2(3))
750 makevtele();
751 } else if (rnd_rect() && create_vault()) {
752 vault_x = rooms[nroom].lx;
753 vault_y = rooms[nroom].ly;
754 if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
755 goto fill_vault;
756 else
757 rooms[nroom].hx = -1;
758 }
759 }
760
761 {
762 register int u_depth = depth(&u.uz);
763
764 if (wizard && nh_getenv("SHOPTYPE"))
765 mkroom(SHOPBASE);
766 else if (u_depth > 1 && u_depth < depth(&medusa_level)
767 && nroom >= room_threshold && rn2(u_depth) < 3)
768 mkroom(SHOPBASE);
769 else if (u_depth > 4 && !rn2(6))
770 mkroom(COURT);
771 else if (u_depth > 5 && !rn2(8)
772 && !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE))
773 mkroom(LEPREHALL);
774 else if (u_depth > 6 && !rn2(7))
775 mkroom(ZOO);
776 else if (u_depth > 8 && !rn2(5))
777 mkroom(TEMPLE);
778 else if (u_depth > 9 && !rn2(5)
779 && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE))
780 mkroom(BEEHIVE);
781 else if (u_depth > 11 && !rn2(6))
782 mkroom(MORGUE);
783 else if (u_depth > 12 && !rn2(8) && antholemon())
784 mkroom(ANTHOLE);
785 else if (u_depth > 14 && !rn2(4)
786 && !(mvitals[PM_SOLDIER].mvflags & G_GONE))
787 mkroom(BARRACKS);
788 else if (u_depth > 15 && !rn2(6))
789 mkroom(SWAMP);
790 else if (u_depth > 16 && !rn2(8)
791 && !(mvitals[PM_COCKATRICE].mvflags & G_GONE))
792 mkroom(COCKNEST);
793 }
794
795 skip0:
796 /* Place multi-dungeon branch. */
797 place_branch(branchp, 0, 0);
798
799 /* for each room: put things inside */
800 for (croom = rooms; croom->hx > 0; croom++) {
801 if (croom->rtype != OROOM)
802 continue;
803
804 /* put a sleeping monster inside */
805 /* Note: monster may be on the stairs. This cannot be
806 avoided: maybe the player fell through a trap door
807 while a monster was on the stairs. Conclusion:
808 we have to check for monsters on the stairs anyway. */
809
810 if (u.uhave.amulet || !rn2(3)) {
811 x = somex(croom);
812 y = somey(croom);
813 tmonst = makemon((struct permonst *) 0, x, y, MM_NOGRP);
814 if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER]
815 && !occupied(x, y))
816 (void) maketrap(x, y, WEB);
817 }
818 /* put traps and mimics inside */
819 x = 8 - (level_difficulty() / 6);
820 if (x <= 1)
821 x = 2;
822 while (!rn2(x))
823 mktrap(0, 0, croom, (coord *) 0);
824 if (!rn2(3))
825 (void) mkgold(0L, somex(croom), somey(croom));
826 if (Is_rogue_level(&u.uz))
827 goto skip_nonrogue;
828 if (!rn2(10))
829 mkfount(0, croom);
830 if (!rn2(60))
831 mksink(croom);
832 if (!rn2(60))
833 mkaltar(croom);
834 x = 80 - (depth(&u.uz) * 2);
835 if (x < 2)
836 x = 2;
837 if (!rn2(x))
838 mkgrave(croom);
839
840 /* put statues inside */
841 if (!rn2(20))
842 (void) mkcorpstat(STATUE, (struct monst *) 0,
843 (struct permonst *) 0, somex(croom),
844 somey(croom), CORPSTAT_INIT);
845 /* put box/chest inside;
846 * 40% chance for at least 1 box, regardless of number
847 * of rooms; about 5 - 7.5% for 2 boxes, least likely
848 * when few rooms; chance for 3 or more is negligible.
849 */
850 if (!rn2(nroom * 5 / 2))
851 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, somex(croom),
852 somey(croom), TRUE, FALSE);
853
854 /* maybe make some graffiti */
855 if (!rn2(27 + 3 * abs(depth(&u.uz)))) {
856 char buf[BUFSZ];
857 const char *mesg = random_engraving(buf);
858
859 if (mesg) {
860 do {
861 x = somex(croom);
862 y = somey(croom);
863 } while (levl[x][y].typ != ROOM && !rn2(40));
864 if (!(IS_POOL(levl[x][y].typ)
865 || IS_FURNITURE(levl[x][y].typ)))
866 make_engr_at(x, y, mesg, 0L, MARK);
867 }
868 }
869
870 skip_nonrogue:
871 if (!rn2(3)) {
872 (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
873 tryct = 0;
874 while (!rn2(5)) {
875 if (++tryct > 100) {
876 impossible("tryct overflow4");
877 break;
878 }
879 (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
880 }
881 }
882 }
883 }
884
885 /*
886 * Place deposits of minerals (gold and misc gems) in the stone
887 * surrounding the rooms on the map.
888 * Also place kelp in water.
889 * mineralize(-1, -1, -1, -1, FALSE); => "default" behaviour
890 */
891 void
mineralize(kelp_pool,kelp_moat,goldprob,gemprob,skip_lvl_checks)892 mineralize(kelp_pool, kelp_moat, goldprob, gemprob, skip_lvl_checks)
893 int kelp_pool, kelp_moat, goldprob, gemprob;
894 boolean skip_lvl_checks;
895 {
896 s_level *sp;
897 struct obj *otmp;
898 int x, y, cnt;
899
900 if (kelp_pool < 0)
901 kelp_pool = 10;
902 if (kelp_moat < 0)
903 kelp_moat = 30;
904
905 /* Place kelp, except on the plane of water */
906 if (!skip_lvl_checks && In_endgame(&u.uz))
907 return;
908 for (x = 2; x < (COLNO - 2); x++)
909 for (y = 1; y < (ROWNO - 1); y++)
910 if ((kelp_pool && levl[x][y].typ == POOL && !rn2(kelp_pool))
911 || (kelp_moat && levl[x][y].typ == MOAT && !rn2(kelp_moat)))
912 (void) mksobj_at(KELP_FROND, x, y, TRUE, FALSE);
913
914 /* determine if it is even allowed;
915 almost all special levels are excluded */
916 if (!skip_lvl_checks
917 && (In_hell(&u.uz) || In_V_tower(&u.uz) || Is_rogue_level(&u.uz)
918 || level.flags.arboreal
919 || ((sp = Is_special(&u.uz)) != 0 && !Is_oracle_level(&u.uz)
920 && (!In_mines(&u.uz) || sp->flags.town))))
921 return;
922
923 /* basic level-related probabilities */
924 if (goldprob < 0)
925 goldprob = 20 + depth(&u.uz) / 3;
926 if (gemprob < 0)
927 gemprob = goldprob / 4;
928
929 /* mines have ***MORE*** goodies - otherwise why mine? */
930 if (!skip_lvl_checks) {
931 if (In_mines(&u.uz)) {
932 goldprob *= 2;
933 gemprob *= 3;
934 } else if (In_quest(&u.uz)) {
935 goldprob /= 4;
936 gemprob /= 6;
937 }
938 }
939
940 /*
941 * Seed rock areas with gold and/or gems.
942 * We use fairly low level object handling to avoid unnecessary
943 * overhead from placing things in the floor chain prior to burial.
944 */
945 for (x = 2; x < (COLNO - 2); x++)
946 for (y = 1; y < (ROWNO - 1); y++)
947 if (levl[x][y + 1].typ != STONE) { /* <x,y> spot not eligible */
948 y += 2; /* next two spots aren't eligible either */
949 } else if (levl[x][y].typ != STONE) { /* this spot not eligible */
950 y += 1; /* next spot isn't eligible either */
951 } else if (!(levl[x][y].wall_info & W_NONDIGGABLE)
952 && levl[x][y - 1].typ == STONE
953 && levl[x + 1][y - 1].typ == STONE
954 && levl[x - 1][y - 1].typ == STONE
955 && levl[x + 1][y].typ == STONE
956 && levl[x - 1][y].typ == STONE
957 && levl[x + 1][y + 1].typ == STONE
958 && levl[x - 1][y + 1].typ == STONE) {
959 if (rn2(1000) < goldprob) {
960 if ((otmp = mksobj(GOLD_PIECE, FALSE, FALSE)) != 0) {
961 otmp->ox = x, otmp->oy = y;
962 otmp->quan = 1L + rnd(goldprob * 3);
963 otmp->owt = weight(otmp);
964 if (!rn2(3))
965 add_to_buried(otmp);
966 else
967 place_object(otmp, x, y);
968 }
969 }
970 if (rn2(1000) < gemprob) {
971 for (cnt = rnd(2 + dunlev(&u.uz) / 3); cnt > 0; cnt--)
972 if ((otmp = mkobj(GEM_CLASS, FALSE)) != 0) {
973 if (otmp->otyp == ROCK) {
974 dealloc_obj(otmp); /* discard it */
975 } else {
976 otmp->ox = x, otmp->oy = y;
977 if (!rn2(3))
978 add_to_buried(otmp);
979 else
980 place_object(otmp, x, y);
981 }
982 }
983 }
984 }
985 }
986
987 void
mklev()988 mklev()
989 {
990 struct mkroom *croom;
991 int ridx;
992
993 reseed_random(rn2);
994 reseed_random(rn2_on_display_rng);
995
996 init_mapseen(&u.uz);
997 if (getbones())
998 return;
999
1000 in_mklev = TRUE;
1001 makelevel();
1002 bound_digging();
1003 mineralize(-1, -1, -1, -1, FALSE);
1004 in_mklev = FALSE;
1005 /* has_morgue gets cleared once morgue is entered; graveyard stays
1006 set (graveyard might already be set even when has_morgue is clear
1007 [see fixup_special()], so don't update it unconditionally) */
1008 if (level.flags.has_morgue)
1009 level.flags.graveyard = 1;
1010 if (!level.flags.is_maze_lev) {
1011 for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
1012 #ifdef SPECIALIZATION
1013 topologize(croom, FALSE);
1014 #else
1015 topologize(croom);
1016 #endif
1017 }
1018 set_wall_state();
1019 /* for many room types, rooms[].rtype is zeroed once the room has been
1020 entered; rooms[].orig_rtype always retains original rtype value */
1021 for (ridx = 0; ridx < SIZE(rooms); ridx++)
1022 rooms[ridx].orig_rtype = rooms[ridx].rtype;
1023
1024 /* something like this usually belongs in clear_level_structures()
1025 but these aren't saved and restored so might not retain their
1026 values for the life of the current level; reset them to default
1027 now so that they never do and no one will be tempted to introduce
1028 a new use of them for anything on this level */
1029 dnstairs_room = upstairs_room = sstairs_room = (struct mkroom *) 0;
1030
1031 reseed_random(rn2);
1032 reseed_random(rn2_on_display_rng);
1033 }
1034
1035 void
1036 #ifdef SPECIALIZATION
topologize(croom,do_ordinary)1037 topologize(croom, do_ordinary)
1038 struct mkroom *croom;
1039 boolean do_ordinary;
1040 #else
1041 topologize(croom)
1042 struct mkroom *croom;
1043 #endif
1044 {
1045 register int x, y, roomno = (int) ((croom - rooms) + ROOMOFFSET);
1046 int lowx = croom->lx, lowy = croom->ly;
1047 int hix = croom->hx, hiy = croom->hy;
1048 #ifdef SPECIALIZATION
1049 schar rtype = croom->rtype;
1050 #endif
1051 int subindex, nsubrooms = croom->nsubrooms;
1052
1053 /* skip the room if already done; i.e. a shop handled out of order */
1054 /* also skip if this is non-rectangular (it _must_ be done already) */
1055 if ((int) levl[lowx][lowy].roomno == roomno || croom->irregular)
1056 return;
1057 #ifdef SPECIALIZATION
1058 if (Is_rogue_level(&u.uz))
1059 do_ordinary = TRUE; /* vision routine helper */
1060 if ((rtype != OROOM) || do_ordinary)
1061 #endif
1062 {
1063 /* do innards first */
1064 for (x = lowx; x <= hix; x++)
1065 for (y = lowy; y <= hiy; y++)
1066 #ifdef SPECIALIZATION
1067 if (rtype == OROOM)
1068 levl[x][y].roomno = NO_ROOM;
1069 else
1070 #endif
1071 levl[x][y].roomno = roomno;
1072 /* top and bottom edges */
1073 for (x = lowx - 1; x <= hix + 1; x++)
1074 for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
1075 levl[x][y].edge = 1;
1076 if (levl[x][y].roomno)
1077 levl[x][y].roomno = SHARED;
1078 else
1079 levl[x][y].roomno = roomno;
1080 }
1081 /* sides */
1082 for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
1083 for (y = lowy; y <= hiy; y++) {
1084 levl[x][y].edge = 1;
1085 if (levl[x][y].roomno)
1086 levl[x][y].roomno = SHARED;
1087 else
1088 levl[x][y].roomno = roomno;
1089 }
1090 }
1091 /* subrooms */
1092 for (subindex = 0; subindex < nsubrooms; subindex++)
1093 #ifdef SPECIALIZATION
1094 topologize(croom->sbrooms[subindex], (boolean) (rtype != OROOM));
1095 #else
1096 topologize(croom->sbrooms[subindex]);
1097 #endif
1098 }
1099
1100 /* Find an unused room for a branch location. */
1101 STATIC_OVL struct mkroom *
find_branch_room(mp)1102 find_branch_room(mp)
1103 coord *mp;
1104 {
1105 struct mkroom *croom = 0;
1106
1107 if (nroom == 0) {
1108 mazexy(mp); /* already verifies location */
1109 } else {
1110 /* not perfect - there may be only one stairway */
1111 if (nroom > 2) {
1112 int tryct = 0;
1113
1114 do
1115 croom = &rooms[rn2(nroom)];
1116 while ((croom == dnstairs_room || croom == upstairs_room
1117 || croom->rtype != OROOM) && (++tryct < 100));
1118 } else
1119 croom = &rooms[rn2(nroom)];
1120
1121 do {
1122 if (!somexy(croom, mp))
1123 impossible("Can't place branch!");
1124 } while (occupied(mp->x, mp->y)
1125 || (levl[mp->x][mp->y].typ != CORR
1126 && levl[mp->x][mp->y].typ != ROOM));
1127 }
1128 return croom;
1129 }
1130
1131 /* Find the room for (x,y). Return null if not in a room. */
1132 STATIC_OVL struct mkroom *
pos_to_room(x,y)1133 pos_to_room(x, y)
1134 xchar x, y;
1135 {
1136 int i;
1137 struct mkroom *curr;
1138
1139 for (curr = rooms, i = 0; i < nroom; curr++, i++)
1140 if (inside_room(curr, x, y))
1141 return curr;
1142 ;
1143 return (struct mkroom *) 0;
1144 }
1145
1146 /* If given a branch, randomly place a special stair or portal. */
1147 void
place_branch(br,x,y)1148 place_branch(br, x, y)
1149 branch *br; /* branch to place */
1150 xchar x, y; /* location */
1151 {
1152 coord m;
1153 d_level *dest;
1154 boolean make_stairs;
1155 struct mkroom *br_room;
1156
1157 /*
1158 * Return immediately if there is no branch to make or we have
1159 * already made one. This routine can be called twice when
1160 * a special level is loaded that specifies an SSTAIR location
1161 * as a favored spot for a branch.
1162 */
1163 if (!br || made_branch)
1164 return;
1165
1166 if (!x) { /* find random coordinates for branch */
1167 br_room = find_branch_room(&m);
1168 x = m.x;
1169 y = m.y;
1170 } else {
1171 br_room = pos_to_room(x, y);
1172 }
1173
1174 if (on_level(&br->end1, &u.uz)) {
1175 /* we're on end1 */
1176 make_stairs = br->type != BR_NO_END1;
1177 dest = &br->end2;
1178 } else {
1179 /* we're on end2 */
1180 make_stairs = br->type != BR_NO_END2;
1181 dest = &br->end1;
1182 }
1183
1184 if (br->type == BR_PORTAL) {
1185 mkportal(x, y, dest->dnum, dest->dlevel);
1186 } else if (make_stairs) {
1187 sstairs.sx = x;
1188 sstairs.sy = y;
1189 sstairs.up =
1190 (char) on_level(&br->end1, &u.uz) ? br->end1_up : !br->end1_up;
1191 assign_level(&sstairs.tolev, dest);
1192 sstairs_room = br_room;
1193
1194 levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
1195 levl[x][y].typ = STAIRS;
1196 }
1197 /*
1198 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
1199 * make_stairs is false) since there is currently only one branch
1200 * per level, if we failed once, we're going to fail again on the
1201 * next call.
1202 */
1203 made_branch = TRUE;
1204 }
1205
1206 STATIC_OVL boolean
bydoor(x,y)1207 bydoor(x, y)
1208 register xchar x, y;
1209 {
1210 register int typ;
1211
1212 if (isok(x + 1, y)) {
1213 typ = levl[x + 1][y].typ;
1214 if (IS_DOOR(typ) || typ == SDOOR)
1215 return TRUE;
1216 }
1217 if (isok(x - 1, y)) {
1218 typ = levl[x - 1][y].typ;
1219 if (IS_DOOR(typ) || typ == SDOOR)
1220 return TRUE;
1221 }
1222 if (isok(x, y + 1)) {
1223 typ = levl[x][y + 1].typ;
1224 if (IS_DOOR(typ) || typ == SDOOR)
1225 return TRUE;
1226 }
1227 if (isok(x, y - 1)) {
1228 typ = levl[x][y - 1].typ;
1229 if (IS_DOOR(typ) || typ == SDOOR)
1230 return TRUE;
1231 }
1232 return FALSE;
1233 }
1234
1235 /* see whether it is allowable to create a door at [x,y] */
1236 int
okdoor(x,y)1237 okdoor(x, y)
1238 xchar x, y;
1239 {
1240 boolean near_door = bydoor(x, y);
1241
1242 return ((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL)
1243 && doorindex < DOORMAX && !near_door);
1244 }
1245
1246 void
dodoor(x,y,aroom)1247 dodoor(x, y, aroom)
1248 int x, y;
1249 struct mkroom *aroom;
1250 {
1251 if (doorindex >= DOORMAX) {
1252 impossible("DOORMAX exceeded?");
1253 return;
1254 }
1255
1256 dosdoor(x, y, aroom, rn2(8) ? DOOR : SDOOR);
1257 }
1258
1259 boolean
occupied(x,y)1260 occupied(x, y)
1261 register xchar x, y;
1262 {
1263 return (boolean) (t_at(x, y) || IS_FURNITURE(levl[x][y].typ)
1264 || is_lava(x, y) || is_pool(x, y)
1265 || invocation_pos(x, y));
1266 }
1267
1268 /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
1269 /* if tm != null, make trap at that location */
1270 void
mktrap(num,mazeflag,croom,tm)1271 mktrap(num, mazeflag, croom, tm)
1272 int num, mazeflag;
1273 struct mkroom *croom;
1274 coord *tm;
1275 {
1276 register int kind;
1277 struct trap *t;
1278 unsigned lvl = level_difficulty();
1279 coord m;
1280
1281 /* no traps in pools */
1282 if (tm && is_pool(tm->x, tm->y))
1283 return;
1284
1285 if (num > 0 && num < TRAPNUM) {
1286 kind = num;
1287 } else if (Is_rogue_level(&u.uz)) {
1288 switch (rn2(7)) {
1289 default:
1290 kind = BEAR_TRAP;
1291 break; /* 0 */
1292 case 1:
1293 kind = ARROW_TRAP;
1294 break;
1295 case 2:
1296 kind = DART_TRAP;
1297 break;
1298 case 3:
1299 kind = TRAPDOOR;
1300 break;
1301 case 4:
1302 kind = PIT;
1303 break;
1304 case 5:
1305 kind = SLP_GAS_TRAP;
1306 break;
1307 case 6:
1308 kind = RUST_TRAP;
1309 break;
1310 }
1311 } else if (Inhell && !rn2(5)) {
1312 /* bias the frequency of fire traps in Gehennom */
1313 kind = FIRE_TRAP;
1314 } else {
1315 do {
1316 kind = rnd(TRAPNUM - 1);
1317 /* reject "too hard" traps */
1318 switch (kind) {
1319 case MAGIC_PORTAL:
1320 case VIBRATING_SQUARE:
1321 kind = NO_TRAP;
1322 break;
1323 case ROLLING_BOULDER_TRAP:
1324 case SLP_GAS_TRAP:
1325 if (lvl < 2)
1326 kind = NO_TRAP;
1327 break;
1328 case LEVEL_TELEP:
1329 if (lvl < 5 || level.flags.noteleport)
1330 kind = NO_TRAP;
1331 break;
1332 case SPIKED_PIT:
1333 if (lvl < 5)
1334 kind = NO_TRAP;
1335 break;
1336 case LANDMINE:
1337 if (lvl < 6)
1338 kind = NO_TRAP;
1339 break;
1340 case WEB:
1341 if (lvl < 7)
1342 kind = NO_TRAP;
1343 break;
1344 case STATUE_TRAP:
1345 case POLY_TRAP:
1346 if (lvl < 8)
1347 kind = NO_TRAP;
1348 break;
1349 case FIRE_TRAP:
1350 if (!Inhell)
1351 kind = NO_TRAP;
1352 break;
1353 case TELEP_TRAP:
1354 if (level.flags.noteleport)
1355 kind = NO_TRAP;
1356 break;
1357 case HOLE:
1358 /* make these much less often than other traps */
1359 if (rn2(7))
1360 kind = NO_TRAP;
1361 break;
1362 }
1363 } while (kind == NO_TRAP);
1364 }
1365
1366 if (is_hole(kind) && !Can_fall_thru(&u.uz))
1367 kind = ROCKTRAP;
1368
1369 if (tm) {
1370 m = *tm;
1371 } else {
1372 register int tryct = 0;
1373 boolean avoid_boulder = (is_pit(kind) || is_hole(kind));
1374
1375 do {
1376 if (++tryct > 200)
1377 return;
1378 if (mazeflag)
1379 mazexy(&m);
1380 else if (!somexy(croom, &m))
1381 return;
1382 } while (occupied(m.x, m.y)
1383 || (avoid_boulder && sobj_at(BOULDER, m.x, m.y)));
1384 }
1385
1386 t = maketrap(m.x, m.y, kind);
1387 /* we should always get type of trap we're asking for (occupied() test
1388 should prevent cases where that might not happen) but be paranoid */
1389 kind = t ? t->ttyp : NO_TRAP;
1390
1391 if (kind == WEB)
1392 (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
1393
1394 /* The hero isn't the only person who's entered the dungeon in
1395 search of treasure. On the very shallowest levels, there's a
1396 chance that a created trap will have killed something already
1397 (and this is guaranteed on the first level).
1398
1399 This isn't meant to give any meaningful treasure (in fact, any
1400 items we drop here are typically cursed, other than ammo fired
1401 by the trap). Rather, it's mostly just for flavour and to give
1402 players on very early levels a sufficient chance to avoid traps
1403 that may end up killing them before they have a fair chance to
1404 build max HP. Including cursed items gives the same fair chance
1405 to the starting pet, and fits the rule that possessions of the
1406 dead are normally cursed.
1407
1408 Some types of traps are excluded because they're entirely
1409 nonlethal, even indirectly. We also exclude all of the
1410 later/fancier traps because they tend to have special
1411 considerations (e.g. webs, portals), often are indirectly
1412 lethal, and tend not to generate on shallower levels anyway.
1413 Finally, pits are excluded because it's weird to see an item
1414 in a pit and yet not be able to identify that the pit is there. */
1415 if (kind != NO_TRAP && lvl <= (unsigned) rnd(4)
1416 && kind != SQKY_BOARD && kind != RUST_TRAP
1417 /* rolling boulder trap might not have a boulder if there was no
1418 viable path (such as when placed in the corner of a room), in
1419 which case tx,ty==launch.x,y; no boulder => no dead predecessor */
1420 && !(kind == ROLLING_BOULDER_TRAP
1421 && t->launch.x == t->tx && t->launch.y == t->ty)
1422 && !is_pit(kind) && kind < HOLE) {
1423 /* Object generated by the trap; initially NULL, stays NULL if
1424 we fail to generate an object or if the trap doesn't
1425 generate objects. */
1426 struct obj *otmp = NULL;
1427 int victim_mnum; /* race of the victim */
1428
1429 /* Not all trap types have special handling here; only the ones
1430 that kill in a specific way that's obvious after the fact. */
1431 switch (kind) {
1432 case ARROW_TRAP:
1433 otmp = mksobj(ARROW, TRUE, FALSE);
1434 otmp->opoisoned = 0;
1435 /* don't adjust the quantity; maybe the trap shot multiple
1436 times, there was an untrapping attempt, etc... */
1437 break;
1438 case DART_TRAP:
1439 otmp = mksobj(DART, TRUE, FALSE);
1440 break;
1441 case ROCKTRAP:
1442 otmp = mksobj(ROCK, TRUE, FALSE);
1443 break;
1444 default:
1445 /* no item dropped by the trap */
1446 break;
1447 }
1448 if (otmp) {
1449 place_object(otmp, m.x, m.y);
1450 }
1451
1452 /* now otmp is reused for other items we're placing */
1453
1454 /* Place a random possession. This could be a weapon, tool,
1455 food, or gem, i.e. the item classes that are typically
1456 nonmagical and not worthless. */
1457 do {
1458 int poss_class = RANDOM_CLASS; /* init => lint suppression */
1459
1460 switch (rn2(4)) {
1461 case 0:
1462 poss_class = WEAPON_CLASS;
1463 break;
1464 case 1:
1465 poss_class = TOOL_CLASS;
1466 break;
1467 case 2:
1468 poss_class = FOOD_CLASS;
1469 break;
1470 case 3:
1471 poss_class = GEM_CLASS;
1472 break;
1473 }
1474
1475 otmp = mkobj(poss_class, FALSE);
1476 /* these items are always cursed, both for flavour (owned
1477 by a dead adventurer, bones-pile-style) and for balance
1478 (less useful to use, and encourage pets to avoid the trap) */
1479 if (otmp) {
1480 otmp->blessed = 0;
1481 otmp->cursed = 1;
1482 otmp->owt = weight(otmp);
1483 place_object(otmp, m.x, m.y);
1484 }
1485
1486 /* 20% chance of placing an additional item, recursively */
1487 } while (!rn2(5));
1488
1489 /* Place a corpse. */
1490 switch (rn2(15)) {
1491 case 0:
1492 /* elf corpses are the rarest as they're the most useful */
1493 victim_mnum = PM_ELF;
1494 /* elven adventurers get sleep resistance early; so don't
1495 generate elf corpses on sleeping gas traps unless a)
1496 we're on dlvl 2 (1 is impossible) and b) we pass a coin
1497 flip */
1498 if (kind == SLP_GAS_TRAP && !(lvl <= 2 && rn2(2)))
1499 victim_mnum = PM_HUMAN;
1500 break;
1501 case 1: case 2:
1502 victim_mnum = PM_DWARF;
1503 break;
1504 case 3: case 4: case 5:
1505 victim_mnum = PM_ORC;
1506 break;
1507 case 6: case 7: case 8: case 9:
1508 /* more common as they could have come from the Mines */
1509 victim_mnum = PM_GNOME;
1510 /* 10% chance of a candle too */
1511 if (!rn2(10)) {
1512 otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
1513 TRUE, FALSE);
1514 otmp->quan = 1;
1515 otmp->blessed = 0;
1516 otmp->cursed = 1;
1517 otmp->owt = weight(otmp);
1518 place_object(otmp, m.x, m.y);
1519 }
1520 break;
1521 default:
1522 /* the most common race */
1523 victim_mnum = PM_HUMAN;
1524 break;
1525 }
1526 otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
1527 CORPSTAT_INIT);
1528 if (otmp)
1529 otmp->age -= 51; /* died too long ago to eat */
1530 }
1531 }
1532
1533 void
mkstairs(x,y,up,croom)1534 mkstairs(x, y, up, croom)
1535 xchar x, y;
1536 char up;
1537 struct mkroom *croom;
1538 {
1539 if (!x) {
1540 impossible("mkstairs: bogus stair attempt at <%d,%d>", x, y);
1541 return;
1542 }
1543
1544 /*
1545 * We can't make a regular stair off an end of the dungeon. This
1546 * attempt can happen when a special level is placed at an end and
1547 * has an up or down stair specified in its description file.
1548 */
1549 if ((dunlev(&u.uz) == 1 && up)
1550 || (dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
1551 return;
1552
1553 if (up) {
1554 xupstair = x;
1555 yupstair = y;
1556 upstairs_room = croom;
1557 } else {
1558 xdnstair = x;
1559 ydnstair = y;
1560 dnstairs_room = croom;
1561 }
1562
1563 levl[x][y].typ = STAIRS;
1564 levl[x][y].ladder = up ? LA_UP : LA_DOWN;
1565 }
1566
1567 STATIC_OVL void
mkfount(mazeflag,croom)1568 mkfount(mazeflag, croom)
1569 int mazeflag;
1570 struct mkroom *croom;
1571 {
1572 coord m;
1573 register int tryct = 0;
1574
1575 do {
1576 if (++tryct > 200)
1577 return;
1578 if (mazeflag)
1579 mazexy(&m);
1580 else if (!somexy(croom, &m))
1581 return;
1582 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1583
1584 /* Put a fountain at m.x, m.y */
1585 levl[m.x][m.y].typ = FOUNTAIN;
1586 /* Is it a "blessed" fountain? (affects drinking from fountain) */
1587 if (!rn2(7))
1588 levl[m.x][m.y].blessedftn = 1;
1589
1590 level.flags.nfountains++;
1591 }
1592
1593 STATIC_OVL void
mksink(croom)1594 mksink(croom)
1595 struct mkroom *croom;
1596 {
1597 coord m;
1598 register int tryct = 0;
1599
1600 do {
1601 if (++tryct > 200)
1602 return;
1603 if (!somexy(croom, &m))
1604 return;
1605 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1606
1607 /* Put a sink at m.x, m.y */
1608 levl[m.x][m.y].typ = SINK;
1609
1610 level.flags.nsinks++;
1611 }
1612
1613 STATIC_OVL void
mkaltar(croom)1614 mkaltar(croom)
1615 struct mkroom *croom;
1616 {
1617 coord m;
1618 register int tryct = 0;
1619 aligntyp al;
1620
1621 if (croom->rtype != OROOM)
1622 return;
1623
1624 do {
1625 if (++tryct > 200)
1626 return;
1627 if (!somexy(croom, &m))
1628 return;
1629 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1630
1631 /* Put an altar at m.x, m.y */
1632 levl[m.x][m.y].typ = ALTAR;
1633
1634 /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
1635 al = rn2((int) A_LAWFUL + 2) - 1;
1636 levl[m.x][m.y].altarmask = Align2amask(al);
1637 }
1638
1639 static void
mkgrave(croom)1640 mkgrave(croom)
1641 struct mkroom *croom;
1642 {
1643 coord m;
1644 register int tryct = 0;
1645 register struct obj *otmp;
1646 boolean dobell = !rn2(10);
1647
1648 if (croom->rtype != OROOM)
1649 return;
1650
1651 do {
1652 if (++tryct > 200)
1653 return;
1654 if (!somexy(croom, &m))
1655 return;
1656 } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1657
1658 /* Put a grave at <m.x,m.y> */
1659 make_grave(m.x, m.y, dobell ? "Saved by the bell!" : (char *) 0);
1660
1661 /* Possibly fill it with objects */
1662 if (!rn2(3)) {
1663 /* this used to use mkgold(), which puts a stack of gold on
1664 the ground (or merges it with an existing one there if
1665 present), and didn't bother burying it; now we create a
1666 loose, easily buriable, stack but we make no attempt to
1667 replicate mkgold()'s level-based formula for the amount */
1668 struct obj *gold = mksobj(GOLD_PIECE, TRUE, FALSE);
1669
1670 gold->quan = (long) (rnd(20) + level_difficulty() * rnd(5));
1671 gold->owt = weight(gold);
1672 gold->ox = m.x, gold->oy = m.y;
1673 add_to_buried(gold);
1674 }
1675 for (tryct = rn2(5); tryct; tryct--) {
1676 otmp = mkobj(RANDOM_CLASS, TRUE);
1677 if (!otmp)
1678 return;
1679 curse(otmp);
1680 otmp->ox = m.x;
1681 otmp->oy = m.y;
1682 add_to_buried(otmp);
1683 }
1684
1685 /* Leave a bell, in case we accidentally buried someone alive */
1686 if (dobell)
1687 (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE);
1688 return;
1689 }
1690
1691 /* maze levels have slightly different constraints from normal levels */
1692 #define x_maze_min 2
1693 #define y_maze_min 2
1694
1695 /*
1696 * Major level transmutation: add a set of stairs (to the Sanctum) after
1697 * an earthquake that leaves behind a new topology, centered at inv_pos.
1698 * Assumes there are no rooms within the invocation area and that inv_pos
1699 * is not too close to the edge of the map. Also assume the hero can see,
1700 * which is guaranteed for normal play due to the fact that sight is needed
1701 * to read the Book of the Dead. [That assumption is not valid; it is
1702 * possible that "the Book reads the hero" rather than vice versa if
1703 * attempted while blind (in order to make blind-from-birth conduct viable).]
1704 */
1705 void
mkinvokearea()1706 mkinvokearea()
1707 {
1708 int dist;
1709 xchar xmin = inv_pos.x, xmax = inv_pos.x,
1710 ymin = inv_pos.y, ymax = inv_pos.y;
1711 register xchar i;
1712
1713 /* slightly odd if levitating, but not wrong */
1714 pline_The("floor shakes violently under you!");
1715 /*
1716 * TODO:
1717 * Suppress this message if player has dug out all the walls
1718 * that would otherwise be affected.
1719 */
1720 pline_The("walls around you begin to bend and crumble!");
1721 display_nhwindow(WIN_MESSAGE, TRUE);
1722
1723 /* any trap hero is stuck in will be going away now */
1724 if (u.utrap) {
1725 if (u.utraptype == TT_BURIEDBALL)
1726 buried_ball_to_punishment();
1727 reset_utrap(FALSE);
1728 }
1729 mkinvpos(xmin, ymin, 0); /* middle, before placing stairs */
1730
1731 for (dist = 1; dist < 7; dist++) {
1732 xmin--;
1733 xmax++;
1734
1735 /* top and bottom */
1736 if (dist != 3) { /* the area is wider that it is high */
1737 ymin--;
1738 ymax++;
1739 for (i = xmin + 1; i < xmax; i++) {
1740 mkinvpos(i, ymin, dist);
1741 mkinvpos(i, ymax, dist);
1742 }
1743 }
1744
1745 /* left and right */
1746 for (i = ymin; i <= ymax; i++) {
1747 mkinvpos(xmin, i, dist);
1748 mkinvpos(xmax, i, dist);
1749 }
1750
1751 flush_screen(1); /* make sure the new glyphs shows up */
1752 delay_output();
1753 }
1754
1755 You("are standing at the top of a stairwell leading down!");
1756 mkstairs(u.ux, u.uy, 0, (struct mkroom *) 0); /* down */
1757 newsym(u.ux, u.uy);
1758 vision_full_recalc = 1; /* everything changed */
1759 }
1760
1761 /* Change level topology. Boulders in the vicinity are eliminated.
1762 * Temporarily overrides vision in the name of a nice effect.
1763 */
1764 STATIC_OVL void
mkinvpos(x,y,dist)1765 mkinvpos(x, y, dist)
1766 xchar x, y;
1767 int dist;
1768 {
1769 struct trap *ttmp;
1770 struct obj *otmp;
1771 boolean make_rocks;
1772 register struct rm *lev = &levl[x][y];
1773 struct monst *mon;
1774
1775 /* clip at existing map borders if necessary */
1776 if (!within_bounded_area(x, y, x_maze_min + 1, y_maze_min + 1,
1777 x_maze_max - 1, y_maze_max - 1)) {
1778 /* outermost 2 columns and/or rows may be truncated due to edge */
1779 if (dist < (7 - 2))
1780 panic("mkinvpos: <%d,%d> (%d) off map edge!", x, y, dist);
1781 return;
1782 }
1783
1784 /* clear traps */
1785 if ((ttmp = t_at(x, y)) != 0)
1786 deltrap(ttmp);
1787
1788 /* clear boulders; leave some rocks for non-{moat|trap} locations */
1789 make_rocks = (dist != 1 && dist != 4 && dist != 5) ? TRUE : FALSE;
1790 while ((otmp = sobj_at(BOULDER, x, y)) != 0) {
1791 if (make_rocks) {
1792 fracture_rock(otmp);
1793 make_rocks = FALSE; /* don't bother with more rocks */
1794 } else {
1795 obj_extract_self(otmp);
1796 obfree(otmp, (struct obj *) 0);
1797 }
1798 }
1799
1800 /* fake out saved state */
1801 lev->seenv = 0;
1802 lev->doormask = 0;
1803 if (dist < 6)
1804 lev->lit = TRUE;
1805 lev->waslit = TRUE;
1806 lev->horizontal = FALSE;
1807 /* short-circuit vision recalc */
1808 viz_array[y][x] = (dist < 6) ? (IN_SIGHT | COULD_SEE) : COULD_SEE;
1809
1810 switch (dist) {
1811 case 1: /* fire traps */
1812 if (is_pool(x, y))
1813 break;
1814 lev->typ = ROOM;
1815 ttmp = maketrap(x, y, FIRE_TRAP);
1816 if (ttmp)
1817 ttmp->tseen = TRUE;
1818 break;
1819 case 0: /* lit room locations */
1820 case 2:
1821 case 3:
1822 case 6: /* unlit room locations */
1823 lev->typ = ROOM;
1824 break;
1825 case 4: /* pools (aka a wide moat) */
1826 case 5:
1827 lev->typ = MOAT;
1828 /* No kelp! */
1829 break;
1830 default:
1831 impossible("mkinvpos called with dist %d", dist);
1832 break;
1833 }
1834
1835 if ((mon = m_at(x, y)) != 0) {
1836 /* wake up mimics, don't want to deal with them blocking vision */
1837 if (mon->m_ap_type)
1838 seemimic(mon);
1839
1840 if ((ttmp = t_at(x, y)) != 0)
1841 (void) mintrap(mon);
1842 else
1843 (void) minliquid(mon);
1844 }
1845
1846 if (!does_block(x, y, lev))
1847 unblock_point(x, y); /* make sure vision knows this location is open */
1848
1849 /* display new value of position; could have a monster/object on it */
1850 newsym(x, y);
1851 }
1852
1853 /*
1854 * The portal to Ludios is special. The entrance can only occur within a
1855 * vault in the main dungeon at a depth greater than 10. The Ludios branch
1856 * structure reflects this by having a bogus "source" dungeon: the value
1857 * of n_dgns (thus, Is_branchlev() will never find it).
1858 *
1859 * Ludios will remain isolated until the branch is corrected by this function.
1860 */
1861 STATIC_OVL void
mk_knox_portal(x,y)1862 mk_knox_portal(x, y)
1863 xchar x, y;
1864 {
1865 extern int n_dgns; /* from dungeon.c */
1866 d_level *source;
1867 branch *br;
1868 schar u_depth;
1869
1870 br = dungeon_branch("Fort Ludios");
1871 if (on_level(&knox_level, &br->end1)) {
1872 source = &br->end2;
1873 } else {
1874 /* disallow Knox branch on a level with one branch already */
1875 if (Is_branchlev(&u.uz))
1876 return;
1877 source = &br->end1;
1878 }
1879
1880 /* Already set or 2/3 chance of deferring until a later level. */
1881 if (source->dnum < n_dgns || (rn2(3) && !wizard))
1882 return;
1883
1884 if (!(u.uz.dnum == oracle_level.dnum /* in main dungeon */
1885 && !at_dgn_entrance("The Quest") /* but not Quest's entry */
1886 && (u_depth = depth(&u.uz)) > 10 /* beneath 10 */
1887 && u_depth < depth(&medusa_level))) /* and above Medusa */
1888 return;
1889
1890 /* Adjust source to be current level and re-insert branch. */
1891 *source = u.uz;
1892 insert_branch(br, TRUE);
1893
1894 debugpline0("Made knox portal.");
1895 place_branch(br, x, y);
1896 }
1897
1898 /*mklev.c*/
1899