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