Home | History | Annotate | Line # | Download | only in hack
hack.makemon.c revision 1.4
      1 /*	$NetBSD: hack.makemon.c,v 1.4 1997/10/19 16:58:17 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
      5  */
      6 
      7 #include <sys/cdefs.h>
      8 #ifndef lint
      9 __RCSID("$NetBSD: hack.makemon.c,v 1.4 1997/10/19 16:58:17 christos Exp $");
     10 #endif				/* not lint */
     11 
     12 #include	"hack.h"
     13 #include	"extern.h"
     14 
     15 struct monst zeromonst;
     16 
     17 /*
     18  * called with [x,y] = coordinates;
     19  *	[0,0] means anyplace
     20  *	[u.ux,u.uy] means: call mnexto (if !in_mklev)
     21  *
     22  *	In case we make an Orc or killer bee, we make an entire horde (swarm);
     23  *	note that in this case we return only one of them (the one at [x,y]).
     24  */
     25 struct monst   *
     26 makemon(ptr, x, y)
     27 	struct permonst *ptr;
     28 {
     29 	struct monst   *mtmp;
     30 	int		tmp, ct;
     31 	boolean         anything = (!ptr);
     32 
     33 	if (x != 0 || y != 0)
     34 		if (m_at(x, y))
     35 			return ((struct monst *) 0);
     36 	if (ptr) {
     37 		if (strchr(fut_geno, ptr->mlet))
     38 			return ((struct monst *) 0);
     39 	} else {
     40 		ct = CMNUM - strlen(fut_geno);
     41 		if (strchr(fut_geno, 'm'))
     42 			ct++;	/* make only 1 minotaur */
     43 		if (strchr(fut_geno, '@'))
     44 			ct++;
     45 		if (ct <= 0)
     46 			return (0);	/* no more monsters! */
     47 		tmp = rn2(ct * dlevel / 24 + 7);
     48 		if (tmp < dlevel - 4)
     49 			tmp = rn2(ct * dlevel / 24 + 12);
     50 		if (tmp >= ct)
     51 			tmp = rn1(ct - ct / 2, ct / 2);
     52 		for (ct = 0; ct < CMNUM; ct++) {
     53 			ptr = &mons[ct];
     54 			if (strchr(fut_geno, ptr->mlet))
     55 				continue;
     56 			if (!tmp--)
     57 				goto gotmon;
     58 		}
     59 		panic("makemon?");
     60 	}
     61 gotmon:
     62 	mtmp = newmonst(ptr->pxlth);
     63 	*mtmp = zeromonst;	/* clear all entries in structure */
     64 	for (ct = 0; ct < ptr->pxlth; ct++)
     65 		((char *) &(mtmp->mextra[0]))[ct] = 0;
     66 	mtmp->nmon = fmon;
     67 	fmon = mtmp;
     68 	mtmp->m_id = flags.ident++;
     69 	mtmp->data = ptr;
     70 	mtmp->mxlth = ptr->pxlth;
     71 	if (ptr->mlet == 'D')
     72 		mtmp->mhpmax = mtmp->mhp = 80;
     73 	else if (!ptr->mlevel)
     74 		mtmp->mhpmax = mtmp->mhp = rnd(4);
     75 	else
     76 		mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8);
     77 	mtmp->mx = x;
     78 	mtmp->my = y;
     79 	mtmp->mcansee = 1;
     80 	if (ptr->mlet == 'M') {
     81 		mtmp->mimic = 1;
     82 		mtmp->mappearance = ']';
     83 	}
     84 	if (!in_mklev) {
     85 		if (x == u.ux && y == u.uy && ptr->mlet != ' ')
     86 			mnexto(mtmp);
     87 		if (x == 0 && y == 0)
     88 			rloc(mtmp);
     89 	}
     90 	if (ptr->mlet == 's' || ptr->mlet == 'S') {
     91 		mtmp->mhide = mtmp->mundetected = 1;
     92 		if (in_mklev)
     93 			if (mtmp->mx && mtmp->my)
     94 				(void) mkobj_at(0, mtmp->mx, mtmp->my);
     95 	}
     96 	if (ptr->mlet == ':') {
     97 		mtmp->cham = 1;
     98 		(void) newcham(mtmp, &mons[dlevel + 14 + rn2(CMNUM - 14 - dlevel)]);
     99 	}
    100 	if (ptr->mlet == 'I' || ptr->mlet == ';')
    101 		mtmp->minvis = 1;
    102 	if (ptr->mlet == 'L' || ptr->mlet == 'N'
    103 	    || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5))
    104 		)
    105 		mtmp->msleep = 1;
    106 
    107 #ifndef NOWORM
    108 	if (ptr->mlet == 'w' && getwn(mtmp))
    109 		initworm(mtmp);
    110 #endif	/* NOWORM */
    111 
    112 	if (anything)
    113 		if (ptr->mlet == 'O' || ptr->mlet == 'k') {
    114 			coord           mm;
    115 			int             cnt = rnd(10);
    116 			mm.x = x;
    117 			mm.y = y;
    118 			while (cnt--) {
    119 				mm = enexto(mm.x, mm.y);
    120 				(void) makemon(ptr, mm.x, mm.y);
    121 			}
    122 		}
    123 	return (mtmp);
    124 }
    125 
    126 coord
    127 enexto(xx, yy)
    128 	xchar           xx, yy;
    129 {
    130 	xchar           x, y;
    131 	coord           foo[15], *tfoo;
    132 	int             range;
    133 
    134 	tfoo = foo;
    135 	range = 1;
    136 	do {			/* full kludge action. */
    137 		for (x = xx - range; x <= xx + range; x++)
    138 			if (goodpos(x, yy - range)) {
    139 				tfoo->x = x;
    140 				tfoo++->y = yy - range;
    141 				if (tfoo == &foo[15])
    142 					goto foofull;
    143 			}
    144 		for (x = xx - range; x <= xx + range; x++)
    145 			if (goodpos(x, yy + range)) {
    146 				tfoo->x = x;
    147 				tfoo++->y = yy + range;
    148 				if (tfoo == &foo[15])
    149 					goto foofull;
    150 			}
    151 		for (y = yy + 1 - range; y < yy + range; y++)
    152 			if (goodpos(xx - range, y)) {
    153 				tfoo->x = xx - range;
    154 				tfoo++->y = y;
    155 				if (tfoo == &foo[15])
    156 					goto foofull;
    157 			}
    158 		for (y = yy + 1 - range; y < yy + range; y++)
    159 			if (goodpos(xx + range, y)) {
    160 				tfoo->x = xx + range;
    161 				tfoo++->y = y;
    162 				if (tfoo == &foo[15])
    163 					goto foofull;
    164 			}
    165 		range++;
    166 	} while (tfoo == foo);
    167 foofull:
    168 	return (foo[rn2(tfoo - foo)]);
    169 }
    170 
    171 int
    172 goodpos(x, y)
    173 {				/* used only in mnexto and rloc */
    174 	return (
    175 		!(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 ||
    176 		  m_at(x, y) || !ACCESSIBLE(levl[x][y].typ)
    177 		  || (x == u.ux && y == u.uy)
    178 		  || sobj_at(ENORMOUS_ROCK, x, y)
    179 		  ));
    180 }
    181 
    182 void
    183 rloc(mtmp)
    184 	struct monst   *mtmp;
    185 {
    186 	int		tx, ty;
    187 	char            ch = mtmp->data->mlet;
    188 
    189 #ifndef NOWORM
    190 	if (ch == 'w' && mtmp->mx)
    191 		return;		/* do not relocate worms */
    192 #endif	/* NOWORM */
    193 	do {
    194 		tx = rn1(COLNO - 3, 2);
    195 		ty = rn2(ROWNO);
    196 	} while (!goodpos(tx, ty));
    197 	mtmp->mx = tx;
    198 	mtmp->my = ty;
    199 	if (u.ustuck == mtmp) {
    200 		if (u.uswallow) {
    201 			u.ux = tx;
    202 			u.uy = ty;
    203 			docrt();
    204 		} else
    205 			u.ustuck = 0;
    206 	}
    207 	pmon(mtmp);
    208 }
    209 
    210 struct monst   *
    211 mkmon_at(let, x, y)
    212 	char            let;
    213 	int             x, y;
    214 {
    215 	int             ct;
    216 	struct permonst *ptr;
    217 
    218 	for (ct = 0; ct < CMNUM; ct++) {
    219 		ptr = &mons[ct];
    220 		if (ptr->mlet == let)
    221 			return (makemon(ptr, x, y));
    222 	}
    223 	return (0);
    224 }
    225