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