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