]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.mklev.c
1 /* $NetBSD: hack.mklev.c,v 1.4 1997/10/19 16:58:24 christos Exp $ */
4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
9 __RCSID("$NetBSD: hack.mklev.c,v 1.4 1997/10/19 16:58:24 christos Exp $");
17 #define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
18 #define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
20 #include "def.mkroom.h"
21 #define XLIM 4 /* define minimum required space around a
24 boolean secret
; /* TRUE while making a vault: increase
26 struct mkroom rooms
[MAXNROFROOMS
+ 1];
27 int smeq
[MAXNROFROOMS
+ 1];
34 xchar xdnstair
, xupstair
, ydnstair
, yupstair
;
36 /* Definitions used by makerooms() and addrs() */
37 #define MAXRS 50 /* max lth of temp rectangle table -
40 xchar rlx
, rly
, rhx
, rhy
;
42 int rscnt
, rsmax
; /* 0..rscnt-1: currently under consideration */
43 /* rscnt..rsmax: discarded */
48 struct mkroom
*croom
, *troom
;
54 rooms
[0].hx
= -1; /* in case we are in a maze */
56 for (x
= 0; x
< COLNO
; x
++)
57 for (y
= 0; y
< ROWNO
; y
++)
60 oinit(); /* assign level dependent obj probabilities */
62 if (dlevel
>= rn1(3, 26)) { /* there might be several mazes */
66 /* construct the rooms */
71 /* construct stairs (up and down in different rooms if possible) */
72 croom
= &rooms
[rn2(nroom
)];
75 levl
[xdnstair
][ydnstair
].scrsym
= '>';
76 levl
[xdnstair
][ydnstair
].typ
= STAIRS
;
79 croom
= &rooms
[rn2(nroom
- 1)];
83 xupstair
= somex(); /* %% < and > might be in the same place */
85 levl
[xupstair
][yupstair
].scrsym
= '<';
86 levl
[xupstair
][yupstair
].typ
= STAIRS
;
88 /* for each room: put things inside */
89 for (croom
= rooms
; croom
->hx
> 0; croom
++) {
91 /* put a sleeping monster inside */
93 * Note: monster may be on the stairs. This cannot be
94 * avoided: maybe the player fell through a trapdoor while a
95 * monster was on the stairs. Conclusion: we have to check
96 * for monsters on the stairs anyway.
100 makemon((struct permonst
*) 0, somex(), somey());
102 /* put traps and mimics inside */
104 while (!rn2(8 - (dlevel
/ 6)))
106 if (!goldseen
&& !rn2(3))
107 mkgold(0L, somex(), somey());
109 (void) mkobj_at(0, somex(), somey());
113 printf("tryct overflow4\n");
116 (void) mkobj_at(0, somex(), somey());
121 qsort((char *) rooms
, nroom
, sizeof(struct mkroom
), comp
);
125 /* make a secret treasure vault, not connected to the rest */
126 if (nroom
<= (2 * MAXNROFROOMS
/ 3))
128 troom
= &rooms
[nroom
];
131 troom
->rtype
= VAULT
; /* treasure vault */
132 for (x
= troom
->lx
; x
<= troom
->hx
; x
++)
133 for (y
= troom
->ly
; y
<= troom
->hy
; y
++)
134 mkgold((long) (rnd(dlevel
* 100) + 50), x
, y
);
141 if (wizard
&& getenv("SHOPTYPE"))
145 if (dlevel
> 1 && dlevel
< 20 && rn2(dlevel
) < 3)
147 else if (dlevel
> 6 && !rn2(7))
149 else if (dlevel
> 9 && !rn2(5))
151 else if (dlevel
> 11 && !rn2(6))
153 else if (dlevel
> 18 && !rn2(6))
161 struct rectangle
*rsp
;
162 int lx
, ly
, hx
, hy
, lowx
, lowy
, hix
, hiy
, dx
, dy
;
163 int tryct
= 0, xlim
, ylim
;
166 xlim
= XLIM
+ secret
;
167 ylim
= YLIM
+ secret
;
170 rsp
->rlx
= rsp
->rly
= 0;
171 rsp
->rhx
= COLNO
- 1;
172 rsp
->rhy
= ROWNO
- 1;
177 /* make rooms until satisfied */
178 while (rscnt
> 0 && nroom
< MAXNROFROOMS
- 1) {
179 if (!secret
&& nroom
> (MAXNROFROOMS
/ 3) &&
180 !rn2((MAXNROFROOMS
- nroom
) * (MAXNROFROOMS
- nroom
)))
183 /* pick a rectangle */
184 rsp
= &rs
[rn2(rscnt
)];
190 /* find size of room */
194 dx
= 2 + rn2((hx
- lx
- 8 > 20) ? 12 : 8);
200 /* look whether our room will fit */
201 if (hx
- lx
< dx
+ dx
/ 2 + 2 * xlim
|| hy
- ly
< dy
+ dy
/ 3 + 2 * ylim
) {
203 /* maybe we throw this area out */
204 if (secret
|| !rn2(MAXNROFROOMS
+ 1 - nroom
- tryct
)) {
208 rs
[rscnt
] = rs
[rsmax
];
214 lowx
= lx
+ xlim
+ rn2(hx
- lx
- dx
- 2 * xlim
+ 1);
215 lowy
= ly
+ ylim
+ rn2(hy
- ly
- dy
- 2 * ylim
+ 1);
219 if (maker(lowx
, dx
, lowy
, dy
)) {
222 addrs(lowx
- 1, lowy
- 1, hix
+ 1, hiy
+ 1);
224 } else if (tryct
++ > 100)
227 return (0); /* failed to make vault - very strange */
231 addrs(lowx
, lowy
, hix
, hiy
)
232 int lowx
, lowy
, hix
, hiy
;
234 struct rectangle
*rsp
;
235 int lx
, ly
, hx
, hy
, xlim
, ylim
;
238 xlim
= XLIM
+ secret
;
239 ylim
= YLIM
+ secret
;
241 /* walk down since rscnt and rsmax change */
242 for (rsp
= &rs
[rsmax
- 1]; rsp
>= rs
; rsp
--) {
244 if ((lx
= rsp
->rlx
) > hix
|| (ly
= rsp
->rly
) > hiy
||
245 (hx
= rsp
->rhx
) < lowx
|| (hy
= rsp
->rhy
) < lowy
)
247 if ((discarded
= (rsp
>= &rs
[rscnt
]))) {
254 rs
[rscnt
] = rs
[rsmax
];
256 if (lowy
- ly
> 2 * ylim
+ 4)
257 addrsx(lx
, ly
, hx
, lowy
- 2, discarded
);
258 if (lowx
- lx
> 2 * xlim
+ 4)
259 addrsx(lx
, ly
, lowx
- 2, hy
, discarded
);
260 if (hy
- hiy
> 2 * ylim
+ 4)
261 addrsx(lx
, hiy
+ 2, hx
, hy
, discarded
);
262 if (hx
- hix
> 2 * xlim
+ 4)
263 addrsx(hix
+ 2, ly
, hx
, hy
, discarded
);
268 addrsx(lx
, ly
, hx
, hy
, discarded
)
270 boolean discarded
; /* piece of a discarded area */
272 struct rectangle
*rsp
;
274 /* check inclusions */
275 for (rsp
= rs
; rsp
< &rs
[rsmax
]; rsp
++) {
276 if (lx
>= rsp
->rlx
&& hx
<= rsp
->rhx
&&
277 ly
>= rsp
->rly
&& hy
<= rsp
->rhy
)
281 /* make a new entry */
282 if (rsmax
>= MAXRS
) {
285 pline("MAXRS may be too small.");
305 const struct mkroom
*x
= vx
, *y
= vy
;
308 return (x
->lx
> y
->lx
);
312 finddpos(xl
, yl
, xh
, yh
)
317 x
= (xl
== xh
) ? xl
: (xl
+ rn2(xh
- xl
+ 1));
318 y
= (yl
== yh
) ? yl
: (yl
+ rn2(yh
- yl
+ 1));
322 for (x
= xl
; x
<= xh
; x
++)
323 for (y
= yl
; y
<= yh
; y
++)
327 for (x
= xl
; x
<= xh
; x
++)
328 for (y
= yl
; y
<= yh
; y
++)
329 if (levl
[x
][y
].typ
== DOOR
|| levl
[x
][y
].typ
== SDOOR
)
331 /* cannot find something reasonable -- strange */
340 /* see whether it is allowable to create a door at [x,y] */
345 if (levl
[x
- 1][y
].typ
== DOOR
|| levl
[x
+ 1][y
].typ
== DOOR
||
346 levl
[x
][y
+ 1].typ
== DOOR
|| levl
[x
][y
- 1].typ
== DOOR
||
347 levl
[x
- 1][y
].typ
== SDOOR
|| levl
[x
+ 1][y
].typ
== SDOOR
||
348 levl
[x
][y
- 1].typ
== SDOOR
|| levl
[x
][y
+ 1].typ
== SDOOR
||
349 (levl
[x
][y
].typ
!= HWALL
&& levl
[x
][y
].typ
!= VWALL
) ||
350 doorindex
>= DOORMAX
)
358 struct mkroom
*aroom
;
360 if (doorindex
>= DOORMAX
) {
361 impossible("DOORMAX exceeded?");
364 if (!okdoor(x
, y
) && nxcor
)
366 dosdoor(x
, y
, aroom
, rn2(8) ? DOOR
: SDOOR
);
370 dosdoor(x
, y
, aroom
, type
)
372 struct mkroom
*aroom
;
375 struct mkroom
*broom
;
378 if (!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs with '+' as scrsym */
380 levl
[x
][y
].typ
= type
;
382 levl
[x
][y
].scrsym
= '+';
388 for (tmp
= doorindex
; tmp
> broom
->fdoor
; tmp
--)
389 doors
[tmp
] = doors
[tmp
- 1];
393 for (; broom
->hx
>= 0; broom
++)
397 /* Only called from makerooms() */
399 maker(lowx
, ddx
, lowy
, ddy
)
400 schar lowx
, ddx
, lowy
, ddy
;
402 struct mkroom
*croom
;
403 int x
, y
, hix
= lowx
+ ddx
, hiy
= lowy
+ ddy
;
404 int xlim
= XLIM
+ secret
, ylim
= YLIM
+ secret
;
406 if (nroom
>= MAXNROFROOMS
)
412 if (hix
> COLNO
- XLIM
- 1)
413 hix
= COLNO
- XLIM
- 1;
414 if (hiy
> ROWNO
- YLIM
- 1)
415 hiy
= ROWNO
- YLIM
- 1;
417 if (hix
<= lowx
|| hiy
<= lowy
)
420 /* check area around room (and make room smaller if necessary) */
421 for (x
= lowx
- xlim
; x
<= hix
+ xlim
; x
++) {
422 for (y
= lowy
- ylim
; y
<= hiy
+ ylim
; y
++) {
423 if (levl
[x
][y
].typ
) {
425 if (wizard
&& !secret
)
426 pline("Strange area [%d,%d] in maker().", x
, y
);
443 croom
= &rooms
[nroom
];
445 /* on low levels the room is lit (usually) */
446 /* secret vaults are always lit */
447 if ((rnd(dlevel
) < 10 && rn2(77)) || (ddx
== 1 && ddy
== 1)) {
448 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
449 for (y
= lowy
- 1; y
<= hiy
+ 1; y
++)
458 croom
->rtype
= croom
->doorct
= croom
->fdoor
= 0;
460 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
461 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
462 levl
[x
][y
].scrsym
= '-';
463 levl
[x
][y
].typ
= HWALL
;
465 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
466 for (y
= lowy
; y
<= hiy
; y
++) {
467 levl
[x
][y
].scrsym
= '|';
468 levl
[x
][y
].typ
= VWALL
;
470 for (x
= lowx
; x
<= hix
; x
++)
471 for (y
= lowy
; y
<= hiy
; y
++) {
472 levl
[x
][y
].scrsym
= '.';
473 levl
[x
][y
].typ
= ROOM
;
489 for (a
= 0; a
< nroom
- 1; a
++)
491 for (a
= 0; a
< nroom
- 2; a
++)
492 if (smeq
[a
] != smeq
[a
+ 2])
494 for (a
= 0; a
< nroom
; a
++)
495 for (b
= 0; b
< nroom
; b
++)
496 if (smeq
[a
] != smeq
[b
])
499 for (nxcor
= rn2(nroom
) + 4; nxcor
; nxcor
--) {
515 struct mkroom
*croom
, *troom
;
516 int dx
, dy
, dix
, diy
, cct
;
522 * find positions cc and tt for doors in croom and troom and
523 * direction for a corridor between them
526 if (troom
->hx
< 0 || croom
->hx
< 0 || doorindex
>= DOORMAX
)
528 if (troom
->lx
> croom
->hx
) {
533 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
534 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
535 } else if (troom
->hy
< croom
->ly
) {
539 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
541 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
542 } else if (troom
->hx
< croom
->lx
) {
547 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
548 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
554 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
555 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
561 if (nxcor
&& levl
[xx
+ dx
][yy
+ dy
].typ
)
563 dodoor(xx
, yy
, croom
);
566 while (xx
!= tx
|| yy
!= ty
) {
570 /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
571 if (cct
++ > 500 || (nxcor
&& !rn2(35)))
574 if (xx
== COLNO
- 1 || xx
== 0 || yy
== 0 || yy
== ROWNO
- 1)
575 return; /* impossible */
581 crm
->scrsym
= CORR_SYM
;
582 if (nxcor
&& !rn2(50))
583 (void) mkobj_at(ROCK_SYM
, xx
, yy
);
588 } else if (crm
->typ
!= CORR
&& crm
->typ
!= SCORR
) {
592 /* find next corridor position */
596 /* do we have to change direction ? */
597 if (dy
&& dix
> diy
) {
598 int ddx
= (xx
> tx
) ? -1 : 1;
600 crm
= &levl
[xx
+ ddx
][yy
];
601 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
606 } else if (dx
&& diy
> dix
) {
607 int ddy
= (yy
> ty
) ? -1 : 1;
609 crm
= &levl
[xx
][yy
+ ddy
];
610 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
616 /* continue straight on? */
617 crm
= &levl
[xx
+ dx
][yy
+ dy
];
618 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
621 /* no, what must we do now?? */
624 dy
= (ty
< yy
) ? -1 : 1;
625 crm
= &levl
[xx
+ dx
][yy
+ dy
];
626 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
632 dx
= (tx
< xx
) ? -1 : 1;
633 crm
= &levl
[xx
+ dx
][yy
+ dy
];
634 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
641 /* we succeeded in digging the corridor */
642 dodoor(tt
.x
, tt
.y
, troom
);
644 if (smeq
[a
] < smeq
[b
])
653 int ct
= rnd(nroom
/ 2 + 1);
668 struct mkroom
*aroom
;
675 if (doorindex
< DOORMAX
)
677 aroom
= &rooms
[rn2(nroom
- 1)];
678 if (aroom
->rtype
!= 0)
679 continue; /* not an ordinary room */
680 if (aroom
->doorct
== 1 && rn2(5))
684 dd
= finddpos(aroom
->lx
, aroom
->hy
+ 1, aroom
->hx
, aroom
->hy
+ 1);
687 dd
= finddpos(aroom
->lx
, aroom
->ly
- 1, aroom
->hx
, aroom
->ly
- 1);
691 if ((rm
= &levl
[xx
][yy
+ dy
])->typ
)
693 if (with_trap
|| !rn2(4)) {
697 ttmp
= maketrap(xx
, yy
+ dy
, TELEP_TRAP
);
699 make_engr_at(xx
, yy
- dy
, "ad ae?ar um");
701 dosdoor(xx
, yy
, aroom
, SDOOR
);
704 rm
->scrsym
= CORR_SYM
;
706 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
708 mksobj_at(SCR_TELEPORTATION
, xx
, yy
+ dy
);
710 (void) mkobj_at(0, xx
, yy
+ dy
);
717 /* make a trap somewhere (in croom if mazeflag = 0) */
719 mktrap(num
, mazeflag
, croom
)
721 struct mkroom
*croom
;
724 int kind
, nopierc
, nomimic
, fakedoor
, fakegold
, tryct
= 0;
727 if (!num
|| num
>= TRAPNUM
) {
728 nopierc
= (dlevel
< 4) ? 1 : 0;
729 nomimic
= (dlevel
< 9 || goldseen
) ? 1 : 0;
730 if (strchr(fut_geno
, 'M'))
732 kind
= rn2(TRAPNUM
- nopierc
- nomimic
);
733 /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
740 fakedoor
= (!rn2(3) && !mazeflag
);
741 fakegold
= (!fakedoor
&& !rn2(2));
748 /* note: fakedoor maybe on actual door */
762 } else if (mazeflag
) {
771 } while (m_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
772 if ((mtmp
= makemon(PM_MIMIC
, mx
, my
)) != NULL
) {
775 fakegold
? '$' : fakedoor
? '+' :
776 (mazeflag
&& rn2(2)) ? AMULET_SYM
:
793 } while (t_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
794 ttmp
= maketrap(mx
, my
, kind
);
795 if (mazeflag
&& !rn2(10) && ttmp
->ttyp
< PIERC
)