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