]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.mklev.c
2 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
6 static char rcsid
[] = "$Id: hack.mklev.c,v 1.2 1993/08/02 17:17:23 mycroft Exp $";
11 extern char *getlogin(), *getenv();
12 extern struct monst
*makemon();
13 extern struct obj
*mkobj_at();
14 extern struct trap
*maketrap();
16 #define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
17 #define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
19 #include "def.mkroom.h"
20 #define XLIM 4 /* define minimum required space around a room */
22 boolean secret
; /* TRUE while making a vault: increase [XY]LIM */
23 struct mkroom rooms
[MAXNROFROOMS
+1];
24 int smeq
[MAXNROFROOMS
+1];
32 xchar xdnstair
,xupstair
,ydnstair
,yupstair
;
34 /* Definitions used by makerooms() and addrs() */
35 #define MAXRS 50 /* max lth of temp rectangle table - arbitrary */
37 xchar rlx
,rly
,rhx
,rhy
;
39 int rscnt
,rsmax
; /* 0..rscnt-1: currently under consideration */
40 /* rscnt..rsmax: discarded */
44 register struct mkroom
*croom
, *troom
;
45 register unsigned tryct
;
50 rooms
[0].hx
= -1; /* in case we are in a maze */
52 for(x
=0; x
<COLNO
; x
++) for(y
=0; y
<ROWNO
; y
++)
55 oinit(); /* assign level dependent obj probabilities */
57 if(dlevel
>= rn1(3, 26)) { /* there might be several mazes */
62 /* construct the rooms */
67 /* construct stairs (up and down in different rooms if possible) */
68 croom
= &rooms
[rn2(nroom
)];
71 levl
[xdnstair
][ydnstair
].scrsym
='>';
72 levl
[xdnstair
][ydnstair
].typ
= STAIRS
;
75 croom
= &rooms
[rn2(nroom
-1)];
76 if(croom
>= troom
) croom
++;
78 xupstair
= somex(); /* %% < and > might be in the same place */
80 levl
[xupstair
][yupstair
].scrsym
='<';
81 levl
[xupstair
][yupstair
].typ
= STAIRS
;
83 /* for each room: put things inside */
84 for(croom
= rooms
; croom
->hx
> 0; croom
++) {
86 /* put a sleeping monster inside */
87 /* Note: monster may be on the stairs. This cannot be
88 avoided: maybe the player fell through a trapdoor
89 while a monster was on the stairs. Conclusion:
90 we have to check for monsters on the stairs anyway. */
92 makemon((struct permonst
*) 0, somex(), somey());
94 /* put traps and mimics inside */
96 while(!rn2(8-(dlevel
/6))) mktrap(0,0,croom
);
97 if(!goldseen
&& !rn2(3)) mkgold(0L,somex(),somey());
99 (void) mkobj_at(0, somex(), somey());
103 printf("tryct overflow4\n");
106 (void) mkobj_at(0, somex(), somey());
111 qsort((char *) rooms
, nroom
, sizeof(struct mkroom
), comp
);
115 /* make a secret treasure vault, not connected to the rest */
116 if(nroom
<= (2*MAXNROFROOMS
/3)) if(rn2(3)) {
117 troom
= &rooms
[nroom
];
120 troom
->rtype
= VAULT
; /* treasure vault */
121 for(x
= troom
->lx
; x
<= troom
->hx
; x
++)
122 for(y
= troom
->ly
; y
<= troom
->hy
; y
++)
123 mkgold((long)(rnd(dlevel
*100) + 50), x
, y
);
131 if(wizard
&& getenv("SHOPTYPE")) mkshop(); else
133 if(dlevel
> 1 && dlevel
< 20 && rn2(dlevel
) < 3) mkshop();
135 if(dlevel
> 6 && !rn2(7)) mkzoo(ZOO
);
137 if(dlevel
> 9 && !rn2(5)) mkzoo(BEEHIVE
);
139 if(dlevel
> 11 && !rn2(6)) mkzoo(MORGUE
);
141 if(dlevel
> 18 && !rn2(6)) mkswamp();
146 register struct rectangle
*rsp
;
147 register int lx
, ly
, hx
, hy
, lowx
, lowy
, hix
, hiy
, dx
, dy
;
148 int tryct
= 0, xlim
, ylim
;
151 xlim
= XLIM
+ secret
;
152 ylim
= YLIM
+ secret
;
155 rsp
->rlx
= rsp
->rly
= 0;
162 /* make rooms until satisfied */
163 while(rscnt
> 0 && nroom
< MAXNROFROOMS
-1) {
164 if(!secret
&& nroom
> (MAXNROFROOMS
/3) &&
165 !rn2((MAXNROFROOMS
-nroom
)*(MAXNROFROOMS
-nroom
)))
168 /* pick a rectangle */
169 rsp
= &rs
[rn2(rscnt
)];
175 /* find size of room */
179 dx
= 2 + rn2((hx
-lx
-8 > 20) ? 12 : 8);
185 /* look whether our room will fit */
186 if(hx
-lx
< dx
+ dx
/2 + 2*xlim
|| hy
-ly
< dy
+ dy
/3 + 2*ylim
) {
188 /* maybe we throw this area out */
189 if(secret
|| !rn2(MAXNROFROOMS
+1-nroom
-tryct
)) {
193 rs
[rscnt
] = rs
[rsmax
];
200 lowx
= lx
+ xlim
+ rn2(hx
- lx
- dx
- 2*xlim
+ 1);
201 lowy
= ly
+ ylim
+ rn2(hy
- ly
- dy
- 2*ylim
+ 1);
205 if(maker(lowx
, dx
, lowy
, dy
)) {
208 addrs(lowx
-1, lowy
-1, hix
+1, hiy
+1);
214 return(0); /* failed to make vault - very strange */
217 addrs(lowx
,lowy
,hix
,hiy
)
218 register int lowx
,lowy
,hix
,hiy
;
220 register struct rectangle
*rsp
;
221 register int lx
,ly
,hx
,hy
,xlim
,ylim
;
224 xlim
= XLIM
+ secret
;
225 ylim
= YLIM
+ secret
;
227 /* walk down since rscnt and rsmax change */
228 for(rsp
= &rs
[rsmax
-1]; rsp
>= rs
; rsp
--) {
230 if((lx
= rsp
->rlx
) > hix
|| (ly
= rsp
->rly
) > hiy
||
231 (hx
= rsp
->rhx
) < lowx
|| (hy
= rsp
->rhy
) < lowy
)
233 if((discarded
= (rsp
>= &rs
[rscnt
]))) {
240 rs
[rscnt
] = rs
[rsmax
];
242 if(lowy
- ly
> 2*ylim
+ 4)
243 addrsx(lx
,ly
,hx
,lowy
-2,discarded
);
244 if(lowx
- lx
> 2*xlim
+ 4)
245 addrsx(lx
,ly
,lowx
-2,hy
,discarded
);
246 if(hy
- hiy
> 2*ylim
+ 4)
247 addrsx(lx
,hiy
+2,hx
,hy
,discarded
);
248 if(hx
- hix
> 2*xlim
+ 4)
249 addrsx(hix
+2,ly
,hx
,hy
,discarded
);
253 addrsx(lx
,ly
,hx
,hy
,discarded
)
254 register int lx
,ly
,hx
,hy
;
255 boolean discarded
; /* piece of a discarded area */
257 register struct rectangle
*rsp
;
259 /* check inclusions */
260 for(rsp
= rs
; rsp
< &rs
[rsmax
]; rsp
++) {
261 if(lx
>= rsp
->rlx
&& hx
<= rsp
->rhx
&&
262 ly
>= rsp
->rly
&& hy
<= rsp
->rhy
)
266 /* make a new entry */
269 if(wizard
) pline("MAXRS may be too small.");
286 register struct mkroom
*x
,*y
;
288 if(x
->lx
< y
->lx
) return(-1);
289 return(x
->lx
> y
->lx
);
293 finddpos(xl
,yl
,xh
,yh
) {
297 x
= (xl
== xh
) ? xl
: (xl
+ rn2(xh
-xl
+1));
298 y
= (yl
== yh
) ? yl
: (yl
+ rn2(yh
-yl
+1));
302 for(x
= xl
; x
<= xh
; x
++) for(y
= yl
; y
<= yh
; y
++)
306 for(x
= xl
; x
<= xh
; x
++) for(y
= yl
; y
<= yh
; y
++)
307 if(levl
[x
][y
].typ
== DOOR
|| levl
[x
][y
].typ
== SDOOR
)
309 /* cannot find something reasonable -- strange */
318 /* see whether it is allowable to create a door at [x,y] */
322 if(levl
[x
-1][y
].typ
== DOOR
|| levl
[x
+1][y
].typ
== DOOR
||
323 levl
[x
][y
+1].typ
== DOOR
|| levl
[x
][y
-1].typ
== DOOR
||
324 levl
[x
-1][y
].typ
== SDOOR
|| levl
[x
+1][y
].typ
== SDOOR
||
325 levl
[x
][y
-1].typ
== SDOOR
|| levl
[x
][y
+1].typ
== SDOOR
||
326 (levl
[x
][y
].typ
!= HWALL
&& levl
[x
][y
].typ
!= VWALL
) ||
327 doorindex
>= DOORMAX
)
334 register struct mkroom
*aroom
;
336 if(doorindex
>= DOORMAX
) {
337 impossible("DOORMAX exceeded?");
340 if(!okdoor(x
,y
) && nxcor
)
342 dosdoor(x
,y
,aroom
,rn2(8) ? DOOR
: SDOOR
);
345 dosdoor(x
,y
,aroom
,type
)
347 register struct mkroom
*aroom
;
350 register struct mkroom
*broom
;
353 if(!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs with '+' as scrsym */
355 levl
[x
][y
].typ
= type
;
357 levl
[x
][y
].scrsym
= '+';
360 if(broom
->hx
< 0) tmp
= doorindex
; else
361 for(tmp
= doorindex
; tmp
> broom
->fdoor
; tmp
--)
362 doors
[tmp
] = doors
[tmp
-1];
366 for( ; broom
->hx
>= 0; broom
++) broom
->fdoor
++;
369 /* Only called from makerooms() */
370 maker(lowx
,ddx
,lowy
,ddy
)
371 schar lowx
,ddx
,lowy
,ddy
;
373 register struct mkroom
*croom
;
374 register x
, y
, hix
= lowx
+ddx
, hiy
= lowy
+ddy
;
375 register xlim
= XLIM
+ secret
, ylim
= YLIM
+ secret
;
377 if(nroom
>= MAXNROFROOMS
) return(0);
378 if(lowx
< XLIM
) lowx
= XLIM
;
379 if(lowy
< YLIM
) lowy
= YLIM
;
380 if(hix
> COLNO
-XLIM
-1) hix
= COLNO
-XLIM
-1;
381 if(hiy
> ROWNO
-YLIM
-1) hiy
= ROWNO
-YLIM
-1;
383 if(hix
<= lowx
|| hiy
<= lowy
) return(0);
385 /* check area around room (and make room smaller if necessary) */
386 for(x
= lowx
- xlim
; x
<= hix
+ xlim
; x
++) {
387 for(y
= lowy
- ylim
; y
<= hiy
+ ylim
; y
++) {
390 if(wizard
&& !secret
)
391 pline("Strange area [%d,%d] in maker().",x
,y
);
393 if(!rn2(3)) return(0);
407 croom
= &rooms
[nroom
];
409 /* on low levels the room is lit (usually) */
410 /* secret vaults are always lit */
411 if((rnd(dlevel
) < 10 && rn2(77)) || (ddx
== 1 && ddy
== 1)) {
412 for(x
= lowx
-1; x
<= hix
+1; x
++)
413 for(y
= lowy
-1; y
<= hiy
+1; y
++)
422 croom
->rtype
= croom
->doorct
= croom
->fdoor
= 0;
424 for(x
= lowx
-1; x
<= hix
+1; x
++)
425 for(y
= lowy
-1; y
<= hiy
+1; y
+= (hiy
-lowy
+2)) {
426 levl
[x
][y
].scrsym
= '-';
427 levl
[x
][y
].typ
= HWALL
;
429 for(x
= lowx
-1; x
<= hix
+1; x
+= (hix
-lowx
+2))
430 for(y
= lowy
; y
<= hiy
; y
++) {
431 levl
[x
][y
].scrsym
= '|';
432 levl
[x
][y
].typ
= VWALL
;
434 for(x
= lowx
; x
<= hix
; x
++)
435 for(y
= lowy
; y
<= hiy
; y
++) {
436 levl
[x
][y
].scrsym
= '.';
437 levl
[x
][y
].typ
= ROOM
;
451 for(a
= 0; a
< nroom
-1; a
++)
453 for(a
= 0; a
< nroom
-2; a
++)
454 if(smeq
[a
] != smeq
[a
+2])
456 for(a
= 0; a
< nroom
; a
++)
457 for(b
= 0; b
< nroom
; b
++)
458 if(smeq
[a
] != smeq
[b
])
461 for(nxcor
= rn2(nroom
) + 4; nxcor
; nxcor
--) {
473 register tx
, ty
, xx
, yy
;
474 register struct rm
*crm
;
475 register struct mkroom
*croom
, *troom
;
476 register dx
, dy
, dix
, diy
, cct
;
481 /* find positions cc and tt for doors in croom and troom
482 and direction for a corridor between them */
484 if(troom
->hx
< 0 || croom
->hx
< 0 || doorindex
>= DOORMAX
) return;
485 if(troom
->lx
> croom
->hx
) {
490 cc
= finddpos(xx
,croom
->ly
,xx
,croom
->hy
);
491 tt
= finddpos(tx
,troom
->ly
,tx
,troom
->hy
);
492 } else if(troom
->hy
< croom
->ly
) {
496 cc
= finddpos(croom
->lx
,yy
,croom
->hx
,yy
);
498 tt
= finddpos(troom
->lx
,ty
,troom
->hx
,ty
);
499 } else if(troom
->hx
< croom
->lx
) {
504 cc
= finddpos(xx
,croom
->ly
,xx
,croom
->hy
);
505 tt
= finddpos(tx
,troom
->ly
,tx
,troom
->hy
);
511 cc
= finddpos(croom
->lx
,yy
,croom
->hx
,yy
);
512 tt
= finddpos(troom
->lx
,ty
,troom
->hx
,ty
);
518 if(nxcor
&& levl
[xx
+dx
][yy
+dy
].typ
)
523 while(xx
!= tx
|| yy
!= ty
) {
527 /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
528 if(cct
++ > 500 || (nxcor
&& !rn2(35)))
531 if(xx
== COLNO
-1 || xx
== 0 || yy
== 0 || yy
== ROWNO
-1)
532 return; /* impossible */
538 crm
->scrsym
= CORR_SYM
;
539 if(nxcor
&& !rn2(50))
540 (void) mkobj_at(ROCK_SYM
, xx
, yy
);
546 if(crm
->typ
!= CORR
&& crm
->typ
!= SCORR
) {
551 /* find next corridor position */
555 /* do we have to change direction ? */
556 if(dy
&& dix
> diy
) {
557 register ddx
= (xx
> tx
) ? -1 : 1;
559 crm
= &levl
[xx
+ddx
][yy
];
560 if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
565 } else if(dx
&& diy
> dix
) {
566 register ddy
= (yy
> ty
) ? -1 : 1;
568 crm
= &levl
[xx
][yy
+ddy
];
569 if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
576 /* continue straight on? */
577 crm
= &levl
[xx
+dx
][yy
+dy
];
578 if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
581 /* no, what must we do now?? */
584 dy
= (ty
< yy
) ? -1 : 1;
585 crm
= &levl
[xx
+dx
][yy
+dy
];
586 if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
592 dx
= (tx
< xx
) ? -1 : 1;
593 crm
= &levl
[xx
+dx
][yy
+dy
];
594 if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
601 /* we succeeded in digging the corridor */
602 dodoor(tt
.x
, tt
.y
, troom
);
604 if(smeq
[a
] < smeq
[b
])
612 register int ct
= rnd(nroom
/2 + 1);
613 while(ct
--) makeniche(FALSE
);
624 register struct mkroom
*aroom
;
625 register struct rm
*rm
;
626 register int vct
= 8;
629 register struct trap
*ttmp
;
631 if(doorindex
< DOORMAX
)
633 aroom
= &rooms
[rn2(nroom
-1)];
634 if(aroom
->rtype
!= 0) continue; /* not an ordinary room */
635 if(aroom
->doorct
== 1 && rn2(5)) continue;
638 dd
= finddpos(aroom
->lx
,aroom
->hy
+1,aroom
->hx
,aroom
->hy
+1);
641 dd
= finddpos(aroom
->lx
,aroom
->ly
-1,aroom
->hx
,aroom
->ly
-1);
645 if((rm
= &levl
[xx
][yy
+dy
])->typ
) continue;
646 if(with_trap
|| !rn2(4)) {
650 ttmp
= maketrap(xx
, yy
+dy
, TELEP_TRAP
);
652 make_engr_at(xx
, yy
-dy
, "ad ae?ar um");
654 dosdoor(xx
, yy
, aroom
, SDOOR
);
657 rm
->scrsym
= CORR_SYM
;
659 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
661 mksobj_at(SCR_TELEPORTATION
, xx
, yy
+dy
);
662 if(!rn2(3)) (void) mkobj_at(0, xx
, yy
+dy
);
669 /* make a trap somewhere (in croom if mazeflag = 0) */
670 mktrap(num
,mazeflag
,croom
)
671 register num
,mazeflag
;
672 register struct mkroom
*croom
;
674 register struct trap
*ttmp
;
675 register int kind
,nopierc
,nomimic
,fakedoor
,fakegold
,tryct
= 0;
676 register xchar mx
,my
;
677 extern char fut_geno
[];
679 if(!num
|| num
>= TRAPNUM
) {
680 nopierc
= (dlevel
< 4) ? 1 : 0;
681 nomimic
= (dlevel
< 9 || goldseen
) ? 1 : 0;
682 if(index(fut_geno
, 'M')) nomimic
= 1;
683 kind
= rn2(TRAPNUM
- nopierc
- nomimic
);
684 /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
688 register struct monst
*mtmp
;
690 fakedoor
= (!rn2(3) && !mazeflag
);
691 fakegold
= (!fakedoor
&& !rn2(2));
692 if(fakegold
) goldseen
= TRUE
;
694 if(++tryct
> 200) return;
696 /* note: fakedoor maybe on actual door */
700 else mx
= croom
->lx
-1;
705 else my
= croom
->ly
-1;
708 } else if(mazeflag
) {
709 extern coord
mazexy();
718 } while(m_at(mx
,my
) || levl
[mx
][my
].typ
== STAIRS
);
719 if(mtmp
= makemon(PM_MIMIC
,mx
,my
)) {
722 fakegold
? '$' : fakedoor
? '+' :
723 (mazeflag
&& rn2(2)) ? AMULET_SYM
:
724 "=/)%?![<>" [ rn2(9) ];
733 extern coord
mazexy();
742 } while(t_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
743 ttmp
= maketrap(mx
, my
, kind
);
744 if(mazeflag
&& !rn2(10) && ttmp
->ttyp
< PIERC
)