static void cast_protection(void) { int loglev = 0; int l = u.ulevel; int natac = get_player_ac() + u.uspellprot; int gain; /* loglev=log2(u.ulevel)+1 (1..5) */ while (l) { loglev++; l /= 2; } /* * The more u.uspellprot you already have, the less you get, * and the better your natural ac, the less you get. * * LEVEL AC SPELLPROT from sucessive SPE_PROTECTION casts * 1 10 0, 1, 2, 3, 4 * 1 0 0, 1, 2, 3 * 1 -10 0, 1, 2 * 2-3 10 0, 2, 4, 5, 6, 7, 8 * 2-3 0 0, 2, 4, 5, 6 * 2-3 -10 0, 2, 3, 4 * 4-7 10 0, 3, 6, 8, 9, 10, 11, 12 * 4-7 0 0, 3, 5, 7, 8, 9 * 4-7 -10 0, 3, 5, 6 * 7-15 -10 0, 3, 5, 6 * 8-15 10 0, 4, 7, 10, 12, 13, 14, 15, 16 * 8-15 0 0, 4, 7, 9, 10, 11, 12 * 8-15 -10 0, 4, 6, 7, 8 * 16-30 10 0, 5, 9, 12, 14, 16, 17, 18, 19, 20 * 16-30 0 0, 5, 9, 11, 13, 14, 15 * 16-30 -10 0, 5, 8, 9, 10 */ gain = loglev - (int)u.uspellprot / (4 - min(3, (10 - natac) / 10)); if (gain > 0) { if (!Blind) { const char *hgolden = hcolor("golden"); if (u.uspellprot) pline("The %s haze around you becomes more dense.", hgolden); else pline("The %s around you begins to shimmer with %s haze.", (Underwater || Is_waterlevel(&u.uz)) ? "water" : Engulfed ? mbodypart(u.ustuck, STOMACH) : IS_STWALL(level->locations[u.ux][u.uy].typ) ? "stone" : "air", an(hgolden)); } u.uspellprot += gain; u.uspmtime = P_SKILL(spell_skilltype(SPE_PROTECTION)) == P_EXPERT ? 20 : 10; if (!u.usptime) u.usptime = u.uspmtime; } else { pline("Your %s feels warm for a moment.", body_part(SKIN)); } }
const char *body_part(int part) { return mbodypart(&youmonst, part); }
/* 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; }