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