1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.mklev.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.mklev.c,v 1.6 1999/11/16 10:26:36 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.mklev.c,v 1.3 2004/11/06 12:29:17 eirikn Exp $ */
11 extern struct monst *makemon();
12 extern struct obj *mkobj_at();
13 extern struct trap *maketrap();
15 #define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
16 #define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
18 #include "def.mkroom.h"
19 #define XLIM 4 /* define minimum required space around a room */
21 boolean secret; /* TRUE while making a vault: increase [XY]LIM */
22 struct mkroom rooms[MAXNROFROOMS+1];
23 int smeq[MAXNROFROOMS+1];
31 xchar xdnstair,xupstair,ydnstair,yupstair;
33 /* Definitions used by makerooms() and addrs() */
34 #define MAXRS 50 /* max lth of temp rectangle table - arbitrary */
36 xchar rlx,rly,rhx,rhy;
38 int rscnt,rsmax; /* 0..rscnt-1: currently under consideration */
39 /* rscnt..rsmax: discarded */
43 struct mkroom *croom, *troom;
49 rooms[0].hx = -1; /* in case we are in a maze */
51 for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
54 oinit(); /* assign level dependent obj probabilities */
56 if(dlevel >= rn1(3, 26)) { /* there might be several mazes */
61 /* construct the rooms */
66 /* construct stairs (up and down in different rooms if possible) */
67 croom = &rooms[rn2(nroom)];
70 levl[xdnstair][ydnstair].scrsym ='>';
71 levl[xdnstair][ydnstair].typ = STAIRS;
74 croom = &rooms[rn2(nroom-1)];
75 if(croom >= troom) croom++;
77 xupstair = somex(); /* %% < and > might be in the same place */
79 levl[xupstair][yupstair].scrsym ='<';
80 levl[xupstair][yupstair].typ = STAIRS;
82 /* for each room: put things inside */
83 for(croom = rooms; croom->hx > 0; croom++) {
85 /* put a sleeping monster inside */
86 /* Note: monster may be on the stairs. This cannot be
87 avoided: maybe the player fell through a trapdoor
88 while a monster was on the stairs. Conclusion:
89 we have to check for monsters on the stairs anyway. */
91 makemon((struct permonst *) 0, somex(), somey());
93 /* put traps and mimics inside */
95 while(!rn2(8-(dlevel/6))) mktrap(0,0,croom);
96 if(!goldseen && !rn2(3)) mkgold(0L,somex(),somey());
98 (void) mkobj_at(0, somex(), somey());
102 printf("tryct overflow4\n");
105 (void) mkobj_at(0, somex(), somey());
110 qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
114 /* make a secret treasure vault, not connected to the rest */
115 if(nroom <= (2*MAXNROFROOMS/3)) if(rn2(3)) {
116 troom = &rooms[nroom];
119 troom->rtype = VAULT; /* treasure vault */
120 for(x = troom->lx; x <= troom->hx; x++)
121 for(y = troom->ly; y <= troom->hy; y++)
122 mkgold((long)(rnd(dlevel*100) + 50), x, y);
130 if(wizard && getenv("SHOPTYPE")) mkshop(); else
132 if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3) mkshop();
134 if(dlevel > 6 && !rn2(7)) mkzoo(ZOO);
136 if(dlevel > 9 && !rn2(5)) mkzoo(BEEHIVE);
138 if(dlevel > 11 && !rn2(6)) mkzoo(MORGUE);
140 if(dlevel > 18 && !rn2(6)) mkswamp();
145 struct rectangle *rsp;
146 int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy;
147 int tryct = 0, xlim, ylim;
150 xlim = XLIM + secret;
151 ylim = YLIM + secret;
154 rsp->rlx = rsp->rly = 0;
161 /* make rooms until satisfied */
162 while(rscnt > 0 && nroom < MAXNROFROOMS-1) {
163 if(!secret && nroom > (MAXNROFROOMS/3) &&
164 !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom)))
167 /* pick a rectangle */
168 rsp = &rs[rn2(rscnt)];
174 /* find size of room */
178 dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8);
184 /* look whether our room will fit */
185 if(hx-lx < dx + dx/2 + 2*xlim || hy-ly < dy + dy/3 + 2*ylim) {
187 /* maybe we throw this area out */
188 if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) {
192 rs[rscnt] = rs[rsmax];
199 lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1);
200 lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1);
204 if(maker(lowx, dx, lowy, dy)) {
207 addrs(lowx-1, lowy-1, hix+1, hiy+1);
213 return(0); /* failed to make vault - very strange */
216 addrs(lowx,lowy,hix,hiy)
217 int lowx,lowy,hix,hiy;
219 struct rectangle *rsp;
220 int lx,ly,hx,hy,xlim,ylim;
223 xlim = XLIM + secret;
224 ylim = YLIM + secret;
226 /* walk down since rscnt and rsmax change */
227 for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) {
229 if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy ||
230 (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy)
232 if((discarded = (rsp >= &rs[rscnt]))) {
239 rs[rscnt] = rs[rsmax];
241 if(lowy - ly > 2*ylim + 4)
242 addrsx(lx,ly,hx,lowy-2,discarded);
243 if(lowx - lx > 2*xlim + 4)
244 addrsx(lx,ly,lowx-2,hy,discarded);
245 if(hy - hiy > 2*ylim + 4)
246 addrsx(lx,hiy+2,hx,hy,discarded);
247 if(hx - hix > 2*xlim + 4)
248 addrsx(hix+2,ly,hx,hy,discarded);
252 addrsx(lx,ly,hx,hy,discarded)
254 boolean discarded; /* piece of a discarded area */
256 struct rectangle *rsp;
258 /* check inclusions */
259 for(rsp = rs; rsp < &rs[rsmax]; rsp++) {
260 if(lx >= rsp->rlx && hx <= rsp->rhx &&
261 ly >= rsp->rly && hy <= rsp->rhy)
265 /* make a new entry */
268 if(wizard) pline("MAXRS may be too small.");
287 if(x->lx < y->lx) return(-1);
288 return(x->lx > y->lx);
292 finddpos(xl,yl,xh,yh) {
296 x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
297 y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
301 for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
305 for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
306 if(levl[x][y].typ == DOOR || levl[x][y].typ == SDOOR)
308 /* cannot find something reasonable -- strange */
317 /* see whether it is allowable to create a door at [x,y] */
321 if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
322 levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
323 levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
324 levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
325 (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
326 doorindex >= DOORMAX)
333 struct mkroom *aroom;
335 if(doorindex >= DOORMAX) {
336 impossible("DOORMAX exceeded?");
339 if(!okdoor(x,y) && nxcor)
341 dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
344 dosdoor(x,y,aroom,type)
346 struct mkroom *aroom;
349 struct mkroom *broom;
352 if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with '+' as scrsym */
354 levl[x][y].typ = type;
356 levl[x][y].scrsym = '+';
359 if(broom->hx < 0) tmp = doorindex; else
360 for(tmp = doorindex; tmp > broom->fdoor; tmp--)
361 doors[tmp] = doors[tmp-1];
365 for( ; broom->hx >= 0; broom++) broom->fdoor++;
368 /* Only called from makerooms() */
369 maker(lowx,ddx,lowy,ddy)
370 schar lowx,ddx,lowy,ddy;
372 struct mkroom *croom;
373 int x, y, hix = lowx+ddx, hiy = lowy+ddy;
374 int xlim = XLIM + secret, ylim = YLIM + secret;
376 if(nroom >= MAXNROFROOMS) return(0);
377 if(lowx < XLIM) lowx = XLIM;
378 if(lowy < YLIM) lowy = YLIM;
379 if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1;
380 if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1;
382 if(hix <= lowx || hiy <= lowy) return(0);
384 /* check area around room (and make room smaller if necessary) */
385 for(x = lowx - xlim; x <= hix + xlim; x++) {
386 for(y = lowy - ylim; y <= hiy + ylim; y++) {
389 if(wizard && !secret)
390 pline("Strange area [%d,%d] in maker().",x,y);
392 if(!rn2(3)) return(0);
406 croom = &rooms[nroom];
408 /* on low levels the room is lit (usually) */
409 /* secret vaults are always lit */
410 if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) {
411 for(x = lowx-1; x <= hix+1; x++)
412 for(y = lowy-1; y <= hiy+1; y++)
421 croom->rtype = croom->doorct = croom->fdoor = 0;
423 for(x = lowx-1; x <= hix+1; x++)
424 for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
425 levl[x][y].scrsym = '-';
426 levl[x][y].typ = HWALL;
428 for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
429 for(y = lowy; y <= hiy; y++) {
430 levl[x][y].scrsym = '|';
431 levl[x][y].typ = VWALL;
433 for(x = lowx; x <= hix; x++)
434 for(y = lowy; y <= hiy; y++) {
435 levl[x][y].scrsym = '.';
436 levl[x][y].typ = ROOM;
450 for(a = 0; a < nroom-1; a++)
452 for(a = 0; a < nroom-2; a++)
453 if(smeq[a] != smeq[a+2])
455 for(a = 0; a < nroom; a++)
456 for(b = 0; b < nroom; b++)
457 if(smeq[a] != smeq[b])
460 for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
474 struct mkroom *croom, *troom;
475 int dx, dy, dix, diy, cct;
480 /* find positions cc and tt for doors in croom and troom
481 and direction for a corridor between them */
483 if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
484 if(troom->lx > croom->hx) {
489 cc = finddpos(xx,croom->ly,xx,croom->hy);
490 tt = finddpos(tx,troom->ly,tx,troom->hy);
491 } else if(troom->hy < croom->ly) {
495 cc = finddpos(croom->lx,yy,croom->hx,yy);
497 tt = finddpos(troom->lx,ty,troom->hx,ty);
498 } else if(troom->hx < croom->lx) {
503 cc = finddpos(xx,croom->ly,xx,croom->hy);
504 tt = finddpos(tx,troom->ly,tx,troom->hy);
510 cc = finddpos(croom->lx,yy,croom->hx,yy);
511 tt = finddpos(troom->lx,ty,troom->hx,ty);
517 if(nxcor && levl[xx+dx][yy+dy].typ)
522 while(xx != tx || yy != ty) {
526 /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
527 if(cct++ > 500 || (nxcor && !rn2(35)))
530 if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1)
531 return; /* impossible */
537 crm->scrsym = CORR_SYM;
538 if(nxcor && !rn2(50))
539 (void) mkobj_at(ROCK_SYM, xx, yy);
545 if(crm->typ != CORR && crm->typ != SCORR) {
550 /* find next corridor position */
554 /* do we have to change direction ? */
555 if(dy && dix > diy) {
556 int ddx = (xx > tx) ? -1 : 1;
558 crm = &levl[xx+ddx][yy];
559 if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
564 } else if(dx && diy > dix) {
565 int ddy = (yy > ty) ? -1 : 1;
567 crm = &levl[xx][yy+ddy];
568 if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
575 /* continue straight on? */
576 crm = &levl[xx+dx][yy+dy];
577 if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
580 /* no, what must we do now?? */
583 dy = (ty < yy) ? -1 : 1;
584 crm = &levl[xx+dx][yy+dy];
585 if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
591 dx = (tx < xx) ? -1 : 1;
592 crm = &levl[xx+dx][yy+dy];
593 if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
600 /* we succeeded in digging the corridor */
601 dodoor(tt.x, tt.y, troom);
603 if(smeq[a] < smeq[b])
611 int ct = rnd(nroom/2 + 1);
612 while(ct--) makeniche(FALSE);
623 struct mkroom *aroom;
630 if(doorindex < DOORMAX)
632 aroom = &rooms[rn2(nroom-1)];
633 if(aroom->rtype != 0) continue; /* not an ordinary room */
634 if(aroom->doorct == 1 && rn2(5)) continue;
637 dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1);
640 dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1);
644 if((rm = &levl[xx][yy+dy])->typ) continue;
645 if(with_trap || !rn2(4)) {
649 ttmp = maketrap(xx, yy+dy, TELEP_TRAP);
651 make_engr_at(xx, yy-dy, "ad ae?ar um");
653 dosdoor(xx, yy, aroom, SDOOR);
656 rm->scrsym = CORR_SYM;
658 dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
660 mksobj_at(SCR_TELEPORTATION, xx, yy+dy);
661 if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy);
668 /* make a trap somewhere (in croom if mazeflag = 0) */
669 mktrap(num,mazeflag,croom)
671 struct mkroom *croom;
674 int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0;
676 extern char fut_geno[];
678 if(!num || num >= TRAPNUM) {
679 nopierc = (dlevel < 4) ? 1 : 0;
680 nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
681 if(index(fut_geno, 'M')) nomimic = 1;
682 kind = rn2(TRAPNUM - nopierc - nomimic);
683 /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
689 fakedoor = (!rn2(3) && !mazeflag);
690 fakegold = (!fakedoor && !rn2(2));
691 if(fakegold) goldseen = TRUE;
693 if(++tryct > 200) return;
695 /* note: fakedoor maybe on actual door */
699 else mx = croom->lx-1;
704 else my = croom->ly-1;
707 } else if(mazeflag) {
708 extern coord mazexy();
717 } while(m_at(mx,my) || levl[mx][my].typ == STAIRS);
718 if(mtmp = makemon(PM_MIMIC,mx,my)) {
721 fakegold ? '$' : fakedoor ? '+' :
722 (mazeflag && rn2(2)) ? AMULET_SYM :
723 "=/)%?![<>" [ rn2(9) ];
732 extern coord mazexy();
741 } while(t_at(mx, my) || levl[mx][my].typ == STAIRS);
742 ttmp = maketrap(mx, my, kind);
743 if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC)