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