1 /* NetHack 3.6 artifact.c $NHDT-Date: 1446369462 2015/11/01 09:17:42 $ $NHDT-Branch: master $:$NHDT-Revision: 1.96 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
15 * Note: both artilist[] and artiexist[] have a dummy element #0,
16 * so loops over them should normally start at #1. The primary
17 * exception is the save & restore code, which doesn't care about
18 * the contents, just the total size.
21 extern boolean notonhead; /* for long worms */
23 #define get_artifact(o) \
24 (((o) && (o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
27 FDECL(bane_applies, (const struct artifact *, struct monst *));
28 STATIC_DCL int FDECL(spec_applies, (const struct artifact *, struct monst *));
29 STATIC_DCL int FDECL(arti_invoke, (struct obj *));
31 FDECL(Mb_hit, (struct monst * magr, struct monst *mdef, struct obj *, int *,
32 int, BOOLEAN_P, char *));
33 STATIC_DCL unsigned long FDECL(abil_to_spfx, (long *));
34 STATIC_DCL uchar FDECL(abil_to_adtyp, (long *));
35 STATIC_DCL boolean FDECL(untouchable, (struct obj *, BOOLEAN_P));
37 /* The amount added to the victim's total hit points to insure that the
38 victim will be killed even after damage bonus/penalty adjustments.
39 Most such penalties are small, and 200 is plenty; the exception is
40 half physical damage. 3.3.1 and previous versions tried to use a very
41 large number to account for this case; now, we just compute the fatal
42 damage by adding it to 2 times the total hit points instead of 1 time.
43 Note: this will still break if they have more than about half the number
44 of hit points that will fit in a 15 bit integer. */
45 #define FATAL_DAMAGE_MODIFIER 200
47 /* coordinate effects from spec_dbon() with messages in artifact_hit() */
48 STATIC_OVL int spec_dbon_applies = 0;
50 /* flags including which artifacts have already been created */
51 static boolean artiexist[1 + NROFARTIFACTS + 1];
52 /* and a discovery list for them (no dummy first entry here) */
53 STATIC_OVL xchar artidisco[NROFARTIFACTS];
55 STATIC_DCL void NDECL(hack_artifacts);
56 STATIC_DCL boolean FDECL(attacks, (int, struct obj *));
58 /* handle some special cases; must be called after u_init() */
63 int alignmnt = aligns[flags.initalign].value;
65 /* Fix up the alignments of "gift" artifacts */
66 for (art = artilist + 1; art->otyp; art++)
67 if (art->role == Role_switch && art->alignment != A_NONE)
68 art->alignment = alignmnt;
70 /* Excalibur can be used by any lawful character, not just knights */
71 if (!Role_if(PM_KNIGHT))
72 artilist[ART_EXCALIBUR].role = NON_PM;
74 /* Fix up the quest artifact */
75 if (urole.questarti) {
76 artilist[urole.questarti].alignment = alignmnt;
77 artilist[urole.questarti].role = Role_switch;
82 /* zero out the artifact existence list */
86 (void) memset((genericptr_t) artiexist, 0, sizeof artiexist);
87 (void) memset((genericptr_t) artidisco, 0, sizeof artidisco);
95 bwrite(fd, (genericptr_t) artiexist, sizeof artiexist);
96 bwrite(fd, (genericptr_t) artidisco, sizeof artidisco);
100 restore_artifacts(fd)
103 mread(fd, (genericptr_t) artiexist, sizeof artiexist);
104 mread(fd, (genericptr_t) artidisco, sizeof artidisco);
105 hack_artifacts(); /* redo non-saved special cases */
112 if (artinum <= 0 || artinum > NROFARTIFACTS)
114 return artilist[artinum].name;
118 Make an artifact. If a specific alignment is specified, then an object of
119 the appropriate alignment is created from scratch, or 0 is returned if
120 none is available. (If at least one aligned artifact has already been
121 given, then unaligned ones also become eligible for this.)
122 If no alignment is given, then 'otmp' is converted
123 into an artifact of matching type, or returned as-is if that's not
125 For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE);''
126 for the 1st, ``obj = mk_artifact((struct obj *)0, some_alignment);''.
129 mk_artifact(otmp, alignment)
130 struct obj *otmp; /* existing object; ignored if alignment specified */
131 aligntyp alignment; /* target alignment, or A_NONE */
133 const struct artifact *a;
135 boolean by_align = (alignment != A_NONE);
136 short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
137 boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
138 short eligible[NROFARTIFACTS];
140 n = altn = 0; /* no candidates found yet */
141 eligible[0] = 0; /* lint suppression */
142 /* gather eligible artifacts */
143 for (m = 1, a = &artilist[m]; a->otyp; a++, m++) {
146 if ((a->spfx & SPFX_NOGEN) || unique)
150 /* looking for a particular type of item; not producing a
151 divine gift so we don't care about role's first choice */
152 if (a->otyp == o_typ)
154 continue; /* move on to next possibility */
157 /* we're looking for an alignment-specific item
158 suitable for hero's role+race */
159 if ((a->alignment == alignment || a->alignment == A_NONE)
160 /* avoid enemies' equipment */
161 && (a->race == NON_PM || !race_hostile(&mons[a->race]))) {
162 /* when a role-specific first choice is available, use it */
163 if (Role_if(a->role)) {
164 /* make this be the only possibility in the list */
167 break; /* skip all other candidates */
169 /* found something to consider for random selection */
170 if (a->alignment != A_NONE || u.ugifts > 0) {
171 /* right alignment, or non-aligned with at least 1
172 previous gift bestowed, makes this one viable */
175 /* non-aligned with no previous gifts;
176 if no candidates have been found yet, record
177 this one as a[nother] fallback possibility in
178 case all aligned candidates have been used up
179 (via wishing, naming, bones, random generation) */
181 eligible[altn++] = m;
182 /* [once a regular candidate is found, the list
183 is overwritten and `altn' becomes irrelevant] */
188 /* resort to fallback list if main list was empty */
193 /* found at least one candidate; pick one at random */
194 m = eligible[rn2(n)]; /* [0..n-1] */
197 /* make an appropriate object if necessary, then christen it */
199 otmp = mksobj((int) a->otyp, TRUE, FALSE);
202 otmp = oname(otmp, a->name);
207 /* nothing appropriate could be found; return original object */
209 otmp = 0; /* (there was no original object) */
215 * Returns the full name (with articles and correct capitalization) of an
216 * artifact named "name" if one exists, or NULL, it not.
217 * The given name must be rather close to the real name for it to match.
218 * The object type of the artifact is returned in otyp if the return value
222 artifact_name(name, otyp)
226 register const struct artifact *a;
227 register const char *aname;
229 if (!strncmpi(name, "the ", 4))
232 for (a = artilist + 1; a->otyp; a++) {
234 if (!strncmpi(aname, "the ", 4))
236 if (!strcmpi(name, aname)) {
246 exist_artifact(otyp, name)
250 register const struct artifact *a;
254 for (a = artilist + 1, arex = artiexist + 1; a->otyp; a++, arex++)
255 if ((int) a->otyp == otyp && !strcmp(a->name, name))
261 artifact_exists(otmp, name, mod)
266 register const struct artifact *a;
269 for (a = artilist + 1; a->otyp; a++)
270 if (a->otyp == otmp->otyp && !strcmp(a->name, name)) {
271 register int m = (int) (a - artilist);
272 otmp->oartifact = (char) (mod ? m : 0);
274 if (otmp->otyp == RIN_INCREASE_DAMAGE)
286 int n = SIZE(artiexist);
296 spec_ability(otmp, abil)
300 const struct artifact *arti = get_artifact(otmp);
302 return (boolean) (arti && (arti->spfx & abil) != 0L);
305 /* used so that callers don't need to known about SPFX_ codes */
310 /* might as well check for this too */
311 if (obj->otyp == LUCKSTONE)
314 return (boolean) (obj->oartifact && spec_ability(obj, SPFX_LUCK));
317 /* used to check whether a monster is getting reflection from an artifact */
322 const struct artifact *arti = get_artifact(obj);
325 /* while being worn */
326 if ((obj->owornmask & ~W_ART) && (arti->spfx & SPFX_REFLECT))
328 /* just being carried */
329 if (arti->cspfx & SPFX_REFLECT)
335 /* decide whether this obj is effective when attacking against shades;
336 does not consider the bonus for blessed objects versus undead */
341 const struct artifact *arti;
343 /* any silver object is effective */
344 if (objects[obj->otyp].oc_material == SILVER)
346 /* non-silver artifacts with bonus against undead also are effective */
347 arti = get_artifact(obj);
348 if (arti && (arti->spfx & SPFX_DFLAG2) && arti->mtype == M2_UNDEAD)
350 /* [if there was anything with special bonus against noncorporeals,
351 it would be effective too] */
352 /* otherwise, harmless to shades */
356 /* returns 1 if name is restricted for otmp->otyp */
358 restrict_name(otmp, name)
362 register const struct artifact *a;
363 const char *aname, *odesc, *other;
364 boolean sametype[NUM_OBJECTS];
365 int i, lo, hi, otyp = otmp->otyp, ocls = objects[otyp].oc_class;
369 if (!strncmpi(name, "the ", 4))
372 /* decide what types of objects are the same as otyp;
373 if it's been discovered, then only itself matches;
374 otherwise, include all other undiscovered objects
375 of the same class which have the same description
376 or share the same pool of shuffled descriptions */
377 (void) memset((genericptr_t) sametype, 0, sizeof sametype); /* FALSE */
378 sametype[otyp] = TRUE;
379 if (!objects[otyp].oc_name_known
380 && (odesc = OBJ_DESCR(objects[otyp])) != 0) {
381 obj_shuffle_range(otyp, &lo, &hi);
382 for (i = bases[ocls]; i < NUM_OBJECTS; i++) {
383 if (objects[i].oc_class != ocls)
385 if (!objects[i].oc_name_known
386 && (other = OBJ_DESCR(objects[i])) != 0
387 && (!strcmp(odesc, other) || (i >= lo && i <= hi)))
392 /* Since almost every artifact is SPFX_RESTR, it doesn't cost
393 us much to do the string comparison before the spfx check.
394 Bug fix: don't name multiple elven daggers "Sting".
396 for (a = artilist + 1; a->otyp; a++) {
397 if (!sametype[a->otyp])
400 if (!strncmpi(aname, "the ", 4))
402 if (!strcmp(aname, name))
403 return (boolean) ((a->spfx & (SPFX_NOGEN | SPFX_RESTR)) != 0
415 register const struct artifact *weap;
417 if ((weap = get_artifact(otmp)) != 0)
418 return (boolean) (weap->attk.adtyp == adtyp);
427 register const struct artifact *weap;
429 if ((weap = get_artifact(otmp)) != 0)
430 return (boolean) (weap->defn.adtyp == adtyp);
434 /* used for monsters */
436 defends_when_carried(adtyp, otmp)
440 register const struct artifact *weap;
442 if ((weap = get_artifact(otmp)) != 0)
443 return (boolean) (weap->cary.adtyp == adtyp);
447 /* determine whether an item confers Protection */
449 protects(otmp, being_worn)
453 const struct artifact *arti;
455 if (being_worn && objects[otmp->otyp].oc_oprop == PROTECTION)
457 arti = get_artifact(otmp);
460 return (boolean) ((arti->cspfx & SPFX_PROTECT) != 0
461 || (being_worn && (arti->spfx & SPFX_PROTECT) != 0));
465 * a potential artifact has just been worn/wielded/picked-up or
466 * unworn/unwielded/dropped. Pickup/drop only set/reset the W_ART mask.
469 set_artifact_intrinsic(otmp, on, wp_mask)
470 register struct obj *otmp;
475 register const struct artifact *oart = get_artifact(otmp);
482 /* effects from the defn field */
483 dtyp = (wp_mask != W_ART) ? oart->defn.adtyp : oart->cary.adtyp;
486 mask = &EFire_resistance;
487 else if (dtyp == AD_COLD)
488 mask = &ECold_resistance;
489 else if (dtyp == AD_ELEC)
490 mask = &EShock_resistance;
491 else if (dtyp == AD_MAGM)
493 else if (dtyp == AD_DISN)
494 mask = &EDisint_resistance;
495 else if (dtyp == AD_DRST)
496 mask = &EPoison_resistance;
498 if (mask && wp_mask == W_ART && !on) {
499 /* find out if some other artifact also confers this intrinsic */
500 /* if so, leave the mask alone */
501 register struct obj *obj;
502 for (obj = invent; obj; obj = obj->nobj)
503 if (obj != otmp && obj->oartifact) {
504 register const struct artifact *art = get_artifact(obj);
505 if (art->cary.adtyp == dtyp) {
518 /* intrinsics from the spfx field; there could be more than one */
519 spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
520 if (spfx && wp_mask == W_ART && !on) {
521 /* don't change any spfx also conferred by other artifacts */
522 register struct obj *obj;
523 for (obj = invent; obj; obj = obj->nobj)
524 if (obj != otmp && obj->oartifact) {
525 register const struct artifact *art = get_artifact(obj);
530 if (spfx & SPFX_SEARCH) {
532 ESearching |= wp_mask;
534 ESearching &= ~wp_mask;
536 if (spfx & SPFX_HALRES) {
537 /* make_hallucinated must (re)set the mask itself to get
538 * the display right */
539 /* restoring needed because this is the only artifact intrinsic
540 * that can print a message--need to guard against being printed
541 * when restoring a game
543 (void) make_hallucinated((long) !on, restoring ? FALSE : TRUE,
546 if (spfx & SPFX_ESP) {
550 ETelepat &= ~wp_mask;
553 if (spfx & SPFX_STLTH) {
557 EStealth &= ~wp_mask;
559 if (spfx & SPFX_REGEN) {
561 ERegeneration |= wp_mask;
563 ERegeneration &= ~wp_mask;
565 if (spfx & SPFX_TCTRL) {
567 ETeleport_control |= wp_mask;
569 ETeleport_control &= ~wp_mask;
571 if (spfx & SPFX_WARN) {
574 EWarn_of_mon |= wp_mask;
575 context.warntype.obj |= spec_m2(otmp);
577 EWarn_of_mon &= ~wp_mask;
578 context.warntype.obj &= ~spec_m2(otmp);
585 EWarning &= ~wp_mask;
588 if (spfx & SPFX_EREGEN) {
590 EEnergy_regeneration |= wp_mask;
592 EEnergy_regeneration &= ~wp_mask;
594 if (spfx & SPFX_HSPDAM) {
596 EHalf_spell_damage |= wp_mask;
598 EHalf_spell_damage &= ~wp_mask;
600 if (spfx & SPFX_HPHDAM) {
602 EHalf_physical_damage |= wp_mask;
604 EHalf_physical_damage &= ~wp_mask;
606 if (spfx & SPFX_XRAY) {
607 /* this assumes that no one else is using xray_range */
612 vision_full_recalc = 1;
614 if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
616 EReflecting |= wp_mask;
618 EReflecting &= ~wp_mask;
620 if (spfx & SPFX_PROTECT) {
622 EProtection |= wp_mask;
624 EProtection &= ~wp_mask;
627 if (wp_mask == W_ART && !on && oart->inv_prop) {
628 /* might have to turn off invoked power too */
629 if (oart->inv_prop <= LAST_PROP
630 && (u.uprops[oart->inv_prop].extrinsic & W_ARTI))
631 (void) arti_invoke(otmp);
635 /* touch_artifact()'s return value isn't sufficient to tell whether it
636 dished out damage, and tracking changes to u.uhp, u.mh, Lifesaved
637 when trying to avoid second wounding is too cumbersome */
638 STATIC_VAR boolean touch_blasted; /* for retouch_object() */
641 * creature (usually hero) tries to touch (pick up or wield) an artifact obj.
642 * Returns 0 if the object refuses to be touched.
643 * This routine does not change any object chains.
644 * Ignores such things as gauntlets, assuming the artifact is not
645 * fooled by such trappings.
648 touch_artifact(obj, mon)
652 register const struct artifact *oart = get_artifact(obj);
653 boolean badclass, badalign, self_willed, yours;
655 touch_blasted = FALSE;
659 yours = (mon == &youmonst);
660 /* all quest artifacts are self-willed; it this ever changes, `badclass'
661 will have to be extended to explicitly include quest artifacts */
662 self_willed = ((oart->spfx & SPFX_INTEL) != 0);
664 badclass = self_willed
665 && ((oart->role != NON_PM && !Role_if(oart->role))
666 || (oart->race != NON_PM && !Race_if(oart->race)));
668 (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
669 && (oart->alignment != u.ualign.type || u.ualign.record < 0);
670 } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) {
671 badclass = self_willed && oart->role != NON_PM
672 && oart != &artilist[ART_EXCALIBUR];
673 badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
674 && (oart->alignment != mon_aligntyp(mon));
675 } else { /* an M3_WANTSxxx monster or a fake player */
676 /* special monsters trying to take the Amulet, invocation tools or
677 quest item can touch anything except `spec_applies' artifacts */
678 badclass = badalign = FALSE;
680 /* weapons which attack specific categories of monsters are
681 bad for them even if their alignments happen to match */
683 badalign = bane_applies(oart, mon);
685 if (((badclass || badalign) && self_willed)
686 || (badalign && (!yours || !rn2(4)))) {
693 You("are blasted by %s power!", s_suffix(the(xname(obj))));
695 You("%s
\82Ì
\97Í
\82ð
\97\81\82Ñ
\82½
\81I", xname(obj));
696 touch_blasted = TRUE;
697 dmg = d((Antimagic ? 2 : 4), (self_willed ? 10 : 4));
698 /* add half (maybe quarter) of the usual silver damage bonus */
699 if (objects[obj->otyp].oc_material == SILVER && Hate_silver)
700 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
702 Sprintf(buf, "touching %s", oart->name);
704 Sprintf(buf, "%s
\82É
\90G
\82ê
\82Ä", oart->name);
705 losehp(dmg, buf, KILLED_BY); /* magic damage, not physical */
706 exercise(A_WIS, FALSE);
709 /* can pick it up unless you're totally non-synch'd with the artifact */
710 if (badclass && badalign && self_willed) {
714 pline("%s your grasp!", Tobjnam(obj, "evade"));
716 pline("%s
\82Í
\88¬
\82ë
\82¤
\82Æ
\82·
\82é
\82Æ
\82·
\82é
\82è
\82Æ
\94²
\82¯
\82½
\81I", xname(obj));
719 pline("%s beyond your control!", Tobjnam(obj, "are"));
721 pline("%s
\82Í
\90§
\8cä
\82Å
\82«
\82È
\82¢
\81I", xname(obj));
729 /* decide whether an artifact itself is vulnerable to a particular type
730 of erosion damage, independent of the properties of its bearer */
732 arti_immune(obj, dtyp)
736 register const struct artifact *weap = get_artifact(obj);
741 return FALSE; /* nothing is immune to phys dmg */
742 return (boolean) (weap->attk.adtyp == dtyp
743 || weap->defn.adtyp == dtyp
744 || weap->cary.adtyp == dtyp);
748 bane_applies(oart, mon)
749 const struct artifact *oart;
752 struct artifact atmp;
754 if (oart && (oart->spfx & SPFX_DBONUS) != 0) {
756 atmp.spfx &= SPFX_DBONUS; /* clear other spfx fields */
757 if (spec_applies(&atmp, mon))
763 /* decide whether an artifact's special attacks apply against mtmp */
765 spec_applies(weap, mtmp)
766 register const struct artifact *weap;
769 struct permonst *ptr;
772 if (!(weap->spfx & (SPFX_DBONUS | SPFX_ATTK)))
773 return (weap->attk.adtyp == AD_PHYS);
775 yours = (mtmp == &youmonst);
778 if (weap->spfx & SPFX_DMONS) {
779 return (ptr == &mons[(int) weap->mtype]);
780 } else if (weap->spfx & SPFX_DCLAS) {
781 return (weap->mtype == (unsigned long) ptr->mlet);
782 } else if (weap->spfx & SPFX_DFLAG1) {
783 return ((ptr->mflags1 & weap->mtype) != 0L);
784 } else if (weap->spfx & SPFX_DFLAG2) {
785 return ((ptr->mflags2 & weap->mtype)
787 && ((!Upolyd && (urace.selfmask & weap->mtype))
788 || ((weap->mtype & M2_WERE) && u.ulycn >= LOW_PM))));
789 } else if (weap->spfx & SPFX_DALIGN) {
790 return yours ? (u.ualign.type != weap->alignment)
791 : (ptr->maligntyp == A_NONE
792 || sgn(ptr->maligntyp) != weap->alignment);
793 } else if (weap->spfx & SPFX_ATTK) {
794 struct obj *defending_weapon = (yours ? uwep : MON_WEP(mtmp));
796 if (defending_weapon && defending_weapon->oartifact
797 && defends((int) weap->attk.adtyp, defending_weapon))
799 switch (weap->attk.adtyp) {
801 return !(yours ? Fire_resistance : resists_fire(mtmp));
803 return !(yours ? Cold_resistance : resists_cold(mtmp));
805 return !(yours ? Shock_resistance : resists_elec(mtmp));
808 return !(yours ? Antimagic : (rn2(100) < ptr->mr));
810 return !(yours ? Poison_resistance : resists_poison(mtmp));
812 return !(yours ? Drain_resistance : resists_drli(mtmp));
814 return !(yours ? Stone_resistance : resists_ston(mtmp));
816 impossible("Weird weapon special attack.");
822 /* return the M2 flags of monster that an artifact's special attacks apply
828 const struct artifact *artifact = get_artifact(otmp);
831 return artifact->mtype;
835 /* special attack bonus */
841 const struct artifact *weap = get_artifact(otmp);
843 /* no need for an extra check for `NO_ATTK' because this will
844 always return 0 for any artifact which has that attribute */
846 if (weap && weap->attk.damn && spec_applies(weap, mon))
847 return rnd((int) weap->attk.damn);
851 /* special damage bonus */
853 spec_dbon(otmp, mon, tmp)
858 register const struct artifact *weap = get_artifact(otmp);
860 if (!weap || (weap->attk.adtyp == AD_PHYS /* check for `NO_ATTK' */
861 && weap->attk.damn == 0 && weap->attk.damd == 0))
862 spec_dbon_applies = FALSE;
863 else if (otmp->oartifact == ART_GRIMTOOTH)
864 /* Grimtooth has SPFX settings to warn against elves but we want its
865 damage bonus to apply to all targets, so bypass spec_applies() */
866 spec_dbon_applies = TRUE;
868 spec_dbon_applies = spec_applies(weap, mon);
870 if (spec_dbon_applies)
871 return weap->attk.damd ? rnd((int) weap->attk.damd) : max(tmp, 1);
875 /* add identified artifact to discoveries list */
882 /* look for this artifact in the discoveries list;
883 if we hit an empty slot then it's not present, so add it */
884 for (i = 0; i < NROFARTIFACTS; i++)
885 if (artidisco[i] == 0 || artidisco[i] == m) {
889 /* there is one slot per artifact, so we should never reach the
890 end without either finding the artifact or an empty slot... */
891 impossible("couldn't discover artifact (%d)", (int) m);
894 /* used to decide whether an artifact has been fully identified */
896 undiscovered_artifact(m)
901 /* look for this artifact in the discoveries list;
902 if we hit an empty slot then it's undiscovered */
903 for (i = 0; i < NROFARTIFACTS; i++)
904 if (artidisco[i] == m)
906 else if (artidisco[i] == 0)
911 /* display a list of discovered artifacts; return their count */
913 disp_artifact_discoveries(tmpwin)
914 winid tmpwin; /* supplied by dodiscover() */
919 for (i = 0; i < NROFARTIFACTS; i++) {
920 if (artidisco[i] == 0)
921 break; /* empty slot implies end of list */
922 if (tmpwin == WIN_ERR)
923 continue; /* for WIN_ERR, we just count */
927 putstr(tmpwin, iflags.menu_headings, "Artifacts");
929 putstr(tmpwin, iflags.menu_headings, "
\90¹
\8aí");
931 otyp = artilist[m].otyp;
932 Sprintf(buf, " %s [%s %s]", artiname(m),
933 align_str(artilist[m].alignment), simple_typename(otyp));
934 putstr(tmpwin, 0, buf);
940 * Magicbane's intrinsic magic is incompatible with normal
941 * enchantment magic. Thus, its effects have a negative
942 * dependence on spe. Against low mr victims, it typically
943 * does "double athame" damage, 2d4. Occasionally, it will
944 * cast unbalancing magic which effectively averages out to
945 * 4d4 damage (3d4 against high mr victims), for spe = 0.
947 * Prior to 3.4.1, the cancel (aka purge) effect always
948 * included the scare effect too; now it's one or the other.
949 * Likewise, the stun effect won't be combined with either
950 * of those two; it will be chosen separately or possibly
951 * used as a fallback when scare or cancel fails.
953 * [Historical note: a change to artifact_hit() for 3.4.0
954 * unintentionally made all of Magicbane's special effects
955 * be blocked if the defender successfully saved against a
956 * stun attack. As of 3.4.1, those effects can occur but
957 * will be slightly less likely than they were in 3.3.x.]
959 #define MB_MAX_DIEROLL 8 /* rolls above this aren't magical */
960 static const char *const mb_verb[2][4] = {
962 { "probe", "stun", "scare", "cancel" },
963 { "prod", "amaze", "tickle", "purge" },
965 /* Mb_hit()
\82Å "%s
\82½"
\82Ì
\8c`
\82Å
\97\98\97p */
966 {"
\92²
\8d¸
\82µ", "
\82
\82ç
\82
\82ç
\82³
\82¹", "
\8b¯
\82¦
\82³
\82¹", "
\8fò
\89»
\82µ"},
967 { "
\97ã
\82Ü
\82µ", "
\8bÁ
\82©
\82¹", "
\82
\82·
\82®
\82Á", "
\90´
\82ß" },
970 #define MB_INDEX_PROBE 0
971 #define MB_INDEX_STUN 1
972 #define MB_INDEX_SCARE 2
973 #define MB_INDEX_CANCEL 3
975 /* called when someone is being hit by Magicbane */
977 Mb_hit(magr, mdef, mb, dmgptr, dieroll, vis, hittee)
978 struct monst *magr, *mdef; /* attacker and defender */
979 struct obj *mb; /* Magicbane */
980 int *dmgptr; /* extra damage target will suffer */
981 int dieroll; /* d20 that has already scored a hit */
982 boolean vis; /* whether the action can be seen */
983 char *hittee; /* target's name: "you" or mon_nam(mdef) */
985 struct permonst *old_uasmon;
986 const char *verb, *fakename;
987 boolean youattack = (magr == &youmonst), youdefend = (mdef == &youmonst),
988 resisted = FALSE, do_stun, do_confuse, result;
989 int attack_indx, scare_dieroll = MB_MAX_DIEROLL / 2;
991 result = FALSE; /* no message given yet */
992 /* the most severe effects are less likely at higher enchantment */
994 scare_dieroll /= (1 << (mb->spe / 3));
995 /* if target successfully resisted the artifact damage bonus,
996 reduce overall likelihood of the assorted special effects */
997 if (!spec_dbon_applies)
1000 /* might stun even when attempting a more severe effect, but
1001 in that case it will only happen if the other effect fails;
1002 extra damage will apply regardless; 3.4.1: sometimes might
1003 just probe even when it hasn't been enchanted */
1004 do_stun = (max(mb->spe, 0) < rn2(spec_dbon_applies ? 11 : 7));
1006 /* the special effects also boost physical damage; increments are
1007 generally cumulative, but since the stun effect is based on a
1008 different criterium its damage might not be included; the base
1009 damage is either 1d4 (athame) or 2d4 (athame+spec_dbon) depending
1010 on target's resistance check against AD_STUN (handled by caller)
1011 [note that a successful save against AD_STUN doesn't actually
1012 prevent the target from ending up stunned] */
1013 attack_indx = MB_INDEX_PROBE;
1014 *dmgptr += rnd(4); /* (2..3)d4 */
1016 attack_indx = MB_INDEX_STUN;
1017 *dmgptr += rnd(4); /* (3..4)d4 */
1019 if (dieroll <= scare_dieroll) {
1020 attack_indx = MB_INDEX_SCARE;
1021 *dmgptr += rnd(4); /* (3..5)d4 */
1023 if (dieroll <= (scare_dieroll / 2)) {
1024 attack_indx = MB_INDEX_CANCEL;
1025 *dmgptr += rnd(4); /* (4..6)d4 */
1028 /* give the hit message prior to inflicting the effects */
1029 verb = mb_verb[!!Hallucination][attack_indx];
1030 if (youattack || youdefend || vis) {
1033 pline_The("magic-absorbing blade %s %s!",
1034 vtense((const char *) 0, verb), hittee);
1036 pline("
\96\82\97Í
\82ð
\8bz
\82¢
\82Æ
\82é
\90n
\82ª%s
\82ð%s
\82½
\81I",
1039 /* assume probing has some sort of noticeable feedback
1040 even if it is being done by one monster to another */
1041 if (attack_indx == MB_INDEX_PROBE && !canspotmon(mdef))
1042 map_invisible(mdef->mx, mdef->my);
1045 /* now perform special effects */
1046 switch (attack_indx) {
1047 case MB_INDEX_CANCEL:
1048 old_uasmon = youmonst.data;
1049 /* No mdef->mcan check: even a cancelled monster can be polymorphed
1050 * into a golem, and the "cancel" effect acts as if some magical
1051 * energy remains in spellcasting defenders to be absorbed later.
1053 if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
1058 if (youmonst.data != old_uasmon)
1059 *dmgptr = 0; /* rehumanized, so no more damage */
1062 You("lose magical energy!");
1064 You("
\96\82\96@
\82Ì
\83G
\83l
\83\8b\83M
\81[
\82ð
\8e¸
\82Á
\82½
\81I");
1071 if (mdef->data == &mons[PM_CLAY_GOLEM])
1072 mdef->mhp = 1; /* cancelled clay golems will die */
1073 if (youattack && attacktype(mdef->data, AT_MAGC)) {
1075 You("absorb magical energy!");
1077 You("
\96\82\96@
\82Ì
\83G
\83l
\83\8b\83M
\81[
\82ð
\8bz
\82¢
\82Æ
\82Á
\82½
\81I");
1086 case MB_INDEX_SCARE:
1092 multi_reason = "being scared stiff";
1094 if (magr && magr == u.ustuck && sticks(youmonst.data)) {
1095 u.ustuck = (struct monst *) 0;
1097 You("release %s!", mon_nam(magr));
1099 You("%s
\82ð
\89ð
\95ú
\82µ
\82½
\81I", mon_nam(magr));
1103 if (rn2(2) && resist(mdef, WEAPON_CLASS, 0, NOTELL))
1106 monflee(mdef, 3, FALSE, (mdef->mhp > *dmgptr));
1113 do_stun = TRUE; /* (this is redundant...) */
1116 case MB_INDEX_PROBE:
1117 if (youattack && (mb->spe == 0 || !rn2(3 * abs(mb->spe)))) {
1119 pline_The("%s is insightful.", verb);
1121 pline("
\91\8a\8eè
\82ð%s
\82½
\81D", verb);
1122 /* pre-damage status */
1123 probe_monster(mdef);
1127 /* stun if that was selected and a worse effect didn't occur */
1130 make_stunned(((HStun & TIMEOUT) + 3L), FALSE);
1133 /* avoid extra stun message below if we used mb_verb["stun"] above */
1134 if (attack_indx == MB_INDEX_STUN)
1137 /* lastly, all this magic can be confusing... */
1138 do_confuse = !rn2(12);
1141 make_confused((HConfusion & TIMEOUT) + 4L, FALSE);
1146 /* now give message(s) describing side-effects;
1147 don't let vtense() be fooled by assigned name ending in 's' */
1148 fakename = youdefend ? "you" : "mon";
1149 if (youattack || youdefend || vis) {
1150 (void) upstart(hittee); /* capitalize */
1153 pline("%s %s!", hittee, vtense(fakename, "resist"));
1155 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", hittee);
1156 shieldeff(youdefend ? u.ux : mdef->mx,
1157 youdefend ? u.uy : mdef->my);
1159 if ((do_stun || do_confuse) && flags.verbose) {
1165 Strcat(buf, "stunned");
1166 if (do_stun && do_confuse)
1167 Strcat(buf, " and ");
1169 Strcat(buf, "confused");
1170 pline("%s %s %s%c", hittee, vtense(fakename, "are"), buf,
1171 (do_stun && do_confuse) ? '!' : '.');
1173 if (do_stun && do_confuse)
1174 Strcat(buf, "
\82æ
\82ë
\82ß
\82¢
\82Ä");
1176 Strcat(buf, "
\82æ
\82ë
\82ß
\82¢
\82½");
1178 Strcat(buf, "
\8d¬
\97\90\82µ
\82½");
1179 pline("%s
\82Í%s%s", hittee,
1180 buf, (do_stun && do_confuse) ? "
\81I" : "
\81D");
1188 /* Function used when someone attacks someone else with an artifact
1189 * weapon. Only adds the special (artifact) damage, and returns a 1 if it
1190 * did something special (in which case the caller won't print the normal
1191 * hit message). This should be called once upon every artifact attack;
1192 * dmgval() no longer takes artifact bonuses into account. Possible
1193 * extension: change the killer so that when an orc kills you with
1194 * Stormbringer it's "killed by Stormbringer" instead of "killed by an orc".
1197 artifact_hit(magr, mdef, otmp, dmgptr, dieroll)
1198 struct monst *magr, *mdef;
1201 int dieroll; /* needed for Magicbane and vorpal blades */
1203 boolean youattack = (magr == &youmonst);
1204 boolean youdefend = (mdef == &youmonst);
1205 boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
1206 || (!youdefend && cansee(mdef->mx, mdef->my))
1207 || (youattack && u.uswallow && mdef == u.ustuck && !Blind);
1208 boolean realizes_damage;
1209 const char *wepdesc;
1211 static const char you[] = "you";
1213 static const char you[] = "
\82 \82È
\82½";
1216 Strcpy(hittee, youdefend ? you : mon_nam(mdef));
1218 /* The following takes care of most of the damage, but not all--
1219 * the exception being for level draining, which is specially
1220 * handled. Messages are done in this function, however.
1222 *dmgptr += spec_dbon(otmp, mdef, *dmgptr);
1224 if (youattack && youdefend) {
1225 impossible("attacking yourself with weapon?");
1229 realizes_damage = (youdefend || vis
1230 /* feel the effect even if not seen */
1231 || (youattack && mdef == u.ustuck));
1233 /* the four basic attacks: fire, cold, shock and missiles */
1234 if (attacks(AD_FIRE, otmp)) {
1235 if (realizes_damage)
1237 pline_The("fiery blade %s %s%c",
1240 : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1241 ? "vaporizes part of"
1243 hittee, !spec_dbon_applies ? '.' : '!');
1245 pline_The("
\96Ò
\89Î
\82ª%s%s",
1248 ? "
\82É
\96½
\92\86\82µ
\82½
\81D"
1249 : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1250 ? "
\82Ì
\88ê
\95\94\82ð
\8fÁ
\96Å
\82³
\82¹
\82½
\81I"
1251 : "
\82ð
\8fÄ
\82¢
\82½
\81I");
1254 (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1256 (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1258 (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1259 if (youdefend && Slimed)
1261 return realizes_damage;
1263 if (attacks(AD_COLD, otmp)) {
1264 if (realizes_damage)
1266 pline_The("ice-cold blade %s %s%c",
1267 !spec_dbon_applies ? "hits" : "freezes", hittee,
1268 !spec_dbon_applies ? '.' : '!');
1270 pline_The("
\96Ò
\90\81\90á
\82ª%s%s",
1272 !spec_dbon_applies ? "
\82É
\96½
\92\86\82µ
\82½
\81D" : "
\82ð
\8fP
\82Á
\82½
\81I");
1275 (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1276 return realizes_damage;
1278 if (attacks(AD_ELEC, otmp)) {
1279 if (realizes_damage)
1281 pline_The("massive hammer hits%s %s%c",
1282 !spec_dbon_applies ? "" : "! Lightning strikes",
1283 hittee, !spec_dbon_applies ? '.' : '!');
1285 pline("
\8b\90\91å
\82È
\83n
\83\93\83}
\81[
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", hittee,
1286 !spec_dbon_applies ? "
\81D" : "
\81I
\93d
\8c\82\82ª
\8fP
\82Á
\82½
\81I");
1289 (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1291 (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1292 return realizes_damage;
1294 if (attacks(AD_MAGM, otmp)) {
1295 if (realizes_damage)
1297 pline_The("imaginary widget hits%s %s%c",
1300 : "! A hail of magic missiles strikes",
1301 hittee, !spec_dbon_applies ? '.' : '!');
1303 pline("
\8eÀ
\91Ì
\82ð
\8e\9d\82½
\82È
\82¢
\95¨
\91Ì
\82ª%s
\82ð
\8dU
\8c\82\82µ
\82½%s",
1305 !spec_dbon_applies ? "
\81D" :
1306 "
\81I
\96\82\96@
\82Ì
\96î
\82ª
\89J
\82 \82ç
\82ê
\82Æ
\96½
\92\86\82µ
\82½
\81I");
1308 return realizes_damage;
1311 if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
1312 /* Magicbane's special attacks (possibly modifies hittee[]) */
1313 return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
1316 if (!spec_dbon_applies) {
1317 /* since damage bonus didn't apply, nothing more to do;
1318 no further attacks have side-effects on inventory */
1322 /* We really want "on a natural 20" but Nethack does it in */
1323 /* reverse from AD&D. */
1324 if (spec_ability(otmp, SPFX_BEHEAD)) {
1325 if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) {
1327 wepdesc = "The razor-sharp blade";
1329 wepdesc = "
\8ea
\93S
\8c\95";
1330 /* not really beheading, but so close, why add another SPFX */
1331 if (youattack && u.uswallow && mdef == u.ustuck) {
1333 You("slice %s wide open!", mon_nam(mdef));
1335 You("%s
\82ð
\97Ö
\90Ø
\82è
\82É
\82µ
\82½
\81I", mon_nam(mdef));
1336 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1340 /* allow normal cutworm() call to add extra damage */
1344 if (bigmonst(mdef->data)) {
1347 You("slice deeply into %s!", mon_nam(mdef));
1349 You("%s
\82É
\90[
\82
\8ea
\82è
\82Â
\82¯
\82½
\81I",mon_nam(mdef));
1351 pline("%s cuts deeply into %s!", Monnam(magr),
1356 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1358 pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
1360 pline("%s
\82ª%s
\82ð
\90^
\82Á
\93ñ
\82Â
\82É
\82µ
\82½
\81I", wepdesc, mon_nam(mdef));
1361 otmp->dknown = TRUE;
1364 if (bigmonst(youmonst.data)) {
1366 pline("%s cuts deeply into you!",
1368 pline("%s
\82Í
\82 \82È
\82½
\82É
\90[
\82
\8ea
\82è
\82Â
\82¯
\82½
\81I",
1369 magr ? Monnam(magr) : wepdesc);
1374 /* Players with negative AC's take less damage instead
1375 * of just not getting hit. We must add a large enough
1376 * value to the damage so that this reduction in
1377 * damage does not prevent death.
1379 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1381 pline("%s cuts you in half!", wepdesc);
1383 pline("%s
\82ª
\82 \82È
\82½
\82ð
\90^
\82Á
\93ñ
\82Â
\82É
\82µ
\82½
\81I", wepdesc);
1384 otmp->dknown = TRUE;
1387 } else if (otmp->oartifact == ART_VORPAL_BLADE
1388 && (dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) {
1390 static const char *const behead_msg[2] = { "%s beheads %s!",
1391 "%s decapitates %s!" };
1393 static const char *const behead_msg[2] = { "%s
\82Í%s
\82Ì
\8eñ
\82ð
\90Ø
\82Á
\82½
\81I",
1394 "%s
\82Í%s
\82Ì
\8eñ
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81I" };
1397 if (youattack && u.uswallow && mdef == u.ustuck)
1399 wepdesc = artilist[ART_VORPAL_BLADE].name;
1401 if (!has_head(mdef->data) || notonhead || u.uswallow) {
1404 pline("Somehow, you miss %s wildly.", mon_nam(mdef));
1406 pline("
\82È
\82º
\82©
\81C%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D", mon_nam(mdef));
1409 pline("Somehow, %s misses wildly.", mon_nam(magr));
1411 pline("
\82È
\82º
\82©
\81C%s
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D", mon_nam(magr));
1413 return (boolean) (youattack || vis);
1415 if (noncorporeal(mdef->data) || amorphous(mdef->data)) {
1417 pline("%s slices through %s %s.", wepdesc,
1419 pline("%s
\82Í%s
\82Ì%s
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81D", wepdesc,
1420 s_suffix(mon_nam(mdef)), mbodypart(mdef, NECK));
1423 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1424 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc,
1426 if (Hallucination && !flags.female)
1428 pline("Good job Henry, but that wasn't Anne.");
1430 pline("
\83w
\83\93\83\8a\81[
\82æ
\82
\82â
\82Á
\82½
\81C
\82¾
\82ª
\82»
\82¢
\82Â
\82Í
\83A
\83\93\82¶
\82á
\82È
\82¢
\81D");
1431 otmp->dknown = TRUE;
1434 if (!has_head(youmonst.data)) {
1436 pline("Somehow, %s misses you wildly.",
1438 pline("
\82È
\82º
\82©
\81C%s
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D",
1439 magr ? mon_nam(magr) : wepdesc);
1443 if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) {
1445 pline("%s slices through your %s.", wepdesc,
1447 pline("%s
\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81D", wepdesc,
1451 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1453 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
1455 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "
\82 \82È
\82½");
1456 otmp->dknown = TRUE;
1457 /* Should amulets fall off? */
1462 if (spec_ability(otmp, SPFX_DRLI)) {
1463 /* some non-living creatures (golems, vortices) are
1464 vulnerable to life drain effects */
1466 const char *life = nonliving(mdef->data) ? "animating force" : "life";
1468 const char *life = nonliving(mdef->data) ? "
\93®
\8dì
\97Í" : "
\90¶
\96½
\97Í";
1472 if (otmp->oartifact == ART_STORMBRINGER)
1474 pline_The("%s blade draws the %s from %s!",
1475 hcolor(NH_BLACK), life, mon_nam(mdef));
1477 pline("%s
\90n
\82ª%s
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I",
1478 hcolor(NH_BLACK), mon_nam(mdef), life);
1482 pline("%s draws the %s from %s!",
1483 The(distant_name(otmp, xname)), life,
1486 pline("%s
\82Í%s
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I",
1487 The(distant_name(otmp, xname)),
1488 mon_nam(mdef), life);
1491 if (mdef->m_lev == 0) {
1492 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1494 int drain = monhp_per_lvl(mdef);
1497 mdef->mhpmax -= drain;
1501 healup(drain, 0, FALSE, FALSE);
1504 } else { /* youdefend */
1505 int oldhpmax = u.uhpmax;
1509 You_feel("an %s drain your %s!",
1510 (otmp->oartifact == ART_STORMBRINGER)
1515 pline("%s
\82É%s
\82ð
\92D
\82í
\82ê
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
1516 (otmp->oartifact == ART_STORMBRINGER)
1517 ? "
\95s
\8fò
\82È
\90n"
1521 else if (otmp->oartifact == ART_STORMBRINGER)
1523 pline_The("%s blade drains your %s!", hcolor(NH_BLACK), life);
1525 pline("%s
\90n
\82ª
\82 \82È
\82½
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I", hcolor(NH_BLACK), life);
1528 pline("%s drains your %s!", The(distant_name(otmp, xname)),
1531 pline("%s
\82ª
\82 \82È
\82½
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I", The(distant_name(otmp, xname)),
1535 losexp("life drainage");
1537 losexp("
\90¶
\96½
\97Í
\82ð
\8bz
\8eû
\82³
\82ê
\82Ä");
1538 if (magr && magr->mhp < magr->mhpmax) {
1539 magr->mhp += (oldhpmax - u.uhpmax) / 2;
1540 if (magr->mhp > magr->mhpmax)
1541 magr->mhp = magr->mhpmax;
1549 static NEARDATA const char recharge_type[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
1550 static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 };
1551 /* #invoke: an "ugly check" filters out most objects */
1553 /* the #invoke command */
1559 obj = getobj(invoke_types, "invoke");
1562 if (!retouch_object(&obj, FALSE))
1564 return arti_invoke(obj);
1571 register const struct artifact *oart = get_artifact(obj);
1573 impossible("arti_invoke without obj");
1576 if (!oart || !oart->inv_prop) {
1577 if (obj->otyp == CRYSTAL_BALL)
1578 use_crystal_ball(&obj);
1580 pline1(nothing_happens);
1584 if (oart->inv_prop > LAST_PROP) {
1585 /* It's a special power, not "just" a property */
1586 if (obj->age > monstermoves) {
1587 /* the artifact is tired :-) */
1589 You_feel("that %s %s ignoring you.", the(xname(obj)),
1590 otense(obj, "are"));
1592 You_feel("%s
\82ª
\96³
\8e\8b\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8a´
\82¶
\82½
\81D", xname(obj));
1594 /* and just got more so; patience is essential... */
1595 obj->age += (long) d(3, 10);
1598 obj->age = monstermoves + rnz(100);
1600 switch (oart->inv_prop) {
1605 zeroobj; /* neither cursed nor blessed, zero oextra too */
1606 pseudo.otyp = SCR_TAMING;
1607 (void) seffects(&pseudo);
1611 int healamt = (u.uhpmax + 1 - u.uhp) / 2;
1612 long creamed = (long) u.ucreamed;
1615 healamt = (u.mhmax + 1 - u.mh) / 2;
1616 if (healamt || Sick || Slimed || Blinded > creamed)
1618 You_feel("better.");
1620 You_feel("
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81D");
1622 goto nothing_special;
1630 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1632 make_slimed(0L, (char *) 0);
1633 if (Blinded > creamed)
1634 make_blinded(creamed, FALSE);
1638 case ENERGY_BOOST: {
1639 int epboost = (u.uenmax + 1 - u.uen) / 2;
1641 epboost = 120; /* arbitrary */
1642 else if (epboost < 12)
1643 epboost = u.uenmax - u.uen;
1646 You_feel("re-energized.");
1648 You("
\83G
\83l
\83\8b\83M
\81[
\82Å
\96\9e\82½
\82³
\82ê
\82½
\81D");
1652 goto nothing_special;
1656 if (!untrap(TRUE)) {
1657 obj->age = 0; /* don't charge for changing their mind */
1663 struct obj *otmp = getobj(recharge_type, "charge");
1671 obj->blessed && (Role_switch == oart->role || !oart->role);
1672 recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
1679 case CREATE_PORTAL: {
1680 int i, num_ok_dungeons, last_ok_dungeon = 0;
1682 extern int n_dgns; /* from dungeon.c */
1683 winid tmpwin = create_nhwindow(NHW_MENU);
1686 any = zeroany; /* set all bits to zero */
1688 /* use index+1 (cant use 0) as identifier */
1689 for (i = num_ok_dungeons = 0; i < n_dgns; i++) {
1690 if (!dungeons[i].dunlev_ureached)
1693 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1694 dungeons[i].dname, MENU_UNSELECTED);
1696 last_ok_dungeon = i;
1699 end_menu(tmpwin, "Open a portal to which dungeon?");
1701 end_menu(tmpwin, "
\82Ç
\82Ì
\96À
\8b{
\82Ö
\82Ì
\96\82\96@
\82Ì
\93ü
\8cû
\82ð
\8aJ
\82«
\82Ü
\82·
\82©
\81H");
1702 if (num_ok_dungeons > 1) {
1703 /* more than one entry; display menu for choices */
1704 menu_item *selected;
1707 n = select_menu(tmpwin, PICK_ONE, &selected);
1709 destroy_nhwindow(tmpwin);
1710 goto nothing_special;
1712 i = selected[0].item.a_int - 1;
1713 free((genericptr_t) selected);
1715 i = last_ok_dungeon; /* also first & only OK dungeon */
1716 destroy_nhwindow(tmpwin);
1719 * i is now index into dungeon structure for the new dungeon.
1720 * Find the closest level in the given dungeon, open
1721 * a use-once portal to that dungeon and go there.
1722 * The closest level is either the entry or dunlev_ureached.
1725 if (dungeons[i].depth_start >= depth(&u.uz))
1726 newlev.dlevel = dungeons[i].entry_lev;
1728 newlev.dlevel = dungeons[i].dunlev_ureached;
1730 if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
1731 || newlev.dnum == u.uz.dnum || !next_to_u()) {
1733 You_feel("very disoriented for a moment.");
1735 You("
\88ê
\8fu
\95û
\8cü
\8a´
\8ao
\82ð
\8e¸
\82Á
\82½
\81D");
1739 You("are surrounded by a shimmering sphere!");
1741 You("
\83`
\83J
\83`
\83J
\8cõ
\82é
\8b\85\91Ì
\82É
\95¢
\82í
\82ê
\82½
\81I");
1744 You_feel("weightless for a moment.");
1746 You_feel("
\88ê
\8fu
\81C
\96³
\8fd
\97Í
\8a´
\82ð
\8a´
\82¶
\82½
\81D");
1747 goto_level(&newlev, FALSE, FALSE, FALSE);
1752 enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
1755 struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
1758 goto nothing_special;
1759 otmp->blessed = obj->blessed;
1760 otmp->cursed = obj->cursed;
1761 otmp->bknown = obj->bknown;
1765 otmp->quan += rnd(10);
1766 } else if (obj->cursed) {
1770 otmp->quan += rnd(5);
1771 otmp->owt = weight(otmp);
1774 hold_another_object(otmp, "Suddenly %s out.",
1775 aobjnam(otmp, "fall"), (const char *) 0);
1777 hold_another_object(otmp, "
\93Ë
\91R%s
\82ª
\97\8e\82¿
\82½
\81D",
1784 long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
1785 iprop = u.uprops[oart->inv_prop].intrinsic;
1786 boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */
1788 if (on && obj->age > monstermoves) {
1789 /* the artifact is tired :-) */
1790 u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
1792 You_feel("that %s %s ignoring you.", the(xname(obj)),
1793 otense(obj, "are"));
1795 You_feel("%s
\82ª
\96³
\8e\8b\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8a´
\82¶
\82½
\81D", xname(obj));
1797 /* can't just keep repeatedly trying */
1798 obj->age += (long) d(3, 10);
1801 /* when turning off property, determine downtime */
1802 /* arbitrary for now until we can tune this -dlc */
1803 obj->age = monstermoves + rnz(100);
1806 if ((eprop & ~W_ARTI) || iprop) {
1808 /* you had the property from some other source too */
1811 You_feel("a surge of power, but nothing seems to happen.");
1813 You("
\97Í
\82Ì
\8d\82\82Ü
\82è
\82ð
\8a´
\82¶
\82½
\82ª
\81C
\89½
\82à
\8bN
\82«
\82È
\82©
\82Á
\82½
\82æ
\82¤
\82¾
\81D");
1816 switch (oart->inv_prop) {
1820 You_feel("like a rabble-rouser.");
1822 You("
\96¯
\8fO
\90î
\93®
\89Æ
\82Ì
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
1825 You_feel("the tension decrease around you.");
1827 pline("
\82Ü
\82í
\82è
\82Ì
\8bÙ
\92£
\8a´
\82ª
\82È
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
1834 (void) float_down(I_SPECIAL | TIMEOUT, W_ARTI);
1837 if (BInvis || Blind)
1838 goto nothing_special;
1842 Your("body takes on a %s transparency...",
1843 Hallucination ? "normal" : "strange");
1845 pline("%s
\81C
\91Ì
\82Í
\93§
\89ß
\90«
\82ð
\82à
\82Á
\82½
\81D
\81D
\81D",
1846 Hallucination ? "
\82 \82½
\82è
\82Ü
\82¦
\82Ì
\82±
\82Æ
\82¾
\82ª" : "
\8aï
\96
\82È
\82±
\82Æ
\82É");
1850 Your("body seems to unfade...");
1852 Your("
\91Ì
\82Í
\8e\9f\91æ
\82É
\8c©
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82Á
\82Ä
\82«
\82½
\81D
\81D
\81D");
1860 /* will freeing this object from inventory cause levitation to end? */
1862 finesse_ahriman(obj)
1865 const struct artifact *oart;
1866 struct prop save_Lev;
1869 /* if we aren't levitating or this isn't an artifact which confers
1870 levitation via #invoke then freeinv() won't toggle levitation */
1871 if (!Levitation || (oart = get_artifact(obj)) == 0
1872 || oart->inv_prop != LEVITATION || !(ELevitation & W_ARTI))
1875 /* arti_invoke(off) -> float_down() clears I_SPECIAL|TIMEOUT & W_ARTI;
1876 probe ahead to see whether that actually results in floating down;
1877 (this assumes that there aren't two simultaneously invoked artifacts
1878 both conferring levitation--safe, since if there were two of them,
1879 invoking the 2nd would negate the 1st rather than stack with it) */
1880 save_Lev = u.uprops[LEVITATION];
1881 HLevitation &= ~(I_SPECIAL | TIMEOUT);
1882 ELevitation &= ~W_ARTI;
1883 result = (boolean) !Levitation;
1884 u.uprops[LEVITATION] = save_Lev;
1888 /* WAC return TRUE if artifact is always lit */
1893 return (boolean) (get_artifact(obj) && obj->oartifact == ART_SUNSWORD);
1896 /* KMH -- Talking artifacts are finally implemented */
1901 register const struct artifact *oart = get_artifact(obj);
1905 /* Is this a speaking artifact? */
1906 if (!oart || !(oart->spfx & SPFX_SPEAK))
1909 line = getrumor(bcsign(obj), buf, TRUE);
1912 line = "NetHack rumors file closed for renovation.";
1914 line = "
\89\
\82Ì
\90^
\91\8a\82Í
\90V
\91\95\82Ì
\82½
\82ß
\88ê
\8e\9e\95Â
\93X
\81D";
1916 pline("%s:", Tobjnam(obj, "whisper"));
1918 pline("%s
\82Í
\82³
\82³
\82â
\82¢
\82½
\81F", xname(obj));
1924 artifact_has_invprop(otmp, inv_prop)
1928 const struct artifact *arti = get_artifact(otmp);
1930 return (boolean) (arti && (arti->inv_prop == inv_prop));
1933 /* Return the price sold to the hero of a given artifact or unique item */
1938 if (!otmp->oartifact)
1939 return (long) objects[otmp->otyp].oc_cost;
1940 else if (artilist[(int) otmp->oartifact].cost)
1941 return artilist[(int) otmp->oartifact].cost;
1943 return (100L * (long) objects[otmp->otyp].oc_cost);
1950 struct abil2adtyp_tag {
1954 { &EFire_resistance, AD_FIRE },
1955 { &ECold_resistance, AD_COLD },
1956 { &EShock_resistance, AD_ELEC },
1957 { &EAntimagic, AD_MAGM },
1958 { &EDisint_resistance, AD_DISN },
1959 { &EPoison_resistance, AD_DRST },
1963 for (k = 0; k < SIZE(abil2adtyp); k++) {
1964 if (abil2adtyp[k].abil == abil)
1965 return abil2adtyp[k].adtyp;
1970 STATIC_OVL unsigned long
1974 static const struct abil2spfx_tag {
1978 { &ESearching, SPFX_SEARCH },
1979 { &EHalluc_resistance, SPFX_HALRES },
1980 { &ETelepat, SPFX_ESP },
1981 { &EStealth, SPFX_STLTH },
1982 { &ERegeneration, SPFX_REGEN },
1983 { &ETeleport_control, SPFX_TCTRL },
1984 { &EWarn_of_mon, SPFX_WARN },
1985 { &EWarning, SPFX_WARN },
1986 { &EEnergy_regeneration, SPFX_EREGEN },
1987 { &EHalf_spell_damage, SPFX_HSPDAM },
1988 { &EHalf_physical_damage, SPFX_HPHDAM },
1989 { &EReflecting, SPFX_REFLECT },
1993 for (k = 0; k < SIZE(abil2spfx); k++) {
1994 if (abil2spfx[k].abil == abil)
1995 return abil2spfx[k].spfx;
2001 * Return the first item that is conveying a particular intrinsic.
2011 long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS
2012 | W_ARMG | W_ARMF | W_ARMU
2013 | W_AMUL | W_RINGL | W_RINGR | W_TOOL
2014 /* [do W_ART and W_ARTI actually belong here?] */
2018 wornmask |= W_SWAPWEP;
2019 dtyp = abil_to_adtyp(abil);
2020 spfx = abil_to_spfx(abil);
2021 wornbits = (wornmask & *abil);
2023 for (obj = invent; obj; obj = obj->nobj) {
2025 && (abil != &EWarn_of_mon || context.warntype.obj)) {
2026 const struct artifact *art = get_artifact(obj);
2030 if (art->cary.adtyp == dtyp || art->defn.adtyp == dtyp)
2034 /* property conferred when carried */
2035 if ((art->cspfx & spfx) == spfx)
2037 /* property conferred when wielded or worn */
2038 if ((art->spfx & spfx) == spfx && obj->owornmask)
2043 if (wornbits && wornbits == (wornmask & obj->owornmask))
2047 return (struct obj *) 0;
2051 glow_color(arti_indx)
2054 int colornum = artilist[arti_indx].acolor;
2055 const char *colorstr = clr2colorname(colornum);
2057 return hcolor(colorstr);
2060 /* use for warning "glow" for Sting, Orcrist, and Grimtooth */
2062 Sting_effects(orc_count)
2063 int orc_count; /* new count (warn_obj_cnt is old count); -1 is a flag value */
2066 && (uwep->oartifact == ART_STING
2067 || uwep->oartifact == ART_ORCRIST
2068 || uwep->oartifact == ART_GRIMTOOTH)) {
2069 if (orc_count == -1 && warn_obj_cnt > 0) {
2070 /* -1 means that blindness has just been toggled; give a
2071 'continue' message that eventual 'stop' message will match */
2072 pline("%s is %s.", bare_artifactname(uwep),
2073 !Blind ? "glowing" : "quivering");
2074 } else if (orc_count > 0 && warn_obj_cnt == 0) {
2075 /* 'start' message */
2077 pline("%s %s %s!", bare_artifactname(uwep),
2078 otense(uwep, "glow"), glow_color(uwep->oartifact));
2080 pline("%s quivers slightly.", bare_artifactname(uwep));
2081 } else if (orc_count == 0 && warn_obj_cnt > 0) {
2082 /* 'stop' message */
2083 pline("%s stops %s.", bare_artifactname(uwep),
2084 !Blind ? "glowing" : "quivering");
2089 /* called when hero is wielding/applying/invoking a carried item, or
2090 after undergoing a transformation (alignment change, lycanthropy,
2091 polymorph) which might affect item access */
2093 retouch_object(objp, loseit)
2094 struct obj **objp; /* might be destroyed or unintentionally dropped */
2095 boolean loseit; /* whether to drop it if hero can longer touch it */
2097 struct obj *obj = *objp;
2099 if (touch_artifact(obj, &youmonst)) {
2103 (objects[obj->otyp].oc_material == SILVER && Hate_silver),
2104 bane = bane_applies(get_artifact(obj), &youmonst);
2106 /* nothing else to do if hero can successfully handle this object */
2110 /* hero can't handle this object, but didn't get touch_artifact()'s
2111 "<obj> evades your grasp|control" message; give an alternate one */
2112 You_cant("handle %s%s!", yname(obj),
2113 obj->owornmask ? " anymore" : "");
2114 /* also inflict damage unless touch_artifact() already did so */
2115 if (!touch_blasted) {
2116 /* damage is somewhat arbitrary; half the usual 1d20 physical
2117 for silver, 1d10 magical for <foo>bane, potentially both */
2119 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
2122 Sprintf(buf, "handling %s", killer_xname(obj));
2123 losehp(dmg, buf, KILLED_BY);
2124 exercise(A_CON, FALSE);
2128 /* removing a worn item might result in loss of levitation,
2129 dropping the hero onto a polymorph trap or into water or
2130 lava and potentially dropping or destroying the item */
2131 if (obj->owornmask) {
2134 remove_worn_item(obj, FALSE);
2135 for (otmp = invent; otmp; otmp = otmp->nobj)
2142 /* if we still have it and caller wants us to drop it, do so now */
2143 if (loseit && obj) {
2148 /* dropx gives a message iff item lands on an altar */
2149 if (!IS_ALTAR(levl[u.ux][u.uy].typ))
2150 pline("%s to the %s.", Tobjnam(obj, "fall"),
2151 surface(u.ux, u.uy));
2154 *objp = obj = 0; /* no longer in inventory */
2159 /* an item which is worn/wielded or an artifact which conveys
2160 something via being carried or which has an #invoke effect
2161 currently in operation undergoes a touch test; if it fails,
2162 it will be unworn/unwielded and revoked but not dropped */
2164 untouchable(obj, drop_untouchable)
2166 boolean drop_untouchable;
2168 struct artifact *art;
2169 boolean beingworn, carryeffect, invoked;
2170 long wearmask = ~(W_QUIVER | (u.twoweap ? 0L : W_SWAPWEP) | W_BALL);
2172 beingworn = ((obj->owornmask & wearmask) != 0L
2173 /* some items in use don't have any wornmask setting */
2174 || (obj->oclass == TOOL_CLASS
2175 && (obj->lamplit || (obj->otyp == LEASH && obj->leashmon)
2176 || (Is_container(obj) && Has_contents(obj)))));
2178 if ((art = get_artifact(obj)) != 0) {
2179 carryeffect = (art->cary.adtyp || art->cspfx);
2180 invoked = (art->inv_prop > 0 && art->inv_prop <= LAST_PROP
2181 && (u.uprops[art->inv_prop].extrinsic & W_ARTI) != 0L);
2183 carryeffect = invoked = FALSE;
2186 if (beingworn || carryeffect || invoked) {
2187 if (!retouch_object(&obj, drop_untouchable)) {
2188 /* "<artifact> is beyond your control" or "you can't handle
2189 <object>" has been given and it is now unworn/unwielded
2190 and possibly dropped (depending upon caller); if dropped,
2191 carried effect was turned off, else we leave that alone;
2192 we turn off invocation property here if still carried */
2194 arti_invoke(obj); /* reverse #invoke */
2201 /* check all items currently in use (mostly worn) for touchability */
2203 retouch_equipment(dropflag)
2204 int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
2206 static int nesting = 0; /* recursion control */
2208 boolean dropit, had_gloves = (uarmg != 0);
2209 int had_rings = (!!uleft + !!uright);
2212 * We can potentially be called recursively if losing/unwearing
2213 * an item causes worn helm of opposite alignment to come off or
2216 * BUG: if the initial call was due to putting on a helm of
2217 * opposite alignment and it does come off to trigger recursion,
2218 * after the inner call executes, the outer call will finish
2219 * using the non-helm alignment rather than the helm alignment
2220 * which triggered this in the first place.
2223 clear_bypasses(); /* init upon initial entry */
2225 dropit = (dropflag > 0); /* drop all or drop weapon */
2226 /* check secondary weapon first, before possibly unwielding primary */
2228 (void) untouchable(uswapwep, dropit);
2229 /* check primary weapon next so that they're handled together */
2231 (void) untouchable(uwep, dropit);
2233 /* in case someone is daft enough to add artifact or silver saddle */
2234 if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
2235 /* untouchable() calls retouch_object() which expects an object in
2236 hero's inventory, but remove_worn_item() will be harmless for
2237 saddle and we're suppressing drop, so this works as intended */
2238 if (untouchable(obj, FALSE))
2239 dismount_steed(DISMOUNT_THROWN);
2242 * TODO? Force off gloves if either or both rings are going to
2243 * become unworn; force off cloak [suit] before suit [shirt].
2244 * The torso handling is hypothetical; the case for gloves is
2245 * not, due to the possibility of unwearing silver rings.
2248 dropit = (dropflag == 1); /* all untouchable items */
2249 /* loss of levitation (silver ring, or Heart of Ahriman invocation)
2250 might cause hero to lose inventory items (by dropping into lava,
2251 for instance), so inventory traversal needs to rescan the whole
2252 invent chain each time it moves on to another object; we use bypass
2253 handling to keep track of which items have already been processed */
2254 while ((obj = nxt_unbypassed_obj(invent)) != 0)
2255 (void) untouchable(obj, dropit);
2257 if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
2258 uncurse(uarmg); /* temporary? hack for ring removal plausibility */
2259 if (had_gloves && !uarmg)
2260 selftouch("After losing your gloves, you");
2263 clear_bypasses(); /* reset upon final exit */