hack.mhitu.c revision 1.6 1 1.6 jsm /* $NetBSD: hack.mhitu.c,v 1.6 2003/04/02 18:36:37 jsm Exp $ */
2 1.4 christos
3 1.2 mycroft /*
4 1.6 jsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 1.6 jsm * Amsterdam
6 1.6 jsm * All rights reserved.
7 1.6 jsm *
8 1.6 jsm * Redistribution and use in source and binary forms, with or without
9 1.6 jsm * modification, are permitted provided that the following conditions are
10 1.6 jsm * met:
11 1.6 jsm *
12 1.6 jsm * - Redistributions of source code must retain the above copyright notice,
13 1.6 jsm * this list of conditions and the following disclaimer.
14 1.6 jsm *
15 1.6 jsm * - Redistributions in binary form must reproduce the above copyright
16 1.6 jsm * notice, this list of conditions and the following disclaimer in the
17 1.6 jsm * documentation and/or other materials provided with the distribution.
18 1.6 jsm *
19 1.6 jsm * - Neither the name of the Stichting Centrum voor Wiskunde en
20 1.6 jsm * Informatica, nor the names of its contributors may be used to endorse or
21 1.6 jsm * promote products derived from this software without specific prior
22 1.6 jsm * written permission.
23 1.6 jsm *
24 1.6 jsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 1.6 jsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 1.6 jsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 1.6 jsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 1.6 jsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 1.6 jsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 1.6 jsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 1.6 jsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 1.6 jsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 1.6 jsm */
36 1.6 jsm
37 1.6 jsm /*
38 1.6 jsm * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
39 1.6 jsm * All rights reserved.
40 1.6 jsm *
41 1.6 jsm * Redistribution and use in source and binary forms, with or without
42 1.6 jsm * modification, are permitted provided that the following conditions
43 1.6 jsm * are met:
44 1.6 jsm * 1. Redistributions of source code must retain the above copyright
45 1.6 jsm * notice, this list of conditions and the following disclaimer.
46 1.6 jsm * 2. Redistributions in binary form must reproduce the above copyright
47 1.6 jsm * notice, this list of conditions and the following disclaimer in the
48 1.6 jsm * documentation and/or other materials provided with the distribution.
49 1.6 jsm * 3. The name of the author may not be used to endorse or promote products
50 1.6 jsm * derived from this software without specific prior written permission.
51 1.6 jsm *
52 1.6 jsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 1.6 jsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 1.6 jsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 1.6 jsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 1.6 jsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 1.6 jsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 1.6 jsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 1.6 jsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 1.2 mycroft */
63 1.2 mycroft
64 1.4 christos #include <sys/cdefs.h>
65 1.2 mycroft #ifndef lint
66 1.6 jsm __RCSID("$NetBSD: hack.mhitu.c,v 1.6 2003/04/02 18:36:37 jsm Exp $");
67 1.4 christos #endif /* not lint */
68 1.1 cgd
69 1.4 christos #include "hack.h"
70 1.4 christos #include "extern.h"
71 1.1 cgd
72 1.1 cgd /*
73 1.1 cgd * mhitu: monster hits you
74 1.1 cgd * returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
75 1.1 cgd */
76 1.4 christos int
77 1.1 cgd mhitu(mtmp)
78 1.4 christos struct monst *mtmp;
79 1.1 cgd {
80 1.5 jsm const struct permonst *mdat = mtmp->data;
81 1.4 christos int tmp, ctmp;
82 1.1 cgd
83 1.1 cgd nomul(0);
84 1.1 cgd
85 1.1 cgd /* If swallowed, can only be affected by hissers and by u.ustuck */
86 1.4 christos if (u.uswallow) {
87 1.4 christos if (mtmp != u.ustuck) {
88 1.4 christos if (mdat->mlet == 'c' && !rn2(13)) {
89 1.1 cgd pline("Outside, you hear %s's hissing!",
90 1.4 christos monnam(mtmp));
91 1.1 cgd pline("%s gets turned to stone!",
92 1.4 christos Monnam(u.ustuck));
93 1.1 cgd pline("And the same fate befalls you.");
94 1.1 cgd done_in_by(mtmp);
95 1.1 cgd /* "notreached": not return(1); */
96 1.1 cgd }
97 1.4 christos return (0);
98 1.1 cgd }
99 1.4 christos switch (mdat->mlet) { /* now mtmp == u.ustuck */
100 1.1 cgd case ',':
101 1.4 christos youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
102 1.1 cgd 5, "The trapper");
103 1.1 cgd break;
104 1.1 cgd case '\'':
105 1.4 christos youswld(mtmp, rnd(6), 7, "The lurker above");
106 1.1 cgd break;
107 1.1 cgd case 'P':
108 1.4 christos youswld(mtmp, d(2, 4), 12, "The purple worm");
109 1.1 cgd break;
110 1.1 cgd default:
111 1.1 cgd /* This is not impossible! */
112 1.1 cgd pline("The mysterious monster totally digests you.");
113 1.1 cgd u.uhp = 0;
114 1.1 cgd }
115 1.4 christos if (u.uhp < 1)
116 1.4 christos done_in_by(mtmp);
117 1.4 christos return (0);
118 1.1 cgd }
119 1.4 christos if (mdat->mlet == 'c' && Stoned)
120 1.4 christos return (0);
121 1.1 cgd
122 1.1 cgd /* make eels visible the moment they hit/miss us */
123 1.4 christos if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
124 1.1 cgd mtmp->minvis = 0;
125 1.1 cgd pmon(mtmp);
126 1.1 cgd }
127 1.4 christos if (!strchr("1&DuxynNF", mdat->mlet))
128 1.4 christos tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
129 1.1 cgd else
130 1.1 cgd tmp = 0;
131 1.4 christos if (strchr(UNDEAD, mdat->mlet) && midnight())
132 1.4 christos tmp += hitu(mtmp, d(mdat->damn, mdat->damd));
133 1.1 cgd
134 1.1 cgd ctmp = tmp && !mtmp->mcan &&
135 1.4 christos (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
136 1.4 christos switch (mdat->mlet) {
137 1.1 cgd case '1':
138 1.4 christos if (wiz_hit(mtmp))
139 1.4 christos return (1); /* he disappeared */
140 1.1 cgd break;
141 1.1 cgd case '&':
142 1.4 christos if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
143 1.4 christos (void) makemon(PM_DEMON, u.ux, u.uy);
144 1.1 cgd } else {
145 1.4 christos (void) hitu(mtmp, d(2, 6));
146 1.4 christos (void) hitu(mtmp, d(2, 6));
147 1.4 christos (void) hitu(mtmp, rnd(3));
148 1.4 christos (void) hitu(mtmp, rnd(3));
149 1.4 christos (void) hitu(mtmp, rn1(4, 2));
150 1.1 cgd }
151 1.1 cgd break;
152 1.1 cgd case ',':
153 1.4 christos if (tmp)
154 1.4 christos justswld(mtmp, "The trapper");
155 1.1 cgd break;
156 1.1 cgd case '\'':
157 1.4 christos if (tmp)
158 1.4 christos justswld(mtmp, "The lurker above");
159 1.1 cgd break;
160 1.1 cgd case ';':
161 1.4 christos if (ctmp) {
162 1.4 christos if (!u.ustuck && !rn2(10)) {
163 1.1 cgd pline("%s swings itself around you!",
164 1.4 christos Monnam(mtmp));
165 1.1 cgd u.ustuck = mtmp;
166 1.4 christos } else if (u.ustuck == mtmp &&
167 1.4 christos levl[mtmp->mx][mtmp->my].typ == POOL) {
168 1.1 cgd pline("%s drowns you ...", Monnam(mtmp));
169 1.1 cgd done("drowned");
170 1.1 cgd }
171 1.1 cgd }
172 1.1 cgd break;
173 1.1 cgd case 'A':
174 1.4 christos if (ctmp && rn2(2)) {
175 1.4 christos if (Poison_resistance)
176 1.4 christos pline("The sting doesn't seem to affect you.");
177 1.4 christos else {
178 1.4 christos pline("You feel weaker!");
179 1.4 christos losestr(1);
180 1.4 christos }
181 1.1 cgd }
182 1.1 cgd break;
183 1.1 cgd case 'C':
184 1.4 christos (void) hitu(mtmp, rnd(6));
185 1.1 cgd break;
186 1.1 cgd case 'c':
187 1.4 christos if (!rn2(5)) {
188 1.1 cgd pline("You hear %s's hissing!", monnam(mtmp));
189 1.4 christos if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
190 1.4 christos && !carrying(DEAD_LIZARD))) {
191 1.1 cgd Stoned = 5;
192 1.1 cgd /* pline("You get turned to stone!"); */
193 1.1 cgd /* done_in_by(mtmp); */
194 1.1 cgd }
195 1.1 cgd }
196 1.1 cgd break;
197 1.1 cgd case 'D':
198 1.4 christos if (rn2(6) || mtmp->mcan) {
199 1.4 christos (void) hitu(mtmp, d(3, 10));
200 1.4 christos (void) hitu(mtmp, rnd(8));
201 1.4 christos (void) hitu(mtmp, rnd(8));
202 1.1 cgd break;
203 1.1 cgd }
204 1.4 christos kludge("%s breathes fire!", "The dragon");
205 1.4 christos buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
206 1.1 cgd break;
207 1.1 cgd case 'd':
208 1.4 christos (void) hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
209 1.1 cgd break;
210 1.1 cgd case 'e':
211 1.4 christos (void) hitu(mtmp, d(3, 6));
212 1.1 cgd break;
213 1.1 cgd case 'F':
214 1.4 christos if (mtmp->mcan)
215 1.4 christos break;
216 1.4 christos kludge("%s explodes!", "The freezing sphere");
217 1.4 christos if (Cold_resistance)
218 1.4 christos pline("You don't seem affected by it.");
219 1.1 cgd else {
220 1.4 christos xchar dn;
221 1.4 christos if (17 - (u.ulevel / 2) > rnd(20)) {
222 1.1 cgd pline("You get blasted!");
223 1.1 cgd dn = 6;
224 1.1 cgd } else {
225 1.1 cgd pline("You duck the blast...");
226 1.1 cgd dn = 3;
227 1.1 cgd }
228 1.4 christos losehp_m(d(dn, 6), mtmp);
229 1.1 cgd }
230 1.1 cgd mondead(mtmp);
231 1.4 christos return (1);
232 1.1 cgd case 'g':
233 1.4 christos if (ctmp && multi >= 0 && !rn2(3)) {
234 1.4 christos kludge("You are frozen by %ss juices", "the cube'");
235 1.1 cgd nomul(-rnd(10));
236 1.1 cgd }
237 1.1 cgd break;
238 1.1 cgd case 'h':
239 1.4 christos if (ctmp && multi >= 0 && !rn2(5)) {
240 1.1 cgd nomul(-rnd(10));
241 1.1 cgd kludge("You are put to sleep by %ss bite!",
242 1.4 christos "the homunculus'");
243 1.1 cgd }
244 1.1 cgd break;
245 1.1 cgd case 'j':
246 1.4 christos tmp = hitu(mtmp, rnd(3));
247 1.4 christos tmp &= hitu(mtmp, rnd(3));
248 1.4 christos if (tmp) {
249 1.4 christos (void) hitu(mtmp, rnd(4));
250 1.4 christos (void) hitu(mtmp, rnd(4));
251 1.1 cgd }
252 1.1 cgd break;
253 1.1 cgd case 'k':
254 1.4 christos if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) {
255 1.4 christos poisoned("bee's sting", mdat->mname);
256 1.1 cgd }
257 1.1 cgd break;
258 1.1 cgd case 'L':
259 1.4 christos if (tmp)
260 1.4 christos stealgold(mtmp);
261 1.1 cgd break;
262 1.1 cgd case 'N':
263 1.4 christos if (mtmp->mcan && !Blind) {
264 1.4 christos pline("%s tries to seduce you, but you seem not interested.",
265 1.4 christos Amonnam(mtmp, "plain"));
266 1.4 christos if (rn2(3))
267 1.4 christos rloc(mtmp);
268 1.4 christos } else if (steal(mtmp)) {
269 1.1 cgd rloc(mtmp);
270 1.1 cgd mtmp->mflee = 1;
271 1.1 cgd }
272 1.1 cgd break;
273 1.1 cgd case 'n':
274 1.4 christos if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
275 1.4 christos pline("%s hits! (I hope you don't mind)",
276 1.4 christos Monnam(mtmp));
277 1.1 cgd u.uhp += rnd(7);
278 1.4 christos if (!rn2(7))
279 1.4 christos u.uhpmax++;
280 1.4 christos if (u.uhp > u.uhpmax)
281 1.4 christos u.uhp = u.uhpmax;
282 1.1 cgd flags.botl = 1;
283 1.4 christos if (!rn2(50))
284 1.4 christos rloc(mtmp);
285 1.1 cgd } else {
286 1.4 christos (void) hitu(mtmp, d(2, 6));
287 1.4 christos (void) hitu(mtmp, d(2, 6));
288 1.1 cgd }
289 1.1 cgd break;
290 1.1 cgd case 'o':
291 1.4 christos tmp = hitu(mtmp, rnd(6));
292 1.4 christos if (hitu(mtmp, rnd(6)) && tmp && /* hits with both paws */
293 1.1 cgd !u.ustuck && rn2(2)) {
294 1.1 cgd u.ustuck = mtmp;
295 1.4 christos kludge("%s has grabbed you!", "The owlbear");
296 1.4 christos u.uhp -= d(2, 8);
297 1.4 christos } else if (u.ustuck == mtmp) {
298 1.4 christos u.uhp -= d(2, 8);
299 1.1 cgd pline("You are being crushed.");
300 1.1 cgd }
301 1.1 cgd break;
302 1.1 cgd case 'P':
303 1.4 christos if (ctmp && !rn2(4))
304 1.4 christos justswld(mtmp, "The purple worm");
305 1.1 cgd else
306 1.4 christos (void) hitu(mtmp, d(2, 4));
307 1.1 cgd break;
308 1.1 cgd case 'Q':
309 1.4 christos (void) hitu(mtmp, rnd(2));
310 1.4 christos (void) hitu(mtmp, rnd(2));
311 1.1 cgd break;
312 1.1 cgd case 'R':
313 1.4 christos if (tmp && uarmh && !uarmh->rustfree &&
314 1.1 cgd (int) uarmh->spe >= -1) {
315 1.1 cgd pline("Your helmet rusts!");
316 1.1 cgd uarmh->spe--;
317 1.4 christos } else if (ctmp && uarm && !uarm->rustfree && /* Mike Newton */
318 1.4 christos uarm->otyp < STUDDED_LEATHER_ARMOR &&
319 1.4 christos (int) uarm->spe >= -1) {
320 1.1 cgd pline("Your armor rusts!");
321 1.1 cgd uarm->spe--;
322 1.1 cgd }
323 1.1 cgd break;
324 1.1 cgd case 'S':
325 1.4 christos if (ctmp && !rn2(8)) {
326 1.4 christos poisoned("snake's bite", mdat->mname);
327 1.1 cgd }
328 1.1 cgd break;
329 1.1 cgd case 's':
330 1.4 christos if (tmp && !rn2(8)) {
331 1.4 christos poisoned("scorpion's sting", mdat->mname);
332 1.1 cgd }
333 1.4 christos (void) hitu(mtmp, rnd(8));
334 1.4 christos (void) hitu(mtmp, rnd(8));
335 1.1 cgd break;
336 1.1 cgd case 'T':
337 1.4 christos (void) hitu(mtmp, rnd(6));
338 1.4 christos (void) hitu(mtmp, rnd(6));
339 1.1 cgd break;
340 1.1 cgd case 't':
341 1.4 christos if (!rn2(5))
342 1.4 christos rloc(mtmp);
343 1.1 cgd break;
344 1.1 cgd case 'u':
345 1.1 cgd mtmp->mflee = 1;
346 1.1 cgd break;
347 1.1 cgd case 'U':
348 1.4 christos (void) hitu(mtmp, d(3, 4));
349 1.4 christos (void) hitu(mtmp, d(3, 4));
350 1.1 cgd break;
351 1.1 cgd case 'v':
352 1.4 christos if (ctmp && !u.ustuck)
353 1.4 christos u.ustuck = mtmp;
354 1.1 cgd break;
355 1.1 cgd case 'V':
356 1.4 christos if (tmp)
357 1.4 christos u.uhp -= 4;
358 1.4 christos if (ctmp)
359 1.4 christos losexp();
360 1.1 cgd break;
361 1.1 cgd case 'W':
362 1.4 christos if (ctmp)
363 1.4 christos losexp();
364 1.1 cgd break;
365 1.1 cgd #ifndef NOWORM
366 1.1 cgd case 'w':
367 1.4 christos if (tmp)
368 1.4 christos wormhit(mtmp);
369 1.4 christos #endif /* NOWORM */
370 1.1 cgd break;
371 1.1 cgd case 'X':
372 1.4 christos (void) hitu(mtmp, rnd(5));
373 1.4 christos (void) hitu(mtmp, rnd(5));
374 1.4 christos (void) hitu(mtmp, rnd(5));
375 1.1 cgd break;
376 1.1 cgd case 'x':
377 1.4 christos {
378 1.4 christos long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
379 1.4 christos pline("%s pricks in your %s leg!",
380 1.4 christos Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
381 1.4 christos set_wounded_legs(side, rnd(50));
382 1.4 christos losehp_m(2, mtmp);
383 1.4 christos break;
384 1.1 cgd }
385 1.1 cgd case 'y':
386 1.4 christos if (mtmp->mcan)
387 1.4 christos break;
388 1.1 cgd mondead(mtmp);
389 1.4 christos if (!Blind) {
390 1.1 cgd pline("You are blinded by a blast of light!");
391 1.4 christos Blind = d(4, 12);
392 1.1 cgd seeoff(0);
393 1.1 cgd }
394 1.4 christos return (1);
395 1.1 cgd case 'Y':
396 1.4 christos (void) hitu(mtmp, rnd(6));
397 1.1 cgd break;
398 1.1 cgd }
399 1.4 christos if (u.uhp < 1)
400 1.4 christos done_in_by(mtmp);
401 1.4 christos return (0);
402 1.1 cgd }
403 1.1 cgd
404 1.4 christos int
405 1.4 christos hitu(mtmp, dam)
406 1.4 christos struct monst *mtmp;
407 1.4 christos int dam;
408 1.1 cgd {
409 1.4 christos int tmp, res;
410 1.1 cgd
411 1.1 cgd nomul(0);
412 1.4 christos if (u.uswallow)
413 1.4 christos return (0);
414 1.1 cgd
415 1.4 christos if (mtmp->mhide && mtmp->mundetected) {
416 1.1 cgd mtmp->mundetected = 0;
417 1.4 christos if (!Blind) {
418 1.4 christos struct obj *obj;
419 1.4 christos if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL)
420 1.1 cgd pline("%s was hidden under %s!",
421 1.4 christos Xmonnam(mtmp), doname(obj));
422 1.1 cgd }
423 1.1 cgd }
424 1.1 cgd tmp = u.uac;
425 1.1 cgd /* give people with Ac = -10 at least some vulnerability */
426 1.4 christos if (tmp < 0) {
427 1.4 christos dam += tmp; /* decrease damage */
428 1.4 christos if (dam <= 0)
429 1.4 christos dam = 1;
430 1.1 cgd tmp = -rn2(-tmp);
431 1.1 cgd }
432 1.1 cgd tmp += mtmp->data->mlevel;
433 1.4 christos if (multi < 0)
434 1.4 christos tmp += 4;
435 1.4 christos if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee)
436 1.4 christos tmp -= 2;
437 1.4 christos if (mtmp->mtrapped)
438 1.4 christos tmp -= 2;
439 1.4 christos if (tmp <= rnd(20)) {
440 1.4 christos if (Blind)
441 1.4 christos pline("It misses.");
442 1.4 christos else
443 1.4 christos pline("%s misses.", Monnam(mtmp));
444 1.1 cgd res = 0;
445 1.1 cgd } else {
446 1.4 christos if (Blind)
447 1.4 christos pline("It hits!");
448 1.4 christos else
449 1.4 christos pline("%s hits!", Monnam(mtmp));
450 1.1 cgd losehp_m(dam, mtmp);
451 1.1 cgd res = 1;
452 1.1 cgd }
453 1.1 cgd stop_occupation();
454 1.4 christos return (res);
455 1.1 cgd }
456