void done_in_by(struct monst *mtmp, const char *override_msg) { pline(msgc_fatal_predone, "You die..."); if (mtmp->data->mlet == S_WRAITH && !noncorporeal(mtmp->data)) u.ugrave_arise = PM_WRAITH; else if (mtmp->data->mlet == S_MUMMY && urace.mummynum != NON_PM) u.ugrave_arise = urace.mummynum; else if (mtmp->data->mlet == S_VAMPIRE && Race_if(PM_HUMAN)) u.ugrave_arise = PM_VAMPIRE; else if (mtmp->data == &mons[PM_GHOUL]) u.ugrave_arise = PM_GHOUL; if (u.ugrave_arise >= LOW_PM && (mvitals[u.ugrave_arise].mvflags & G_GENOD)) u.ugrave_arise = NON_PM; if (touch_petrifies(mtmp->data)) { done(STONING, override_msg ? override_msg : killer_msg_mon(STONING, mtmp)); } else { done(DIED, override_msg ? override_msg : killer_msg_mon(DIED, mtmp)); } return; }
/* Can this monster wear a saddle? */ boolean can_saddle(struct monst *mtmp) { const struct permonst *ptr = mtmp->data; return (strchr(steeds, ptr->mlet) && (ptr->msize >= MZ_MEDIUM) && (!humanoid(ptr) || ptr->mlet == S_CENTAUR) && !amorphous(ptr) && !noncorporeal(ptr) && !is_whirly(ptr) && !unsolid(ptr)); }
/* * Simple-minded "can it be here?" routine */ static boolean e_survives_at(struct entity *etmp, int x, int y) { if (noncorporeal(etmp->edata)) return TRUE; if (is_pool(level, x, y)) return (boolean) (waterwalks(etmp->emon) || unbreathing(etmp->emon) || swims(etmp->emon) || flying(etmp->emon) || levitates(etmp->emon)); /* must force call to lava_effects in e_died if is_u */ if (is_lava(level, x, y)) return (boolean) (likes_lava(etmp->edata) || flying(etmp->emon) || levitates(etmp->emon)); if (is_db_wall(x, y)) return !!phasing(etmp->emon); return TRUE; }
/* * Simple-minded "can it be here?" routine */ static boolean e_survives_at(struct entity *etmp, int x, int y) { if (noncorporeal(etmp->edata)) return TRUE; if (is_pool(level, x, y)) return (boolean)((is_u(etmp) && (Wwalking || Amphibious || Swimming || Flying || Levitation)) || is_swimmer(etmp->edata) || is_flyer(etmp->edata) || is_floater(etmp->edata)); /* must force call to lava_effects in e_died if is_u */ if (is_lava(level, x, y)) return (boolean)((is_u(etmp) && (Levitation || Flying)) || likes_lava(etmp->edata) || is_flyer(etmp->edata)); if (is_db_wall(x, y)) return((boolean)(is_u(etmp) ? Passes_walls : passes_walls(etmp->edata))); return TRUE; }
/* creature will slide out of armor */ boolean sliparm(const struct permonst * ptr) { return ((boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL || noncorporeal(ptr))); }
/* * These are never directly affected by a bridge or portcullis. */ static boolean automiss(struct entity *etmp) { return (boolean)((is_u(etmp) ? Passes_walls : passes_walls(etmp->edata)) || noncorporeal(etmp->edata)); }
/* the tsurugi of muramasa or vorpal blade hit someone */ static boolean artifact_hit_behead(struct monst *magr, struct monst *mdef, struct obj *otmp, int *dmgptr, int dieroll) { boolean youattack = (magr == &youmonst); boolean youdefend = (mdef == &youmonst); boolean vis = (!youattack && magr && cansee(magr->mx, magr->my)) || (!youdefend && cansee(mdef->mx, mdef->my)) || (youattack && u.uswallow && mdef == u.ustuck && !Blind); const char *wepdesc; char hittee[BUFSZ]; strcpy(hittee, youdefend ? "you" : mon_nam(mdef)); /* We really want "on a natural 20" but Nethack does it in reverse from AD&D. */ if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) { wepdesc = "The razor-sharp blade"; /* not really beheading, but so close, why add another SPFX */ if (youattack && u.uswallow && mdef == u.ustuck) { pline("You slice %s wide open!", mon_nam(mdef)); *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; return TRUE; } if (!youdefend) { /* allow normal cutworm() call to add extra damage */ if (notonhead) return FALSE; if (bigmonst(mdef->data)) { if (youattack) pline("You slice deeply into %s!", mon_nam(mdef)); else if (vis) pline("%s cuts deeply into %s!", Monnam(magr), hittee); *dmgptr *= 2; return TRUE; } *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; pline("%s cuts %s in half!", wepdesc, mon_nam(mdef)); otmp->dknown = TRUE; return TRUE; } else { if (bigmonst(youmonst.data)) { pline("%s cuts deeply into you!", magr ? Monnam(magr) : wepdesc); *dmgptr *= 2; return TRUE; } /* Players with negative AC's take less damage instead * of just not getting hit. We must add a large enough * value to the damage so that this reduction in * damage does not prevent death. */ *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER; pline("%s cuts you in half!", wepdesc); otmp->dknown = TRUE; return TRUE; } } else if (otmp->oartifact == ART_VORPAL_BLADE && (dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) { static const char * const behead_msg[2] = { "%s beheads %s!", "%s decapitates %s!" }; if (youattack && u.uswallow && mdef == u.ustuck) return FALSE; wepdesc = artilist[ART_VORPAL_BLADE].name; if (!youdefend) { if (!has_head(mdef->data) || notonhead || u.uswallow) { if (youattack) pline("Somehow, you miss %s wildly.", mon_nam(mdef)); else if (vis) pline("Somehow, %s misses wildly.", mon_nam(magr)); *dmgptr = 0; return (boolean)(youattack || vis); } if (noncorporeal(mdef->data) || amorphous(mdef->data)) { pline("%s slices through %s %s.", wepdesc, s_suffix(mon_nam(mdef)), mbodypart(mdef,NECK)); return TRUE; } *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, mon_nam(mdef)); otmp->dknown = TRUE; return TRUE; } else { if (!has_head(youmonst.data)) { pline("Somehow, %s misses you wildly.", magr ? mon_nam(magr) : wepdesc); *dmgptr = 0; return TRUE; } if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) { pline("%s slices through your %s.", wepdesc, body_part(NECK)); return TRUE; } *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER; pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you"); otmp->dknown = TRUE; /* Should amulets fall off? */ return TRUE; } } return FALSE; }
/* * These are never directly affected by a bridge or portcullis. */ static boolean automiss(struct entity *etmp) { return (boolean) (phasing(etmp->emon) || noncorporeal(etmp->edata)); }