hack.mhitu.c revision 1.5 1 1.5 jsm /* $NetBSD: hack.mhitu.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.mhitu.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.4 christos #include "hack.h"
13 1.4 christos #include "extern.h"
14 1.1 cgd
15 1.1 cgd /*
16 1.1 cgd * mhitu: monster hits you
17 1.1 cgd * returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
18 1.1 cgd */
19 1.4 christos int
20 1.1 cgd mhitu(mtmp)
21 1.4 christos struct monst *mtmp;
22 1.1 cgd {
23 1.5 jsm const struct permonst *mdat = mtmp->data;
24 1.4 christos int tmp, ctmp;
25 1.1 cgd
26 1.1 cgd nomul(0);
27 1.1 cgd
28 1.1 cgd /* If swallowed, can only be affected by hissers and by u.ustuck */
29 1.4 christos if (u.uswallow) {
30 1.4 christos if (mtmp != u.ustuck) {
31 1.4 christos if (mdat->mlet == 'c' && !rn2(13)) {
32 1.1 cgd pline("Outside, you hear %s's hissing!",
33 1.4 christos monnam(mtmp));
34 1.1 cgd pline("%s gets turned to stone!",
35 1.4 christos Monnam(u.ustuck));
36 1.1 cgd pline("And the same fate befalls you.");
37 1.1 cgd done_in_by(mtmp);
38 1.1 cgd /* "notreached": not return(1); */
39 1.1 cgd }
40 1.4 christos return (0);
41 1.1 cgd }
42 1.4 christos switch (mdat->mlet) { /* now mtmp == u.ustuck */
43 1.1 cgd case ',':
44 1.4 christos youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
45 1.1 cgd 5, "The trapper");
46 1.1 cgd break;
47 1.1 cgd case '\'':
48 1.4 christos youswld(mtmp, rnd(6), 7, "The lurker above");
49 1.1 cgd break;
50 1.1 cgd case 'P':
51 1.4 christos youswld(mtmp, d(2, 4), 12, "The purple worm");
52 1.1 cgd break;
53 1.1 cgd default:
54 1.1 cgd /* This is not impossible! */
55 1.1 cgd pline("The mysterious monster totally digests you.");
56 1.1 cgd u.uhp = 0;
57 1.1 cgd }
58 1.4 christos if (u.uhp < 1)
59 1.4 christos done_in_by(mtmp);
60 1.4 christos return (0);
61 1.1 cgd }
62 1.4 christos if (mdat->mlet == 'c' && Stoned)
63 1.4 christos return (0);
64 1.1 cgd
65 1.1 cgd /* make eels visible the moment they hit/miss us */
66 1.4 christos if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
67 1.1 cgd mtmp->minvis = 0;
68 1.1 cgd pmon(mtmp);
69 1.1 cgd }
70 1.4 christos if (!strchr("1&DuxynNF", mdat->mlet))
71 1.4 christos tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
72 1.1 cgd else
73 1.1 cgd tmp = 0;
74 1.4 christos if (strchr(UNDEAD, mdat->mlet) && midnight())
75 1.4 christos tmp += hitu(mtmp, d(mdat->damn, mdat->damd));
76 1.1 cgd
77 1.1 cgd ctmp = tmp && !mtmp->mcan &&
78 1.4 christos (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
79 1.4 christos switch (mdat->mlet) {
80 1.1 cgd case '1':
81 1.4 christos if (wiz_hit(mtmp))
82 1.4 christos return (1); /* he disappeared */
83 1.1 cgd break;
84 1.1 cgd case '&':
85 1.4 christos if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
86 1.4 christos (void) makemon(PM_DEMON, u.ux, u.uy);
87 1.1 cgd } else {
88 1.4 christos (void) hitu(mtmp, d(2, 6));
89 1.4 christos (void) hitu(mtmp, d(2, 6));
90 1.4 christos (void) hitu(mtmp, rnd(3));
91 1.4 christos (void) hitu(mtmp, rnd(3));
92 1.4 christos (void) hitu(mtmp, rn1(4, 2));
93 1.1 cgd }
94 1.1 cgd break;
95 1.1 cgd case ',':
96 1.4 christos if (tmp)
97 1.4 christos justswld(mtmp, "The trapper");
98 1.1 cgd break;
99 1.1 cgd case '\'':
100 1.4 christos if (tmp)
101 1.4 christos justswld(mtmp, "The lurker above");
102 1.1 cgd break;
103 1.1 cgd case ';':
104 1.4 christos if (ctmp) {
105 1.4 christos if (!u.ustuck && !rn2(10)) {
106 1.1 cgd pline("%s swings itself around you!",
107 1.4 christos Monnam(mtmp));
108 1.1 cgd u.ustuck = mtmp;
109 1.4 christos } else if (u.ustuck == mtmp &&
110 1.4 christos levl[mtmp->mx][mtmp->my].typ == POOL) {
111 1.1 cgd pline("%s drowns you ...", Monnam(mtmp));
112 1.1 cgd done("drowned");
113 1.1 cgd }
114 1.1 cgd }
115 1.1 cgd break;
116 1.1 cgd case 'A':
117 1.4 christos if (ctmp && rn2(2)) {
118 1.4 christos if (Poison_resistance)
119 1.4 christos pline("The sting doesn't seem to affect you.");
120 1.4 christos else {
121 1.4 christos pline("You feel weaker!");
122 1.4 christos losestr(1);
123 1.4 christos }
124 1.1 cgd }
125 1.1 cgd break;
126 1.1 cgd case 'C':
127 1.4 christos (void) hitu(mtmp, rnd(6));
128 1.1 cgd break;
129 1.1 cgd case 'c':
130 1.4 christos if (!rn2(5)) {
131 1.1 cgd pline("You hear %s's hissing!", monnam(mtmp));
132 1.4 christos if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
133 1.4 christos && !carrying(DEAD_LIZARD))) {
134 1.1 cgd Stoned = 5;
135 1.1 cgd /* pline("You get turned to stone!"); */
136 1.1 cgd /* done_in_by(mtmp); */
137 1.1 cgd }
138 1.1 cgd }
139 1.1 cgd break;
140 1.1 cgd case 'D':
141 1.4 christos if (rn2(6) || mtmp->mcan) {
142 1.4 christos (void) hitu(mtmp, d(3, 10));
143 1.4 christos (void) hitu(mtmp, rnd(8));
144 1.4 christos (void) hitu(mtmp, rnd(8));
145 1.1 cgd break;
146 1.1 cgd }
147 1.4 christos kludge("%s breathes fire!", "The dragon");
148 1.4 christos buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
149 1.1 cgd break;
150 1.1 cgd case 'd':
151 1.4 christos (void) hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
152 1.1 cgd break;
153 1.1 cgd case 'e':
154 1.4 christos (void) hitu(mtmp, d(3, 6));
155 1.1 cgd break;
156 1.1 cgd case 'F':
157 1.4 christos if (mtmp->mcan)
158 1.4 christos break;
159 1.4 christos kludge("%s explodes!", "The freezing sphere");
160 1.4 christos if (Cold_resistance)
161 1.4 christos pline("You don't seem affected by it.");
162 1.1 cgd else {
163 1.4 christos xchar dn;
164 1.4 christos if (17 - (u.ulevel / 2) > rnd(20)) {
165 1.1 cgd pline("You get blasted!");
166 1.1 cgd dn = 6;
167 1.1 cgd } else {
168 1.1 cgd pline("You duck the blast...");
169 1.1 cgd dn = 3;
170 1.1 cgd }
171 1.4 christos losehp_m(d(dn, 6), mtmp);
172 1.1 cgd }
173 1.1 cgd mondead(mtmp);
174 1.4 christos return (1);
175 1.1 cgd case 'g':
176 1.4 christos if (ctmp && multi >= 0 && !rn2(3)) {
177 1.4 christos kludge("You are frozen by %ss juices", "the cube'");
178 1.1 cgd nomul(-rnd(10));
179 1.1 cgd }
180 1.1 cgd break;
181 1.1 cgd case 'h':
182 1.4 christos if (ctmp && multi >= 0 && !rn2(5)) {
183 1.1 cgd nomul(-rnd(10));
184 1.1 cgd kludge("You are put to sleep by %ss bite!",
185 1.4 christos "the homunculus'");
186 1.1 cgd }
187 1.1 cgd break;
188 1.1 cgd case 'j':
189 1.4 christos tmp = hitu(mtmp, rnd(3));
190 1.4 christos tmp &= hitu(mtmp, rnd(3));
191 1.4 christos if (tmp) {
192 1.4 christos (void) hitu(mtmp, rnd(4));
193 1.4 christos (void) hitu(mtmp, rnd(4));
194 1.1 cgd }
195 1.1 cgd break;
196 1.1 cgd case 'k':
197 1.4 christos if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) {
198 1.4 christos poisoned("bee's sting", mdat->mname);
199 1.1 cgd }
200 1.1 cgd break;
201 1.1 cgd case 'L':
202 1.4 christos if (tmp)
203 1.4 christos stealgold(mtmp);
204 1.1 cgd break;
205 1.1 cgd case 'N':
206 1.4 christos if (mtmp->mcan && !Blind) {
207 1.4 christos pline("%s tries to seduce you, but you seem not interested.",
208 1.4 christos Amonnam(mtmp, "plain"));
209 1.4 christos if (rn2(3))
210 1.4 christos rloc(mtmp);
211 1.4 christos } else if (steal(mtmp)) {
212 1.1 cgd rloc(mtmp);
213 1.1 cgd mtmp->mflee = 1;
214 1.1 cgd }
215 1.1 cgd break;
216 1.1 cgd case 'n':
217 1.4 christos if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
218 1.4 christos pline("%s hits! (I hope you don't mind)",
219 1.4 christos Monnam(mtmp));
220 1.1 cgd u.uhp += rnd(7);
221 1.4 christos if (!rn2(7))
222 1.4 christos u.uhpmax++;
223 1.4 christos if (u.uhp > u.uhpmax)
224 1.4 christos u.uhp = u.uhpmax;
225 1.1 cgd flags.botl = 1;
226 1.4 christos if (!rn2(50))
227 1.4 christos rloc(mtmp);
228 1.1 cgd } else {
229 1.4 christos (void) hitu(mtmp, d(2, 6));
230 1.4 christos (void) hitu(mtmp, d(2, 6));
231 1.1 cgd }
232 1.1 cgd break;
233 1.1 cgd case 'o':
234 1.4 christos tmp = hitu(mtmp, rnd(6));
235 1.4 christos if (hitu(mtmp, rnd(6)) && tmp && /* hits with both paws */
236 1.1 cgd !u.ustuck && rn2(2)) {
237 1.1 cgd u.ustuck = mtmp;
238 1.4 christos kludge("%s has grabbed you!", "The owlbear");
239 1.4 christos u.uhp -= d(2, 8);
240 1.4 christos } else if (u.ustuck == mtmp) {
241 1.4 christos u.uhp -= d(2, 8);
242 1.1 cgd pline("You are being crushed.");
243 1.1 cgd }
244 1.1 cgd break;
245 1.1 cgd case 'P':
246 1.4 christos if (ctmp && !rn2(4))
247 1.4 christos justswld(mtmp, "The purple worm");
248 1.1 cgd else
249 1.4 christos (void) hitu(mtmp, d(2, 4));
250 1.1 cgd break;
251 1.1 cgd case 'Q':
252 1.4 christos (void) hitu(mtmp, rnd(2));
253 1.4 christos (void) hitu(mtmp, rnd(2));
254 1.1 cgd break;
255 1.1 cgd case 'R':
256 1.4 christos if (tmp && uarmh && !uarmh->rustfree &&
257 1.1 cgd (int) uarmh->spe >= -1) {
258 1.1 cgd pline("Your helmet rusts!");
259 1.1 cgd uarmh->spe--;
260 1.4 christos } else if (ctmp && uarm && !uarm->rustfree && /* Mike Newton */
261 1.4 christos uarm->otyp < STUDDED_LEATHER_ARMOR &&
262 1.4 christos (int) uarm->spe >= -1) {
263 1.1 cgd pline("Your armor rusts!");
264 1.1 cgd uarm->spe--;
265 1.1 cgd }
266 1.1 cgd break;
267 1.1 cgd case 'S':
268 1.4 christos if (ctmp && !rn2(8)) {
269 1.4 christos poisoned("snake's bite", mdat->mname);
270 1.1 cgd }
271 1.1 cgd break;
272 1.1 cgd case 's':
273 1.4 christos if (tmp && !rn2(8)) {
274 1.4 christos poisoned("scorpion's sting", mdat->mname);
275 1.1 cgd }
276 1.4 christos (void) hitu(mtmp, rnd(8));
277 1.4 christos (void) hitu(mtmp, rnd(8));
278 1.1 cgd break;
279 1.1 cgd case 'T':
280 1.4 christos (void) hitu(mtmp, rnd(6));
281 1.4 christos (void) hitu(mtmp, rnd(6));
282 1.1 cgd break;
283 1.1 cgd case 't':
284 1.4 christos if (!rn2(5))
285 1.4 christos rloc(mtmp);
286 1.1 cgd break;
287 1.1 cgd case 'u':
288 1.1 cgd mtmp->mflee = 1;
289 1.1 cgd break;
290 1.1 cgd case 'U':
291 1.4 christos (void) hitu(mtmp, d(3, 4));
292 1.4 christos (void) hitu(mtmp, d(3, 4));
293 1.1 cgd break;
294 1.1 cgd case 'v':
295 1.4 christos if (ctmp && !u.ustuck)
296 1.4 christos u.ustuck = mtmp;
297 1.1 cgd break;
298 1.1 cgd case 'V':
299 1.4 christos if (tmp)
300 1.4 christos u.uhp -= 4;
301 1.4 christos if (ctmp)
302 1.4 christos losexp();
303 1.1 cgd break;
304 1.1 cgd case 'W':
305 1.4 christos if (ctmp)
306 1.4 christos losexp();
307 1.1 cgd break;
308 1.1 cgd #ifndef NOWORM
309 1.1 cgd case 'w':
310 1.4 christos if (tmp)
311 1.4 christos wormhit(mtmp);
312 1.4 christos #endif /* NOWORM */
313 1.1 cgd break;
314 1.1 cgd case 'X':
315 1.4 christos (void) hitu(mtmp, rnd(5));
316 1.4 christos (void) hitu(mtmp, rnd(5));
317 1.4 christos (void) hitu(mtmp, rnd(5));
318 1.1 cgd break;
319 1.1 cgd case 'x':
320 1.4 christos {
321 1.4 christos long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
322 1.4 christos pline("%s pricks in your %s leg!",
323 1.4 christos Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
324 1.4 christos set_wounded_legs(side, rnd(50));
325 1.4 christos losehp_m(2, mtmp);
326 1.4 christos break;
327 1.1 cgd }
328 1.1 cgd case 'y':
329 1.4 christos if (mtmp->mcan)
330 1.4 christos break;
331 1.1 cgd mondead(mtmp);
332 1.4 christos if (!Blind) {
333 1.1 cgd pline("You are blinded by a blast of light!");
334 1.4 christos Blind = d(4, 12);
335 1.1 cgd seeoff(0);
336 1.1 cgd }
337 1.4 christos return (1);
338 1.1 cgd case 'Y':
339 1.4 christos (void) hitu(mtmp, rnd(6));
340 1.1 cgd break;
341 1.1 cgd }
342 1.4 christos if (u.uhp < 1)
343 1.4 christos done_in_by(mtmp);
344 1.4 christos return (0);
345 1.1 cgd }
346 1.1 cgd
347 1.4 christos int
348 1.4 christos hitu(mtmp, dam)
349 1.4 christos struct monst *mtmp;
350 1.4 christos int dam;
351 1.1 cgd {
352 1.4 christos int tmp, res;
353 1.1 cgd
354 1.1 cgd nomul(0);
355 1.4 christos if (u.uswallow)
356 1.4 christos return (0);
357 1.1 cgd
358 1.4 christos if (mtmp->mhide && mtmp->mundetected) {
359 1.1 cgd mtmp->mundetected = 0;
360 1.4 christos if (!Blind) {
361 1.4 christos struct obj *obj;
362 1.4 christos if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL)
363 1.1 cgd pline("%s was hidden under %s!",
364 1.4 christos Xmonnam(mtmp), doname(obj));
365 1.1 cgd }
366 1.1 cgd }
367 1.1 cgd tmp = u.uac;
368 1.1 cgd /* give people with Ac = -10 at least some vulnerability */
369 1.4 christos if (tmp < 0) {
370 1.4 christos dam += tmp; /* decrease damage */
371 1.4 christos if (dam <= 0)
372 1.4 christos dam = 1;
373 1.1 cgd tmp = -rn2(-tmp);
374 1.1 cgd }
375 1.1 cgd tmp += mtmp->data->mlevel;
376 1.4 christos if (multi < 0)
377 1.4 christos tmp += 4;
378 1.4 christos if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee)
379 1.4 christos tmp -= 2;
380 1.4 christos if (mtmp->mtrapped)
381 1.4 christos tmp -= 2;
382 1.4 christos if (tmp <= rnd(20)) {
383 1.4 christos if (Blind)
384 1.4 christos pline("It misses.");
385 1.4 christos else
386 1.4 christos pline("%s misses.", Monnam(mtmp));
387 1.1 cgd res = 0;
388 1.1 cgd } else {
389 1.4 christos if (Blind)
390 1.4 christos pline("It hits!");
391 1.4 christos else
392 1.4 christos pline("%s hits!", Monnam(mtmp));
393 1.1 cgd losehp_m(dam, mtmp);
394 1.1 cgd res = 1;
395 1.1 cgd }
396 1.1 cgd stop_occupation();
397 1.4 christos return (res);
398 1.1 cgd }
399