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 #include "artilistj.h"
18 * Note: both artilist[] and artiexist[] have a dummy element #0,
19 * so loops over them should normally start at #1. The primary
20 * exception is the save & restore code, which doesn't care about
21 * the contents, just the total size.
24 extern boolean notonhead; /* for long worms */
26 #define get_artifact(o) \
27 (((o) && (o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
30 FDECL(bane_applies, (const struct artifact *, struct monst *));
31 STATIC_DCL int FDECL(spec_applies, (const struct artifact *, struct monst *));
32 STATIC_DCL int FDECL(arti_invoke, (struct obj *));
34 FDECL(Mb_hit, (struct monst * magr, struct monst *mdef, struct obj *, int *,
35 int, BOOLEAN_P, char *));
36 STATIC_DCL unsigned long FDECL(abil_to_spfx, (long *));
37 STATIC_DCL uchar FDECL(abil_to_adtyp, (long *));
38 STATIC_DCL boolean FDECL(untouchable, (struct obj *, BOOLEAN_P));
40 /* The amount added to the victim's total hit points to insure that the
41 victim will be killed even after damage bonus/penalty adjustments.
42 Most such penalties are small, and 200 is plenty; the exception is
43 half physical damage. 3.3.1 and previous versions tried to use a very
44 large number to account for this case; now, we just compute the fatal
45 damage by adding it to 2 times the total hit points instead of 1 time.
46 Note: this will still break if they have more than about half the number
47 of hit points that will fit in a 15 bit integer. */
48 #define FATAL_DAMAGE_MODIFIER 200
50 /* coordinate effects from spec_dbon() with messages in artifact_hit() */
51 STATIC_OVL int spec_dbon_applies = 0;
53 /* flags including which artifacts have already been created */
54 static boolean artiexist[1 + NROFARTIFACTS + 1];
55 /* and a discovery list for them (no dummy first entry here) */
56 STATIC_OVL xchar artidisco[NROFARTIFACTS];
58 STATIC_DCL void NDECL(hack_artifacts);
59 STATIC_DCL boolean FDECL(attacks, (int, struct obj *));
61 /* handle some special cases; must be called after u_init() */
66 int alignmnt = aligns[flags.initalign].value;
68 /* Fix up the alignments of "gift" artifacts */
69 for (art = artilist + 1; art->otyp; art++)
70 if (art->role == Role_switch && art->alignment != A_NONE)
71 art->alignment = alignmnt;
73 /* Excalibur can be used by any lawful character, not just knights */
74 if (!Role_if(PM_KNIGHT))
75 artilist[ART_EXCALIBUR].role = NON_PM;
77 /* Fix up the quest artifact */
78 if (urole.questarti) {
79 artilist[urole.questarti].alignment = alignmnt;
80 artilist[urole.questarti].role = Role_switch;
85 /* zero out the artifact existence list */
89 (void) memset((genericptr_t) artiexist, 0, sizeof artiexist);
90 (void) memset((genericptr_t) artidisco, 0, sizeof artidisco);
98 bwrite(fd, (genericptr_t) artiexist, sizeof artiexist);
99 bwrite(fd, (genericptr_t) artidisco, sizeof artidisco);
103 restore_artifacts(fd)
106 mread(fd, (genericptr_t) artiexist, sizeof artiexist);
107 mread(fd, (genericptr_t) artidisco, sizeof artidisco);
108 hack_artifacts(); /* redo non-saved special cases */
115 if (artinum <= 0 || artinum > NROFARTIFACTS)
117 return artilist[artinum].name;
121 Make an artifact. If a specific alignment is specified, then an object of
122 the appropriate alignment is created from scratch, or 0 is returned if
123 none is available. (If at least one aligned artifact has already been
124 given, then unaligned ones also become eligible for this.)
125 If no alignment is given, then 'otmp' is converted
126 into an artifact of matching type, or returned as-is if that's not
128 For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE);''
129 for the 1st, ``obj = mk_artifact((struct obj *)0, some_alignment);''.
132 mk_artifact(otmp, alignment)
133 struct obj *otmp; /* existing object; ignored if alignment specified */
134 aligntyp alignment; /* target alignment, or A_NONE */
136 const struct artifact *a;
138 boolean by_align = (alignment != A_NONE);
139 short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
140 boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
141 short eligible[NROFARTIFACTS];
143 n = altn = 0; /* no candidates found yet */
144 eligible[0] = 0; /* lint suppression */
145 /* gather eligible artifacts */
146 for (m = 1, a = &artilist[m]; a->otyp; a++, m++) {
149 if ((a->spfx & SPFX_NOGEN) || unique)
153 /* looking for a particular type of item; not producing a
154 divine gift so we don't care about role's first choice */
155 if (a->otyp == o_typ)
157 continue; /* move on to next possibility */
160 /* we're looking for an alignment-specific item
161 suitable for hero's role+race */
162 if ((a->alignment == alignment || a->alignment == A_NONE)
163 /* avoid enemies' equipment */
164 && (a->race == NON_PM || !race_hostile(&mons[a->race]))) {
165 /* when a role-specific first choice is available, use it */
166 if (Role_if(a->role)) {
167 /* make this be the only possibility in the list */
170 break; /* skip all other candidates */
172 /* found something to consider for random selection */
173 if (a->alignment != A_NONE || u.ugifts > 0) {
174 /* right alignment, or non-aligned with at least 1
175 previous gift bestowed, makes this one viable */
178 /* non-aligned with no previous gifts;
179 if no candidates have been found yet, record
180 this one as a[nother] fallback possibility in
181 case all aligned candidates have been used up
182 (via wishing, naming, bones, random generation) */
184 eligible[altn++] = m;
185 /* [once a regular candidate is found, the list
186 is overwritten and `altn' becomes irrelevant] */
191 /* resort to fallback list if main list was empty */
196 /* found at least one candidate; pick one at random */
197 m = eligible[rn2(n)]; /* [0..n-1] */
200 /* make an appropriate object if necessary, then christen it */
202 otmp = mksobj((int) a->otyp, TRUE, FALSE);
205 otmp = oname(otmp, a->name);
210 /* nothing appropriate could be found; return original object */
212 otmp = 0; /* (there was no original object) */
218 * Returns the full name (with articles and correct capitalization) of an
219 * artifact named "name" if one exists, or NULL, it not.
220 * The given name must be rather close to the real name for it to match.
221 * The object type of the artifact is returned in otyp if the return value
225 artifact_name(name, otyp)
229 register const struct artifact *a;
230 register const char *aname;
232 if (!strncmpi(name, "the ", 4))
235 for (a = artilist + 1; a->otyp; a++) {
237 if (!strncmpi(aname, "the ", 4))
239 if (!strcmpi(name, aname)) {
249 exist_artifact(otyp, name)
253 register const struct artifact *a;
257 for (a = artilist + 1, arex = artiexist + 1; a->otyp; a++, arex++)
258 if ((int) a->otyp == otyp && !strcmp(a->name, name))
264 artifact_exists(otmp, name, mod)
269 register const struct artifact *a;
272 for (a = artilist + 1; a->otyp; a++)
273 if (a->otyp == otmp->otyp && !strcmp(a->name, name)) {
274 register int m = (int) (a - artilist);
275 otmp->oartifact = (char) (mod ? m : 0);
277 if (otmp->otyp == RIN_INCREASE_DAMAGE)
289 int n = SIZE(artiexist);
299 spec_ability(otmp, abil)
303 const struct artifact *arti = get_artifact(otmp);
305 return (boolean) (arti && (arti->spfx & abil) != 0L);
308 /* used so that callers don't need to known about SPFX_ codes */
313 /* might as well check for this too */
314 if (obj->otyp == LUCKSTONE)
317 return (boolean) (obj->oartifact && spec_ability(obj, SPFX_LUCK));
320 /* used to check whether a monster is getting reflection from an artifact */
325 const struct artifact *arti = get_artifact(obj);
328 /* while being worn */
329 if ((obj->owornmask & ~W_ART) && (arti->spfx & SPFX_REFLECT))
331 /* just being carried */
332 if (arti->cspfx & SPFX_REFLECT)
338 /* decide whether this obj is effective when attacking against shades;
339 does not consider the bonus for blessed objects versus undead */
344 const struct artifact *arti;
346 /* any silver object is effective */
347 if (objects[obj->otyp].oc_material == SILVER)
349 /* non-silver artifacts with bonus against undead also are effective */
350 arti = get_artifact(obj);
351 if (arti && (arti->spfx & SPFX_DFLAG2) && arti->mtype == M2_UNDEAD)
353 /* [if there was anything with special bonus against noncorporeals,
354 it would be effective too] */
355 /* otherwise, harmless to shades */
359 /* returns 1 if name is restricted for otmp->otyp */
361 restrict_name(otmp, name)
365 register const struct artifact *a;
366 const char *aname, *odesc, *other;
367 boolean sametype[NUM_OBJECTS];
368 int i, lo, hi, otyp = otmp->otyp, ocls = objects[otyp].oc_class;
372 if (!strncmpi(name, "the ", 4))
375 /* decide what types of objects are the same as otyp;
376 if it's been discovered, then only itself matches;
377 otherwise, include all other undiscovered objects
378 of the same class which have the same description
379 or share the same pool of shuffled descriptions */
380 (void) memset((genericptr_t) sametype, 0, sizeof sametype); /* FALSE */
381 sametype[otyp] = TRUE;
382 if (!objects[otyp].oc_name_known
383 && (odesc = OBJ_DESCR(objects[otyp])) != 0) {
384 obj_shuffle_range(otyp, &lo, &hi);
385 for (i = bases[ocls]; i < NUM_OBJECTS; i++) {
386 if (objects[i].oc_class != ocls)
388 if (!objects[i].oc_name_known
389 && (other = OBJ_DESCR(objects[i])) != 0
390 && (!strcmp(odesc, other) || (i >= lo && i <= hi)))
395 /* Since almost every artifact is SPFX_RESTR, it doesn't cost
396 us much to do the string comparison before the spfx check.
397 Bug fix: don't name multiple elven daggers "Sting".
399 for (a = artilist + 1; a->otyp; a++) {
400 if (!sametype[a->otyp])
403 if (!strncmpi(aname, "the ", 4))
405 if (!strcmp(aname, name))
406 return (boolean) ((a->spfx & (SPFX_NOGEN | SPFX_RESTR)) != 0
418 register const struct artifact *weap;
420 if ((weap = get_artifact(otmp)) != 0)
421 return (boolean) (weap->attk.adtyp == adtyp);
430 register const struct artifact *weap;
432 if ((weap = get_artifact(otmp)) != 0)
433 return (boolean) (weap->defn.adtyp == adtyp);
437 /* used for monsters */
439 defends_when_carried(adtyp, otmp)
443 register const struct artifact *weap;
445 if ((weap = get_artifact(otmp)) != 0)
446 return (boolean) (weap->cary.adtyp == adtyp);
450 /* determine whether an item confers Protection */
452 protects(otmp, being_worn)
456 const struct artifact *arti;
458 if (being_worn && objects[otmp->otyp].oc_oprop == PROTECTION)
460 arti = get_artifact(otmp);
463 return (boolean) ((arti->cspfx & SPFX_PROTECT) != 0
464 || (being_worn && (arti->spfx & SPFX_PROTECT) != 0));
468 * a potential artifact has just been worn/wielded/picked-up or
469 * unworn/unwielded/dropped. Pickup/drop only set/reset the W_ART mask.
472 set_artifact_intrinsic(otmp, on, wp_mask)
473 register struct obj *otmp;
478 register const struct artifact *oart = get_artifact(otmp);
485 /* effects from the defn field */
486 dtyp = (wp_mask != W_ART) ? oart->defn.adtyp : oart->cary.adtyp;
489 mask = &EFire_resistance;
490 else if (dtyp == AD_COLD)
491 mask = &ECold_resistance;
492 else if (dtyp == AD_ELEC)
493 mask = &EShock_resistance;
494 else if (dtyp == AD_MAGM)
496 else if (dtyp == AD_DISN)
497 mask = &EDisint_resistance;
498 else if (dtyp == AD_DRST)
499 mask = &EPoison_resistance;
501 if (mask && wp_mask == W_ART && !on) {
502 /* find out if some other artifact also confers this intrinsic */
503 /* if so, leave the mask alone */
504 register struct obj *obj;
505 for (obj = invent; obj; obj = obj->nobj)
506 if (obj != otmp && obj->oartifact) {
507 register const struct artifact *art = get_artifact(obj);
508 if (art->cary.adtyp == dtyp) {
521 /* intrinsics from the spfx field; there could be more than one */
522 spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
523 if (spfx && wp_mask == W_ART && !on) {
524 /* don't change any spfx also conferred by other artifacts */
525 register struct obj *obj;
526 for (obj = invent; obj; obj = obj->nobj)
527 if (obj != otmp && obj->oartifact) {
528 register const struct artifact *art = get_artifact(obj);
533 if (spfx & SPFX_SEARCH) {
535 ESearching |= wp_mask;
537 ESearching &= ~wp_mask;
539 if (spfx & SPFX_HALRES) {
540 /* make_hallucinated must (re)set the mask itself to get
541 * the display right */
542 /* restoring needed because this is the only artifact intrinsic
543 * that can print a message--need to guard against being printed
544 * when restoring a game
546 (void) make_hallucinated((long) !on, restoring ? FALSE : TRUE,
549 if (spfx & SPFX_ESP) {
553 ETelepat &= ~wp_mask;
556 if (spfx & SPFX_STLTH) {
560 EStealth &= ~wp_mask;
562 if (spfx & SPFX_REGEN) {
564 ERegeneration |= wp_mask;
566 ERegeneration &= ~wp_mask;
568 if (spfx & SPFX_TCTRL) {
570 ETeleport_control |= wp_mask;
572 ETeleport_control &= ~wp_mask;
574 if (spfx & SPFX_WARN) {
577 EWarn_of_mon |= wp_mask;
578 context.warntype.obj |= spec_m2(otmp);
580 EWarn_of_mon &= ~wp_mask;
581 context.warntype.obj &= ~spec_m2(otmp);
588 EWarning &= ~wp_mask;
591 if (spfx & SPFX_EREGEN) {
593 EEnergy_regeneration |= wp_mask;
595 EEnergy_regeneration &= ~wp_mask;
597 if (spfx & SPFX_HSPDAM) {
599 EHalf_spell_damage |= wp_mask;
601 EHalf_spell_damage &= ~wp_mask;
603 if (spfx & SPFX_HPHDAM) {
605 EHalf_physical_damage |= wp_mask;
607 EHalf_physical_damage &= ~wp_mask;
609 if (spfx & SPFX_XRAY) {
610 /* this assumes that no one else is using xray_range */
615 vision_full_recalc = 1;
617 if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
619 EReflecting |= wp_mask;
621 EReflecting &= ~wp_mask;
623 if (spfx & SPFX_PROTECT) {
625 EProtection |= wp_mask;
627 EProtection &= ~wp_mask;
630 if (wp_mask == W_ART && !on && oart->inv_prop) {
631 /* might have to turn off invoked power too */
632 if (oart->inv_prop <= LAST_PROP
633 && (u.uprops[oart->inv_prop].extrinsic & W_ARTI))
634 (void) arti_invoke(otmp);
638 /* touch_artifact()'s return value isn't sufficient to tell whether it
639 dished out damage, and tracking changes to u.uhp, u.mh, Lifesaved
640 when trying to avoid second wounding is too cumbersome */
641 STATIC_VAR boolean touch_blasted; /* for retouch_object() */
644 * creature (usually hero) tries to touch (pick up or wield) an artifact obj.
645 * Returns 0 if the object refuses to be touched.
646 * This routine does not change any object chains.
647 * Ignores such things as gauntlets, assuming the artifact is not
648 * fooled by such trappings.
651 touch_artifact(obj, mon)
655 register const struct artifact *oart = get_artifact(obj);
656 boolean badclass, badalign, self_willed, yours;
658 touch_blasted = FALSE;
662 yours = (mon == &youmonst);
663 /* all quest artifacts are self-willed; it this ever changes, `badclass'
664 will have to be extended to explicitly include quest artifacts */
665 self_willed = ((oart->spfx & SPFX_INTEL) != 0);
667 badclass = self_willed
668 && ((oart->role != NON_PM && !Role_if(oart->role))
669 || (oart->race != NON_PM && !Race_if(oart->race)));
671 (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
672 && (oart->alignment != u.ualign.type || u.ualign.record < 0);
673 } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) {
674 badclass = self_willed && oart->role != NON_PM
675 && oart != &artilist[ART_EXCALIBUR];
676 badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
677 && (oart->alignment != mon_aligntyp(mon));
678 } else { /* an M3_WANTSxxx monster or a fake player */
679 /* special monsters trying to take the Amulet, invocation tools or
680 quest item can touch anything except `spec_applies' artifacts */
681 badclass = badalign = FALSE;
683 /* weapons which attack specific categories of monsters are
684 bad for them even if their alignments happen to match */
686 badalign = bane_applies(oart, mon);
688 if (((badclass || badalign) && self_willed)
689 || (badalign && (!yours || !rn2(4)))) {
696 You("are blasted by %s power!", s_suffix(the(xname(obj))));
698 You("%s
\82Ì
\97Í
\82ð
\97\81\82Ñ
\82½
\81I", xname(obj));
699 touch_blasted = TRUE;
700 dmg = d((Antimagic ? 2 : 4), (self_willed ? 10 : 4));
701 /* add half (maybe quarter) of the usual silver damage bonus */
702 if (objects[obj->otyp].oc_material == SILVER && Hate_silver)
703 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
705 Sprintf(buf, "touching %s", oart->name);
707 Sprintf(buf, "%s
\82É
\90G
\82ê
\82Ä", oart->name);
708 losehp(dmg, buf, KILLED_BY); /* magic damage, not physical */
709 exercise(A_WIS, FALSE);
712 /* can pick it up unless you're totally non-synch'd with the artifact */
713 if (badclass && badalign && self_willed) {
717 pline("%s your grasp!", Tobjnam(obj, "evade"));
719 pline("%s
\82Í
\88¬
\82ë
\82¤
\82Æ
\82·
\82é
\82Æ
\82·
\82é
\82è
\82Æ
\94²
\82¯
\82½
\81I", xname(obj));
722 pline("%s beyond your control!", Tobjnam(obj, "are"));
724 pline("%s
\82Í
\90§
\8cä
\82Å
\82«
\82È
\82¢
\81I", xname(obj));
732 /* decide whether an artifact itself is vulnerable to a particular type
733 of erosion damage, independent of the properties of its bearer */
735 arti_immune(obj, dtyp)
739 register const struct artifact *weap = get_artifact(obj);
744 return FALSE; /* nothing is immune to phys dmg */
745 return (boolean) (weap->attk.adtyp == dtyp
746 || weap->defn.adtyp == dtyp
747 || weap->cary.adtyp == dtyp);
751 bane_applies(oart, mon)
752 const struct artifact *oart;
755 struct artifact atmp;
757 if (oart && (oart->spfx & SPFX_DBONUS) != 0) {
759 atmp.spfx &= SPFX_DBONUS; /* clear other spfx fields */
760 if (spec_applies(&atmp, mon))
766 /* decide whether an artifact's special attacks apply against mtmp */
768 spec_applies(weap, mtmp)
769 register const struct artifact *weap;
772 struct permonst *ptr;
775 if (!(weap->spfx & (SPFX_DBONUS | SPFX_ATTK)))
776 return (weap->attk.adtyp == AD_PHYS);
778 yours = (mtmp == &youmonst);
781 if (weap->spfx & SPFX_DMONS) {
782 return (ptr == &mons[(int) weap->mtype]);
783 } else if (weap->spfx & SPFX_DCLAS) {
784 return (weap->mtype == (unsigned long) ptr->mlet);
785 } else if (weap->spfx & SPFX_DFLAG1) {
786 return ((ptr->mflags1 & weap->mtype) != 0L);
787 } else if (weap->spfx & SPFX_DFLAG2) {
788 return ((ptr->mflags2 & weap->mtype)
790 && ((!Upolyd && (urace.selfmask & weap->mtype))
791 || ((weap->mtype & M2_WERE) && u.ulycn >= LOW_PM))));
792 } else if (weap->spfx & SPFX_DALIGN) {
793 return yours ? (u.ualign.type != weap->alignment)
794 : (ptr->maligntyp == A_NONE
795 || sgn(ptr->maligntyp) != weap->alignment);
796 } else if (weap->spfx & SPFX_ATTK) {
797 struct obj *defending_weapon = (yours ? uwep : MON_WEP(mtmp));
799 if (defending_weapon && defending_weapon->oartifact
800 && defends((int) weap->attk.adtyp, defending_weapon))
802 switch (weap->attk.adtyp) {
804 return !(yours ? Fire_resistance : resists_fire(mtmp));
806 return !(yours ? Cold_resistance : resists_cold(mtmp));
808 return !(yours ? Shock_resistance : resists_elec(mtmp));
811 return !(yours ? Antimagic : (rn2(100) < ptr->mr));
813 return !(yours ? Poison_resistance : resists_poison(mtmp));
815 return !(yours ? Drain_resistance : resists_drli(mtmp));
817 return !(yours ? Stone_resistance : resists_ston(mtmp));
819 impossible("Weird weapon special attack.");
825 /* return the M2 flags of monster that an artifact's special attacks apply
831 const struct artifact *artifact = get_artifact(otmp);
834 return artifact->mtype;
838 /* special attack bonus */
844 const struct artifact *weap = get_artifact(otmp);
846 /* no need for an extra check for `NO_ATTK' because this will
847 always return 0 for any artifact which has that attribute */
849 if (weap && weap->attk.damn && spec_applies(weap, mon))
850 return rnd((int) weap->attk.damn);
854 /* special damage bonus */
856 spec_dbon(otmp, mon, tmp)
861 register const struct artifact *weap = get_artifact(otmp);
863 if (!weap || (weap->attk.adtyp == AD_PHYS /* check for `NO_ATTK' */
864 && weap->attk.damn == 0 && weap->attk.damd == 0))
865 spec_dbon_applies = FALSE;
866 else if (otmp->oartifact == ART_GRIMTOOTH)
867 /* Grimtooth has SPFX settings to warn against elves but we want its
868 damage bonus to apply to all targets, so bypass spec_applies() */
869 spec_dbon_applies = TRUE;
871 spec_dbon_applies = spec_applies(weap, mon);
873 if (spec_dbon_applies)
874 return weap->attk.damd ? rnd((int) weap->attk.damd) : max(tmp, 1);
878 /* add identified artifact to discoveries list */
885 /* look for this artifact in the discoveries list;
886 if we hit an empty slot then it's not present, so add it */
887 for (i = 0; i < NROFARTIFACTS; i++)
888 if (artidisco[i] == 0 || artidisco[i] == m) {
892 /* there is one slot per artifact, so we should never reach the
893 end without either finding the artifact or an empty slot... */
894 impossible("couldn't discover artifact (%d)", (int) m);
897 /* used to decide whether an artifact has been fully identified */
899 undiscovered_artifact(m)
904 /* look for this artifact in the discoveries list;
905 if we hit an empty slot then it's undiscovered */
906 for (i = 0; i < NROFARTIFACTS; i++)
907 if (artidisco[i] == m)
909 else if (artidisco[i] == 0)
914 /* display a list of discovered artifacts; return their count */
916 disp_artifact_discoveries(tmpwin)
917 winid tmpwin; /* supplied by dodiscover() */
922 for (i = 0; i < NROFARTIFACTS; i++) {
923 if (artidisco[i] == 0)
924 break; /* empty slot implies end of list */
925 if (tmpwin == WIN_ERR)
926 continue; /* for WIN_ERR, we just count */
930 putstr(tmpwin, iflags.menu_headings, "Artifacts");
932 putstr(tmpwin, iflags.menu_headings, "
\90¹
\8aí");
934 otyp = artilist[m].otyp;
935 Sprintf(buf, " %s [%s %s]", artiname(m),
936 align_str(artilist[m].alignment), simple_typename(otyp));
937 putstr(tmpwin, 0, buf);
943 * Magicbane's intrinsic magic is incompatible with normal
944 * enchantment magic. Thus, its effects have a negative
945 * dependence on spe. Against low mr victims, it typically
946 * does "double athame" damage, 2d4. Occasionally, it will
947 * cast unbalancing magic which effectively averages out to
948 * 4d4 damage (3d4 against high mr victims), for spe = 0.
950 * Prior to 3.4.1, the cancel (aka purge) effect always
951 * included the scare effect too; now it's one or the other.
952 * Likewise, the stun effect won't be combined with either
953 * of those two; it will be chosen separately or possibly
954 * used as a fallback when scare or cancel fails.
956 * [Historical note: a change to artifact_hit() for 3.4.0
957 * unintentionally made all of Magicbane's special effects
958 * be blocked if the defender successfully saved against a
959 * stun attack. As of 3.4.1, those effects can occur but
960 * will be slightly less likely than they were in 3.3.x.]
962 #define MB_MAX_DIEROLL 8 /* rolls above this aren't magical */
963 static const char *const mb_verb[2][4] = {
965 { "probe", "stun", "scare", "cancel" },
966 { "prod", "amaze", "tickle", "purge" },
968 /* Mb_hit()
\82Å "%s
\82½"
\82Ì
\8c`
\82Å
\97\98\97p */
969 {"
\92²
\8d¸
\82µ", "
\82
\82ç
\82
\82ç
\82³
\82¹", "
\8b¯
\82¦
\82³
\82¹", "
\8fò
\89»
\82µ"},
970 { "
\97ã
\82Ü
\82µ", "
\8bÁ
\82©
\82¹", "
\82
\82·
\82®
\82Á", "
\90´
\82ß" },
973 #define MB_INDEX_PROBE 0
974 #define MB_INDEX_STUN 1
975 #define MB_INDEX_SCARE 2
976 #define MB_INDEX_CANCEL 3
978 /* called when someone is being hit by Magicbane */
980 Mb_hit(magr, mdef, mb, dmgptr, dieroll, vis, hittee)
981 struct monst *magr, *mdef; /* attacker and defender */
982 struct obj *mb; /* Magicbane */
983 int *dmgptr; /* extra damage target will suffer */
984 int dieroll; /* d20 that has already scored a hit */
985 boolean vis; /* whether the action can be seen */
986 char *hittee; /* target's name: "you" or mon_nam(mdef) */
988 struct permonst *old_uasmon;
989 const char *verb, *fakename;
990 boolean youattack = (magr == &youmonst), youdefend = (mdef == &youmonst),
991 resisted = FALSE, do_stun, do_confuse, result;
992 int attack_indx, scare_dieroll = MB_MAX_DIEROLL / 2;
994 result = FALSE; /* no message given yet */
995 /* the most severe effects are less likely at higher enchantment */
997 scare_dieroll /= (1 << (mb->spe / 3));
998 /* if target successfully resisted the artifact damage bonus,
999 reduce overall likelihood of the assorted special effects */
1000 if (!spec_dbon_applies)
1003 /* might stun even when attempting a more severe effect, but
1004 in that case it will only happen if the other effect fails;
1005 extra damage will apply regardless; 3.4.1: sometimes might
1006 just probe even when it hasn't been enchanted */
1007 do_stun = (max(mb->spe, 0) < rn2(spec_dbon_applies ? 11 : 7));
1009 /* the special effects also boost physical damage; increments are
1010 generally cumulative, but since the stun effect is based on a
1011 different criterium its damage might not be included; the base
1012 damage is either 1d4 (athame) or 2d4 (athame+spec_dbon) depending
1013 on target's resistance check against AD_STUN (handled by caller)
1014 [note that a successful save against AD_STUN doesn't actually
1015 prevent the target from ending up stunned] */
1016 attack_indx = MB_INDEX_PROBE;
1017 *dmgptr += rnd(4); /* (2..3)d4 */
1019 attack_indx = MB_INDEX_STUN;
1020 *dmgptr += rnd(4); /* (3..4)d4 */
1022 if (dieroll <= scare_dieroll) {
1023 attack_indx = MB_INDEX_SCARE;
1024 *dmgptr += rnd(4); /* (3..5)d4 */
1026 if (dieroll <= (scare_dieroll / 2)) {
1027 attack_indx = MB_INDEX_CANCEL;
1028 *dmgptr += rnd(4); /* (4..6)d4 */
1031 /* give the hit message prior to inflicting the effects */
1032 verb = mb_verb[!!Hallucination][attack_indx];
1033 if (youattack || youdefend || vis) {
1036 pline_The("magic-absorbing blade %s %s!",
1037 vtense((const char *) 0, verb), hittee);
1039 pline("
\96\82\97Í
\82ð
\8bz
\82¢
\82Æ
\82é
\90n
\82ª%s
\82ð%s
\82½
\81I",
1042 /* assume probing has some sort of noticeable feedback
1043 even if it is being done by one monster to another */
1044 if (attack_indx == MB_INDEX_PROBE && !canspotmon(mdef))
1045 map_invisible(mdef->mx, mdef->my);
1048 /* now perform special effects */
1049 switch (attack_indx) {
1050 case MB_INDEX_CANCEL:
1051 old_uasmon = youmonst.data;
1052 /* No mdef->mcan check: even a cancelled monster can be polymorphed
1053 * into a golem, and the "cancel" effect acts as if some magical
1054 * energy remains in spellcasting defenders to be absorbed later.
1056 if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
1061 if (youmonst.data != old_uasmon)
1062 *dmgptr = 0; /* rehumanized, so no more damage */
1065 You("lose magical energy!");
1067 You("
\96\82\96@
\82Ì
\83G
\83l
\83\8b\83M
\81[
\82ð
\8e¸
\82Á
\82½
\81I");
1074 if (mdef->data == &mons[PM_CLAY_GOLEM])
1075 mdef->mhp = 1; /* cancelled clay golems will die */
1076 if (youattack && attacktype(mdef->data, AT_MAGC)) {
1078 You("absorb magical energy!");
1080 You("
\96\82\96@
\82Ì
\83G
\83l
\83\8b\83M
\81[
\82ð
\8bz
\82¢
\82Æ
\82Á
\82½
\81I");
1089 case MB_INDEX_SCARE:
1095 multi_reason = "being scared stiff";
1097 if (magr && magr == u.ustuck && sticks(youmonst.data)) {
1098 u.ustuck = (struct monst *) 0;
1100 You("release %s!", mon_nam(magr));
1102 You("%s
\82ð
\89ð
\95ú
\82µ
\82½
\81I", mon_nam(magr));
1106 if (rn2(2) && resist(mdef, WEAPON_CLASS, 0, NOTELL))
1109 monflee(mdef, 3, FALSE, (mdef->mhp > *dmgptr));
1116 do_stun = TRUE; /* (this is redundant...) */
1119 case MB_INDEX_PROBE:
1120 if (youattack && (mb->spe == 0 || !rn2(3 * abs(mb->spe)))) {
1122 pline_The("%s is insightful.", verb);
1124 pline("
\91\8a\8eè
\82ð%s
\82½
\81D", verb);
1125 /* pre-damage status */
1126 probe_monster(mdef);
1130 /* stun if that was selected and a worse effect didn't occur */
1133 make_stunned(((HStun & TIMEOUT) + 3L), FALSE);
1136 /* avoid extra stun message below if we used mb_verb["stun"] above */
1137 if (attack_indx == MB_INDEX_STUN)
1140 /* lastly, all this magic can be confusing... */
1141 do_confuse = !rn2(12);
1144 make_confused((HConfusion & TIMEOUT) + 4L, FALSE);
1149 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1150 /* now give message(s) describing side-effects;
1151 don't let vtense() be fooled by assigned name ending in 's' */
1152 fakename = youdefend ? "you" : "mon";
1154 if (youattack || youdefend || vis) {
1155 (void) upstart(hittee); /* capitalize */
1158 pline("%s %s!", hittee, vtense(fakename, "resist"));
1160 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", hittee);
1161 shieldeff(youdefend ? u.ux : mdef->mx,
1162 youdefend ? u.uy : mdef->my);
1164 if ((do_stun || do_confuse) && flags.verbose) {
1170 Strcat(buf, "stunned");
1171 if (do_stun && do_confuse)
1172 Strcat(buf, " and ");
1174 Strcat(buf, "confused");
1175 pline("%s %s %s%c", hittee, vtense(fakename, "are"), buf,
1176 (do_stun && do_confuse) ? '!' : '.');
1178 if (do_stun && do_confuse)
1179 Strcat(buf, "
\82æ
\82ë
\82ß
\82¢
\82Ä");
1181 Strcat(buf, "
\82æ
\82ë
\82ß
\82¢
\82½");
1183 Strcat(buf, "
\8d¬
\97\90\82µ
\82½");
1184 pline("%s
\82Í%s%s", hittee,
1185 buf, (do_stun && do_confuse) ? "
\81I" : "
\81D");
1193 /* Function used when someone attacks someone else with an artifact
1194 * weapon. Only adds the special (artifact) damage, and returns a 1 if it
1195 * did something special (in which case the caller won't print the normal
1196 * hit message). This should be called once upon every artifact attack;
1197 * dmgval() no longer takes artifact bonuses into account. Possible
1198 * extension: change the killer so that when an orc kills you with
1199 * Stormbringer it's "killed by Stormbringer" instead of "killed by an orc".
1202 artifact_hit(magr, mdef, otmp, dmgptr, dieroll)
1203 struct monst *magr, *mdef;
1206 int dieroll; /* needed for Magicbane and vorpal blades */
1208 boolean youattack = (magr == &youmonst);
1209 boolean youdefend = (mdef == &youmonst);
1210 boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
1211 || (!youdefend && cansee(mdef->mx, mdef->my))
1212 || (youattack && u.uswallow && mdef == u.ustuck && !Blind);
1213 boolean realizes_damage;
1214 const char *wepdesc;
1216 static const char you[] = "you";
1218 static const char you[] = "
\82 \82È
\82½";
1221 Strcpy(hittee, youdefend ? you : mon_nam(mdef));
1223 /* The following takes care of most of the damage, but not all--
1224 * the exception being for level draining, which is specially
1225 * handled. Messages are done in this function, however.
1227 *dmgptr += spec_dbon(otmp, mdef, *dmgptr);
1229 if (youattack && youdefend) {
1230 impossible("attacking yourself with weapon?");
1234 realizes_damage = (youdefend || vis
1235 /* feel the effect even if not seen */
1236 || (youattack && mdef == u.ustuck));
1238 /* the four basic attacks: fire, cold, shock and missiles */
1239 if (attacks(AD_FIRE, otmp)) {
1240 if (realizes_damage)
1242 pline_The("fiery blade %s %s%c",
1245 : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1246 ? "vaporizes part of"
1248 hittee, !spec_dbon_applies ? '.' : '!');
1250 pline_The("
\96Ò
\89Î
\82ª%s%s",
1253 ? "
\82É
\96½
\92\86\82µ
\82½
\81D"
1254 : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1255 ? "
\82Ì
\88ê
\95\94\82ð
\8fÁ
\96Å
\82³
\82¹
\82½
\81I"
1256 : "
\82ð
\8fÄ
\82¢
\82½
\81I");
1259 (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1261 (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1263 (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1264 if (youdefend && Slimed)
1266 return realizes_damage;
1268 if (attacks(AD_COLD, otmp)) {
1269 if (realizes_damage)
1271 pline_The("ice-cold blade %s %s%c",
1272 !spec_dbon_applies ? "hits" : "freezes", hittee,
1273 !spec_dbon_applies ? '.' : '!');
1275 pline_The("
\96Ò
\90\81\90á
\82ª%s%s",
1277 !spec_dbon_applies ? "
\82É
\96½
\92\86\82µ
\82½
\81D" : "
\82ð
\8fP
\82Á
\82½
\81I");
1280 (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1281 return realizes_damage;
1283 if (attacks(AD_ELEC, otmp)) {
1284 if (realizes_damage)
1286 pline_The("massive hammer hits%s %s%c",
1287 !spec_dbon_applies ? "" : "! Lightning strikes",
1288 hittee, !spec_dbon_applies ? '.' : '!');
1290 pline("
\8b\90\91å
\82È
\83n
\83\93\83}
\81[
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", hittee,
1291 !spec_dbon_applies ? "
\81D" : "
\81I
\93d
\8c\82\82ª
\8fP
\82Á
\82½
\81I");
1294 (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1296 (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1297 return realizes_damage;
1299 if (attacks(AD_MAGM, otmp)) {
1300 if (realizes_damage)
1302 pline_The("imaginary widget hits%s %s%c",
1305 : "! A hail of magic missiles strikes",
1306 hittee, !spec_dbon_applies ? '.' : '!');
1308 pline("
\8eÀ
\91Ì
\82ð
\8e\9d\82½
\82È
\82¢
\95¨
\91Ì
\82ª%s
\82ð
\8dU
\8c\82\82µ
\82½%s",
1310 !spec_dbon_applies ? "
\81D" :
1311 "
\81I
\96\82\96@
\82Ì
\96î
\82ª
\89J
\82 \82ç
\82ê
\82Æ
\96½
\92\86\82µ
\82½
\81I");
1313 return realizes_damage;
1316 if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
1317 /* Magicbane's special attacks (possibly modifies hittee[]) */
1318 return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
1321 if (!spec_dbon_applies) {
1322 /* since damage bonus didn't apply, nothing more to do;
1323 no further attacks have side-effects on inventory */
1327 /* We really want "on a natural 20" but Nethack does it in */
1328 /* reverse from AD&D. */
1329 if (spec_ability(otmp, SPFX_BEHEAD)) {
1330 if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) {
1332 wepdesc = "The razor-sharp blade";
1334 wepdesc = "
\8ea
\93S
\8c\95";
1335 /* not really beheading, but so close, why add another SPFX */
1336 if (youattack && u.uswallow && mdef == u.ustuck) {
1338 You("slice %s wide open!", mon_nam(mdef));
1340 You("%s
\82ð
\97Ö
\90Ø
\82è
\82É
\82µ
\82½
\81I", mon_nam(mdef));
1341 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1345 /* allow normal cutworm() call to add extra damage */
1349 if (bigmonst(mdef->data)) {
1352 You("slice deeply into %s!", mon_nam(mdef));
1354 You("%s
\82É
\90[
\82
\8ea
\82è
\82Â
\82¯
\82½
\81I",mon_nam(mdef));
1357 pline("%s cuts deeply into %s!", Monnam(magr),
1360 pline("%s
\82Í%s
\82É
\90[
\82
\8ea
\82è
\82Â
\82¯
\82½
\81I", Monnam(magr),
1366 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1368 pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
1370 pline("%s
\82ª%s
\82ð
\90^
\82Á
\93ñ
\82Â
\82É
\82µ
\82½
\81I", wepdesc, mon_nam(mdef));
1371 otmp->dknown = TRUE;
1374 if (bigmonst(youmonst.data)) {
1376 pline("%s cuts deeply into you!",
1378 pline("%s
\82Í
\82 \82È
\82½
\82É
\90[
\82
\8ea
\82è
\82Â
\82¯
\82½
\81I",
1379 magr ? Monnam(magr) : wepdesc);
1384 /* Players with negative AC's take less damage instead
1385 * of just not getting hit. We must add a large enough
1386 * value to the damage so that this reduction in
1387 * damage does not prevent death.
1389 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1391 pline("%s cuts you in half!", wepdesc);
1393 pline("%s
\82ª
\82 \82È
\82½
\82ð
\90^
\82Á
\93ñ
\82Â
\82É
\82µ
\82½
\81I", wepdesc);
1394 otmp->dknown = TRUE;
1397 } else if (otmp->oartifact == ART_VORPAL_BLADE
1398 && (dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) {
1400 static const char *const behead_msg[2] = { "%s beheads %s!",
1401 "%s decapitates %s!" };
1403 static const char *const behead_msg[2] = { "%s
\82Í%s
\82Ì
\8eñ
\82ð
\90Ø
\82Á
\82½
\81I",
1404 "%s
\82Í%s
\82Ì
\8eñ
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81I" };
1407 if (youattack && u.uswallow && mdef == u.ustuck)
1409 wepdesc = artilist[ART_VORPAL_BLADE].name;
1411 if (!has_head(mdef->data) || notonhead || u.uswallow) {
1414 pline("Somehow, you miss %s wildly.", mon_nam(mdef));
1416 pline("
\82È
\82º
\82©
\81C%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D", mon_nam(mdef));
1419 pline("Somehow, %s misses wildly.", mon_nam(magr));
1421 pline("
\82È
\82º
\82©
\81C%s
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D", mon_nam(magr));
1423 return (boolean) (youattack || vis);
1425 if (noncorporeal(mdef->data) || amorphous(mdef->data)) {
1427 pline("%s slices through %s %s.", wepdesc,
1429 pline("%s
\82Í%s
\82Ì%s
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81D", wepdesc,
1430 s_suffix(mon_nam(mdef)), mbodypart(mdef, NECK));
1433 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1434 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc,
1436 if (Hallucination && !flags.female)
1438 pline("Good job Henry, but that wasn't Anne.");
1440 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");
1441 otmp->dknown = TRUE;
1444 if (!has_head(youmonst.data)) {
1446 pline("Somehow, %s misses you wildly.",
1448 pline("
\82È
\82º
\82©
\81C%s
\82Ì
\8dU
\8c\82\82Í
\91å
\82«
\82
\82Í
\82¸
\82ê
\82½
\81D",
1449 magr ? mon_nam(magr) : wepdesc);
1453 if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) {
1455 pline("%s slices through your %s.", wepdesc,
1457 pline("%s
\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\90Ø
\82è
\97\8e\82µ
\82½
\81D", wepdesc,
1461 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1463 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
1465 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "
\82 \82È
\82½");
1466 otmp->dknown = TRUE;
1467 /* Should amulets fall off? */
1472 if (spec_ability(otmp, SPFX_DRLI)) {
1473 /* some non-living creatures (golems, vortices) are
1474 vulnerable to life drain effects */
1476 const char *life = nonliving(mdef->data) ? "animating force" : "life";
1478 const char *life = nonliving(mdef->data) ? "
\93®
\8dì
\97Í" : "
\90¶
\96½
\97Í";
1482 if (otmp->oartifact == ART_STORMBRINGER)
1484 pline_The("%s blade draws the %s from %s!",
1485 hcolor(NH_BLACK), life, mon_nam(mdef));
1487 pline("%s
\90n
\82ª%s
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I",
1488 hcolor(NH_BLACK), mon_nam(mdef), life);
1492 pline("%s draws the %s from %s!",
1493 The(distant_name(otmp, xname)), life,
1496 pline("%s
\82Í%s
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I",
1497 The(distant_name(otmp, xname)),
1498 mon_nam(mdef), life);
1501 if (mdef->m_lev == 0) {
1502 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1504 int drain = monhp_per_lvl(mdef);
1507 mdef->mhpmax -= drain;
1511 healup(drain, 0, FALSE, FALSE);
1514 } else { /* youdefend */
1515 int oldhpmax = u.uhpmax;
1519 You_feel("an %s drain your %s!",
1520 (otmp->oartifact == ART_STORMBRINGER)
1525 pline("%s
\82É%s
\82ð
\92D
\82í
\82ê
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
1526 (otmp->oartifact == ART_STORMBRINGER)
1527 ? "
\95s
\8fò
\82È
\90n"
1531 else if (otmp->oartifact == ART_STORMBRINGER)
1533 pline_The("%s blade drains your %s!", hcolor(NH_BLACK), life);
1535 pline("%s
\90n
\82ª
\82 \82È
\82½
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I", hcolor(NH_BLACK), life);
1538 pline("%s drains your %s!", The(distant_name(otmp, xname)),
1541 pline("%s
\82ª
\82 \82È
\82½
\82Ì%s
\82ð
\92D
\82Á
\82½
\81I", The(distant_name(otmp, xname)),
1545 losexp("life drainage");
1547 losexp("
\90¶
\96½
\97Í
\82ð
\8bz
\8eû
\82³
\82ê
\82Ä");
1548 if (magr && magr->mhp < magr->mhpmax) {
1549 magr->mhp += (oldhpmax - u.uhpmax) / 2;
1550 if (magr->mhp > magr->mhpmax)
1551 magr->mhp = magr->mhpmax;
1559 static NEARDATA const char recharge_type[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
1560 static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 };
1561 /* #invoke: an "ugly check" filters out most objects */
1563 /* the #invoke command */
1569 obj = getobj(invoke_types, "invoke");
1572 if (!retouch_object(&obj, FALSE))
1574 return arti_invoke(obj);
1581 register const struct artifact *oart = get_artifact(obj);
1583 impossible("arti_invoke without obj");
1586 if (!oart || !oart->inv_prop) {
1587 if (obj->otyp == CRYSTAL_BALL)
1588 use_crystal_ball(&obj);
1590 pline1(nothing_happens);
1594 if (oart->inv_prop > LAST_PROP) {
1595 /* It's a special power, not "just" a property */
1596 if (obj->age > monstermoves) {
1597 /* the artifact is tired :-) */
1599 You_feel("that %s %s ignoring you.", the(xname(obj)),
1600 otense(obj, "are"));
1602 You_feel("%s
\82ª
\96³
\8e\8b\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8a´
\82¶
\82½
\81D", xname(obj));
1604 /* and just got more so; patience is essential... */
1605 obj->age += (long) d(3, 10);
1608 obj->age = monstermoves + rnz(100);
1610 switch (oart->inv_prop) {
1615 zeroobj; /* neither cursed nor blessed, zero oextra too */
1616 pseudo.otyp = SCR_TAMING;
1617 (void) seffects(&pseudo);
1621 int healamt = (u.uhpmax + 1 - u.uhp) / 2;
1622 long creamed = (long) u.ucreamed;
1625 healamt = (u.mhmax + 1 - u.mh) / 2;
1626 if (healamt || Sick || Slimed || Blinded > creamed)
1628 You_feel("better.");
1630 You_feel("
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81D");
1632 goto nothing_special;
1640 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1642 make_slimed(0L, (char *) 0);
1643 if (Blinded > creamed)
1644 make_blinded(creamed, FALSE);
1648 case ENERGY_BOOST: {
1649 int epboost = (u.uenmax + 1 - u.uen) / 2;
1651 epboost = 120; /* arbitrary */
1652 else if (epboost < 12)
1653 epboost = u.uenmax - u.uen;
1656 You_feel("re-energized.");
1658 You("
\83G
\83l
\83\8b\83M
\81[
\82Å
\96\9e\82½
\82³
\82ê
\82½
\81D");
1662 goto nothing_special;
1666 if (!untrap(TRUE)) {
1667 obj->age = 0; /* don't charge for changing their mind */
1673 struct obj *otmp = getobj(recharge_type, "charge");
1681 obj->blessed && (Role_switch == oart->role || !oart->role);
1682 recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
1689 case CREATE_PORTAL: {
1690 int i, num_ok_dungeons, last_ok_dungeon = 0;
1692 extern int n_dgns; /* from dungeon.c */
1693 winid tmpwin = create_nhwindow(NHW_MENU);
1696 any = zeroany; /* set all bits to zero */
1698 /* use index+1 (cant use 0) as identifier */
1699 for (i = num_ok_dungeons = 0; i < n_dgns; i++) {
1700 if (!dungeons[i].dunlev_ureached)
1703 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1704 dungeons[i].dname, MENU_UNSELECTED);
1706 last_ok_dungeon = i;
1709 end_menu(tmpwin, "Open a portal to which dungeon?");
1711 end_menu(tmpwin, "
\82Ç
\82Ì
\96À
\8b{
\82Ö
\82Ì
\96\82\96@
\82Ì
\93ü
\8cû
\82ð
\8aJ
\82«
\82Ü
\82·
\82©
\81H");
1712 if (num_ok_dungeons > 1) {
1713 /* more than one entry; display menu for choices */
1714 menu_item *selected;
1717 n = select_menu(tmpwin, PICK_ONE, &selected);
1719 destroy_nhwindow(tmpwin);
1720 goto nothing_special;
1722 i = selected[0].item.a_int - 1;
1723 free((genericptr_t) selected);
1725 i = last_ok_dungeon; /* also first & only OK dungeon */
1726 destroy_nhwindow(tmpwin);
1729 * i is now index into dungeon structure for the new dungeon.
1730 * Find the closest level in the given dungeon, open
1731 * a use-once portal to that dungeon and go there.
1732 * The closest level is either the entry or dunlev_ureached.
1735 if (dungeons[i].depth_start >= depth(&u.uz))
1736 newlev.dlevel = dungeons[i].entry_lev;
1738 newlev.dlevel = dungeons[i].dunlev_ureached;
1740 if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
1741 || newlev.dnum == u.uz.dnum || !next_to_u()) {
1743 You_feel("very disoriented for a moment.");
1745 You("
\88ê
\8fu
\95û
\8cü
\8a´
\8ao
\82ð
\8e¸
\82Á
\82½
\81D");
1749 You("are surrounded by a shimmering sphere!");
1751 You("
\83`
\83J
\83`
\83J
\8cõ
\82é
\8b\85\91Ì
\82É
\95¢
\82í
\82ê
\82½
\81I");
1754 You_feel("weightless for a moment.");
1756 You_feel("
\88ê
\8fu
\81C
\96³
\8fd
\97Í
\8a´
\82ð
\8a´
\82¶
\82½
\81D");
1757 goto_level(&newlev, FALSE, FALSE, FALSE);
1762 enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
1765 struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
1768 goto nothing_special;
1769 otmp->blessed = obj->blessed;
1770 otmp->cursed = obj->cursed;
1771 otmp->bknown = obj->bknown;
1775 otmp->quan += rnd(10);
1776 } else if (obj->cursed) {
1780 otmp->quan += rnd(5);
1781 otmp->owt = weight(otmp);
1784 hold_another_object(otmp, "Suddenly %s out.",
1785 aobjnam(otmp, "fall"), (const char *) 0);
1787 hold_another_object(otmp, "
\93Ë
\91R%s
\82ª
\97\8e\82¿
\82½
\81D",
1794 long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
1795 iprop = u.uprops[oart->inv_prop].intrinsic;
1796 boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */
1798 if (on && obj->age > monstermoves) {
1799 /* the artifact is tired :-) */
1800 u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
1802 You_feel("that %s %s ignoring you.", the(xname(obj)),
1803 otense(obj, "are"));
1805 You_feel("%s
\82ª
\96³
\8e\8b\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8a´
\82¶
\82½
\81D", xname(obj));
1807 /* can't just keep repeatedly trying */
1808 obj->age += (long) d(3, 10);
1811 /* when turning off property, determine downtime */
1812 /* arbitrary for now until we can tune this -dlc */
1813 obj->age = monstermoves + rnz(100);
1816 if ((eprop & ~W_ARTI) || iprop) {
1818 /* you had the property from some other source too */
1821 You_feel("a surge of power, but nothing seems to happen.");
1823 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");
1826 switch (oart->inv_prop) {
1830 You_feel("like a rabble-rouser.");
1832 You("
\96¯
\8fO
\90î
\93®
\89Æ
\82Ì
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
1835 You_feel("the tension decrease around you.");
1837 pline("
\82Ü
\82í
\82è
\82Ì
\8bÙ
\92£
\8a´
\82ª
\82È
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
1844 (void) float_down(I_SPECIAL | TIMEOUT, W_ARTI);
1847 if (BInvis || Blind)
1848 goto nothing_special;
1852 Your("body takes on a %s transparency...",
1853 Hallucination ? "normal" : "strange");
1855 pline("%s
\81C
\91Ì
\82Í
\93§
\89ß
\90«
\82ð
\82à
\82Á
\82½
\81D
\81D
\81D",
1856 Hallucination ? "
\82 \82½
\82è
\82Ü
\82¦
\82Ì
\82±
\82Æ
\82¾
\82ª" : "
\8aï
\96
\82È
\82±
\82Æ
\82É");
1860 Your("body seems to unfade...");
1862 Your("
\91Ì
\82Í
\8e\9f\91æ
\82É
\8c©
\82¦
\82é
\82æ
\82¤
\82É
\82È
\82Á
\82Ä
\82«
\82½
\81D
\81D
\81D");
1870 /* will freeing this object from inventory cause levitation to end? */
1872 finesse_ahriman(obj)
1875 const struct artifact *oart;
1876 struct prop save_Lev;
1879 /* if we aren't levitating or this isn't an artifact which confers
1880 levitation via #invoke then freeinv() won't toggle levitation */
1881 if (!Levitation || (oart = get_artifact(obj)) == 0
1882 || oart->inv_prop != LEVITATION || !(ELevitation & W_ARTI))
1885 /* arti_invoke(off) -> float_down() clears I_SPECIAL|TIMEOUT & W_ARTI;
1886 probe ahead to see whether that actually results in floating down;
1887 (this assumes that there aren't two simultaneously invoked artifacts
1888 both conferring levitation--safe, since if there were two of them,
1889 invoking the 2nd would negate the 1st rather than stack with it) */
1890 save_Lev = u.uprops[LEVITATION];
1891 HLevitation &= ~(I_SPECIAL | TIMEOUT);
1892 ELevitation &= ~W_ARTI;
1893 result = (boolean) !Levitation;
1894 u.uprops[LEVITATION] = save_Lev;
1898 /* WAC return TRUE if artifact is always lit */
1903 return (boolean) (get_artifact(obj) && obj->oartifact == ART_SUNSWORD);
1906 /* KMH -- Talking artifacts are finally implemented */
1911 register const struct artifact *oart = get_artifact(obj);
1915 /* Is this a speaking artifact? */
1916 if (!oart || !(oart->spfx & SPFX_SPEAK))
1919 line = getrumor(bcsign(obj), buf, TRUE);
1922 line = "NetHack rumors file closed for renovation.";
1924 line = "
\89\
\82Ì
\90^
\91\8a\82Í
\90V
\91\95\82Ì
\82½
\82ß
\88ê
\8e\9e\95Â
\93X
\81D";
1926 pline("%s:", Tobjnam(obj, "whisper"));
1928 pline("%s
\82Í
\82³
\82³
\82â
\82¢
\82½
\81F", xname(obj));
1934 artifact_has_invprop(otmp, inv_prop)
1938 const struct artifact *arti = get_artifact(otmp);
1940 return (boolean) (arti && (arti->inv_prop == inv_prop));
1943 /* Return the price sold to the hero of a given artifact or unique item */
1948 if (!otmp->oartifact)
1949 return (long) objects[otmp->otyp].oc_cost;
1950 else if (artilist[(int) otmp->oartifact].cost)
1951 return artilist[(int) otmp->oartifact].cost;
1953 return (100L * (long) objects[otmp->otyp].oc_cost);
1960 struct abil2adtyp_tag {
1964 { &EFire_resistance, AD_FIRE },
1965 { &ECold_resistance, AD_COLD },
1966 { &EShock_resistance, AD_ELEC },
1967 { &EAntimagic, AD_MAGM },
1968 { &EDisint_resistance, AD_DISN },
1969 { &EPoison_resistance, AD_DRST },
1973 for (k = 0; k < SIZE(abil2adtyp); k++) {
1974 if (abil2adtyp[k].abil == abil)
1975 return abil2adtyp[k].adtyp;
1980 STATIC_OVL unsigned long
1984 static const struct abil2spfx_tag {
1988 { &ESearching, SPFX_SEARCH },
1989 { &EHalluc_resistance, SPFX_HALRES },
1990 { &ETelepat, SPFX_ESP },
1991 { &EStealth, SPFX_STLTH },
1992 { &ERegeneration, SPFX_REGEN },
1993 { &ETeleport_control, SPFX_TCTRL },
1994 { &EWarn_of_mon, SPFX_WARN },
1995 { &EWarning, SPFX_WARN },
1996 { &EEnergy_regeneration, SPFX_EREGEN },
1997 { &EHalf_spell_damage, SPFX_HSPDAM },
1998 { &EHalf_physical_damage, SPFX_HPHDAM },
1999 { &EReflecting, SPFX_REFLECT },
2003 for (k = 0; k < SIZE(abil2spfx); k++) {
2004 if (abil2spfx[k].abil == abil)
2005 return abil2spfx[k].spfx;
2011 * Return the first item that is conveying a particular intrinsic.
2021 long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS
2022 | W_ARMG | W_ARMF | W_ARMU
2023 | W_AMUL | W_RINGL | W_RINGR | W_TOOL
2024 /* [do W_ART and W_ARTI actually belong here?] */
2028 wornmask |= W_SWAPWEP;
2029 dtyp = abil_to_adtyp(abil);
2030 spfx = abil_to_spfx(abil);
2031 wornbits = (wornmask & *abil);
2033 for (obj = invent; obj; obj = obj->nobj) {
2035 && (abil != &EWarn_of_mon || context.warntype.obj)) {
2036 const struct artifact *art = get_artifact(obj);
2040 if (art->cary.adtyp == dtyp || art->defn.adtyp == dtyp)
2044 /* property conferred when carried */
2045 if ((art->cspfx & spfx) == spfx)
2047 /* property conferred when wielded or worn */
2048 if ((art->spfx & spfx) == spfx && obj->owornmask)
2053 if (wornbits && wornbits == (wornmask & obj->owornmask))
2057 return (struct obj *) 0;
2061 glow_color(arti_indx)
2064 int colornum = artilist[arti_indx].acolor;
2065 const char *colorstr = clr2colorname(colornum);
2067 return hcolor(colorstr);
2070 /* use for warning "glow" for Sting, Orcrist, and Grimtooth */
2072 Sting_effects(orc_count)
2073 int orc_count; /* new count (warn_obj_cnt is old count); -1 is a flag value */
2076 && (uwep->oartifact == ART_STING
2077 || uwep->oartifact == ART_ORCRIST
2078 || uwep->oartifact == ART_GRIMTOOTH)) {
2079 if (orc_count == -1 && warn_obj_cnt > 0) {
2080 /* -1 means that blindness has just been toggled; give a
2081 'continue' message that eventual 'stop' message will match */
2083 pline("%s is %s.", bare_artifactname(uwep),
2084 !Blind ? "glowing" : "quivering");
2086 pline("%s
\82Í%s
\82Ä
\82¢
\82é
\81D", bare_artifactname(uwep),
2087 !Blind ? "
\8bP
\82¢" : "
\90k
\82¦");
2089 } else if (orc_count > 0 && warn_obj_cnt == 0) {
2090 /* 'start' message */
2093 pline("%s %s %s!", bare_artifactname(uwep),
2094 otense(uwep, "glow"), glow_color(uwep->oartifact));
2096 pline("%s
\82Í%s
\8bP
\82¢
\82½
\81I", bare_artifactname(uwep),
2097 glow_color(uwep->oartifact));
2101 pline("%s quivers slightly.", bare_artifactname(uwep));
2103 pline("%s
\82Í
\8f
\82µ
\90k
\82¦
\82½
\81D", bare_artifactname(uwep));
2104 } else if (orc_count == 0 && warn_obj_cnt > 0) {
2105 /* 'stop' message */
2107 pline("%s stops %s.", bare_artifactname(uwep),
2108 !Blind ? "glowing" : "quivering");
2110 pline("%s
\82Ì%s
\82Í
\8e~
\82Ü
\82Á
\82½
\81D", bare_artifactname(uwep),
2111 !Blind ? "
\8bP
\82«" : "
\90k
\82¦");
2117 /* called when hero is wielding/applying/invoking a carried item, or
2118 after undergoing a transformation (alignment change, lycanthropy,
2119 polymorph) which might affect item access */
2121 retouch_object(objp, loseit)
2122 struct obj **objp; /* might be destroyed or unintentionally dropped */
2123 boolean loseit; /* whether to drop it if hero can longer touch it */
2125 struct obj *obj = *objp;
2127 if (touch_artifact(obj, &youmonst)) {
2131 (objects[obj->otyp].oc_material == SILVER && Hate_silver),
2132 bane = bane_applies(get_artifact(obj), &youmonst);
2134 /* nothing else to do if hero can successfully handle this object */
2138 /* hero can't handle this object, but didn't get touch_artifact()'s
2139 "<obj> evades your grasp|control" message; give an alternate one */
2141 You_cant("handle %s%s!", yname(obj),
2142 obj->owornmask ? " anymore" : "");
2144 You_cant("%s%s
\82ð
\88µ
\82¦
\82È
\82¢
\81I", obj->owornmask ? "
\82à
\82¤" : "",
2147 /* also inflict damage unless touch_artifact() already did so */
2148 if (!touch_blasted) {
2149 /* damage is somewhat arbitrary; half the usual 1d20 physical
2150 for silver, 1d10 magical for <foo>bane, potentially both */
2152 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
2156 Sprintf(buf, "handling %s", killer_xname(obj));
2158 Sprintf(buf, "%s
\82ð
\88µ
\82Á
\82Ä", killer_xname(obj));
2159 losehp(dmg, buf, KILLED_BY);
2160 exercise(A_CON, FALSE);
2164 /* removing a worn item might result in loss of levitation,
2165 dropping the hero onto a polymorph trap or into water or
2166 lava and potentially dropping or destroying the item */
2167 if (obj->owornmask) {
2170 remove_worn_item(obj, FALSE);
2171 for (otmp = invent; otmp; otmp = otmp->nobj)
2178 /* if we still have it and caller wants us to drop it, do so now */
2179 if (loseit && obj) {
2184 /* dropx gives a message iff item lands on an altar */
2185 if (!IS_ALTAR(levl[u.ux][u.uy].typ))
2187 pline("%s to the %s.", Tobjnam(obj, "fall"),
2188 surface(u.ux, u.uy));
2190 pline("%s
\82Í%s
\82É
\97\8e\82¿
\82½
\81D", xname(obj),
2191 surface(u.ux, u.uy));
2195 *objp = obj = 0; /* no longer in inventory */
2200 /* an item which is worn/wielded or an artifact which conveys
2201 something via being carried or which has an #invoke effect
2202 currently in operation undergoes a touch test; if it fails,
2203 it will be unworn/unwielded and revoked but not dropped */
2205 untouchable(obj, drop_untouchable)
2207 boolean drop_untouchable;
2209 struct artifact *art;
2210 boolean beingworn, carryeffect, invoked;
2211 long wearmask = ~(W_QUIVER | (u.twoweap ? 0L : W_SWAPWEP) | W_BALL);
2213 beingworn = ((obj->owornmask & wearmask) != 0L
2214 /* some items in use don't have any wornmask setting */
2215 || (obj->oclass == TOOL_CLASS
2216 && (obj->lamplit || (obj->otyp == LEASH && obj->leashmon)
2217 || (Is_container(obj) && Has_contents(obj)))));
2219 if ((art = get_artifact(obj)) != 0) {
2220 carryeffect = (art->cary.adtyp || art->cspfx);
2221 invoked = (art->inv_prop > 0 && art->inv_prop <= LAST_PROP
2222 && (u.uprops[art->inv_prop].extrinsic & W_ARTI) != 0L);
2224 carryeffect = invoked = FALSE;
2227 if (beingworn || carryeffect || invoked) {
2228 if (!retouch_object(&obj, drop_untouchable)) {
2229 /* "<artifact> is beyond your control" or "you can't handle
2230 <object>" has been given and it is now unworn/unwielded
2231 and possibly dropped (depending upon caller); if dropped,
2232 carried effect was turned off, else we leave that alone;
2233 we turn off invocation property here if still carried */
2235 arti_invoke(obj); /* reverse #invoke */
2242 /* check all items currently in use (mostly worn) for touchability */
2244 retouch_equipment(dropflag)
2245 int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
2247 static int nesting = 0; /* recursion control */
2249 boolean dropit, had_gloves = (uarmg != 0);
2250 int had_rings = (!!uleft + !!uright);
2253 * We can potentially be called recursively if losing/unwearing
2254 * an item causes worn helm of opposite alignment to come off or
2257 * BUG: if the initial call was due to putting on a helm of
2258 * opposite alignment and it does come off to trigger recursion,
2259 * after the inner call executes, the outer call will finish
2260 * using the non-helm alignment rather than the helm alignment
2261 * which triggered this in the first place.
2264 clear_bypasses(); /* init upon initial entry */
2266 dropit = (dropflag > 0); /* drop all or drop weapon */
2267 /* check secondary weapon first, before possibly unwielding primary */
2269 (void) untouchable(uswapwep, dropit);
2270 /* check primary weapon next so that they're handled together */
2272 (void) untouchable(uwep, dropit);
2274 /* in case someone is daft enough to add artifact or silver saddle */
2275 if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
2276 /* untouchable() calls retouch_object() which expects an object in
2277 hero's inventory, but remove_worn_item() will be harmless for
2278 saddle and we're suppressing drop, so this works as intended */
2279 if (untouchable(obj, FALSE))
2280 dismount_steed(DISMOUNT_THROWN);
2283 * TODO? Force off gloves if either or both rings are going to
2284 * become unworn; force off cloak [suit] before suit [shirt].
2285 * The torso handling is hypothetical; the case for gloves is
2286 * not, due to the possibility of unwearing silver rings.
2289 dropit = (dropflag == 1); /* all untouchable items */
2290 /* loss of levitation (silver ring, or Heart of Ahriman invocation)
2291 might cause hero to lose inventory items (by dropping into lava,
2292 for instance), so inventory traversal needs to rescan the whole
2293 invent chain each time it moves on to another object; we use bypass
2294 handling to keep track of which items have already been processed */
2295 while ((obj = nxt_unbypassed_obj(invent)) != 0)
2296 (void) untouchable(obj, dropit);
2298 if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
2299 uncurse(uarmg); /* temporary? hack for ring removal plausibility */
2300 if (had_gloves && !uarmg)
2302 selftouch("After losing your gloves, you");
2304 selftouch("
\8f¬
\8eè
\82ð
\8e¸
\82Á
\82½
\82 \82Æ
\81C
\82 \82È
\82½
\82Í");
2307 clear_bypasses(); /* reset upon final exit */