]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.mklev.c
1 /* $NetBSD: hack.mklev.c,v 1.5 2001/03/25 20:44:01 jsm Exp $ */
4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
9 __RCSID("$NetBSD: hack.mklev.c,v 1.5 2001/03/25 20:44:01 jsm 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 int smeq
[MAXNROFROOMS
+ 1];
33 /* Definitions used by makerooms() and addrs() */
34 #define MAXRS 50 /* max lth of temp rectangle table -
37 xchar rlx
, rly
, rhx
, rhy
;
39 int rscnt
, rsmax
; /* 0..rscnt-1: currently under consideration */
40 /* rscnt..rsmax: discarded */
45 struct mkroom
*croom
, *troom
;
51 rooms
[0].hx
= -1; /* in case we are in a maze */
53 for (x
= 0; x
< COLNO
; x
++)
54 for (y
= 0; y
< ROWNO
; y
++)
57 oinit(); /* assign level dependent obj probabilities */
59 if (dlevel
>= rn1(3, 26)) { /* there might be several mazes */
63 /* construct the rooms */
68 /* construct stairs (up and down in different rooms if possible) */
69 croom
= &rooms
[rn2(nroom
)];
72 levl
[xdnstair
][ydnstair
].scrsym
= '>';
73 levl
[xdnstair
][ydnstair
].typ
= STAIRS
;
76 croom
= &rooms
[rn2(nroom
- 1)];
80 xupstair
= somex(); /* %% < and > might be in the same place */
82 levl
[xupstair
][yupstair
].scrsym
= '<';
83 levl
[xupstair
][yupstair
].typ
= STAIRS
;
85 /* for each room: put things inside */
86 for (croom
= rooms
; croom
->hx
> 0; croom
++) {
88 /* put a sleeping monster inside */
90 * Note: monster may be on the stairs. This cannot be
91 * avoided: maybe the player fell through a trapdoor while a
92 * monster was on the stairs. Conclusion: we have to check
93 * for monsters on the stairs anyway.
97 makemon((struct permonst
*) 0, somex(), somey());
99 /* put traps and mimics inside */
101 while (!rn2(8 - (dlevel
/ 6)))
103 if (!goldseen
&& !rn2(3))
104 mkgold(0L, somex(), somey());
106 (void) mkobj_at(0, somex(), somey());
110 printf("tryct overflow4\n");
113 (void) mkobj_at(0, somex(), somey());
118 qsort((char *) rooms
, nroom
, sizeof(struct mkroom
), comp
);
122 /* make a secret treasure vault, not connected to the rest */
123 if (nroom
<= (2 * MAXNROFROOMS
/ 3))
125 troom
= &rooms
[nroom
];
128 troom
->rtype
= VAULT
; /* treasure vault */
129 for (x
= troom
->lx
; x
<= troom
->hx
; x
++)
130 for (y
= troom
->ly
; y
<= troom
->hy
; y
++)
131 mkgold((long) (rnd(dlevel
* 100) + 50), x
, y
);
138 if (wizard
&& getenv("SHOPTYPE"))
142 if (dlevel
> 1 && dlevel
< 20 && rn2(dlevel
) < 3)
144 else if (dlevel
> 6 && !rn2(7))
146 else if (dlevel
> 9 && !rn2(5))
148 else if (dlevel
> 11 && !rn2(6))
150 else if (dlevel
> 18 && !rn2(6))
158 struct rectangle
*rsp
;
159 int lx
, ly
, hx
, hy
, lowx
, lowy
, hix
, hiy
, dx
, dy
;
160 int tryct
= 0, xlim
, ylim
;
163 xlim
= XLIM
+ secret
;
164 ylim
= YLIM
+ secret
;
167 rsp
->rlx
= rsp
->rly
= 0;
168 rsp
->rhx
= COLNO
- 1;
169 rsp
->rhy
= ROWNO
- 1;
174 /* make rooms until satisfied */
175 while (rscnt
> 0 && nroom
< MAXNROFROOMS
- 1) {
176 if (!secret
&& nroom
> (MAXNROFROOMS
/ 3) &&
177 !rn2((MAXNROFROOMS
- nroom
) * (MAXNROFROOMS
- nroom
)))
180 /* pick a rectangle */
181 rsp
= &rs
[rn2(rscnt
)];
187 /* find size of room */
191 dx
= 2 + rn2((hx
- lx
- 8 > 20) ? 12 : 8);
197 /* look whether our room will fit */
198 if (hx
- lx
< dx
+ dx
/ 2 + 2 * xlim
|| hy
- ly
< dy
+ dy
/ 3 + 2 * ylim
) {
200 /* maybe we throw this area out */
201 if (secret
|| !rn2(MAXNROFROOMS
+ 1 - nroom
- tryct
)) {
205 rs
[rscnt
] = rs
[rsmax
];
211 lowx
= lx
+ xlim
+ rn2(hx
- lx
- dx
- 2 * xlim
+ 1);
212 lowy
= ly
+ ylim
+ rn2(hy
- ly
- dy
- 2 * ylim
+ 1);
216 if (maker(lowx
, dx
, lowy
, dy
)) {
219 addrs(lowx
- 1, lowy
- 1, hix
+ 1, hiy
+ 1);
221 } else if (tryct
++ > 100)
224 return (0); /* failed to make vault - very strange */
228 addrs(lowx
, lowy
, hix
, hiy
)
229 int lowx
, lowy
, hix
, hiy
;
231 struct rectangle
*rsp
;
232 int lx
, ly
, hx
, hy
, xlim
, ylim
;
235 xlim
= XLIM
+ secret
;
236 ylim
= YLIM
+ secret
;
238 /* walk down since rscnt and rsmax change */
239 for (rsp
= &rs
[rsmax
- 1]; rsp
>= rs
; rsp
--) {
241 if ((lx
= rsp
->rlx
) > hix
|| (ly
= rsp
->rly
) > hiy
||
242 (hx
= rsp
->rhx
) < lowx
|| (hy
= rsp
->rhy
) < lowy
)
244 if ((discarded
= (rsp
>= &rs
[rscnt
]))) {
251 rs
[rscnt
] = rs
[rsmax
];
253 if (lowy
- ly
> 2 * ylim
+ 4)
254 addrsx(lx
, ly
, hx
, lowy
- 2, discarded
);
255 if (lowx
- lx
> 2 * xlim
+ 4)
256 addrsx(lx
, ly
, lowx
- 2, hy
, discarded
);
257 if (hy
- hiy
> 2 * ylim
+ 4)
258 addrsx(lx
, hiy
+ 2, hx
, hy
, discarded
);
259 if (hx
- hix
> 2 * xlim
+ 4)
260 addrsx(hix
+ 2, ly
, hx
, hy
, discarded
);
265 addrsx(lx
, ly
, hx
, hy
, discarded
)
267 boolean discarded
; /* piece of a discarded area */
269 struct rectangle
*rsp
;
271 /* check inclusions */
272 for (rsp
= rs
; rsp
< &rs
[rsmax
]; rsp
++) {
273 if (lx
>= rsp
->rlx
&& hx
<= rsp
->rhx
&&
274 ly
>= rsp
->rly
&& hy
<= rsp
->rhy
)
278 /* make a new entry */
279 if (rsmax
>= MAXRS
) {
282 pline("MAXRS may be too small.");
302 const struct mkroom
*x
= vx
, *y
= vy
;
305 return (x
->lx
> y
->lx
);
309 finddpos(int xl
, int yl
, int xh
, int yh
)
314 x
= (xl
== xh
) ? xl
: (xl
+ rn2(xh
- xl
+ 1));
315 y
= (yl
== yh
) ? yl
: (yl
+ rn2(yh
- yl
+ 1));
319 for (x
= xl
; x
<= xh
; x
++)
320 for (y
= yl
; y
<= yh
; y
++)
324 for (x
= xl
; x
<= xh
; x
++)
325 for (y
= yl
; y
<= yh
; y
++)
326 if (levl
[x
][y
].typ
== DOOR
|| levl
[x
][y
].typ
== SDOOR
)
328 /* cannot find something reasonable -- strange */
337 /* see whether it is allowable to create a door at [x,y] */
342 if (levl
[x
- 1][y
].typ
== DOOR
|| levl
[x
+ 1][y
].typ
== DOOR
||
343 levl
[x
][y
+ 1].typ
== DOOR
|| levl
[x
][y
- 1].typ
== DOOR
||
344 levl
[x
- 1][y
].typ
== SDOOR
|| levl
[x
+ 1][y
].typ
== SDOOR
||
345 levl
[x
][y
- 1].typ
== SDOOR
|| levl
[x
][y
+ 1].typ
== SDOOR
||
346 (levl
[x
][y
].typ
!= HWALL
&& levl
[x
][y
].typ
!= VWALL
) ||
347 doorindex
>= DOORMAX
)
355 struct mkroom
*aroom
;
357 if (doorindex
>= DOORMAX
) {
358 impossible("DOORMAX exceeded?");
361 if (!okdoor(x
, y
) && nxcor
)
363 dosdoor(x
, y
, aroom
, rn2(8) ? DOOR
: SDOOR
);
367 dosdoor(x
, y
, aroom
, type
)
369 struct mkroom
*aroom
;
372 struct mkroom
*broom
;
375 if (!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs with '+' as scrsym */
377 levl
[x
][y
].typ
= type
;
379 levl
[x
][y
].scrsym
= '+';
385 for (tmp
= doorindex
; tmp
> broom
->fdoor
; tmp
--)
386 doors
[tmp
] = doors
[tmp
- 1];
390 for (; broom
->hx
>= 0; broom
++)
394 /* Only called from makerooms() */
396 maker(lowx
, ddx
, lowy
, ddy
)
397 schar lowx
, ddx
, lowy
, ddy
;
399 struct mkroom
*croom
;
400 int x
, y
, hix
= lowx
+ ddx
, hiy
= lowy
+ ddy
;
401 int xlim
= XLIM
+ secret
, ylim
= YLIM
+ secret
;
403 if (nroom
>= MAXNROFROOMS
)
409 if (hix
> COLNO
- XLIM
- 1)
410 hix
= COLNO
- XLIM
- 1;
411 if (hiy
> ROWNO
- YLIM
- 1)
412 hiy
= ROWNO
- YLIM
- 1;
414 if (hix
<= lowx
|| hiy
<= lowy
)
417 /* check area around room (and make room smaller if necessary) */
418 for (x
= lowx
- xlim
; x
<= hix
+ xlim
; x
++) {
419 for (y
= lowy
- ylim
; y
<= hiy
+ ylim
; y
++) {
420 if (levl
[x
][y
].typ
) {
422 if (wizard
&& !secret
)
423 pline("Strange area [%d,%d] in maker().", x
, y
);
440 croom
= &rooms
[nroom
];
442 /* on low levels the room is lit (usually) */
443 /* secret vaults are always lit */
444 if ((rnd(dlevel
) < 10 && rn2(77)) || (ddx
== 1 && ddy
== 1)) {
445 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
446 for (y
= lowy
- 1; y
<= hiy
+ 1; y
++)
455 croom
->rtype
= croom
->doorct
= croom
->fdoor
= 0;
457 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
458 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
459 levl
[x
][y
].scrsym
= '-';
460 levl
[x
][y
].typ
= HWALL
;
462 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
463 for (y
= lowy
; y
<= hiy
; y
++) {
464 levl
[x
][y
].scrsym
= '|';
465 levl
[x
][y
].typ
= VWALL
;
467 for (x
= lowx
; x
<= hix
; x
++)
468 for (y
= lowy
; y
<= hiy
; y
++) {
469 levl
[x
][y
].scrsym
= '.';
470 levl
[x
][y
].typ
= ROOM
;
486 for (a
= 0; a
< nroom
- 1; a
++)
488 for (a
= 0; a
< nroom
- 2; a
++)
489 if (smeq
[a
] != smeq
[a
+ 2])
491 for (a
= 0; a
< nroom
; a
++)
492 for (b
= 0; b
< nroom
; b
++)
493 if (smeq
[a
] != smeq
[b
])
496 for (nxcor
= rn2(nroom
) + 4; nxcor
; nxcor
--) {
512 struct mkroom
*croom
, *troom
;
513 int dx
, dy
, dix
, diy
, cct
;
519 * find positions cc and tt for doors in croom and troom and
520 * direction for a corridor between them
523 if (troom
->hx
< 0 || croom
->hx
< 0 || doorindex
>= DOORMAX
)
525 if (troom
->lx
> croom
->hx
) {
530 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
531 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
532 } else if (troom
->hy
< croom
->ly
) {
536 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
538 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
539 } else if (troom
->hx
< croom
->lx
) {
544 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
545 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
551 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
552 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
558 if (nxcor
&& levl
[xx
+ dx
][yy
+ dy
].typ
)
560 dodoor(xx
, yy
, croom
);
563 while (xx
!= tx
|| yy
!= ty
) {
567 /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
568 if (cct
++ > 500 || (nxcor
&& !rn2(35)))
571 if (xx
== COLNO
- 1 || xx
== 0 || yy
== 0 || yy
== ROWNO
- 1)
572 return; /* impossible */
578 crm
->scrsym
= CORR_SYM
;
579 if (nxcor
&& !rn2(50))
580 (void) mkobj_at(ROCK_SYM
, xx
, yy
);
585 } else if (crm
->typ
!= CORR
&& crm
->typ
!= SCORR
) {
589 /* find next corridor position */
593 /* do we have to change direction ? */
594 if (dy
&& dix
> diy
) {
595 int ddx
= (xx
> tx
) ? -1 : 1;
597 crm
= &levl
[xx
+ ddx
][yy
];
598 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
603 } else if (dx
&& diy
> dix
) {
604 int ddy
= (yy
> ty
) ? -1 : 1;
606 crm
= &levl
[xx
][yy
+ ddy
];
607 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
613 /* continue straight on? */
614 crm
= &levl
[xx
+ dx
][yy
+ dy
];
615 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
618 /* no, what must we do now?? */
621 dy
= (ty
< yy
) ? -1 : 1;
622 crm
= &levl
[xx
+ dx
][yy
+ dy
];
623 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
629 dx
= (tx
< xx
) ? -1 : 1;
630 crm
= &levl
[xx
+ dx
][yy
+ dy
];
631 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
638 /* we succeeded in digging the corridor */
639 dodoor(tt
.x
, tt
.y
, troom
);
641 if (smeq
[a
] < smeq
[b
])
650 int ct
= rnd(nroom
/ 2 + 1);
665 struct mkroom
*aroom
;
672 if (doorindex
< DOORMAX
)
674 aroom
= &rooms
[rn2(nroom
- 1)];
675 if (aroom
->rtype
!= 0)
676 continue; /* not an ordinary room */
677 if (aroom
->doorct
== 1 && rn2(5))
681 dd
= finddpos(aroom
->lx
, aroom
->hy
+ 1, aroom
->hx
, aroom
->hy
+ 1);
684 dd
= finddpos(aroom
->lx
, aroom
->ly
- 1, aroom
->hx
, aroom
->ly
- 1);
688 if ((rm
= &levl
[xx
][yy
+ dy
])->typ
)
690 if (with_trap
|| !rn2(4)) {
694 ttmp
= maketrap(xx
, yy
+ dy
, TELEP_TRAP
);
696 make_engr_at(xx
, yy
- dy
, "ad ae?ar um");
698 dosdoor(xx
, yy
, aroom
, SDOOR
);
701 rm
->scrsym
= CORR_SYM
;
703 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
705 mksobj_at(SCR_TELEPORTATION
, xx
, yy
+ dy
);
707 (void) mkobj_at(0, xx
, yy
+ dy
);
714 /* make a trap somewhere (in croom if mazeflag = 0) */
716 mktrap(num
, mazeflag
, croom
)
718 struct mkroom
*croom
;
721 int kind
, nopierc
, nomimic
, fakedoor
, fakegold
, tryct
= 0;
724 if (!num
|| num
>= TRAPNUM
) {
725 nopierc
= (dlevel
< 4) ? 1 : 0;
726 nomimic
= (dlevel
< 9 || goldseen
) ? 1 : 0;
727 if (strchr(fut_geno
, 'M'))
729 kind
= rn2(TRAPNUM
- nopierc
- nomimic
);
730 /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
737 fakedoor
= (!rn2(3) && !mazeflag
);
738 fakegold
= (!fakedoor
&& !rn2(2));
745 /* note: fakedoor maybe on actual door */
759 } else if (mazeflag
) {
768 } while (m_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
769 if ((mtmp
= makemon(PM_MIMIC
, mx
, my
)) != NULL
) {
772 fakegold
? '$' : fakedoor
? '+' :
773 (mazeflag
&& rn2(2)) ? AMULET_SYM
:
790 } while (t_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
791 ttmp
= maketrap(mx
, my
, kind
);
792 if (mazeflag
&& !rn2(10) && ttmp
->ttyp
< PIERC
)