xref: /netbsd/games/hack/hack.makemon.c (revision 9b92b189)
1*9b92b189Sdholland /*	$NetBSD: hack.makemon.c,v 1.9 2009/08/12 07:28:40 dholland Exp $	*/
23ea4a95cSchristos 
302ded532Smycroft /*
41c7f94e5Sjsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm  * Amsterdam
61c7f94e5Sjsm  * All rights reserved.
71c7f94e5Sjsm  *
81c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm  * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm  * met:
111c7f94e5Sjsm  *
121c7f94e5Sjsm  * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm  * this list of conditions and the following disclaimer.
141c7f94e5Sjsm  *
151c7f94e5Sjsm  * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm  * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm  * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm  *
191c7f94e5Sjsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm  * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm  * promote products derived from this software without specific prior
221c7f94e5Sjsm  * written permission.
231c7f94e5Sjsm  *
241c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm  */
361c7f94e5Sjsm 
371c7f94e5Sjsm /*
381c7f94e5Sjsm  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm  * All rights reserved.
401c7f94e5Sjsm  *
411c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm  * modification, are permitted provided that the following conditions
431c7f94e5Sjsm  * are met:
441c7f94e5Sjsm  * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm  * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm  *    documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm  * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm  *    derived from this software without specific prior written permission.
511c7f94e5Sjsm  *
521c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
551c7f94e5Sjsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft  */
6302ded532Smycroft 
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*9b92b189Sdholland __RCSID("$NetBSD: hack.makemon.c,v 1.9 2009/08/12 07:28:40 dholland Exp $");
6702ded532Smycroft #endif				/* not lint */
6861f28255Scgd 
6961f28255Scgd #include	"hack.h"
703ea4a95cSchristos #include	"extern.h"
713ea4a95cSchristos 
72*9b92b189Sdholland static const struct monst zeromonst;
7361f28255Scgd 
7461f28255Scgd /*
7561f28255Scgd  * called with [x,y] = coordinates;
7661f28255Scgd  *	[0,0] means anyplace
7761f28255Scgd  *	[u.ux,u.uy] means: call mnexto (if !in_mklev)
7861f28255Scgd  *
7961f28255Scgd  *	In case we make an Orc or killer bee, we make an entire horde (swarm);
8061f28255Scgd  *	note that in this case we return only one of them (the one at [x,y]).
8161f28255Scgd  */
8261f28255Scgd struct monst   *
makemon(const struct permonst * ptr,int x,int y)83ab8b6343Sjsm makemon(const struct permonst *ptr, int x, int y)
8461f28255Scgd {
853ea4a95cSchristos 	struct monst   *mtmp;
863ea4a95cSchristos 	int		tmp, ct;
873c439f43Sdholland 	unsigned	i;
8861f28255Scgd 	boolean         anything = (!ptr);
8961f28255Scgd 
903ea4a95cSchristos 	if (x != 0 || y != 0)
913ea4a95cSchristos 		if (m_at(x, y))
923ea4a95cSchristos 			return ((struct monst *) 0);
9361f28255Scgd 	if (ptr) {
943ea4a95cSchristos 		if (strchr(fut_geno, ptr->mlet))
953ea4a95cSchristos 			return ((struct monst *) 0);
9661f28255Scgd 	} else {
9761f28255Scgd 		ct = CMNUM - strlen(fut_geno);
983ea4a95cSchristos 		if (strchr(fut_geno, 'm'))
993ea4a95cSchristos 			ct++;	/* make only 1 minotaur */
1003ea4a95cSchristos 		if (strchr(fut_geno, '@'))
1013ea4a95cSchristos 			ct++;
1023ea4a95cSchristos 		if (ct <= 0)
1033ea4a95cSchristos 			return (0);	/* no more monsters! */
10461f28255Scgd 		tmp = rn2(ct * dlevel / 24 + 7);
1053ea4a95cSchristos 		if (tmp < dlevel - 4)
1063ea4a95cSchristos 			tmp = rn2(ct * dlevel / 24 + 12);
1073ea4a95cSchristos 		if (tmp >= ct)
1083ea4a95cSchristos 			tmp = rn1(ct - ct / 2, ct / 2);
10961f28255Scgd 		for (ct = 0; ct < CMNUM; ct++) {
11061f28255Scgd 			ptr = &mons[ct];
1113ea4a95cSchristos 			if (strchr(fut_geno, ptr->mlet))
11261f28255Scgd 				continue;
1133ea4a95cSchristos 			if (!tmp--)
1143ea4a95cSchristos 				goto gotmon;
11561f28255Scgd 		}
11661f28255Scgd 		panic("makemon?");
11761f28255Scgd 	}
11861f28255Scgd gotmon:
11961f28255Scgd 	mtmp = newmonst(ptr->pxlth);
12061f28255Scgd 	*mtmp = zeromonst;	/* clear all entries in structure */
1213c439f43Sdholland 	for (i = 0; i < ptr->pxlth; i++)
1223c439f43Sdholland 		((char *) &(mtmp->mextra[0]))[i] = 0;
12361f28255Scgd 	mtmp->nmon = fmon;
12461f28255Scgd 	fmon = mtmp;
12561f28255Scgd 	mtmp->m_id = flags.ident++;
12661f28255Scgd 	mtmp->data = ptr;
12761f28255Scgd 	mtmp->mxlth = ptr->pxlth;
1283ea4a95cSchristos 	if (ptr->mlet == 'D')
1293ea4a95cSchristos 		mtmp->mhpmax = mtmp->mhp = 80;
1303ea4a95cSchristos 	else if (!ptr->mlevel)
1313ea4a95cSchristos 		mtmp->mhpmax = mtmp->mhp = rnd(4);
1323ea4a95cSchristos 	else
1333ea4a95cSchristos 		mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8);
13461f28255Scgd 	mtmp->mx = x;
13561f28255Scgd 	mtmp->my = y;
13661f28255Scgd 	mtmp->mcansee = 1;
13761f28255Scgd 	if (ptr->mlet == 'M') {
13861f28255Scgd 		mtmp->mimic = 1;
13961f28255Scgd 		mtmp->mappearance = ']';
14061f28255Scgd 	}
14161f28255Scgd 	if (!in_mklev) {
14261f28255Scgd 		if (x == u.ux && y == u.uy && ptr->mlet != ' ')
14361f28255Scgd 			mnexto(mtmp);
14461f28255Scgd 		if (x == 0 && y == 0)
14561f28255Scgd 			rloc(mtmp);
14661f28255Scgd 	}
14761f28255Scgd 	if (ptr->mlet == 's' || ptr->mlet == 'S') {
14861f28255Scgd 		mtmp->mhide = mtmp->mundetected = 1;
14961f28255Scgd 		if (in_mklev)
15061f28255Scgd 			if (mtmp->mx && mtmp->my)
15161f28255Scgd 				(void) mkobj_at(0, mtmp->mx, mtmp->my);
15261f28255Scgd 	}
15361f28255Scgd 	if (ptr->mlet == ':') {
15461f28255Scgd 		mtmp->cham = 1;
15561f28255Scgd 		(void) newcham(mtmp, &mons[dlevel + 14 + rn2(CMNUM - 14 - dlevel)]);
15661f28255Scgd 	}
15761f28255Scgd 	if (ptr->mlet == 'I' || ptr->mlet == ';')
15861f28255Scgd 		mtmp->minvis = 1;
15961f28255Scgd 	if (ptr->mlet == 'L' || ptr->mlet == 'N'
1603ea4a95cSchristos 	    || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5))
1613ea4a95cSchristos 		)
1623ea4a95cSchristos 		mtmp->msleep = 1;
16361f28255Scgd 
16461f28255Scgd #ifndef NOWORM
16561f28255Scgd 	if (ptr->mlet == 'w' && getwn(mtmp))
16661f28255Scgd 		initworm(mtmp);
1673ea4a95cSchristos #endif	/* NOWORM */
16861f28255Scgd 
1693ea4a95cSchristos 	if (anything)
1703ea4a95cSchristos 		if (ptr->mlet == 'O' || ptr->mlet == 'k') {
17161f28255Scgd 			coord           mm;
1723ea4a95cSchristos 			int             cnt = rnd(10);
17361f28255Scgd 			mm.x = x;
17461f28255Scgd 			mm.y = y;
17561f28255Scgd 			while (cnt--) {
17661f28255Scgd 				mm = enexto(mm.x, mm.y);
17761f28255Scgd 				(void) makemon(ptr, mm.x, mm.y);
17861f28255Scgd 			}
17961f28255Scgd 		}
18061f28255Scgd 	return (mtmp);
18161f28255Scgd }
18261f28255Scgd 
18361f28255Scgd coord
enexto(xchar xx,xchar yy)1841fa8a9a6Sdholland enexto(xchar xx, xchar yy)
18561f28255Scgd {
1863ea4a95cSchristos 	xchar           x, y;
18761f28255Scgd 	coord           foo[15], *tfoo;
18861f28255Scgd 	int             range;
18961f28255Scgd 
19061f28255Scgd 	tfoo = foo;
19161f28255Scgd 	range = 1;
19261f28255Scgd 	do {			/* full kludge action. */
19361f28255Scgd 		for (x = xx - range; x <= xx + range; x++)
19461f28255Scgd 			if (goodpos(x, yy - range)) {
19561f28255Scgd 				tfoo->x = x;
19661f28255Scgd 				tfoo++->y = yy - range;
1973ea4a95cSchristos 				if (tfoo == &foo[15])
1983ea4a95cSchristos 					goto foofull;
19961f28255Scgd 			}
20061f28255Scgd 		for (x = xx - range; x <= xx + range; x++)
20161f28255Scgd 			if (goodpos(x, yy + range)) {
20261f28255Scgd 				tfoo->x = x;
20361f28255Scgd 				tfoo++->y = yy + range;
2043ea4a95cSchristos 				if (tfoo == &foo[15])
2053ea4a95cSchristos 					goto foofull;
20661f28255Scgd 			}
20761f28255Scgd 		for (y = yy + 1 - range; y < yy + range; y++)
20861f28255Scgd 			if (goodpos(xx - range, y)) {
20961f28255Scgd 				tfoo->x = xx - range;
21061f28255Scgd 				tfoo++->y = y;
2113ea4a95cSchristos 				if (tfoo == &foo[15])
2123ea4a95cSchristos 					goto foofull;
21361f28255Scgd 			}
21461f28255Scgd 		for (y = yy + 1 - range; y < yy + range; y++)
21561f28255Scgd 			if (goodpos(xx + range, y)) {
21661f28255Scgd 				tfoo->x = xx + range;
21761f28255Scgd 				tfoo++->y = y;
2183ea4a95cSchristos 				if (tfoo == &foo[15])
2193ea4a95cSchristos 					goto foofull;
22061f28255Scgd 			}
22161f28255Scgd 		range++;
22261f28255Scgd 	} while (tfoo == foo);
22361f28255Scgd foofull:
22461f28255Scgd 	return (foo[rn2(tfoo - foo)]);
22561f28255Scgd }
22661f28255Scgd 
2273ea4a95cSchristos int
goodpos(int x,int y)228ab8b6343Sjsm goodpos(int x, int y)
2293ea4a95cSchristos {				/* used only in mnexto and rloc */
23061f28255Scgd 	return (
23161f28255Scgd 		!(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 ||
23261f28255Scgd 		  m_at(x, y) || !ACCESSIBLE(levl[x][y].typ)
23361f28255Scgd 		  || (x == u.ux && y == u.uy)
23461f28255Scgd 		  || sobj_at(ENORMOUS_ROCK, x, y)
23561f28255Scgd 		  ));
23661f28255Scgd }
23761f28255Scgd 
2383ea4a95cSchristos void
rloc(struct monst * mtmp)2391fa8a9a6Sdholland rloc(struct monst *mtmp)
24061f28255Scgd {
2413ea4a95cSchristos 	int		tx, ty;
2423ea4a95cSchristos 	char            ch = mtmp->data->mlet;
24361f28255Scgd 
24461f28255Scgd #ifndef NOWORM
2453ea4a95cSchristos 	if (ch == 'w' && mtmp->mx)
2463ea4a95cSchristos 		return;		/* do not relocate worms */
2473ea4a95cSchristos #endif	/* NOWORM */
24861f28255Scgd 	do {
24961f28255Scgd 		tx = rn1(COLNO - 3, 2);
25061f28255Scgd 		ty = rn2(ROWNO);
25161f28255Scgd 	} while (!goodpos(tx, ty));
25261f28255Scgd 	mtmp->mx = tx;
25361f28255Scgd 	mtmp->my = ty;
25461f28255Scgd 	if (u.ustuck == mtmp) {
25561f28255Scgd 		if (u.uswallow) {
25661f28255Scgd 			u.ux = tx;
25761f28255Scgd 			u.uy = ty;
25861f28255Scgd 			docrt();
2593ea4a95cSchristos 		} else
2603ea4a95cSchristos 			u.ustuck = 0;
26161f28255Scgd 	}
26261f28255Scgd 	pmon(mtmp);
26361f28255Scgd }
26461f28255Scgd 
26561f28255Scgd struct monst   *
mkmon_at(int let,int x,int y)2661fa8a9a6Sdholland mkmon_at(int let, int x, int y)
26761f28255Scgd {
2683ea4a95cSchristos 	int             ct;
269ab8b6343Sjsm 	const struct permonst *ptr;
27061f28255Scgd 
27161f28255Scgd 	for (ct = 0; ct < CMNUM; ct++) {
27261f28255Scgd 		ptr = &mons[ct];
27361f28255Scgd 		if (ptr->mlet == let)
27461f28255Scgd 			return (makemon(ptr, x, y));
27561f28255Scgd 	}
27661f28255Scgd 	return (0);
27761f28255Scgd }
278