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