/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.mklev.c - version 1.0.3 */
extern char *getlogin(), *getenv();
extern struct monst
*makemon();
extern struct obj
*mkobj_at();
extern struct trap
*maketrap();
#define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
#define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
#define XLIM 4 /* define minimum required space around a room */
boolean secret
; /* TRUE while making a vault: increase [XY]LIM */
struct mkroom rooms
[MAXNROFROOMS
+1];
int smeq
[MAXNROFROOMS
+1];
xchar xdnstair
,xupstair
,ydnstair
,yupstair
;
/* Definitions used by makerooms() and addrs() */
#define MAXRS 50 /* max lth of temp rectangle table - arbitrary */
int rscnt
,rsmax
; /* 0..rscnt-1: currently under consideration */
/* rscnt..rsmax: discarded */
register struct mkroom
*croom
, *troom
;
rooms
[0].hx
= -1; /* in case we are in a maze */
for(x
=0; x
<COLNO
; x
++) for(y
=0; y
<ROWNO
; y
++)
oinit(); /* assign level dependent obj probabilities */
if(dlevel
>= rn1(3, 26)) { /* there might be several mazes */
/* construct the rooms */
/* construct stairs (up and down in different rooms if possible) */
croom
= &rooms
[rn2(nroom
)];
levl
[xdnstair
][ydnstair
].scrsym
='>';
levl
[xdnstair
][ydnstair
].typ
= STAIRS
;
croom
= &rooms
[rn2(nroom
-1)];
if(croom
>= troom
) croom
++;
xupstair
= somex(); /* %% < and > might be in the same place */
levl
[xupstair
][yupstair
].scrsym
='<';
levl
[xupstair
][yupstair
].typ
= STAIRS
;
/* for each room: put things inside */
for(croom
= rooms
; croom
->hx
> 0; croom
++) {
/* put a sleeping monster inside */
/* Note: monster may be on the stairs. This cannot be
avoided: maybe the player fell through a trapdoor
while a monster was on the stairs. Conclusion:
we have to check for monsters on the stairs anyway. */
makemon((struct permonst
*) 0, somex(), somey());
/* put traps and mimics inside */
while(!rn2(8-(dlevel
/6))) mktrap(0,0,croom
);
if(!goldseen
&& !rn2(3)) mkgold(0L,somex(),somey());
(void) mkobj_at(0, somex(), somey());
printf("tryct overflow4\n");
(void) mkobj_at(0, somex(), somey());
qsort((char *) rooms
, nroom
, sizeof(struct mkroom
), comp
);
/* make a secret treasure vault, not connected to the rest */
if(nroom
<= (2*MAXNROFROOMS
/3)) if(rn2(3)) {
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(wizard
&& getenv("SHOPTYPE")) mkshop(); else
if(dlevel
> 1 && dlevel
< 20 && rn2(dlevel
) < 3) mkshop();
if(dlevel
> 6 && !rn2(7)) mkzoo(ZOO
);
if(dlevel
> 9 && !rn2(5)) mkzoo(BEEHIVE
);
if(dlevel
> 11 && !rn2(6)) mkzoo(MORGUE
);
if(dlevel
> 18 && !rn2(6)) mkswamp();
register struct rectangle
*rsp
;
register int lx
, ly
, hx
, hy
, lowx
, lowy
, hix
, hiy
, dx
, dy
;
int tryct
= 0, xlim
, ylim
;
/* make rooms until satisfied */
while(rscnt
> 0 && nroom
< MAXNROFROOMS
-1) {
if(!secret
&& nroom
> (MAXNROFROOMS
/3) &&
!rn2((MAXNROFROOMS
-nroom
)*(MAXNROFROOMS
-nroom
)))
dx
= 2 + rn2((hx
-lx
-8 > 20) ? 12 : 8);
/* look whether our room will fit */
if(hx
-lx
< dx
+ dx
/2 + 2*xlim
|| hy
-ly
< dy
+ dy
/3 + 2*ylim
) {
/* maybe we throw this area out */
if(secret
|| !rn2(MAXNROFROOMS
+1-nroom
-tryct
)) {
lowx
= lx
+ xlim
+ rn2(hx
- lx
- dx
- 2*xlim
+ 1);
lowy
= ly
+ ylim
+ rn2(hy
- ly
- dy
- 2*ylim
+ 1);
if(maker(lowx
, dx
, lowy
, dy
)) {
addrs(lowx
-1, lowy
-1, hix
+1, hiy
+1);
return(0); /* failed to make vault - very strange */
register int lowx
,lowy
,hix
,hiy
;
register struct rectangle
*rsp
;
register int lx
,ly
,hx
,hy
,xlim
,ylim
;
/* 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
)
if((discarded
= (rsp
>= &rs
[rscnt
]))) {
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
);
addrsx(lx
,ly
,hx
,hy
,discarded
)
register int lx
,ly
,hx
,hy
;
boolean discarded
; /* piece of a discarded area */
register struct rectangle
*rsp
;
for(rsp
= rs
; rsp
< &rs
[rsmax
]; rsp
++) {
if(lx
>= rsp
->rlx
&& hx
<= rsp
->rhx
&&
ly
>= rsp
->rly
&& hy
<= rsp
->rhy
)
if(wizard
) pline("MAXRS may be too small.");
register struct mkroom
*x
,*y
;
if(x
->lx
< y
->lx
) return(-1);
x
= (xl
== xh
) ? xl
: (xl
+ rn2(xh
-xl
+1));
y
= (yl
== yh
) ? yl
: (yl
+ rn2(yh
-yl
+1));
for(x
= xl
; x
<= xh
; x
++) for(y
= yl
; y
<= yh
; y
++)
for(x
= xl
; x
<= xh
; x
++) for(y
= yl
; y
<= yh
; y
++)
if(levl
[x
][y
].typ
== DOOR
|| levl
[x
][y
].typ
== SDOOR
)
/* cannot find something reasonable -- strange */
/* see whether it is allowable to create a door at [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
) ||
register struct mkroom
*aroom
;
if(doorindex
>= DOORMAX
) {
impossible("DOORMAX exceeded?");
if(!okdoor(x
,y
) && nxcor
)
dosdoor(x
,y
,aroom
,rn2(8) ? DOOR
: SDOOR
);
register struct mkroom
*aroom
;
register struct mkroom
*broom
;
if(!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs with '+' as scrsym */
if(broom
->hx
< 0) tmp
= doorindex
; else
for(tmp
= doorindex
; tmp
> broom
->fdoor
; tmp
--)
doors
[tmp
] = doors
[tmp
-1];
for( ; broom
->hx
>= 0; broom
++) broom
->fdoor
++;
/* Only called from makerooms() */
register struct mkroom
*croom
;
register x
, y
, hix
= lowx
+ddx
, hiy
= lowy
+ddy
;
register 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;
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
++) {
pline("Strange area [%d,%d] in maker().",x
,y
);
/* 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
++)
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)) {
for(x
= lowx
-1; x
<= hix
+1; x
+= (hix
-lowx
+2))
for(y
= lowy
; y
<= hiy
; y
++) {
for(x
= lowx
; x
<= hix
; x
++)
for(y
= lowy
; y
<= hiy
; y
++) {
for(a
= 0; a
< nroom
-1; a
++)
for(a
= 0; a
< nroom
-2; a
++)
for(a
= 0; a
< nroom
; a
++)
for(b
= 0; b
< nroom
; b
++)
for(nxcor
= rn2(nroom
) + 4; nxcor
; nxcor
--) {
register struct mkroom
*croom
, *troom
;
register dx
, dy
, dix
, diy
, cct
;
/* 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
) {
cc
= finddpos(xx
,croom
->ly
,xx
,croom
->hy
);
tt
= finddpos(tx
,troom
->ly
,tx
,troom
->hy
);
} else if(troom
->hy
< croom
->ly
) {
cc
= finddpos(croom
->lx
,yy
,croom
->hx
,yy
);
tt
= finddpos(troom
->lx
,ty
,troom
->hx
,ty
);
} else if(troom
->hx
< croom
->lx
) {
cc
= finddpos(xx
,croom
->ly
,xx
,croom
->hy
);
tt
= finddpos(tx
,troom
->ly
,tx
,troom
->hy
);
cc
= finddpos(croom
->lx
,yy
,croom
->hx
,yy
);
tt
= finddpos(troom
->lx
,ty
,troom
->hx
,ty
);
if(nxcor
&& levl
[xx
+dx
][yy
+dy
].typ
)
while(xx
!= tx
|| yy
!= ty
) {
/* loop: dig corridor at [xx,yy] and find new [xx,yy] */
if(cct
++ > 500 || (nxcor
&& !rn2(35)))
if(xx
== COLNO
-1 || xx
== 0 || yy
== 0 || yy
== ROWNO
-1)
(void) mkobj_at(ROCK_SYM
, xx
, yy
);
if(crm
->typ
!= CORR
&& crm
->typ
!= SCORR
) {
/* find next corridor position */
/* do we have to change direction ? */
register ddx
= (xx
> tx
) ? -1 : 1;
if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
} else if(dx
&& diy
> dix
) {
register ddy
= (yy
> ty
) ? -1 : 1;
if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
/* continue straight on? */
crm
= &levl
[xx
+dx
][yy
+dy
];
if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
/* no, what must we do now?? */
crm
= &levl
[xx
+dx
][yy
+dy
];
if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
crm
= &levl
[xx
+dx
][yy
+dy
];
if(!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
/* we succeeded in digging the corridor */
dodoor(tt
.x
, tt
.y
, troom
);
register int ct
= rnd(nroom
/2 + 1);
while(ct
--) makeniche(FALSE
);
register struct mkroom
*aroom
;
register struct trap
*ttmp
;
aroom
= &rooms
[rn2(nroom
-1)];
if(aroom
->rtype
!= 0) continue; /* not an ordinary room */
if(aroom
->doorct
== 1 && rn2(5)) continue;
dd
= finddpos(aroom
->lx
,aroom
->hy
+1,aroom
->hx
,aroom
->hy
+1);
dd
= finddpos(aroom
->lx
,aroom
->ly
-1,aroom
->hx
,aroom
->ly
-1);
if((rm
= &levl
[xx
][yy
+dy
])->typ
) continue;
if(with_trap
|| !rn2(4)) {
ttmp
= maketrap(xx
, yy
+dy
, TELEP_TRAP
);
make_engr_at(xx
, yy
-dy
, "ad ae?ar um");
dosdoor(xx
, yy
, aroom
, SDOOR
);
dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
mksobj_at(SCR_TELEPORTATION
, xx
, yy
+dy
);
if(!rn2(3)) (void) mkobj_at(0, xx
, yy
+dy
);
/* make a trap somewhere (in croom if mazeflag = 0) */
mktrap(num
,mazeflag
,croom
)
register struct mkroom
*croom
;
register struct trap
*ttmp
;
register int kind
,nopierc
,nomimic
,fakedoor
,fakegold
,tryct
= 0;
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 */
register struct monst
*mtmp
;
fakedoor
= (!rn2(3) && !mazeflag
);
fakegold
= (!fakedoor
&& !rn2(2));
if(fakegold
) goldseen
= TRUE
;
if(++tryct
> 200) return;
/* note: fakedoor maybe on actual door */
} while(m_at(mx
,my
) || levl
[mx
][my
].typ
== STAIRS
);
if(mtmp
= makemon(PM_MIMIC
,mx
,my
)) {
fakegold
? '$' : fakedoor
? '+' :
(mazeflag
&& rn2(2)) ? AMULET_SYM
:
} while(t_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
ttmp
= maketrap(mx
, my
, kind
);
if(mazeflag
&& !rn2(10) && ttmp
->ttyp
< PIERC
)