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