home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* mklev.c version 1.0.1 - new makecorridor() */
- #ifndef MKLEV
- #define MKLEV
- #endif
- #include <stdio.h>
- #include "hack.h"
- #include "def.trap.h"
-
- extern struct monst *makemon();
-
- static char tspe[2],**args;
- static int doorindex;
- static schar nxcor;
-
- char ismklev;
- struct mkroom *croom, *troom;
- boolean goldseen;
- int nroom;
- int smeq[MAXNROFROOMS+1];
- char *tfile;
-
- #ifdef WIZARD
- extern boolean wizard;
- #endif
-
- #define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx)
- #define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly)
-
- extern char nul[40];
- extern struct rm levl[COLNO][ROWNO];
- extern struct monst *fmon;
- extern struct obj *fobj;
- extern struct gen *fgold, *ftrap;
- extern char *fut_geno; /* monsters that should not be created anymore */
- extern struct mkroom rooms[MAXNROFROOMS+1];
- extern coord doors[DOORMAX];
- extern int comp();
- extern xchar dlevel;
- extern xchar xdnstair,xupstair,ydnstair,yupstair;
-
- zeroout(addr, len)
- char *addr;
- int len;
- {
- while(--len>0) *addr++=0;
- }
-
- mklev()
- {
- register unsigned tryct;
-
- tfile = lock;
- troom = NULL;
- doorindex = 0;
- nroom = 0;
-
- if(getbones()) return;
- ismklev = 1;
- if(dlevel < rn1(3, 26)) tspe[0] = 'a'; /* normal level */
- else tspe[0] = 'b'; /* maze */
- tspe[1] = 0;
-
- /* zap the object bases */
- {int i;extern int bases[];
- for(i=0;i<15;bases[i++]=0);}
-
- /* zap the room pictures */
- zeroout(levl,COLNO*ROWNO*sizeof(struct rm));
-
- fmon = NULL;
- fobj = NULL;
- fgold = ftrap = NULL;
-
- zeroout( doors, sizeof(coord)*DOORMAX);
-
- xdnstair = xupstair = ydnstair = yupstair = 0;
- zeroout(rooms, (MAXNROFROOMS+1)*sizeof(struct mkroom));
-
- init_objects();
- rooms[0].hx = -1; /* in case we are in a maze */
-
- /* a: normal; b: maze */
- if(*tspe == 'b') {
- makemaz();
- #ifdef DOSAVE
- {
- int fd;
- if((fd = creat(tfile,FMASK)) < 0)
- panic("Cannot create %s\n", tfile);
- savelev(fd);
- close(fd);
- }
- #endif
- ismklev = 0;
- return(0);
- }
-
- /* construct the rooms */
- while(nroom < (MAXNROFROOMS/3)) {
- croom = rooms;
- nroom = 0;
- (void) makerooms(0); /* not secret */
- }
-
- /* for each room: put things inside */
- for(croom = rooms; croom->hx > 0; croom++) {
-
- /* put a sleeping monster inside */
- if(!rn2(3)) (void)
- makemon((struct permonst *) 0, somex(), somey());
-
- /* put traps and mimics inside */
- goldseen = FALSE;
- while(!rn2(8-(dlevel/6))) mktrap(0,0);
- if(!goldseen && !rn2(3)) mkgold(0,somex(),somey());
- if(!rn2(3)) {
- mkobj_at(0, somex(), somey());
- tryct = 0;
- while(!rn2(5)) {
- if(++tryct > 100){
- myprintf("tryct overflow4\n");
- break;
- }
- mkobj_at(0, somex(), somey());
- }
- }
- }
- tryct = 0;
- do {
- if(++tryct > 1000) panic("Cannot make dnstairs\n");
- croom = &rooms[rn2(nroom)];
- xdnstair = somex();
- ydnstair = somey();
- } while((*tspe =='n' && (!(xdnstair%2) || !(ydnstair%2))) ||
- g_at(xdnstair,ydnstair,ftrap));
- levl[xdnstair][ydnstair].scrsym ='>';
- levl[xdnstair][ydnstair].typ = STAIRS;
- troom = croom;
- do {
- if(++tryct > 2000) panic("Cannot make upstairs\n");
- croom = &rooms[rn2(nroom)];
- xupstair = somex();
- yupstair = somey();
- } while(croom == troom || m_at(xupstair,yupstair) ||
- g_at(xupstair,yupstair,ftrap));
- levl[xupstair][yupstair].scrsym ='<';
- levl[xupstair][yupstair].typ = STAIRS;
-
- #ifdef DEBUG
- dumpit();
- #endif
- qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
- makecorridors();
- make_niches();
-
- /* make a secret treasure vault, not connected to the rest */
- if(nroom < (2*MAXNROFROOMS/3)) if(!rn2(3)) {
- register int x,y;
- troom = croom = &rooms[nroom];
- if(makerooms(1)) { /* make secret room */
- troom->rtype = 6; /* treasure vault */
- for(x = troom->lx; x <= troom->hx; x++)
- for(y = troom->ly; y <= troom->hy; y++)
- mkgold(rnd(dlevel*100) + 50, x, y);
- if(!rn2(3))
- makevtele();
- }
- }
-
- #ifdef WIZARD
- if(wizard){
- if(rn2(3)) mkshop(); else mkzoo();
- } else
- #endif WIZARD
- if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 2)
- mkshop();
- else
- if(dlevel > 6 && !rn2(7) )
- mkzoo();
- #ifdef DOSAVE
- {
- int fd;
- if((fd = creat(tfile,FMASK)) < 0)
- panic("Cannot create %s\n", tfile);
- savelev(fd);
- close(fd);
- }
- #endif
- ismklev = 0;
- return(0);
- }
-
- makerooms(secret)
- int secret;
- {
- register int lowx, lowy;
- register int tryct = 0;
-
- while(nroom < (MAXNROFROOMS/2) || secret)
- for(lowy = rn1(3,3); lowy < ROWNO-7; lowy += rn1(2,4))
- {
- for(lowx = rn1(3,4); lowx < COLNO-10; lowx += rn1(2,7))
- {
- if (tryct++ > 10000) return(0);
-
- if ((lowy += (rn2(5)-2)) < 3)
- lowy = 3;
- else
- if(lowy > ROWNO-6)
- lowy = ROWNO-6;
-
- if(levl[lowx][lowy].typ) continue;
-
- if ((secret && maker(lowx, 1, lowy, 1)) ||
- (!secret && maker(lowx,rn1(9,2),lowy,rn1(4,2))
- && nroom+2 > MAXNROFROOMS)) return(1);
- }
- }
- return(1);
- }
-
- comp(x,y)
- register struct mkroom *x,*y;
- {
- if(x->lx < y->lx) return(-1);
- return(x->lx > y->lx);
- }
-
- coord
- finddpos(xl,yl,xh,yh) {
- coord ff;
- register int x,y;
- ff.x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
- ff.y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
- if(okdoor(ff.x, ff.y)) return(ff);
- if(xl < xh) for(x = xl; x <= xh; x++)
- if(okdoor(x, ff.y)){
- ff.x = x;
- return(ff);
- }
- if(yl < yh) for(y = yl; y <= yh; y++)
- if(okdoor(ff.x, y)){
- ff.y = y;
- return(ff);
- }
- return(ff);
- }
-
- /* if allowable, create a door at [x,y] */
- okdoor(x,y)
- register int x,y;
- {
- if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
- levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
- levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
- levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
- (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
- doorindex >= DOORMAX)
- return(0);
- return(1);
- }
-
- dodoor(x,y,aroom)
- register int x,y;
- register struct mkroom *aroom;
- {
- if(doorindex >= DOORMAX) panic("DOORMAX exceeded?");
- if(!okdoor(x,y) && nxcor) return;
- dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
- }
-
- dosdoor(x,y,aroom,type)
- register int x,y;
- register struct mkroom *aroom;
- register int type;
- {
- register struct mkroom *broom;
- register int tmp;
-
- levl[x][y].typ = type;
- if(type == DOOR)
- levl[x][y].scrsym ='+';
- 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++;
- }
-
- /* Only called from makerooms() */
- maker(lowx,ddx,lowy,ddy)
- schar lowx,ddx,lowy,ddy;
- {
- register int x, y, hix = lowx+ddx, hiy = lowy+ddy;
-
- if(nroom >= MAXNROFROOMS) return(0);
- if(hix > COLNO-5) hix = COLNO-5;
- if(hiy > ROWNO-4) hiy = ROWNO-4;
- chk:
- if(hix <= lowx || hiy <= lowy) return(0);
-
- /* check area around room (and make room smaller if necessary) */
- for(x = lowx-4; x <= hix+4; x++)
- for(y = lowy-3; y <= hiy+3; y++)
- if(levl[x][y].typ) {
- if(rn2(3)) return(0);
- lowx = x+5;
- lowy = y+4;
- goto chk;
- }
-
- /* on low levels the room is lit (usually) */
- /* secret vaults are always lit */
- if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1))
- for(x = lowx-1; x <= hix+1; x++)
- for(y = lowy-1; y <= hiy+1; y++)
- levl[x][y].lit = 1;
- croom->lx = lowx;
- croom->hx = hix;
- croom->ly = lowy;
- croom->hy = hiy;
- croom->rtype = croom->doorct = croom->fdoor = 0;
- for(x = lowx-1; x <= hix+1; x++)
- for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
- levl[x][y].scrsym = '-';
- levl[x][y].typ = HWALL;
- }
- for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
- for(y = lowy; y <= hiy; y++) {
- levl[x][y].scrsym = '|';
- levl[x][y].typ = VWALL;
- }
- for(x = lowx; x <= hix; x++)
- for(y = lowy; y <= hiy; y++) {
- levl[x][y].scrsym = '.';
- levl[x][y].typ = ROOM;
- }
- croom++;
- croom->hx = -1;
- smeq[nroom] = nroom;
- nroom++;
- return(1);
- }
-
- 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);
- }
- }
-
- join(a,b)
- register int a,b;
- {
- coord cc,tt;
- register int tx, ty, xx, yy;
- register struct rm *crm;
- 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;
- cc = finddpos(xx,croom->ly,xx,croom->hy);
- tt = finddpos(tx,troom->ly,tx,troom->hy);
- } else if(troom->hy < croom->ly) {
- dy = -1;
- dx = 0;
- yy = croom->ly-1;
- cc = finddpos(croom->lx,yy,croom->hx,yy);
- ty = troom->hy+1;
- tt = finddpos(troom->lx,ty,troom->hx,ty);
- } else if(troom->hx < croom->lx) {
- dx = -1;
- dy = 0;
- xx = croom->lx-1;
- tx = troom->hx+1;
- cc = finddpos(xx,croom->ly,xx,croom->hy);
- tt = finddpos(tx,troom->ly,tx,troom->hy);
- } else {
- dy = 1;
- dx = 0;
- yy = croom->hy+1;
- ty = troom->ly-1;
- cc = finddpos(croom->lx,yy,croom->hx,yy);
- tt = finddpos(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;
- } else {
- crm->typ = SCORR;
- crm->scrsym = ' ';
- }
- if(nxcor && !rn2(50)) {
- mkobj_at(ROCK_SYM, xx, yy);
- }
- } 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];
- }
-
- make_niches()
- {
- register int ct = rn2(nroom/2 + 1)+1;
- while(ct--) makeniche(FALSE);
- }
-
- makevtele()
- {
- makeniche(TRUE);
- }
-
- makeniche(with_trap)
- boolean with_trap;
- {
- register struct mkroom *aroom;
- register struct rm *rm;
- register int vct = 8;
- coord dd;
- register int dy,xx,yy;
- register struct gen *gtmp;
-
- if(doorindex < DOORMAX)
- while(vct--) {
- aroom = &rooms[rn2(nroom-1)];
- if(aroom->rtype != 0) continue; /* not an ordinary room */
- if(rn2(2)) {
- dy = 1;
- dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1);
- } else {
- dy = -1;
- dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1);
- }
- xx = dd.x;
- yy = dd.y;
- if((rm = &levl[xx][yy+dy])->typ) continue;
- if(with_trap || !rn2(4)) {
- rm->typ = SCORR;
- rm->scrsym = ' ';
- if(with_trap) {
- gtmp = newgen();
- gtmp->gx = xx;
- gtmp->gy = yy+dy;
- gtmp->gflag = TELEP_TRAP | ONCE;
- gtmp->ngen = ftrap;
- ftrap = gtmp;
- make_engr_at(xx,yy-dy,"ad ae?ar um");
- }
- 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 {
- mksobj_at(SCROLL_SYM,SCR_TELEPORTATION,xx,yy+dy);
- if(!rn2(3)) mkobj_at(0,xx,yy+dy);
- }
- }
- return;
- }
- }
-
- /* make a trap somewhere (in croom if mazeflag = 0) */
- mktrap(num,mazeflag)
- register int num,mazeflag;
- {
- register struct gen *gtmp;
- register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0;
- register xchar mx,my;
-
-
- if(!num || num >= TRAPNUM) {
- nopierc = (dlevel < 4) ? 1 : 0;
- nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
- if(index(fut_geno, 'M')) nomimic = 1;
- kind = rn2(TRAPNUM - nopierc - nomimic);
- /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
- } else kind = num;
-
- if(kind == MIMIC) {
- register struct monst *mtmp;
-
- fakedoor = (!rn2(3) && !mazeflag);
- fakegold = (!fakedoor && !rn2(2));
- if(fakegold) goldseen = TRUE;
- do {
- if(++tryct > 200) return;
- if(fakedoor) {
- /* note: fakedoor maybe on actual door */
- if(rn2(2)){
- if(rn2(2))
- mx = croom->hx+1;
- else mx = croom->lx-1;
- my = somey();
- } else {
- if(rn2(2))
- my = croom->hy+1;
- else my = croom->ly-1;
- mx = somex();
- }
- } else if(mazeflag) {
- extern coord mazexy();
- coord mm;
- mm = mazexy();
- mx = mm.x;
- my = mm.y;
- } else {
- mx = somex();
- my = somey();
- }
- } while(m_at(mx,my));
- if(mtmp = makemon(PM_MIMIC,mx,my))
- mtmp->mimic =
- fakegold ? '$' : fakedoor ? '+' :
- (mazeflag && rn2(2)) ? AMULET_SYM :
- "=/)%?![<>" [ rn2(9) ];
- return;
- }
- gtmp = newgen();
- gtmp->gflag = kind;
- do {
- if(++tryct > 200){
- free((char *) gtmp);
- return;
- }
- if(mazeflag){
- extern coord mazexy();
- coord mm;
- mm = mazexy();
- gtmp->gx = mm.x;
- gtmp->gy = mm.y;
- } else {
- gtmp->gx = somex();
- gtmp->gy = somey();
- }
- } while(g_at(gtmp->gx, gtmp->gy, ftrap));
- gtmp->ngen = ftrap;
- ftrap = gtmp;
- if(mazeflag && !rn2(10) && gtmp->gflag < PIERC) gtmp->gflag |= SEEN;
- }
-
- #ifdef DEBUG
- dumpit()
- {
- int x, y;
- struct rm *room;
-
- cgetret();
-
- /* kludge in making everything visible */
- for(y=0; y < ROWNO; y++)
- for(x=0; x < COLNO-3; x++)
- if ( (room = &levl[x][y])->typ)
- at(x,y, (room->scrsym) ? room->scrsym : '¿');
- }
- #endif
-