| File: | src/games/hack/hack.fight.c |
| Warning: | line 123, column 38 Although the value stored to 'pa' is used in the enclosing expression, the value is never actually read from 'pa' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: hack.fight.c,v 1.10 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 <stdio.h> |
| 65 | |
| 66 | #include "hack.h" |
| 67 | |
| 68 | extern struct permonst li_dog, dog, la_dog; |
| 69 | |
| 70 | static boolean far_noise; |
| 71 | static long noisetime; |
| 72 | |
| 73 | static void monstone(struct monst *); |
| 74 | |
| 75 | /* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */ |
| 76 | int |
| 77 | hitmm(struct monst * magr, struct monst * mdef) |
| 78 | { |
| 79 | struct permonst *pa = magr->data, *pd = mdef->data; |
| 80 | int hit; |
| 81 | schar tmp; |
| 82 | boolean vis; |
| 83 | |
| 84 | if(strchr("Eauy", pa->mlet)) return(0); |
| 85 | if(magr->mfroz) return(0); /* riv05!a3 */ |
| 86 | tmp = pd->ac + pa->mlevel; |
| 87 | if(mdef->mconf || mdef->mfroz || mdef->msleep){ |
| 88 | tmp += 4; |
| 89 | if(mdef->msleep) mdef->msleep = 0; |
| 90 | } |
| 91 | hit = (tmp > rnd(20)); |
| 92 | if(hit) mdef->msleep = 0; |
| 93 | vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); |
| 94 | if(vis){ |
| 95 | char buf[BUFSZ256]; |
| 96 | if(mdef->mimic) seemimic(mdef); |
| 97 | if(magr->mimic) seemimic(magr); |
| 98 | (void) snprintf(buf,sizeof buf,"%s %s", Monnam(magr), |
| 99 | hit ? "hits" : "misses"); |
| 100 | pline("%s %s.", buf, monnam(mdef)); |
| 101 | } else { |
| 102 | boolean far = (dist(magr->mx, magr->my) > 15); |
| 103 | if(far != far_noise || moves-noisetime > 10) { |
| 104 | far_noise = far; |
| 105 | noisetime = moves; |
| 106 | pline("You hear some noises%s.", |
| 107 | far ? " in the distance" : ""); |
| 108 | } |
| 109 | } |
| 110 | if(hit){ |
| 111 | if(magr->data->mlet == 'c' && !magr->cham) { |
| 112 | magr->mhpmax += 3; |
| 113 | if(vis) pline("%s is turned to stone!", Monnam(mdef)); |
| 114 | else if(mdef->mtame) |
| 115 | pline("You have a peculiarly sad feeling for a moment, then it passes."); |
| 116 | monstone(mdef); |
| 117 | hit = 2; |
| 118 | } else |
| 119 | if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) { |
| 120 | magr->mhpmax += 1 + rn2(pd->mlevel+1); |
| 121 | if(magr->mtame && magr->mhpmax > 8*pa->mlevel){ |
| 122 | if(pa == &li_dog) magr->data = pa = &dog; |
| 123 | else if(pa == &dog) magr->data = pa = &la_dog; |
Although the value stored to 'pa' is used in the enclosing expression, the value is never actually read from 'pa' | |
| 124 | } |
| 125 | if(vis) pline("%s is killed!", Monnam(mdef)); |
| 126 | else if(mdef->mtame) |
| 127 | pline("You have a sad feeling for a moment, then it passes."); |
| 128 | mondied(mdef); |
| 129 | hit = 2; |
| 130 | } |
| 131 | } |
| 132 | return(hit); |
| 133 | } |
| 134 | |
| 135 | /* drop (perhaps) a cadaver and remove monster */ |
| 136 | void |
| 137 | mondied(struct monst *mdef) |
| 138 | { |
| 139 | struct permonst *pd = mdef->data; |
| 140 | |
| 141 | if(letter(pd->mlet) && rn2(3)){ |
| 142 | (void) mkobj_at(pd->mlet,mdef->mx,mdef->my); |
| 143 | if(cansee(mdef->mx,mdef->my)){ |
| 144 | unpmon(mdef); |
| 145 | atl(mdef->mx,mdef->my,fobj->olet); |
| 146 | } |
| 147 | stackobj(fobj); |
| 148 | } |
| 149 | mondead(mdef); |
| 150 | } |
| 151 | |
| 152 | /* drop a rock and remove monster */ |
| 153 | static void |
| 154 | monstone(struct monst *mdef) |
| 155 | { |
| 156 | extern char mlarge[]; |
| 157 | if(strchr(mlarge, mdef->data->mlet)) |
| 158 | mksobj_at(ENORMOUS_ROCK97, mdef->mx, mdef->my); |
| 159 | else |
| 160 | mksobj_at(ROCK75, mdef->mx, mdef->my); |
| 161 | if(cansee(mdef->mx, mdef->my)){ |
| 162 | unpmon(mdef); |
| 163 | atl(mdef->mx,mdef->my,fobj->olet); |
| 164 | } |
| 165 | mondead(mdef); |
| 166 | } |
| 167 | |
| 168 | int |
| 169 | fightm(struct monst *mtmp) |
| 170 | { |
| 171 | struct monst *mon; |
| 172 | |
| 173 | for(mon = fmon; mon; mon = mon->nmon) if(mon != mtmp) { |
| 174 | if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my)(((mon->mx)-(mtmp->mx))*((mon->mx)-(mtmp->mx)) + ( (mon->my)-(mtmp->my))*((mon->my)-(mtmp->my))) < 3) |
| 175 | if(rn2(4)) |
| 176 | return(hitmm(mtmp,mon)); |
| 177 | } |
| 178 | return(-1); |
| 179 | } |
| 180 | |
| 181 | /* u is hit by sth, but not a monster */ |
| 182 | int |
| 183 | thitu(int tlev, int dam, char *name) |
| 184 | { |
| 185 | char buf[BUFSZ256]; |
| 186 | |
| 187 | setan(name,buf,sizeof buf); |
| 188 | if(u.uac + tlev <= rnd(20)) { |
| 189 | if(Blindu.uprops[(19 +7)].p_flgs) pline("It misses."); |
| 190 | else pline("You are almost hit by %s!", buf); |
| 191 | return(0); |
| 192 | } else { |
| 193 | if(Blindu.uprops[(19 +7)].p_flgs) pline("You are hit!"); |
| 194 | else pline("You are hit by %s!", buf); |
| 195 | losehp(dam,name); |
| 196 | return(1); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | char mlarge[] = "bCDdegIlmnoPSsTUwY',&"; |
| 201 | |
| 202 | /* return TRUE if mon still alive */ |
| 203 | boolean |
| 204 | hmon(struct monst *mon, struct obj *obj, int thrown) |
| 205 | { |
| 206 | int tmp; |
| 207 | boolean hittxt = FALSE0; |
| 208 | |
| 209 | if(!obj){ |
| 210 | tmp = rnd(2); /* attack with bare hands */ |
| 211 | if(mon->data->mlet == 'c' && !uarmg){ |
| 212 | pline("You hit the cockatrice with your bare hands."); |
| 213 | pline("You turn to stone ..."); |
| 214 | done_in_by(mon); |
| 215 | } |
| 216 | } else if(obj->olet == WEAPON_SYM')' || obj->otyp == PICK_AXE93) { |
| 217 | if(obj == uwep && (obj->otyp > SPEAR85 || obj->otyp < BOOMERANG76)) |
| 218 | tmp = rnd(2); |
| 219 | else { |
| 220 | if(strchr(mlarge, mon->data->mlet)) { |
| 221 | tmp = rnd(objects[obj->otyp].wldamoc_oc1); |
| 222 | if(obj->otyp == TWO_HANDED_SWORD81) tmp += d(2,6); |
| 223 | else if(obj->otyp == FLAIL79) tmp += rnd(4); |
| 224 | } else { |
| 225 | tmp = rnd(objects[obj->otyp].wsdamoc_oc2); |
| 226 | } |
| 227 | tmp += obj->spe; |
| 228 | if(!thrown && obj == uwep && obj->otyp == BOOMERANG76 |
| 229 | && !rn2(3)){ |
| 230 | pline("As you hit %s, the boomerang breaks into splinters.", |
| 231 | monnam(mon)); |
| 232 | freeinv(obj); |
| 233 | setworn((struct obj *) 0, obj->owornmask); |
| 234 | obfree(obj, (struct obj *) 0); |
| 235 | tmp++; |
| 236 | } |
| 237 | } |
| 238 | if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD81 && |
| 239 | !strcmp(ONAME(obj)((char *) obj->oextra), "Orcrist")) |
| 240 | tmp += rnd(10); |
| 241 | } else switch(obj->otyp) { |
| 242 | case HEAVY_IRON_BALL95: |
| 243 | tmp = rnd(25); break; |
| 244 | case EXPENSIVE_CAMERA91: |
| 245 | pline("You succeed in destroying your camera. Congratulations!"); |
| 246 | freeinv(obj); |
| 247 | if(obj->owornmask) |
| 248 | setworn((struct obj *) 0, obj->owornmask); |
| 249 | obfree(obj, (struct obj *) 0); |
| 250 | return(TRUE1); |
| 251 | case DEAD_COCKATRICE47: |
| 252 | pline("You hit %s with the cockatrice corpse.", |
| 253 | monnam(mon)); |
| 254 | if(mon->data->mlet == 'c') { |
| 255 | tmp = 1; |
| 256 | hittxt = TRUE1; |
| 257 | break; |
| 258 | } |
| 259 | pline("%s is turned to stone!", Monnam(mon)); |
| 260 | killed(mon); |
| 261 | return(FALSE0); |
| 262 | case CLOVE_OF_GARLIC16: /* no effect against demons */ |
| 263 | if(strchr(UNDEAD"ZVW ", mon->data->mlet)) |
| 264 | mon->mflee = 1; |
| 265 | tmp = 1; |
| 266 | break; |
| 267 | default: |
| 268 | /* non-weapons can damage because of their weight */ |
| 269 | /* (but not too much) */ |
| 270 | tmp = obj->owt/10; |
| 271 | if(tmp < 1) tmp = 1; |
| 272 | else tmp = rnd(tmp); |
| 273 | if(tmp > 6) tmp = 6; |
| 274 | } |
| 275 | |
| 276 | /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ |
| 277 | |
| 278 | tmp += u.udaminc + dbon(); |
| 279 | if(u.uswallow) { |
| 280 | if((tmp -= u.uswldtim) <= 0) { |
| 281 | pline("Your arms are no longer able to hit."); |
| 282 | return(TRUE1); |
| 283 | } |
| 284 | } |
| 285 | if(tmp < 1) tmp = 1; |
| 286 | mon->mhp -= tmp; |
| 287 | if(mon->mhp < 1) { |
| 288 | killed(mon); |
| 289 | return(FALSE0); |
| 290 | } |
| 291 | if(mon->mtame && (!mon->mflee || mon->mfleetim)) { |
| 292 | mon->mflee = 1; /* Rick Richardson */ |
| 293 | mon->mfleetim += 10*rnd(tmp); |
| 294 | } |
| 295 | |
| 296 | if(!hittxt) { |
| 297 | if(thrown) |
| 298 | /* this assumes that we cannot throw plural things */ |
| 299 | hit( xname(obj) /* or: objects[obj->otyp].oc_name */, |
| 300 | mon, exclam(tmp) ); |
| 301 | else if(Blindu.uprops[(19 +7)].p_flgs) |
| 302 | pline("You hit it."); |
| 303 | else |
| 304 | pline("You hit %s%s", monnam(mon), exclam(tmp)); |
| 305 | } |
| 306 | |
| 307 | if(u.umconf && !thrown) { |
| 308 | if(!Blindu.uprops[(19 +7)].p_flgs) { |
| 309 | pline("Your hands stop glowing blue."); |
| 310 | if(!mon->mfroz && !mon->msleep) |
| 311 | pline("%s appears confused.",Monnam(mon)); |
| 312 | } |
| 313 | mon->mconf = 1; |
| 314 | u.umconf = 0; |
| 315 | } |
| 316 | return(TRUE1); /* mon still alive */ |
| 317 | } |
| 318 | |
| 319 | /* try to attack; return FALSE if monster evaded */ |
| 320 | /* u.dx and u.dy must be set */ |
| 321 | boolean |
| 322 | attack(struct monst *mtmp) |
| 323 | { |
| 324 | schar tmp; |
| 325 | boolean malive = TRUE1; |
| 326 | struct permonst *mdat; |
| 327 | mdat = mtmp->data; |
| 328 | |
| 329 | u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */ |
| 330 | |
| 331 | if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && |
| 332 | !mtmp->mconf && mtmp->mcansee && !rn2(7) && |
| 333 | (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ |
| 334 | mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) |
| 335 | return(FALSE0); |
| 336 | |
| 337 | if(mtmp->mimic){ |
| 338 | if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; |
| 339 | switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){ |
| 340 | case '+': |
| 341 | pline("The door actually was a Mimic."); |
| 342 | break; |
| 343 | case '$': |
| 344 | pline("The chest was a Mimic!"); |
| 345 | break; |
| 346 | default: |
| 347 | pline("Wait! That's a Mimic!"); |
| 348 | } |
| 349 | wakeup(mtmp); /* clears mtmp->mimic */ |
| 350 | return(TRUE1); |
| 351 | } |
| 352 | |
| 353 | wakeup(mtmp); |
| 354 | |
| 355 | if(mtmp->mhide && mtmp->mundetected){ |
| 356 | struct obj *obj; |
| 357 | |
| 358 | mtmp->mundetected = 0; |
| 359 | if((obj = o_at(mtmp->mx,mtmp->my)) && !Blindu.uprops[(19 +7)].p_flgs) |
| 360 | pline("Wait! There's a %s hiding under %s!", |
| 361 | mdat->mname, doname(obj)); |
| 362 | return(TRUE1); |
| 363 | } |
| 364 | |
| 365 | tmp = u.uluck + u.ulevel + mdat->ac + abon(); |
| 366 | if(uwep) { |
| 367 | if(uwep->olet == WEAPON_SYM')' || uwep->otyp == PICK_AXE93) |
| 368 | tmp += uwep->spe; |
| 369 | if(uwep->otyp == TWO_HANDED_SWORD81) tmp -= 1; |
| 370 | else if(uwep->otyp == DAGGER82) tmp += 2; |
| 371 | else if(uwep->otyp == CRYSKNIFE84) tmp += 3; |
| 372 | else if(uwep->otyp == SPEAR85 && |
| 373 | strchr("XDne", mdat->mlet)) tmp += 2; |
| 374 | } |
| 375 | if(mtmp->msleep) { |
| 376 | mtmp->msleep = 0; |
| 377 | tmp += 2; |
| 378 | } |
| 379 | if(mtmp->mfroz) { |
| 380 | tmp += 4; |
| 381 | if(!rn2(10)) mtmp->mfroz = 0; |
| 382 | } |
| 383 | if(mtmp->mflee) tmp += 2; |
| 384 | if(u.utrap) tmp -= 3; |
| 385 | |
| 386 | /* with a lot of luggage, your agility diminishes */ |
| 387 | tmp -= (inv_weight() + 40)/20; |
| 388 | |
| 389 | if(tmp <= rnd(20) && !u.uswallow){ |
| 390 | if(Blindu.uprops[(19 +7)].p_flgs) pline("You miss it."); |
| 391 | else pline("You miss %s.",monnam(mtmp)); |
| 392 | } else { |
| 393 | /* we hit the monster; be careful: it might die! */ |
| 394 | |
| 395 | if((malive = hmon(mtmp,uwep,0)) == TRUE1) { |
| 396 | /* monster still alive */ |
| 397 | if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) { |
| 398 | mtmp->mflee = 1; |
| 399 | if(!rn2(3)) mtmp->mfleetim = rnd(100); |
| 400 | if(u.ustuck == mtmp && !u.uswallow) |
| 401 | u.ustuck = 0; |
| 402 | } |
| 403 | #ifndef NOWORM |
| 404 | if(mtmp->wormno) |
| 405 | cutworm(mtmp, u.ux+u.dx, u.uy+u.dy, |
| 406 | uwep ? uwep->otyp : 0); |
| 407 | #endif /* NOWORM */ |
| 408 | } |
| 409 | if(mdat->mlet == 'a') { |
| 410 | if(rn2(2)) { |
| 411 | pline("You are splashed by the blob's acid!"); |
| 412 | losehp_m(rnd(6), mtmp); |
| 413 | if(!rn2(30)) corrode_armor(); |
| 414 | } |
| 415 | if(!rn2(6)) corrode_weapon(); |
| 416 | } |
| 417 | } |
| 418 | if(malive && mdat->mlet == 'E' && canseemon(mtmp) |
| 419 | && !mtmp->mcan && rn2(3)) { |
| 420 | if(mtmp->mcansee) { |
| 421 | pline("You are frozen by the floating eye's gaze!"); |
| 422 | nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); |
| 423 | } else { |
| 424 | pline("The blinded floating eye cannot defend itself."); |
| 425 | if(!rn2(500)) if((int)u.uluck > LUCKMIN(-10)) u.uluck--; |
| 426 | } |
| 427 | } |
| 428 | return(TRUE1); |
| 429 | } |