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