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