This is mklev.c in view mode; [Download] [Up]
/* SCCS Id: @(#)mklev.c 3.0 89/12/06 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */ /* croom->lx etc are schar (width <= int), so % arith ensures that */ /* conversion of result to int is reasonable */ #ifdef SINKS static void FDECL(mksink,(struct mkroom *)); #endif #ifdef ALTARS static void FDECL(mkaltar,(struct mkroom *)); #endif static boolean FDECL(occupied,(XCHAR_P,XCHAR_P)); static void NDECL(makevtele); static void NDECL(init_levels); static void NDECL(makelevel); static boolean FDECL(bydoor,(XCHAR_P,XCHAR_P)); static boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*)); static void FDECL(makeniche,(int)); static void NDECL(make_niches); static void NDECL(makebigroom); static void FDECL(addrsx,(int,int,int,int,BOOLEAN_P)); static void FDECL(addrs,(int,int,int,int)); static int FDECL(comp,(genericptr_t,genericptr_t)); static void FDECL(dosdoor,(int,int,struct mkroom *,int)); static void NDECL(makecorridors); static void FDECL(join,(int,int)); static int NDECL(makerooms); static int FDECL(maker,(SCHAR_P,SCHAR_P,SCHAR_P,SCHAR_P,BOOLEAN_P)); static void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P)); int somex(croom) register struct mkroom *croom; { return rn2(croom->hx-croom->lx+1) + croom->lx; } int somey(croom) register struct mkroom *croom; { return rn2(croom->hy-croom->ly+1) + croom->ly; } #define XLIM 4 /* define minimum required space around a room */ #define YLIM 3 boolean secret; /* TRUE while making a vault: increase [XY]LIM */ struct rm zerorm; schar nxcor; boolean goldseen; /* Definitions used by makerooms() and addrs() */ #define MAXRS 50 /* max lth of temp rectangle table - arbitrary */ struct rectangle { xchar rlx,rly,rhx,rhy; } rs[MAXRS+1]; int rscnt,rsmax; /* 0..rscnt-1: currently under consideration */ /* rscnt..rsmax: discarded */ static void addrsx(lx,ly,hx,hy,discarded) register int lx,ly,hx,hy; boolean discarded; /* piece of a discarded area */ { register struct rectangle *rsp; /* check inclusions */ for(rsp = rs; rsp < &rs[rsmax]; rsp++) { if(lx >= rsp->rlx && hx <= rsp->rhx && ly >= rsp->rly && hy <= rsp->rhy) return; } /* make a new entry */ if(rsmax >= MAXRS) { #ifdef WIZARD if(wizard) pline("MAXRS may be too small."); #endif return; } rsmax++; if(!discarded) { *rsp = rs[rscnt]; rsp = &rs[rscnt]; rscnt++; } rsp->rlx = lx; rsp->rly = ly; rsp->rhx = hx; rsp->rhy = hy; } static void addrs(lowx,lowy,hix,hiy) register int lowx,lowy,hix,hiy; { register struct rectangle *rsp; register int lx,ly,hx,hy,xlim,ylim; boolean discarded; xlim = XLIM + secret; ylim = YLIM + secret; /* walk down since rscnt and rsmax change */ for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) { if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy || (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy) continue; if((discarded = (rsp >= &rs[rscnt]))) { *rsp = rs[--rsmax]; } else { rsmax--; rscnt--; *rsp = rs[rscnt]; if(rscnt != rsmax) rs[rscnt] = rs[rsmax]; } if(lowy - ly > 2*ylim + 4) addrsx(lx,ly,hx,lowy-2,discarded); if(lowx - lx > 2*xlim + 4) addrsx(lx,ly,lowx-2,hy,discarded); if(hy - hiy > 2*ylim + 4) addrsx(lx,hiy+2,hx,hy,discarded); if(hx - hix > 2*xlim + 4) addrsx(hix+2,ly,hx,hy,discarded); } } /* Args must be genericptr_t so that qsort will always be happy. */ static int comp(vx,vy) genericptr_t vx, vy; { #ifdef LINT /* lint complains about possible pointer alignment problems, but we know that vx and vy are always properly aligned. Hence, the following bogus definition: */ return (vx == vy) ? 0 : -1; #else register struct mkroom *x, *y; x = (struct mkroom *)vx; y = (struct mkroom *)vy; if(x->lx < y->lx) return(-1); return(x->lx > y->lx); #endif /* LINT */ } static void finddpos(cc, xl,yl,xh,yh) coord *cc; xchar xl,yl,xh,yh; { register xchar x, y; x = (xl == xh) ? xl : (xl + rn2(xh-xl+1)); y = (yl == yh) ? yl : (yl + rn2(yh-yl+1)); if(okdoor(x, y)) goto gotit; for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) if(okdoor(x, y)) goto gotit; for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR) goto gotit; /* cannot find something reasonable -- strange */ x = xl; y = yh; gotit: cc->x = x; cc->y = y; return; } /* Only called from makerooms() and makebigroom() */ static int maker(lowx,ddx,lowy,ddy,lit) schar lowx,ddx,lowy,ddy; boolean lit; { register struct mkroom *croom; register int x, y, hix = lowx+ddx, hiy = lowy+ddy; register int xlim = XLIM + secret, ylim = YLIM + secret; if(nroom >= MAXNROFROOMS) return(0); if(lowx < XLIM) lowx = XLIM; if(lowy < YLIM) lowy = YLIM; if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1; if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1; chk: if(hix <= lowx || hiy <= lowy) return(0); /* check area around room (and make room smaller if necessary) */ for(x = lowx - xlim; x <= hix + xlim; x++) { for(y = lowy - ylim; y <= hiy + ylim; y++) { if(levl[x][y].typ) { #ifdef WIZARD if(wizard && !secret) pline("Strange area [%d,%d] in maker().",x,y); #endif if(!rn2(3)) return(0); if(x < lowx) lowx = x+xlim+1; else hix = x-xlim-1; if(y < lowy) lowy = y+ylim+1; else hiy = y-ylim-1; goto chk; } } } croom = &rooms[nroom]; /* on low levels the room is lit (usually) */ /* secret vaults are always lit */ /* some other rooms may require lighting */ if((rnd(dlevel) < 10 && rn2(77)) || secret || lit) { for(x = lowx-1; x <= hix+1; x++) for(y = lowy-1; y <= hiy+1; y++) levl[x][y].lit = 1; croom->rlit = 1; } else croom->rlit = 0; croom->lx = lowx; croom->hx = hix; croom->ly = lowy; croom->hy = hiy; croom->rtype = OROOM; croom->doorct = 0; /* if we're not making a vault, doorindex will still be 0 * if we are, we'll have problems adding niches to the previous room * unless fdoor is at least doorindex */ croom->fdoor = doorindex; for(x = lowx-1; x <= hix+1; x++) for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { levl[x][y].typ = HWALL; levl[x][y].scrsym = HWALL_SYM; } for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) for(y = lowy; y <= hiy; y++) { levl[x][y].typ = VWALL; levl[x][y].scrsym = VWALL_SYM; } for(x = lowx; x <= hix; x++) for(y = lowy; y <= hiy; y++) { levl[x][y].typ = ROOM; levl[x][y].scrsym = ROOM_SYM; } levl[lowx-1][lowy-1].typ = TLCORNER; levl[hix+1][lowy-1].typ = TRCORNER; levl[lowx-1][hiy+1].typ = BLCORNER; levl[hix+1][hiy+1].typ = BRCORNER; levl[lowx-1][lowy-1].scrsym = TLCORN_SYM; levl[hix+1][lowy-1].scrsym = TRCORN_SYM; levl[lowx-1][hiy+1].scrsym = BLCORN_SYM; levl[hix+1][hiy+1].scrsym = BRCORN_SYM; smeq[nroom] = nroom; croom++; croom->hx = -1; nroom++; return(1); } static int makerooms() { register struct rectangle *rsp; register int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy; int tryct = 0, xlim, ylim; /* init */ xlim = XLIM + secret; ylim = YLIM + secret; if(nroom == 0) { rsp = rs; rsp->rlx = rsp->rly = 0; rsp->rhx = COLNO-1; rsp->rhy = ROWNO-1; rsmax = 1; } rscnt = rsmax; /* make rooms until satisfied */ while(rscnt > 0 && nroom < MAXNROFROOMS-1) { if(!secret && nroom > (MAXNROFROOMS/4) && !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom))) return 0; /* pick a rectangle */ rsp = &rs[rn2(rscnt)]; hx = rsp->rhx; hy = rsp->rhy; lx = rsp->rlx; ly = rsp->rly; /* find size of room */ if(secret) dx = dy = 1; else { dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8); dy = 2 + rn2(4); if(dx*dy > 50) dy = 50/dx; } /* look whether our room will fit */ if(hx-lx < dx + (dx>>1) + 2*xlim || hy-ly < dy + dy/3 + 2*ylim) { /* no, too small */ /* maybe we throw this area out */ if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) { rscnt--; rs[rsmax] = *rsp; *rsp = rs[rscnt]; rs[rscnt] = rs[rsmax]; tryct = 0; } else tryct++; continue; } lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1); lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1); hix = lowx + dx; hiy = lowy + dy; if(maker(lowx, dx, lowy, dy, FALSE)) { if(secret) return(1); addrs(lowx-1, lowy-1, hix+1, hiy+1); tryct = 0; } else if(tryct++ > 100) break; } return(0); /* failed to make vault - very strange */ } static void join(a,b) register int a, b; { coord cc,tt; register int tx, ty, xx, yy; register struct rm *crm; register struct mkroom *croom, *troom; register int dx, dy, dix, diy, cct; croom = &rooms[a]; troom = &rooms[b]; /* find positions cc and tt for doors in croom and troom and direction for a corridor between them */ if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return; if(troom->lx > croom->hx) { dx = 1; dy = 0; xx = croom->hx+1; tx = troom->lx-1; finddpos(&cc, xx, croom->ly, xx, croom->hy); finddpos(&tt, tx, troom->ly, tx, troom->hy); } else if(troom->hy < croom->ly) { dy = -1; dx = 0; yy = croom->ly-1; finddpos(&cc, croom->lx, yy, croom->hx, yy); ty = troom->hy+1; finddpos(&tt, troom->lx, ty, troom->hx, ty); } else if(troom->hx < croom->lx) { dx = -1; dy = 0; xx = croom->lx-1; tx = troom->hx+1; finddpos(&cc, xx, croom->ly, xx, croom->hy); finddpos(&tt, tx, troom->ly, tx, troom->hy); } else { dy = 1; dx = 0; yy = croom->hy+1; ty = troom->ly-1; finddpos(&cc, croom->lx, yy, croom->hx, yy); finddpos(&tt, troom->lx, ty, troom->hx, ty); } xx = cc.x; yy = cc.y; tx = tt.x - dx; ty = tt.y - dy; if(nxcor && levl[xx+dx][yy+dy].typ) return; dodoor(xx,yy,croom); cct = 0; while(xx != tx || yy != ty) { xx += dx; yy += dy; /* loop: dig corridor at [xx,yy] and find new [xx,yy] */ if(cct++ > 500 || (nxcor && !rn2(35))) return; if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1) return; /* impossible */ crm = &levl[xx][yy]; if(!(crm->typ)) { if(rn2(100)) { crm->typ = CORR; crm->scrsym = CORR_SYM; if(nxcor && !rn2(50)) (void) mksobj_at(BOULDER, xx, yy); } else { crm->typ = SCORR; crm->scrsym = ' '; /* _not_ STONE_SYM */ } } else if(crm->typ != CORR && crm->typ != SCORR) { /* strange ... */ return; } /* find next corridor position */ dix = abs(xx-tx); diy = abs(yy-ty); /* do we have to change direction ? */ if(dy && dix > diy) { register int ddx = (xx > tx) ? -1 : 1; crm = &levl[xx+ddx][yy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { dx = ddx; dy = 0; continue; } } else if(dx && diy > dix) { register int ddy = (yy > ty) ? -1 : 1; crm = &levl[xx][yy+ddy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { dy = ddy; dx = 0; continue; } } /* continue straight on? */ crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; /* no, what must we do now?? */ if(dx) { dx = 0; dy = (ty < yy) ? -1 : 1; crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; dy = -dy; continue; } else { dy = 0; dx = (tx < xx) ? -1 : 1; crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; dx = -dx; continue; } } /* we succeeded in digging the corridor */ dodoor(tt.x, tt.y, troom); if(smeq[a] < smeq[b]) smeq[b] = smeq[a]; else smeq[a] = smeq[b]; } static void makecorridors() { register int a, b; nxcor = 0; for(a = 0; a < nroom-1; a++) join(a, a+1); for(a = 0; a < nroom-2; a++) if(smeq[a] != smeq[a+2]) join(a, a+2); for(a = 0; a < nroom; a++) for(b = 0; b < nroom; b++) if(smeq[a] != smeq[b]) join(a, b); if(nroom > 2) for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) { a = rn2(nroom); b = rn2(nroom-2); if(b >= a) b += 2; join(a, b); } } static void dosdoor(x,y,aroom,type) register int x, y; register struct mkroom *aroom; register int type; { register struct mkroom *broom; register int tmp; boolean shdoor = in_shop(x, y); if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with DOOR_SYM as scrsym */ type = DOOR; levl[x][y].typ = type; if(type == DOOR) { if(!rn2(3)) { /* is it a locked door, closed, or a doorway? */ if(!rn2(5)) levl[x][y].doormask = D_ISOPEN; else if(!rn2(6)) levl[x][y].doormask = D_LOCKED; else levl[x][y].doormask = D_CLOSED; if (levl[x][y].doormask != D_ISOPEN && !shdoor && !rn2(25)) levl[x][y].doormask |= D_TRAPPED; } else levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR); levl[x][y].scrsym = news0(x,y); } else { /* SDOOR */ if(shdoor || !rn2(5)) levl[x][y].doormask = D_LOCKED; else levl[x][y].doormask = D_CLOSED; if(!shdoor && !rn2(20)) levl[x][y].doormask |= D_TRAPPED; } aroom->doorct++; broom = aroom+1; if(broom->hx < 0) tmp = doorindex; else for(tmp = doorindex; tmp > broom->fdoor; tmp--) doors[tmp] = doors[tmp-1]; doorindex++; doors[tmp].x = x; doors[tmp].y = y; for( ; broom->hx >= 0; broom++) broom->fdoor++; } static boolean place_niche(aroom,dy,xx,yy) register struct mkroom *aroom; int *dy, *xx, *yy; { coord dd; if(rn2(2)) { *dy = 1; finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1); } else { *dy = -1; finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1); } *xx = dd.x; *yy = dd.y; return(levl[*xx][(*yy)+(*dy)].typ == STONE); } #ifdef ORACLE boolean place_oracle(aroom,dy,xx,yy) register struct mkroom *aroom; int *dy, *xx, *yy; { if(!place_niche(aroom,dy,xx,yy)) return FALSE; dosdoor(*xx,*yy,aroom,DOOR); levl[*xx][*yy].doormask = D_NODOOR; return TRUE; } #endif /* there should be one of these per trap */ const char *engravings[] = { "", "", "", "", "", "", "?la? ?as ?er?", "ad ae?ar um", "", "", "", "" ,"" , "", "ad ae?ar um" #ifdef SPELLS ,"" #endif ,"" #ifdef POLYSELF ,"" #endif ,"" }; static void makeniche(trap_type) int trap_type; { register struct mkroom *aroom; register struct rm *rm; register int vct = 8; int dy, xx, yy; register struct trap *ttmp; if(doorindex < DOORMAX) while(vct--) { aroom = &rooms[rn2(nroom)]; if(aroom->rtype != OROOM) continue; /* not an ordinary room */ if(aroom->doorct == 1 && rn2(5)) continue; if(!place_niche(aroom,&dy,&xx,&yy)) continue; rm = &levl[xx][yy+dy]; if(trap_type || !rn2(4)) { rm->typ = SCORR; rm->scrsym = ' '; /* _not_ STONE_SYM */ if(trap_type) { ttmp = maketrap(xx, yy+dy, trap_type); ttmp->once = 1; if (strlen(engravings[trap_type]) > 0) make_engr_at(xx, yy-dy, engravings[trap_type]); } dosdoor(xx, yy, aroom, SDOOR); } else { rm->typ = CORR; rm->scrsym = CORR_SYM; if(rn2(7)) dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); else { (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy); if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy); } } return; } } static void make_niches() { register int ct = rnd((nroom>>1) + 1); boolean ltptr = TRUE, vamp = TRUE; while(ct--) { if(dlevel > 15 && !rn2(6) && ltptr) { ltptr = FALSE; makeniche(LEVEL_TELEP); } else if (dlevel > 5 && dlevel < 25 && !rn2(6) && vamp) { vamp = FALSE; makeniche(TRAPDOOR); } else makeniche(NO_TRAP); } } static void makebigroom() { register int x,y,n; register struct mkroom *croom; register struct monst *tmonst; /* make biggest possible room; make sure it's lit */ (void) maker(XLIM, COLNO - 2*XLIM - 1, YLIM, ROWNO - 2*YLIM - 1, TRUE); croom = &rooms[0]; /* add extra monsters and goodies */ n = 10 + rn2(15); while (n--) { x = somex(croom); y = somey(croom); tmonst = makemon((struct permonst *) 0,x,y); if (tmonst && tmonst->data==&mons[PM_GIANT_SPIDER]) (void) maketrap(x,y,WEB); if (tmonst && rn2(2)) tmonst->msleep = 1; } n = 6 + rn2(10); while (n--) (void) mkobj_at(0,somex(croom),somey(croom)); } static void makevtele() { makeniche(TELEP_TRAP); } #define rntwixt(L1,L2) rn1((L2)-(L1),L1) static void init_levels() { #if defined(STRONGHOLD) && defined(MUSIC) register int x; #endif #ifdef LINT /* handle constant in conditional context */ medusa_level = 0; #else medusa_level = rn1(3, HELLLEVEL - 5); #endif /* LINT */ #ifdef STRONGHOLD stronghold_level = rn1(5, medusa_level)+1; # ifdef MUSIC for (x=0; x<5; x++) tune[x] = 'A' + rn2(7); tune[5] = 0; # endif /* The tower will be on 3 levels */ tower_level = rntwixt(stronghold_level, MAXLEVEL-2)+1; /* We don't want the wizard in Vlad's tower */ do wiz_level = rntwixt(stronghold_level, MAXLEVEL)+1; while (wiz_level >= tower_level && wiz_level <= tower_level + 2); #else wiz_level = rntwixt(medusa_level, MAXLEVEL)+1; #endif /* STRONGHOLD /**/ #ifdef WIZARD if (!rn2(15) || wizard) #else if (!rn2(15)) #endif /* between the middle of the dungeon and the medusa level */ bigroom_level = rntwixt(HELLLEVEL>>1, medusa_level); #ifdef REINCARNATION # ifdef WIZARD if (!rn2(3) || wizard) # else if (!rn2(3)) # endif rogue_level = rn1(5,10); #endif #ifdef ORACLE oracle_level = rn1(4,5); #endif } #undef rntwixt static void makelevel() { register struct mkroom *croom, *troom; register unsigned int tryct; register int x,y; struct monst *tmonst; /* always put a web with a spider */ nroom = 0; doorindex = 0; rooms[0].hx = -1; /* in case we are in a maze */ for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) { levl[x][y] = zerorm; level.objects[x][y] = (struct obj *)0; level.monsters[x][y] = (struct monst *)0; } oinit(); /* assign level dependent obj probabilities */ fountsound = 0; sinksound = 0; if (wiz_level == 0) init_levels(); if ( #ifndef STRONGHOLD Inhell #else dlevel >= stronghold_level || dlevel < 0 #endif || (dlevel > medusa_level && rn2(5)) ) { makemaz(); return; } /* construct the rooms */ nroom = 0; secret = FALSE; #ifdef REINCARNATION if (dlevel == rogue_level) { makeroguerooms(); makerogueghost(); } else #endif if (dlevel == bigroom_level) makebigroom(); else (void) makerooms(); /* construct stairs (up and down in different rooms if possible) */ croom = &rooms[rn2(nroom)]; xdnstair = somex(croom); ydnstair = somey(croom); levl[xdnstair][ydnstair].scrsym = DN_SYM; levl[xdnstair][ydnstair].typ = STAIRS; #ifdef MEDUSA if (dlevel == medusa_level) { struct monst *mtmp; struct obj *otmp; if (mtmp = makemon(&mons[PM_MEDUSA], xdnstair, ydnstair)) mtmp->msleep = 1; for (tryct = rn1(1,3); tryct; tryct--) { x = somex(croom); y = somey(croom); if (goodpos(x,y,(struct permonst *)0)) { otmp = mk_tt_object(STATUE, x, y); while(otmp && resists_ston(&mons[otmp->corpsenm])) { otmp->corpsenm = rndmonnum(); otmp->owt = weight(otmp); } } } } #endif if(nroom > 1) { troom = croom; croom = &rooms[rn2(nroom-1)]; if(croom >= troom) croom++; } do { xupstair = somex(croom); yupstair = somey(croom); } while(occupied(xupstair, yupstair)); levl[xupstair][yupstair].scrsym = UP_SYM; levl[xupstair][yupstair].typ = STAIRS; #ifdef STRONGHOLD xdnladder = ydnladder = xupladder = yupladder = 0; #endif is_maze_lev = FALSE; #if defined(SYSV) || defined(DGUX) qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), comp); #else qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), comp); #endif #ifdef REINCARNATION if (dlevel == rogue_level) { You("feel as though you were here in a previous lifetime."); goto skip0; } #endif makecorridors(); make_niches(); /* make a secret treasure vault, not connected to the rest */ if(nroom <= (MAXNROFROOMS/2)) if(rn2(3)) { troom = &rooms[nroom]; secret = TRUE; if(makerooms()) { troom->rtype = VAULT; /* treasure vault */ for(x = troom->lx; x <= troom->hx; x++) for(y = troom->ly; y <= troom->hy; y++) mkgold((long)(rnd(dlevel*100) + 50), x, y); if(!rn2(3)) makevtele(); } } #ifdef WIZARD if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else #endif #ifdef ORACLE if(dlevel == oracle_level) mkroom(DELPHI); /* It is possible that we find no good place to set up Delphi. * It is also possible to get more than one Delphi using bones levels. * The first is not a problem; the second is a minor nuisance. */ else #endif if(dlevel > 1 && dlevel < medusa_level && rn2(dlevel) < 3) mkroom(SHOPBASE); else #ifdef THRONES if(dlevel > 4 && !rn2(6)) mkroom(COURT); else #endif if(dlevel > 6 && !rn2(7)) mkroom(ZOO); else #ifdef ALTARS if(dlevel > 8 && !rn2(5)) mkroom(TEMPLE); else #endif if(dlevel > 9 && !rn2(5) && !(mons[PM_KILLER_BEE].geno & G_GENOD)) mkroom(BEEHIVE); else if(dlevel > 11 && !rn2(6)) mkroom(MORGUE); else #ifdef ARMY if(dlevel > 14 && !rn2(4) && !(mons[PM_SOLDIER].geno & G_GENOD)) mkroom(BARRACKS); else #endif if(dlevel > 18 && !rn2(6)) mkroom(SWAMP); #ifdef REINCARNATION skip0: #endif /* for each room: put things inside */ for(croom = rooms; croom->hx > 0; croom++) { register boolean boxinlev = FALSE; if(croom->rtype != OROOM) continue; /* put a sleeping monster inside */ /* Note: monster may be on the stairs. This cannot be avoided: maybe the player fell through a trap door while a monster was on the stairs. Conclusion: we have to check for monsters on the stairs anyway. */ if(u.uhave_amulet || !rn2(3)) { x = somex(croom); y = somey(croom); tmonst = makemon((struct permonst *) 0, x,y); if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER]) (void) maketrap (x,y,WEB); } /* put traps and mimics inside */ goldseen = FALSE; while(!rn2(8-(dlevel/6))) mktrap(0,0,croom); if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom)); #ifdef REINCARNATION if (dlevel == rogue_level) goto skip_nonrogue; #endif #ifdef FOUNTAINS if(!rn2(10)) mkfount(0,croom); #endif #ifdef SINKS if(!rn2(60)) mksink(croom); #endif #ifdef ALTARS if(!rn2(60)) mkaltar(croom); #endif /* put statues inside */ #ifdef MEDUSA if(!rn2(dlevel == medusa_level ? 1 : 20)) { struct obj *otmp; if (!rn2(dlevel == medusa_level ? 2 : 50)) otmp = mk_tt_object(STATUE, somex(croom), somey(croom)); else { otmp = mkcorpstat(STATUE, (struct permonst *)0, somex(croom), somey(croom)); } if (dlevel == medusa_level && otmp) { /* Medusa statues don't contain books */ otmp->spe = 0; while(resists_ston(&mons[otmp->corpsenm])) { otmp->corpsenm = rndmonnum(); otmp->owt = weight(otmp); } } } #else if(!rn2(20)) (void) mkcorpstat(STATUE, (struct permonst *)0, somex(croom), somey(croom)); #endif /* put box/chest inside */ if(!rn2(20) && !boxinlev) { boxinlev = TRUE; (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, somex(croom), somey(croom)); } #ifdef REINCARNATION skip_nonrogue: #endif if(!rn2(3)) { (void) mkobj_at(0, somex(croom), somey(croom)); tryct = 0; while(!rn2(5)) { if(++tryct > 100){ Printf("tryct overflow4\n"); break; } (void) mkobj_at(0, somex(croom), somey(croom)); } } } } void mklev() { if(getbones()) return; in_mklev = TRUE; makelevel(); bound_digging(); in_mklev = FALSE; } static boolean bydoor(x, y) register xchar x, y; { register boolean tmp1, tmp2; /* break up large expression to help some compilers */ tmp1 = (IS_DOOR(levl[x+1][y].typ) || levl[x+1][y].typ == SDOOR || IS_DOOR(levl[x-1][y].typ) || levl[x-1][y].typ == SDOOR); tmp2 = (IS_DOOR(levl[x][y+1].typ) || levl[x][y+1].typ == SDOOR || IS_DOOR(levl[x][y-1].typ) || levl[x][y-1].typ == SDOOR); return(tmp1 || tmp2); } /* see whether it is allowable to create a door at [x,y] */ int okdoor(x,y) register xchar x, y; { register boolean near_door = bydoor(x, y); return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) && doorindex < DOORMAX && !near_door); } void dodoor(x,y,aroom) register int x, y; register struct mkroom *aroom; { if(doorindex >= DOORMAX) { impossible("DOORMAX exceeded?"); return; } if(!okdoor(x,y) && nxcor) return; dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR); } static boolean occupied(x, y) register xchar x, y; { return(t_at(x, y) || levl[x][y].typ == STAIRS #ifdef FOUNTAINS || IS_FOUNTAIN(levl[x][y].typ) #endif #ifdef THRONES || IS_THRONE(levl[x][y].typ) #endif #ifdef SINKS || IS_SINK(levl[x][y].typ) #endif #ifdef ALTARS || levl[x][y].typ == ALTAR #endif || is_pool(x,y) ); } /* make a trap somewhere (in croom if mazeflag = 0) */ void mktrap(num, mazeflag, croom) register int num, mazeflag; register struct mkroom *croom; { register struct trap *ttmp; register int kind,nomonst,nomimic,nospider, #ifdef POLYSELF nopoly, #endif nospikes, nolevltp, nolandmine, tryct = 0; xchar mx,my; #ifdef __GNULINT__ kind = nomimic = 0; #endif if(!num || num >= TRAPNUM) { nomonst = (dlevel < 4) ? 1 : 0; nolevltp = (dlevel < 5) ? 1 : 0; nospikes = (dlevel < 6) ? 1 : 0; nospider = (dlevel < 7) ? 1 : 0; #ifdef POLYSELF nopoly = (dlevel < 6) ? 1 : 0; #endif nolandmine = (dlevel < 5) ? 1 : 0; nomimic = (dlevel < 9 || goldseen ) ? 1 : 0; if((mons[PM_SMALL_MIMIC].geno & G_GENOD) && (mons[PM_LARGE_MIMIC].geno & G_GENOD) && (mons[PM_GIANT_MIMIC].geno & G_GENOD)) nomimic = 1; if(mons[PM_GIANT_SPIDER].geno & G_GENOD) nospider = 1; do { #ifdef REINCARNATION if (dlevel==rogue_level) { switch(rn2(7)) { case 0: kind = BEAR_TRAP; break; case 1: kind = ARROW_TRAP; break; case 2: kind = DART_TRAP; break; case 3: kind = TRAPDOOR; break; case 4: kind = PIT; break; case 5: kind = SLP_GAS_TRAP; break; case 6: kind = RUST_TRAP; break; } } else #endif kind = rnd(TRAPNUM-1); if((kind == MONST_TRAP && (nomonst && nomimic)) || ((kind == WEB) && nospider) || (kind == SPIKED_PIT && nospikes) || (kind == LEVEL_TELEP && nolevltp) #ifdef POLYSELF || (kind == POLY_TRAP && nopoly) #endif || (kind == LANDMINE && nolandmine) ) kind = NO_TRAP; } while(kind == NO_TRAP); } else kind = num; if(kind == MONST_TRAP && !nomimic && !rn2(4) && !mazeflag) { register struct monst *mtmp; do { if(++tryct > 200) return; /* note: fakedoor maybe on actual door */ if(rn2(2)){ if(rn2(2)) mx = croom->hx+1; else mx = croom->lx-1; my = somey(croom); } else { if(rn2(2)) my = croom->hy+1; else my = croom->ly-1; mx = somex(croom); } } while (MON_AT(mx, my)); if((mtmp = makemon(mkclass(S_MIMIC), mx, my))) { mtmp->mimic = 1; mtmp->m_ap_type = M_AP_FURNITURE; mtmp->mappearance = S_cdoor; } return; } do { if(++tryct > 200) return; if(mazeflag){ coord mm; mazexy(&mm); mx = mm.x; my = mm.y; } else { mx = somex(croom); my = somey(croom); } } while(occupied(mx, my)); ttmp = maketrap(mx, my, kind); if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], mx, my); if(mazeflag && !rn2(10) && ttmp->ttyp < MONST_TRAP) ttmp->tseen = 1; } #ifdef FOUNTAINS void mkfount(mazeflag,croom) register struct mkroom *croom; register int mazeflag; { register xchar mx,my; register int tryct = 0; do { if(++tryct > 200) return; if(mazeflag) { coord mm; mazexy(&mm); mx = mm.x; my = mm.y; } else { mx = somex(croom); my = somey(croom); } } while(occupied(mx, my) || bydoor(mx, my)); /* Put a fountain at mx, my */ levl[mx][my].typ = FOUNTAIN; levl[mx][my].scrsym = FOUNTAIN_SYM; fountsound++; } #endif /* FOUNTAINS /**/ #ifdef SINKS static void mksink(croom) register struct mkroom *croom; { register xchar mx,my; register int tryct = 0; do { if(++tryct > 200) return; mx = somex(croom); my = somey(croom); } while(occupied(mx, my) || bydoor(mx, my)); /* Put a sink at mx, my */ levl[mx][my].typ = SINK; levl[mx][my].scrsym = SINK_SYM; sinksound++; } #endif /* SINKS /**/ #ifdef ALTARS static void mkaltar(croom) register struct mkroom *croom; { register xchar mx,my; register int tryct = 0; if(croom->rtype != OROOM) return; do { if(++tryct > 200) return; mx = somex(croom); my = somey(croom); } while(occupied(mx, my) || bydoor(mx, my)); /* Put an altar at mx, my */ levl[mx][my].typ = ALTAR; levl[mx][my].scrsym = ALTAR_SYM; /* 0 - A_CHAOS, 1 - A_NEUTRAL, 2 - A_LAW */ levl[mx][my].altarmask = rn2((int)A_LAW+1); } #endif /* ALTARS /**/
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.