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