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