OSDN Git Service

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