OSDN Git Service

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