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