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