]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.mklev.c
1 /* $NetBSD: hack.mklev.c,v 1.6 2003/04/02 18:36:38 jsm Exp $ */
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
66 __RCSID("$NetBSD: hack.mklev.c,v 1.6 2003/04/02 18:36:38 jsm Exp $");
74 #define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
75 #define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
77 #include "def.mkroom.h"
78 #define XLIM 4 /* define minimum required space around a
81 boolean secret
; /* TRUE while making a vault: increase
83 int smeq
[MAXNROFROOMS
+ 1];
90 /* Definitions used by makerooms() and addrs() */
91 #define MAXRS 50 /* max lth of temp rectangle table -
94 xchar rlx
, rly
, rhx
, rhy
;
96 int rscnt
, rsmax
; /* 0..rscnt-1: currently under consideration */
97 /* rscnt..rsmax: discarded */
102 struct mkroom
*croom
, *troom
;
108 rooms
[0].hx
= -1; /* in case we are in a maze */
110 for (x
= 0; x
< COLNO
; x
++)
111 for (y
= 0; y
< ROWNO
; y
++)
114 oinit(); /* assign level dependent obj probabilities */
116 if (dlevel
>= rn1(3, 26)) { /* there might be several mazes */
120 /* construct the rooms */
125 /* construct stairs (up and down in different rooms if possible) */
126 croom
= &rooms
[rn2(nroom
)];
129 levl
[xdnstair
][ydnstair
].scrsym
= '>';
130 levl
[xdnstair
][ydnstair
].typ
= STAIRS
;
133 croom
= &rooms
[rn2(nroom
- 1)];
137 xupstair
= somex(); /* %% < and > might be in the same place */
139 levl
[xupstair
][yupstair
].scrsym
= '<';
140 levl
[xupstair
][yupstair
].typ
= STAIRS
;
142 /* for each room: put things inside */
143 for (croom
= rooms
; croom
->hx
> 0; croom
++) {
145 /* put a sleeping monster inside */
147 * Note: monster may be on the stairs. This cannot be
148 * avoided: maybe the player fell through a trapdoor while a
149 * monster was on the stairs. Conclusion: we have to check
150 * for monsters on the stairs anyway.
154 makemon((struct permonst
*) 0, somex(), somey());
156 /* put traps and mimics inside */
158 while (!rn2(8 - (dlevel
/ 6)))
160 if (!goldseen
&& !rn2(3))
161 mkgold(0L, somex(), somey());
163 (void) mkobj_at(0, somex(), somey());
167 printf("tryct overflow4\n");
170 (void) mkobj_at(0, somex(), somey());
175 qsort((char *) rooms
, nroom
, sizeof(struct mkroom
), comp
);
179 /* make a secret treasure vault, not connected to the rest */
180 if (nroom
<= (2 * MAXNROFROOMS
/ 3))
182 troom
= &rooms
[nroom
];
185 troom
->rtype
= VAULT
; /* treasure vault */
186 for (x
= troom
->lx
; x
<= troom
->hx
; x
++)
187 for (y
= troom
->ly
; y
<= troom
->hy
; y
++)
188 mkgold((long) (rnd(dlevel
* 100) + 50), x
, y
);
195 if (wizard
&& getenv("SHOPTYPE"))
199 if (dlevel
> 1 && dlevel
< 20 && rn2(dlevel
) < 3)
201 else if (dlevel
> 6 && !rn2(7))
203 else if (dlevel
> 9 && !rn2(5))
205 else if (dlevel
> 11 && !rn2(6))
207 else if (dlevel
> 18 && !rn2(6))
215 struct rectangle
*rsp
;
216 int lx
, ly
, hx
, hy
, lowx
, lowy
, hix
, hiy
, dx
, dy
;
217 int tryct
= 0, xlim
, ylim
;
220 xlim
= XLIM
+ secret
;
221 ylim
= YLIM
+ secret
;
224 rsp
->rlx
= rsp
->rly
= 0;
225 rsp
->rhx
= COLNO
- 1;
226 rsp
->rhy
= ROWNO
- 1;
231 /* make rooms until satisfied */
232 while (rscnt
> 0 && nroom
< MAXNROFROOMS
- 1) {
233 if (!secret
&& nroom
> (MAXNROFROOMS
/ 3) &&
234 !rn2((MAXNROFROOMS
- nroom
) * (MAXNROFROOMS
- nroom
)))
237 /* pick a rectangle */
238 rsp
= &rs
[rn2(rscnt
)];
244 /* find size of room */
248 dx
= 2 + rn2((hx
- lx
- 8 > 20) ? 12 : 8);
254 /* look whether our room will fit */
255 if (hx
- lx
< dx
+ dx
/ 2 + 2 * xlim
|| hy
- ly
< dy
+ dy
/ 3 + 2 * ylim
) {
257 /* maybe we throw this area out */
258 if (secret
|| !rn2(MAXNROFROOMS
+ 1 - nroom
- tryct
)) {
262 rs
[rscnt
] = rs
[rsmax
];
268 lowx
= lx
+ xlim
+ rn2(hx
- lx
- dx
- 2 * xlim
+ 1);
269 lowy
= ly
+ ylim
+ rn2(hy
- ly
- dy
- 2 * ylim
+ 1);
273 if (maker(lowx
, dx
, lowy
, dy
)) {
276 addrs(lowx
- 1, lowy
- 1, hix
+ 1, hiy
+ 1);
278 } else if (tryct
++ > 100)
281 return (0); /* failed to make vault - very strange */
285 addrs(lowx
, lowy
, hix
, hiy
)
286 int lowx
, lowy
, hix
, hiy
;
288 struct rectangle
*rsp
;
289 int lx
, ly
, hx
, hy
, xlim
, ylim
;
292 xlim
= XLIM
+ secret
;
293 ylim
= YLIM
+ secret
;
295 /* walk down since rscnt and rsmax change */
296 for (rsp
= &rs
[rsmax
- 1]; rsp
>= rs
; rsp
--) {
298 if ((lx
= rsp
->rlx
) > hix
|| (ly
= rsp
->rly
) > hiy
||
299 (hx
= rsp
->rhx
) < lowx
|| (hy
= rsp
->rhy
) < lowy
)
301 if ((discarded
= (rsp
>= &rs
[rscnt
]))) {
308 rs
[rscnt
] = rs
[rsmax
];
310 if (lowy
- ly
> 2 * ylim
+ 4)
311 addrsx(lx
, ly
, hx
, lowy
- 2, discarded
);
312 if (lowx
- lx
> 2 * xlim
+ 4)
313 addrsx(lx
, ly
, lowx
- 2, hy
, discarded
);
314 if (hy
- hiy
> 2 * ylim
+ 4)
315 addrsx(lx
, hiy
+ 2, hx
, hy
, discarded
);
316 if (hx
- hix
> 2 * xlim
+ 4)
317 addrsx(hix
+ 2, ly
, hx
, hy
, discarded
);
322 addrsx(lx
, ly
, hx
, hy
, discarded
)
324 boolean discarded
; /* piece of a discarded area */
326 struct rectangle
*rsp
;
328 /* check inclusions */
329 for (rsp
= rs
; rsp
< &rs
[rsmax
]; rsp
++) {
330 if (lx
>= rsp
->rlx
&& hx
<= rsp
->rhx
&&
331 ly
>= rsp
->rly
&& hy
<= rsp
->rhy
)
335 /* make a new entry */
336 if (rsmax
>= MAXRS
) {
339 pline("MAXRS may be too small.");
359 const struct mkroom
*x
= vx
, *y
= vy
;
362 return (x
->lx
> y
->lx
);
366 finddpos(int xl
, int yl
, int xh
, int yh
)
371 x
= (xl
== xh
) ? xl
: (xl
+ rn2(xh
- xl
+ 1));
372 y
= (yl
== yh
) ? yl
: (yl
+ rn2(yh
- yl
+ 1));
376 for (x
= xl
; x
<= xh
; x
++)
377 for (y
= yl
; y
<= yh
; y
++)
381 for (x
= xl
; x
<= xh
; x
++)
382 for (y
= yl
; y
<= yh
; y
++)
383 if (levl
[x
][y
].typ
== DOOR
|| levl
[x
][y
].typ
== SDOOR
)
385 /* cannot find something reasonable -- strange */
394 /* see whether it is allowable to create a door at [x,y] */
399 if (levl
[x
- 1][y
].typ
== DOOR
|| levl
[x
+ 1][y
].typ
== DOOR
||
400 levl
[x
][y
+ 1].typ
== DOOR
|| levl
[x
][y
- 1].typ
== DOOR
||
401 levl
[x
- 1][y
].typ
== SDOOR
|| levl
[x
+ 1][y
].typ
== SDOOR
||
402 levl
[x
][y
- 1].typ
== SDOOR
|| levl
[x
][y
+ 1].typ
== SDOOR
||
403 (levl
[x
][y
].typ
!= HWALL
&& levl
[x
][y
].typ
!= VWALL
) ||
404 doorindex
>= DOORMAX
)
412 struct mkroom
*aroom
;
414 if (doorindex
>= DOORMAX
) {
415 impossible("DOORMAX exceeded?");
418 if (!okdoor(x
, y
) && nxcor
)
420 dosdoor(x
, y
, aroom
, rn2(8) ? DOOR
: SDOOR
);
424 dosdoor(x
, y
, aroom
, type
)
426 struct mkroom
*aroom
;
429 struct mkroom
*broom
;
432 if (!IS_WALL(levl
[x
][y
].typ
)) /* avoid SDOORs with '+' as scrsym */
434 levl
[x
][y
].typ
= type
;
436 levl
[x
][y
].scrsym
= '+';
442 for (tmp
= doorindex
; tmp
> broom
->fdoor
; tmp
--)
443 doors
[tmp
] = doors
[tmp
- 1];
447 for (; broom
->hx
>= 0; broom
++)
451 /* Only called from makerooms() */
453 maker(lowx
, ddx
, lowy
, ddy
)
454 schar lowx
, ddx
, lowy
, ddy
;
456 struct mkroom
*croom
;
457 int x
, y
, hix
= lowx
+ ddx
, hiy
= lowy
+ ddy
;
458 int xlim
= XLIM
+ secret
, ylim
= YLIM
+ secret
;
460 if (nroom
>= MAXNROFROOMS
)
466 if (hix
> COLNO
- XLIM
- 1)
467 hix
= COLNO
- XLIM
- 1;
468 if (hiy
> ROWNO
- YLIM
- 1)
469 hiy
= ROWNO
- YLIM
- 1;
471 if (hix
<= lowx
|| hiy
<= lowy
)
474 /* check area around room (and make room smaller if necessary) */
475 for (x
= lowx
- xlim
; x
<= hix
+ xlim
; x
++) {
476 for (y
= lowy
- ylim
; y
<= hiy
+ ylim
; y
++) {
477 if (levl
[x
][y
].typ
) {
479 if (wizard
&& !secret
)
480 pline("Strange area [%d,%d] in maker().", x
, y
);
497 croom
= &rooms
[nroom
];
499 /* on low levels the room is lit (usually) */
500 /* secret vaults are always lit */
501 if ((rnd(dlevel
) < 10 && rn2(77)) || (ddx
== 1 && ddy
== 1)) {
502 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
503 for (y
= lowy
- 1; y
<= hiy
+ 1; y
++)
512 croom
->rtype
= croom
->doorct
= croom
->fdoor
= 0;
514 for (x
= lowx
- 1; x
<= hix
+ 1; x
++)
515 for (y
= lowy
- 1; y
<= hiy
+ 1; y
+= (hiy
- lowy
+ 2)) {
516 levl
[x
][y
].scrsym
= '-';
517 levl
[x
][y
].typ
= HWALL
;
519 for (x
= lowx
- 1; x
<= hix
+ 1; x
+= (hix
- lowx
+ 2))
520 for (y
= lowy
; y
<= hiy
; y
++) {
521 levl
[x
][y
].scrsym
= '|';
522 levl
[x
][y
].typ
= VWALL
;
524 for (x
= lowx
; x
<= hix
; x
++)
525 for (y
= lowy
; y
<= hiy
; y
++) {
526 levl
[x
][y
].scrsym
= '.';
527 levl
[x
][y
].typ
= ROOM
;
543 for (a
= 0; a
< nroom
- 1; a
++)
545 for (a
= 0; a
< nroom
- 2; a
++)
546 if (smeq
[a
] != smeq
[a
+ 2])
548 for (a
= 0; a
< nroom
; a
++)
549 for (b
= 0; b
< nroom
; b
++)
550 if (smeq
[a
] != smeq
[b
])
553 for (nxcor
= rn2(nroom
) + 4; nxcor
; nxcor
--) {
569 struct mkroom
*croom
, *troom
;
570 int dx
, dy
, dix
, diy
, cct
;
576 * find positions cc and tt for doors in croom and troom and
577 * direction for a corridor between them
580 if (troom
->hx
< 0 || croom
->hx
< 0 || doorindex
>= DOORMAX
)
582 if (troom
->lx
> croom
->hx
) {
587 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
588 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
589 } else if (troom
->hy
< croom
->ly
) {
593 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
595 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
596 } else if (troom
->hx
< croom
->lx
) {
601 cc
= finddpos(xx
, croom
->ly
, xx
, croom
->hy
);
602 tt
= finddpos(tx
, troom
->ly
, tx
, troom
->hy
);
608 cc
= finddpos(croom
->lx
, yy
, croom
->hx
, yy
);
609 tt
= finddpos(troom
->lx
, ty
, troom
->hx
, ty
);
615 if (nxcor
&& levl
[xx
+ dx
][yy
+ dy
].typ
)
617 dodoor(xx
, yy
, croom
);
620 while (xx
!= tx
|| yy
!= ty
) {
624 /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
625 if (cct
++ > 500 || (nxcor
&& !rn2(35)))
628 if (xx
== COLNO
- 1 || xx
== 0 || yy
== 0 || yy
== ROWNO
- 1)
629 return; /* impossible */
635 crm
->scrsym
= CORR_SYM
;
636 if (nxcor
&& !rn2(50))
637 (void) mkobj_at(ROCK_SYM
, xx
, yy
);
642 } else if (crm
->typ
!= CORR
&& crm
->typ
!= SCORR
) {
646 /* find next corridor position */
650 /* do we have to change direction ? */
651 if (dy
&& dix
> diy
) {
652 int ddx
= (xx
> tx
) ? -1 : 1;
654 crm
= &levl
[xx
+ ddx
][yy
];
655 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
660 } else if (dx
&& diy
> dix
) {
661 int ddy
= (yy
> ty
) ? -1 : 1;
663 crm
= &levl
[xx
][yy
+ ddy
];
664 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
) {
670 /* continue straight on? */
671 crm
= &levl
[xx
+ dx
][yy
+ dy
];
672 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
675 /* no, what must we do now?? */
678 dy
= (ty
< yy
) ? -1 : 1;
679 crm
= &levl
[xx
+ dx
][yy
+ dy
];
680 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
686 dx
= (tx
< xx
) ? -1 : 1;
687 crm
= &levl
[xx
+ dx
][yy
+ dy
];
688 if (!crm
->typ
|| crm
->typ
== CORR
|| crm
->typ
== SCORR
)
695 /* we succeeded in digging the corridor */
696 dodoor(tt
.x
, tt
.y
, troom
);
698 if (smeq
[a
] < smeq
[b
])
707 int ct
= rnd(nroom
/ 2 + 1);
722 struct mkroom
*aroom
;
729 if (doorindex
< DOORMAX
)
731 aroom
= &rooms
[rn2(nroom
- 1)];
732 if (aroom
->rtype
!= 0)
733 continue; /* not an ordinary room */
734 if (aroom
->doorct
== 1 && rn2(5))
738 dd
= finddpos(aroom
->lx
, aroom
->hy
+ 1, aroom
->hx
, aroom
->hy
+ 1);
741 dd
= finddpos(aroom
->lx
, aroom
->ly
- 1, aroom
->hx
, aroom
->ly
- 1);
745 if ((rm
= &levl
[xx
][yy
+ dy
])->typ
)
747 if (with_trap
|| !rn2(4)) {
751 ttmp
= maketrap(xx
, yy
+ dy
, TELEP_TRAP
);
753 make_engr_at(xx
, yy
- dy
, "ad ae?ar um");
755 dosdoor(xx
, yy
, aroom
, SDOOR
);
758 rm
->scrsym
= CORR_SYM
;
760 dosdoor(xx
, yy
, aroom
, rn2(5) ? SDOOR
: DOOR
);
762 mksobj_at(SCR_TELEPORTATION
, xx
, yy
+ dy
);
764 (void) mkobj_at(0, xx
, yy
+ dy
);
771 /* make a trap somewhere (in croom if mazeflag = 0) */
773 mktrap(num
, mazeflag
, croom
)
775 struct mkroom
*croom
;
778 int kind
, nopierc
, nomimic
, fakedoor
, fakegold
, tryct
= 0;
781 if (!num
|| num
>= TRAPNUM
) {
782 nopierc
= (dlevel
< 4) ? 1 : 0;
783 nomimic
= (dlevel
< 9 || goldseen
) ? 1 : 0;
784 if (strchr(fut_geno
, 'M'))
786 kind
= rn2(TRAPNUM
- nopierc
- nomimic
);
787 /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
794 fakedoor
= (!rn2(3) && !mazeflag
);
795 fakegold
= (!fakedoor
&& !rn2(2));
802 /* note: fakedoor maybe on actual door */
816 } else if (mazeflag
) {
825 } while (m_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
826 if ((mtmp
= makemon(PM_MIMIC
, mx
, my
)) != NULL
) {
829 fakegold
? '$' : fakedoor
? '+' :
830 (mazeflag
&& rn2(2)) ? AMULET_SYM
:
847 } while (t_at(mx
, my
) || levl
[mx
][my
].typ
== STAIRS
);
848 ttmp
= maketrap(mx
, my
, kind
);
849 if (mazeflag
&& !rn2(10) && ttmp
->ttyp
< PIERC
)