OSDN Git Service

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