1 /* $OpenBSD: hack.mhitu.c,v 1.7 2009/10/27 23:59:25 deraadt 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 extern struct monst *makemon(); 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 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) done_in_by(mtmp); 110 return(0); 111 } 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)) return(1); /* he disappeared */ 133 break; 134 case '&': 135 if(!mtmp->cham && !mtmp->mcan && !rn2(13)) { 136 (void) makemon(PM_DEMON,u.ux,u.uy); 137 } else { 138 (void) hitu(mtmp,d(2,6)); 139 (void) hitu(mtmp,d(2,6)); 140 (void) hitu(mtmp,rnd(3)); 141 (void) hitu(mtmp,rnd(3)); 142 (void) hitu(mtmp,rn1(4,2)); 143 } 144 break; 145 case ',': 146 if(tmp) justswld(mtmp,"The trapper"); 147 break; 148 case '\'': 149 if(tmp) justswld(mtmp, "The lurker above"); 150 break; 151 case ';': 152 if(ctmp) { 153 if(!u.ustuck && !rn2(10)) { 154 pline("%s swings itself around you!", 155 Monnam(mtmp)); 156 u.ustuck = mtmp; 157 } else if(u.ustuck == mtmp && 158 levl[(int)mtmp->mx][(int)mtmp->my].typ == POOL) { 159 pline("%s drowns you ...", Monnam(mtmp)); 160 done("drowned"); 161 } 162 } 163 break; 164 case 'A': 165 if(ctmp && rn2(2)) { 166 if(Poison_resistance) 167 pline("The sting doesn't seem to affect you."); 168 else { 169 pline("You feel weaker!"); 170 losestr(1); 171 } 172 } 173 break; 174 case 'C': 175 (void) hitu(mtmp,rnd(6)); 176 break; 177 case 'c': 178 if(!rn2(5)) { 179 pline("You hear %s's hissing!", monnam(mtmp)); 180 if(ctmp || !rn2(20) || (flags.moonphase == NEW_MOON 181 && !carrying(DEAD_LIZARD))) { 182 Stoned = 5; 183 /* pline("You get turned to stone!"); */ 184 /* done_in_by(mtmp); */ 185 } 186 } 187 break; 188 case 'D': 189 if(rn2(6) || mtmp->mcan) { 190 (void) hitu(mtmp,d(3,10)); 191 (void) hitu(mtmp,rnd(8)); 192 (void) hitu(mtmp,rnd(8)); 193 break; 194 } 195 kludge("%s breathes fire!","The dragon"); 196 buzz(-1,mtmp->mx,mtmp->my,u.ux-mtmp->mx,u.uy-mtmp->my); 197 break; 198 case 'd': 199 (void) hitu(mtmp,d(2, (flags.moonphase == FULL_MOON) ? 3 : 4)); 200 break; 201 case 'e': 202 (void) hitu(mtmp,d(3,6)); 203 break; 204 case 'F': 205 if(mtmp->mcan) break; 206 kludge("%s explodes!","The freezing sphere"); 207 if(Cold_resistance) pline("You don't seem affected by it."); 208 else { 209 xchar dn; 210 if(17-(u.ulevel/2) > rnd(20)) { 211 pline("You get blasted!"); 212 dn = 6; 213 } else { 214 pline("You duck the blast..."); 215 dn = 3; 216 } 217 losehp_m(d(dn,6), mtmp); 218 } 219 mondead(mtmp); 220 return(1); 221 case 'g': 222 if(ctmp && multi >= 0 && !rn2(3)) { 223 kludge("You are frozen by %ss juices","the cube'"); 224 nomul(-rnd(10)); 225 } 226 break; 227 case 'h': 228 if(ctmp && multi >= 0 && !rn2(5)) { 229 nomul(-rnd(10)); 230 kludge("You are put to sleep by %ss bite!", 231 "the homunculus'"); 232 } 233 break; 234 case 'j': 235 tmp = hitu(mtmp,rnd(3)); 236 tmp &= hitu(mtmp,rnd(3)); 237 if(tmp){ 238 (void) hitu(mtmp,rnd(4)); 239 (void) hitu(mtmp,rnd(4)); 240 } 241 break; 242 case 'k': 243 if((hitu(mtmp,rnd(4)) || !rn2(3)) && ctmp){ 244 poisoned("bee's sting",mdat->mname); 245 } 246 break; 247 case 'L': 248 if(tmp) stealgold(mtmp); 249 break; 250 case 'N': 251 if(mtmp->mcan && !Blind) { 252 pline("%s tries to seduce you, but you seem not interested.", 253 Amonnam(mtmp, "plain")); 254 if(rn2(3)) rloc(mtmp); 255 } else if(steal(mtmp)) { 256 rloc(mtmp); 257 mtmp->mflee = 1; 258 } 259 break; 260 case 'n': 261 if(!uwep && !uarm && !uarmh && !uarms && !uarmg) { 262 pline("%s hits! (I hope you don't mind)", 263 Monnam(mtmp)); 264 u.uhp += rnd(7); 265 if(!rn2(7)) u.uhpmax++; 266 if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; 267 flags.botl = 1; 268 if(!rn2(50)) rloc(mtmp); 269 } else { 270 (void) hitu(mtmp,d(2,6)); 271 (void) hitu(mtmp,d(2,6)); 272 } 273 break; 274 case 'o': 275 tmp = hitu(mtmp,rnd(6)); 276 if(hitu(mtmp,rnd(6)) && tmp && /* hits with both paws */ 277 !u.ustuck && rn2(2)) { 278 u.ustuck = mtmp; 279 kludge("%s has grabbed you!","The owlbear"); 280 u.uhp -= d(2,8); 281 } else if(u.ustuck == mtmp) { 282 u.uhp -= d(2,8); 283 pline("You are being crushed."); 284 } 285 break; 286 case 'P': 287 if(ctmp && !rn2(4)) 288 justswld(mtmp,"The purple worm"); 289 else 290 (void) hitu(mtmp,d(2,4)); 291 break; 292 case 'Q': 293 (void) hitu(mtmp,rnd(2)); 294 (void) hitu(mtmp,rnd(2)); 295 break; 296 case 'R': 297 if(tmp && uarmh && !uarmh->rustfree && 298 (int) uarmh->spe >= -1) { 299 pline("Your helmet rusts!"); 300 uarmh->spe--; 301 } else 302 if(ctmp && uarm && !uarm->rustfree && /* Mike Newton */ 303 uarm->otyp < STUDDED_LEATHER_ARMOR && 304 (int) uarm->spe >= -1) { 305 pline("Your armor rusts!"); 306 uarm->spe--; 307 } 308 break; 309 case 'S': 310 if(ctmp && !rn2(8)) { 311 poisoned("snake's bite",mdat->mname); 312 } 313 break; 314 case 's': 315 if(tmp && !rn2(8)) { 316 poisoned("scorpion's sting",mdat->mname); 317 } 318 (void) hitu(mtmp,rnd(8)); 319 (void) hitu(mtmp,rnd(8)); 320 break; 321 case 'T': 322 (void) hitu(mtmp,rnd(6)); 323 (void) hitu(mtmp,rnd(6)); 324 break; 325 case 't': 326 if(!rn2(5)) rloc(mtmp); 327 break; 328 case 'u': 329 mtmp->mflee = 1; 330 break; 331 case 'U': 332 (void) hitu(mtmp,d(3,4)); 333 (void) hitu(mtmp,d(3,4)); 334 break; 335 case 'v': 336 if(ctmp && !u.ustuck) u.ustuck = mtmp; 337 break; 338 case 'V': 339 if(tmp) u.uhp -= 4; 340 if(ctmp) losexp(); 341 break; 342 case 'W': 343 if(ctmp) losexp(); 344 break; 345 #ifndef NOWORM 346 case 'w': 347 if(tmp) wormhit(mtmp); 348 #endif /* NOWORM */ 349 break; 350 case 'X': 351 (void) hitu(mtmp,rnd(5)); 352 (void) hitu(mtmp,rnd(5)); 353 (void) hitu(mtmp,rnd(5)); 354 break; 355 case 'x': 356 { long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; 357 pline("%s pricks in your %s leg!", 358 Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left"); 359 set_wounded_legs(side, rnd(50)); 360 losehp_m(2, mtmp); 361 break; 362 } 363 case 'y': 364 if(mtmp->mcan) break; 365 mondead(mtmp); 366 if(!Blind) { 367 pline("You are blinded by a blast of light!"); 368 Blind = d(4,12); 369 seeoff(0); 370 } 371 return(1); 372 case 'Y': 373 (void) hitu(mtmp,rnd(6)); 374 break; 375 } 376 if(u.uhp < 1) done_in_by(mtmp); 377 return(0); 378 } 379 380 int 381 hitu(struct monst *mtmp, int dam) 382 { 383 int tmp, res; 384 385 nomul(0); 386 if(u.uswallow) return(0); 387 388 if(mtmp->mhide && mtmp->mundetected) { 389 mtmp->mundetected = 0; 390 if(!Blind) { 391 struct obj *obj; 392 if ((obj = o_at(mtmp->mx,mtmp->my))) 393 pline("%s was hidden under %s!", 394 Xmonnam(mtmp), doname(obj)); 395 } 396 } 397 398 tmp = u.uac; 399 /* give people with Ac = -10 at least some vulnerability */ 400 if(tmp < 0) { 401 dam += tmp; /* decrease damage */ 402 if(dam <= 0) dam = 1; 403 tmp = -rn2(-tmp); 404 } 405 tmp += mtmp->data->mlevel; 406 if(multi < 0) tmp += 4; 407 if((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee) tmp -= 2; 408 if(mtmp->mtrapped) tmp -= 2; 409 if(tmp <= rnd(20)) { 410 if(Blind) pline("It misses."); 411 else pline("%s misses.",Monnam(mtmp)); 412 res = 0; 413 } else { 414 if(Blind) pline("It hits!"); 415 else pline("%s hits!",Monnam(mtmp)); 416 losehp_m(dam, mtmp); 417 res = 1; 418 } 419 stop_occupation(); 420 return(res); 421 } 422