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