OSDN Git Service

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