OSDN Git Service

update year to 2018
[jnethack/source.git] / src / artifact.c
1 /* NetHack 3.6  artifact.c      $NHDT-Date: 1509836679 2017/11/04 23:04:39 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.106 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2013. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12 #include "artifact.h"
13 /*JP
14 #include "artilist.h"
15 */
16 #include "artilistj.h"
17
18 /*
19  * Note:  both artilist[] and artiexist[] have a dummy element #0,
20  *        so loops over them should normally start at #1.  The primary
21  *        exception is the save & restore code, which doesn't care about
22  *        the contents, just the total size.
23  */
24
25 extern boolean notonhead; /* for long worms */
26
27 #define get_artifact(o) \
28     (((o) && (o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
29
30 STATIC_DCL boolean FDECL(bane_applies, (const struct artifact *,
31                                         struct monst *));
32 STATIC_DCL int FDECL(spec_applies, (const struct artifact *, struct monst *));
33 STATIC_DCL int FDECL(arti_invoke, (struct obj *));
34 STATIC_DCL boolean FDECL(Mb_hit, (struct monst * magr, struct monst *mdef,
35                                 struct obj *, int *, 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));
39 STATIC_DCL int FDECL(count_surround_traps, (int, int));
40
41 /* The amount added to the victim's total hit points to insure that the
42    victim will be killed even after damage bonus/penalty adjustments.
43    Most such penalties are small, and 200 is plenty; the exception is
44    half physical damage.  3.3.1 and previous versions tried to use a very
45    large number to account for this case; now, we just compute the fatal
46    damage by adding it to 2 times the total hit points instead of 1 time.
47    Note: this will still break if they have more than about half the number
48    of hit points that will fit in a 15 bit integer. */
49 #define FATAL_DAMAGE_MODIFIER 200
50
51 /* coordinate effects from spec_dbon() with messages in artifact_hit() */
52 STATIC_OVL int spec_dbon_applies = 0;
53
54 /* flags including which artifacts have already been created */
55 static boolean artiexist[1 + NROFARTIFACTS + 1];
56 /* and a discovery list for them (no dummy first entry here) */
57 STATIC_OVL xchar artidisco[NROFARTIFACTS];
58
59 STATIC_DCL void NDECL(hack_artifacts);
60 STATIC_DCL boolean FDECL(attacks, (int, struct obj *));
61
62 /* handle some special cases; must be called after u_init() */
63 STATIC_OVL void
64 hack_artifacts()
65 {
66     struct artifact *art;
67     int alignmnt = aligns[flags.initalign].value;
68
69     /* Fix up the alignments of "gift" artifacts */
70     for (art = artilist + 1; art->otyp; art++)
71         if (art->role == Role_switch && art->alignment != A_NONE)
72             art->alignment = alignmnt;
73
74     /* Excalibur can be used by any lawful character, not just knights */
75     if (!Role_if(PM_KNIGHT))
76         artilist[ART_EXCALIBUR].role = NON_PM;
77
78     /* Fix up the quest artifact */
79     if (urole.questarti) {
80         artilist[urole.questarti].alignment = alignmnt;
81         artilist[urole.questarti].role = Role_switch;
82     }
83     return;
84 }
85
86 /* zero out the artifact existence list */
87 void
88 init_artifacts()
89 {
90     (void) memset((genericptr_t) artiexist, 0, sizeof artiexist);
91     (void) memset((genericptr_t) artidisco, 0, sizeof artidisco);
92     hack_artifacts();
93 }
94
95 void
96 save_artifacts(fd)
97 int fd;
98 {
99     bwrite(fd, (genericptr_t) artiexist, sizeof artiexist);
100     bwrite(fd, (genericptr_t) artidisco, sizeof artidisco);
101 }
102
103 void
104 restore_artifacts(fd)
105 int fd;
106 {
107     mread(fd, (genericptr_t) artiexist, sizeof artiexist);
108     mread(fd, (genericptr_t) artidisco, sizeof artidisco);
109     hack_artifacts(); /* redo non-saved special cases */
110 }
111
112 const char *
113 artiname(artinum)
114 int artinum;
115 {
116     if (artinum <= 0 || artinum > NROFARTIFACTS)
117         return "";
118     return artilist[artinum].name;
119 }
120
121 /*
122    Make an artifact.  If a specific alignment is specified, then an object of
123    the appropriate alignment is created from scratch, or 0 is returned if
124    none is available.  (If at least one aligned artifact has already been
125    given, then unaligned ones also become eligible for this.)
126    If no alignment is given, then 'otmp' is converted
127    into an artifact of matching type, or returned as-is if that's not
128    possible.
129    For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE);''
130    for the 1st, ``obj = mk_artifact((struct obj *)0, some_alignment);''.
131  */
132 struct obj *
133 mk_artifact(otmp, alignment)
134 struct obj *otmp;   /* existing object; ignored if alignment specified */
135 aligntyp alignment; /* target alignment, or A_NONE */
136 {
137     const struct artifact *a;
138     int m, n, altn;
139     boolean by_align = (alignment != A_NONE);
140     short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
141     boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
142     short eligible[NROFARTIFACTS];
143
144     n = altn = 0;    /* no candidates found yet */
145     eligible[0] = 0; /* lint suppression */
146     /* gather eligible artifacts */
147     for (m = 1, a = &artilist[m]; a->otyp; a++, m++) {
148         if (artiexist[m])
149             continue;
150         if ((a->spfx & SPFX_NOGEN) || unique)
151             continue;
152
153         if (!by_align) {
154             /* looking for a particular type of item; not producing a
155                divine gift so we don't care about role's first choice */
156             if (a->otyp == o_typ)
157                 eligible[n++] = m;
158             continue; /* move on to next possibility */
159         }
160
161         /* we're looking for an alignment-specific item
162            suitable for hero's role+race */
163         if ((a->alignment == alignment || a->alignment == A_NONE)
164             /* avoid enemies' equipment */
165             && (a->race == NON_PM || !race_hostile(&mons[a->race]))) {
166             /* when a role-specific first choice is available, use it */
167             if (Role_if(a->role)) {
168                 /* make this be the only possibility in the list */
169                 eligible[0] = m;
170                 n = 1;
171                 break; /* skip all other candidates */
172             }
173             /* found something to consider for random selection */
174             if (a->alignment != A_NONE || u.ugifts > 0) {
175                 /* right alignment, or non-aligned with at least 1
176                    previous gift bestowed, makes this one viable */
177                 eligible[n++] = m;
178             } else {
179                 /* non-aligned with no previous gifts;
180                    if no candidates have been found yet, record
181                    this one as a[nother] fallback possibility in
182                    case all aligned candidates have been used up
183                    (via wishing, naming, bones, random generation) */
184                 if (!n)
185                     eligible[altn++] = m;
186                 /* [once a regular candidate is found, the list
187                    is overwritten and `altn' becomes irrelevant] */
188             }
189         }
190     }
191
192     /* resort to fallback list if main list was empty */
193     if (!n)
194         n = altn;
195
196     if (n) {
197         /* found at least one candidate; pick one at random */
198         m = eligible[rn2(n)]; /* [0..n-1] */
199         a = &artilist[m];
200
201         /* make an appropriate object if necessary, then christen it */
202         if (by_align)
203             otmp = mksobj((int) a->otyp, TRUE, FALSE);
204
205         if (otmp) {
206             otmp = oname(otmp, a->name);
207             otmp->oartifact = m;
208             artiexist[m] = TRUE;
209         }
210     } else {
211         /* nothing appropriate could be found; return original object */
212         if (by_align)
213             otmp = 0; /* (there was no original object) */
214     }
215     return otmp;
216 }
217
218 /*
219  * Returns the full name (with articles and correct capitalization) of an
220  * artifact named "name" if one exists, or NULL, it not.
221  * The given name must be rather close to the real name for it to match.
222  * The object type of the artifact is returned in otyp if the return value
223  * is non-NULL.
224  */
225 const char *
226 artifact_name(name, otyp)
227 const char *name;
228 short *otyp;
229 {
230     register const struct artifact *a;
231     register const char *aname;
232
233     if (!strncmpi(name, "the ", 4))
234         name += 4;
235
236     for (a = artilist + 1; a->otyp; a++) {
237         aname = a->name;
238         if (!strncmpi(aname, "the ", 4))
239             aname += 4;
240         if (!strcmpi(name, aname)) {
241             *otyp = a->otyp;
242             return a->name;
243         }
244     }
245
246     return (char *) 0;
247 }
248
249 boolean
250 exist_artifact(otyp, name)
251 int otyp;
252 const char *name;
253 {
254     register const struct artifact *a;
255     boolean *arex;
256
257     if (otyp && *name)
258         for (a = artilist + 1, arex = artiexist + 1; a->otyp; a++, arex++)
259             if ((int) a->otyp == otyp && !strcmp(a->name, name))
260                 return *arex;
261     return FALSE;
262 }
263
264 void
265 artifact_exists(otmp, name, mod)
266 struct obj *otmp;
267 const char *name;
268 boolean mod;
269 {
270     register const struct artifact *a;
271
272     if (otmp && *name)
273         for (a = artilist + 1; a->otyp; a++)
274             if (a->otyp == otmp->otyp && !strcmp(a->name, name)) {
275                 register int m = (int) (a - artilist);
276                 otmp->oartifact = (char) (mod ? m : 0);
277                 otmp->age = 0;
278                 if (otmp->otyp == RIN_INCREASE_DAMAGE)
279                     otmp->spe = 0;
280                 artiexist[m] = mod;
281                 break;
282             }
283     return;
284 }
285
286 int
287 nartifact_exist()
288 {
289     int a = 0;
290     int n = SIZE(artiexist);
291
292     while (n > 1)
293         if (artiexist[--n])
294             a++;
295
296     return a;
297 }
298
299 boolean
300 spec_ability(otmp, abil)
301 struct obj *otmp;
302 unsigned long abil;
303 {
304     const struct artifact *arti = get_artifact(otmp);
305
306     return (boolean) (arti && (arti->spfx & abil) != 0L);
307 }
308
309 /* used so that callers don't need to known about SPFX_ codes */
310 boolean
311 confers_luck(obj)
312 struct obj *obj;
313 {
314     /* might as well check for this too */
315     if (obj->otyp == LUCKSTONE)
316         return TRUE;
317
318     return (boolean) (obj->oartifact && spec_ability(obj, SPFX_LUCK));
319 }
320
321 /* used to check whether a monster is getting reflection from an artifact */
322 boolean
323 arti_reflects(obj)
324 struct obj *obj;
325 {
326     const struct artifact *arti = get_artifact(obj);
327
328     if (arti) {
329         /* while being worn */
330         if ((obj->owornmask & ~W_ART) && (arti->spfx & SPFX_REFLECT))
331             return TRUE;
332         /* just being carried */
333         if (arti->cspfx & SPFX_REFLECT)
334             return TRUE;
335     }
336     return FALSE;
337 }
338
339 /* decide whether this obj is effective when attacking against shades;
340    does not consider the bonus for blessed objects versus undead */
341 boolean
342 shade_glare(obj)
343 struct obj *obj;
344 {
345     const struct artifact *arti;
346
347     /* any silver object is effective */
348     if (objects[obj->otyp].oc_material == SILVER)
349         return TRUE;
350     /* non-silver artifacts with bonus against undead also are effective */
351     arti = get_artifact(obj);
352     if (arti && (arti->spfx & SPFX_DFLAG2) && arti->mtype == M2_UNDEAD)
353         return TRUE;
354     /* [if there was anything with special bonus against noncorporeals,
355        it would be effective too] */
356     /* otherwise, harmless to shades */
357     return FALSE;
358 }
359
360 /* returns 1 if name is restricted for otmp->otyp */
361 boolean
362 restrict_name(otmp, name)
363 struct obj *otmp;
364 const char *name;
365 {
366     register const struct artifact *a;
367     const char *aname, *odesc, *other;
368     boolean sametype[NUM_OBJECTS];
369     int i, lo, hi, otyp = otmp->otyp, ocls = objects[otyp].oc_class;
370
371     if (!*name)
372         return FALSE;
373     if (!strncmpi(name, "the ", 4))
374         name += 4;
375
376     /* decide what types of objects are the same as otyp;
377        if it's been discovered, then only itself matches;
378        otherwise, include all other undiscovered objects
379        of the same class which have the same description
380        or share the same pool of shuffled descriptions */
381     (void) memset((genericptr_t) sametype, 0, sizeof sametype); /* FALSE */
382     sametype[otyp] = TRUE;
383     if (!objects[otyp].oc_name_known
384         && (odesc = OBJ_DESCR(objects[otyp])) != 0) {
385         obj_shuffle_range(otyp, &lo, &hi);
386         for (i = bases[ocls]; i < NUM_OBJECTS; i++) {
387             if (objects[i].oc_class != ocls)
388                 break;
389             if (!objects[i].oc_name_known
390                 && (other = OBJ_DESCR(objects[i])) != 0
391                 && (!strcmp(odesc, other) || (i >= lo && i <= hi)))
392                 sametype[i] = TRUE;
393         }
394     }
395
396     /* Since almost every artifact is SPFX_RESTR, it doesn't cost
397        us much to do the string comparison before the spfx check.
398        Bug fix:  don't name multiple elven daggers "Sting".
399      */
400     for (a = artilist + 1; a->otyp; a++) {
401         if (!sametype[a->otyp])
402             continue;
403         aname = a->name;
404         if (!strncmpi(aname, "the ", 4))
405             aname += 4;
406         if (!strcmp(aname, name))
407             return (boolean) ((a->spfx & (SPFX_NOGEN | SPFX_RESTR)) != 0
408                               || otmp->quan > 1L);
409     }
410
411     return FALSE;
412 }
413
414 STATIC_OVL boolean
415 attacks(adtyp, otmp)
416 int adtyp;
417 struct obj *otmp;
418 {
419     register const struct artifact *weap;
420
421     if ((weap = get_artifact(otmp)) != 0)
422         return (boolean) (weap->attk.adtyp == adtyp);
423     return FALSE;
424 }
425
426 boolean
427 defends(adtyp, otmp)
428 int adtyp;
429 struct obj *otmp;
430 {
431     register const struct artifact *weap;
432
433     if ((weap = get_artifact(otmp)) != 0)
434         return (boolean) (weap->defn.adtyp == adtyp);
435     return FALSE;
436 }
437
438 /* used for monsters */
439 boolean
440 defends_when_carried(adtyp, otmp)
441 int adtyp;
442 struct obj *otmp;
443 {
444     register const struct artifact *weap;
445
446     if ((weap = get_artifact(otmp)) != 0)
447         return (boolean) (weap->cary.adtyp == adtyp);
448     return FALSE;
449 }
450
451 /* determine whether an item confers Protection */
452 boolean
453 protects(otmp, being_worn)
454 struct obj *otmp;
455 boolean being_worn;
456 {
457     const struct artifact *arti;
458
459     if (being_worn && objects[otmp->otyp].oc_oprop == PROTECTION)
460         return TRUE;
461     arti = get_artifact(otmp);
462     if (!arti)
463         return FALSE;
464     return (boolean) ((arti->cspfx & SPFX_PROTECT) != 0
465                       || (being_worn && (arti->spfx & SPFX_PROTECT) != 0));
466 }
467
468 /*
469  * a potential artifact has just been worn/wielded/picked-up or
470  * unworn/unwielded/dropped.  Pickup/drop only set/reset the W_ART mask.
471  */
472 void
473 set_artifact_intrinsic(otmp, on, wp_mask)
474 struct obj *otmp;
475 boolean on;
476 long wp_mask;
477 {
478     long *mask = 0;
479     register const struct artifact *art, *oart = get_artifact(otmp);
480     register struct obj *obj;
481     register uchar dtyp;
482     register long spfx;
483
484     if (!oart)
485         return;
486
487     /* effects from the defn field */
488     dtyp = (wp_mask != W_ART) ? oart->defn.adtyp : oart->cary.adtyp;
489
490     if (dtyp == AD_FIRE)
491         mask = &EFire_resistance;
492     else if (dtyp == AD_COLD)
493         mask = &ECold_resistance;
494     else if (dtyp == AD_ELEC)
495         mask = &EShock_resistance;
496     else if (dtyp == AD_MAGM)
497         mask = &EAntimagic;
498     else if (dtyp == AD_DISN)
499         mask = &EDisint_resistance;
500     else if (dtyp == AD_DRST)
501         mask = &EPoison_resistance;
502     else if (dtyp == AD_DRLI)
503         mask = &EDrain_resistance;
504
505     if (mask && wp_mask == W_ART && !on) {
506         /* find out if some other artifact also confers this intrinsic;
507            if so, leave the mask alone */
508         for (obj = invent; obj; obj = obj->nobj) {
509             if (obj != otmp && obj->oartifact) {
510                 art = get_artifact(obj);
511                 if (art && art->cary.adtyp == dtyp) {
512                     mask = (long *) 0;
513                     break;
514                 }
515             }
516         }
517     }
518     if (mask) {
519         if (on)
520             *mask |= wp_mask;
521         else
522             *mask &= ~wp_mask;
523     }
524
525     /* intrinsics from the spfx field; there could be more than one */
526     spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
527     if (spfx && wp_mask == W_ART && !on) {
528         /* don't change any spfx also conferred by other artifacts */
529         for (obj = invent; obj; obj = obj->nobj)
530             if (obj != otmp && obj->oartifact) {
531                 art = get_artifact(obj);
532                 if (art)
533                     spfx &= ~art->cspfx;
534             }
535     }
536
537     if (spfx & SPFX_SEARCH) {
538         if (on)
539             ESearching |= wp_mask;
540         else
541             ESearching &= ~wp_mask;
542     }
543     if (spfx & SPFX_HALRES) {
544         /* make_hallucinated must (re)set the mask itself to get
545          * the display right */
546         /* restoring needed because this is the only artifact intrinsic
547          * that can print a message--need to guard against being printed
548          * when restoring a game
549          */
550         (void) make_hallucinated((long) !on, restoring ? FALSE : TRUE,
551                                  wp_mask);
552     }
553     if (spfx & SPFX_ESP) {
554         if (on)
555             ETelepat |= wp_mask;
556         else
557             ETelepat &= ~wp_mask;
558         see_monsters();
559     }
560     if (spfx & SPFX_STLTH) {
561         if (on)
562             EStealth |= wp_mask;
563         else
564             EStealth &= ~wp_mask;
565     }
566     if (spfx & SPFX_REGEN) {
567         if (on)
568             ERegeneration |= wp_mask;
569         else
570             ERegeneration &= ~wp_mask;
571     }
572     if (spfx & SPFX_TCTRL) {
573         if (on)
574             ETeleport_control |= wp_mask;
575         else
576             ETeleport_control &= ~wp_mask;
577     }
578     if (spfx & SPFX_WARN) {
579         if (spec_m2(otmp)) {
580             if (on) {
581                 EWarn_of_mon |= wp_mask;
582                 context.warntype.obj |= spec_m2(otmp);
583             } else {
584                 EWarn_of_mon &= ~wp_mask;
585                 context.warntype.obj &= ~spec_m2(otmp);
586             }
587             see_monsters();
588         } else {
589             if (on)
590                 EWarning |= wp_mask;
591             else
592                 EWarning &= ~wp_mask;
593         }
594     }
595     if (spfx & SPFX_EREGEN) {
596         if (on)
597             EEnergy_regeneration |= wp_mask;
598         else
599             EEnergy_regeneration &= ~wp_mask;
600     }
601     if (spfx & SPFX_HSPDAM) {
602         if (on)
603             EHalf_spell_damage |= wp_mask;
604         else
605             EHalf_spell_damage &= ~wp_mask;
606     }
607     if (spfx & SPFX_HPHDAM) {
608         if (on)
609             EHalf_physical_damage |= wp_mask;
610         else
611             EHalf_physical_damage &= ~wp_mask;
612     }
613     if (spfx & SPFX_XRAY) {
614         /* this assumes that no one else is using xray_range */
615         if (on)
616             u.xray_range = 3;
617         else
618             u.xray_range = -1;
619         vision_full_recalc = 1;
620     }
621     if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
622         if (on)
623             EReflecting |= wp_mask;
624         else
625             EReflecting &= ~wp_mask;
626     }
627     if (spfx & SPFX_PROTECT) {
628         if (on)
629             EProtection |= wp_mask;
630         else
631             EProtection &= ~wp_mask;
632     }
633
634     if (wp_mask == W_ART && !on && oart->inv_prop) {
635         /* might have to turn off invoked power too */
636         if (oart->inv_prop <= LAST_PROP
637             && (u.uprops[oart->inv_prop].extrinsic & W_ARTI))
638             (void) arti_invoke(otmp);
639     }
640 }
641
642 /* touch_artifact()'s return value isn't sufficient to tell whether it
643    dished out damage, and tracking changes to u.uhp, u.mh, Lifesaved
644    when trying to avoid second wounding is too cumbersome */
645 STATIC_VAR boolean touch_blasted; /* for retouch_object() */
646
647 /*
648  * creature (usually hero) tries to touch (pick up or wield) an artifact obj.
649  * Returns 0 if the object refuses to be touched.
650  * This routine does not change any object chains.
651  * Ignores such things as gauntlets, assuming the artifact is not
652  * fooled by such trappings.
653  */
654 int
655 touch_artifact(obj, mon)
656 struct obj *obj;
657 struct monst *mon;
658 {
659     register const struct artifact *oart = get_artifact(obj);
660     boolean badclass, badalign, self_willed, yours;
661
662     touch_blasted = FALSE;
663     if (!oart)
664         return 1;
665
666     yours = (mon == &youmonst);
667     /* all quest artifacts are self-willed; if this ever changes, `badclass'
668        will have to be extended to explicitly include quest artifacts */
669     self_willed = ((oart->spfx & SPFX_INTEL) != 0);
670     if (yours) {
671         badclass = self_willed
672                    && ((oart->role != NON_PM && !Role_if(oart->role))
673                        || (oart->race != NON_PM && !Race_if(oart->race)));
674         badalign = ((oart->spfx & SPFX_RESTR) != 0
675                     && oart->alignment != A_NONE
676                     && (oart->alignment != u.ualign.type
677                         || u.ualign.record < 0));
678     } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) {
679         badclass = self_willed && oart->role != NON_PM
680                    && oart != &artilist[ART_EXCALIBUR];
681         badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
682                    && (oart->alignment != mon_aligntyp(mon));
683     } else { /* an M3_WANTSxxx monster or a fake player */
684         /* special monsters trying to take the Amulet, invocation tools or
685            quest item can touch anything except `spec_applies' artifacts */
686         badclass = badalign = FALSE;
687     }
688     /* weapons which attack specific categories of monsters are
689        bad for them even if their alignments happen to match */
690     if (!badalign)
691         badalign = bane_applies(oart, mon);
692
693     if (((badclass || badalign) && self_willed)
694         || (badalign && (!yours || !rn2(4)))) {
695         int dmg, tmp;
696         char buf[BUFSZ];
697
698         if (!yours)
699             return 0;
700 /*JP
701         You("are blasted by %s power!", s_suffix(the(xname(obj))));
702 */
703         You("%s\82Ì\97Í\82ð\97\81\82Ñ\82½\81I", xname(obj));
704         touch_blasted = TRUE;
705         dmg = d((Antimagic ? 2 : 4), (self_willed ? 10 : 4));
706         /* add half (maybe quarter) of the usual silver damage bonus */
707         if (objects[obj->otyp].oc_material == SILVER && Hate_silver)
708             tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
709 /*JP
710         Sprintf(buf, "touching %s", oart->name);
711 */
712         Sprintf(buf, "%s\82É\90G\82ê\82Ä", oart->name);
713         losehp(dmg, buf, KILLED_BY); /* magic damage, not physical */
714         exercise(A_WIS, FALSE);
715     }
716
717     /* can pick it up unless you're totally non-synch'd with the artifact */
718     if (badclass && badalign && self_willed) {
719         if (yours) {
720             if (!carried(obj))
721 /*JP
722                 pline("%s your grasp!", Tobjnam(obj, "evade"));
723 */
724                 pline("%s\82Í\88¬\82ë\82¤\82Æ\82·\82é\82Æ\82·\82é\82è\82Æ\94²\82¯\82½\81I", xname(obj));
725             else
726 /*JP
727                 pline("%s beyond your control!", Tobjnam(obj, "are"));
728 */
729                 pline("%s\82Í\90§\8cä\82Å\82«\82È\82¢\81I", xname(obj));
730         }
731         return 0;
732     }
733
734     return 1;
735 }
736
737 /* decide whether an artifact itself is vulnerable to a particular type
738    of erosion damage, independent of the properties of its bearer */
739 boolean
740 arti_immune(obj, dtyp)
741 struct obj *obj;
742 int dtyp;
743 {
744     register const struct artifact *weap = get_artifact(obj);
745
746     if (!weap)
747         return FALSE;
748     if (dtyp == AD_PHYS)
749         return FALSE; /* nothing is immune to phys dmg */
750     return (boolean) (weap->attk.adtyp == dtyp
751                       || weap->defn.adtyp == dtyp
752                       || weap->cary.adtyp == dtyp);
753 }
754
755 STATIC_OVL boolean
756 bane_applies(oart, mon)
757 const struct artifact *oart;
758 struct monst *mon;
759 {
760     struct artifact atmp;
761
762     if (oart && (oart->spfx & SPFX_DBONUS) != 0) {
763         atmp = *oart;
764         atmp.spfx &= SPFX_DBONUS; /* clear other spfx fields */
765         if (spec_applies(&atmp, mon))
766             return TRUE;
767     }
768     return FALSE;
769 }
770
771 /* decide whether an artifact's special attacks apply against mtmp */
772 STATIC_OVL int
773 spec_applies(weap, mtmp)
774 register const struct artifact *weap;
775 struct monst *mtmp;
776 {
777     struct permonst *ptr;
778     boolean yours;
779
780     if (!(weap->spfx & (SPFX_DBONUS | SPFX_ATTK)))
781         return (weap->attk.adtyp == AD_PHYS);
782
783     yours = (mtmp == &youmonst);
784     ptr = mtmp->data;
785
786     if (weap->spfx & SPFX_DMONS) {
787         return (ptr == &mons[(int) weap->mtype]);
788     } else if (weap->spfx & SPFX_DCLAS) {
789         return (weap->mtype == (unsigned long) ptr->mlet);
790     } else if (weap->spfx & SPFX_DFLAG1) {
791         return ((ptr->mflags1 & weap->mtype) != 0L);
792     } else if (weap->spfx & SPFX_DFLAG2) {
793         return ((ptr->mflags2 & weap->mtype)
794                 || (yours
795                     && ((!Upolyd && (urace.selfmask & weap->mtype))
796                         || ((weap->mtype & M2_WERE) && u.ulycn >= LOW_PM))));
797     } else if (weap->spfx & SPFX_DALIGN) {
798         return yours ? (u.ualign.type != weap->alignment)
799                      : (ptr->maligntyp == A_NONE
800                         || sgn(ptr->maligntyp) != weap->alignment);
801     } else if (weap->spfx & SPFX_ATTK) {
802         struct obj *defending_weapon = (yours ? uwep : MON_WEP(mtmp));
803
804         if (defending_weapon && defending_weapon->oartifact
805             && defends((int) weap->attk.adtyp, defending_weapon))
806             return FALSE;
807         switch (weap->attk.adtyp) {
808         case AD_FIRE:
809             return !(yours ? Fire_resistance : resists_fire(mtmp));
810         case AD_COLD:
811             return !(yours ? Cold_resistance : resists_cold(mtmp));
812         case AD_ELEC:
813             return !(yours ? Shock_resistance : resists_elec(mtmp));
814         case AD_MAGM:
815         case AD_STUN:
816             return !(yours ? Antimagic : (rn2(100) < ptr->mr));
817         case AD_DRST:
818             return !(yours ? Poison_resistance : resists_poison(mtmp));
819         case AD_DRLI:
820             return !(yours ? Drain_resistance : resists_drli(mtmp));
821         case AD_STON:
822             return !(yours ? Stone_resistance : resists_ston(mtmp));
823         default:
824             impossible("Weird weapon special attack.");
825         }
826     }
827     return 0;
828 }
829
830 /* return the M2 flags of monster that an artifact's special attacks apply
831  * against */
832 long
833 spec_m2(otmp)
834 struct obj *otmp;
835 {
836     const struct artifact *artifact = get_artifact(otmp);
837
838     if (artifact)
839         return artifact->mtype;
840     return 0L;
841 }
842
843 /* special attack bonus */
844 int
845 spec_abon(otmp, mon)
846 struct obj *otmp;
847 struct monst *mon;
848 {
849     const struct artifact *weap = get_artifact(otmp);
850
851     /* no need for an extra check for `NO_ATTK' because this will
852        always return 0 for any artifact which has that attribute */
853
854     if (weap && weap->attk.damn && spec_applies(weap, mon))
855         return rnd((int) weap->attk.damn);
856     return 0;
857 }
858
859 /* special damage bonus */
860 int
861 spec_dbon(otmp, mon, tmp)
862 struct obj *otmp;
863 struct monst *mon;
864 int tmp;
865 {
866     register const struct artifact *weap = get_artifact(otmp);
867
868     if (!weap || (weap->attk.adtyp == AD_PHYS /* check for `NO_ATTK' */
869                   && weap->attk.damn == 0 && weap->attk.damd == 0))
870         spec_dbon_applies = FALSE;
871     else if (otmp->oartifact == ART_GRIMTOOTH)
872         /* Grimtooth has SPFX settings to warn against elves but we want its
873            damage bonus to apply to all targets, so bypass spec_applies() */
874         spec_dbon_applies = TRUE;
875     else
876         spec_dbon_applies = spec_applies(weap, mon);
877
878     if (spec_dbon_applies)
879         return weap->attk.damd ? rnd((int) weap->attk.damd) : max(tmp, 1);
880     return 0;
881 }
882
883 /* add identified artifact to discoveries list */
884 void
885 discover_artifact(m)
886 xchar m;
887 {
888     int i;
889
890     /* look for this artifact in the discoveries list;
891        if we hit an empty slot then it's not present, so add it */
892     for (i = 0; i < NROFARTIFACTS; i++)
893         if (artidisco[i] == 0 || artidisco[i] == m) {
894             artidisco[i] = m;
895             return;
896         }
897     /* there is one slot per artifact, so we should never reach the
898        end without either finding the artifact or an empty slot... */
899     impossible("couldn't discover artifact (%d)", (int) m);
900 }
901
902 /* used to decide whether an artifact has been fully identified */
903 boolean
904 undiscovered_artifact(m)
905 xchar m;
906 {
907     int i;
908
909     /* look for this artifact in the discoveries list;
910        if we hit an empty slot then it's undiscovered */
911     for (i = 0; i < NROFARTIFACTS; i++)
912         if (artidisco[i] == m)
913             return FALSE;
914         else if (artidisco[i] == 0)
915             break;
916     return TRUE;
917 }
918
919 /* display a list of discovered artifacts; return their count */
920 int
921 disp_artifact_discoveries(tmpwin)
922 winid tmpwin; /* supplied by dodiscover() */
923 {
924     int i, m, otyp;
925     char buf[BUFSZ];
926
927     for (i = 0; i < NROFARTIFACTS; i++) {
928         if (artidisco[i] == 0)
929             break; /* empty slot implies end of list */
930         if (tmpwin == WIN_ERR)
931             continue; /* for WIN_ERR, we just count */
932
933         if (i == 0)
934 /*JP
935             putstr(tmpwin, iflags.menu_headings, "Artifacts");
936 */
937             putstr(tmpwin, iflags.menu_headings, "\90¹\8aí");
938         m = artidisco[i];
939         otyp = artilist[m].otyp;
940         Sprintf(buf, "  %s [%s %s]", artiname(m),
941                 align_str(artilist[m].alignment), simple_typename(otyp));
942         putstr(tmpwin, 0, buf);
943     }
944     return i;
945 }
946
947 /*
948  * Magicbane's intrinsic magic is incompatible with normal
949  * enchantment magic.  Thus, its effects have a negative
950  * dependence on spe.  Against low mr victims, it typically
951  * does "double athame" damage, 2d4.  Occasionally, it will
952  * cast unbalancing magic which effectively averages out to
953  * 4d4 damage (3d4 against high mr victims), for spe = 0.
954  *
955  * Prior to 3.4.1, the cancel (aka purge) effect always
956  * included the scare effect too; now it's one or the other.
957  * Likewise, the stun effect won't be combined with either
958  * of those two; it will be chosen separately or possibly
959  * used as a fallback when scare or cancel fails.
960  *
961  * [Historical note: a change to artifact_hit() for 3.4.0
962  * unintentionally made all of Magicbane's special effects
963  * be blocked if the defender successfully saved against a
964  * stun attack.  As of 3.4.1, those effects can occur but
965  * will be slightly less likely than they were in 3.3.x.]
966  */
967
968 enum mb_effect_indices {
969     MB_INDEX_PROBE = 0,
970     MB_INDEX_STUN,
971     MB_INDEX_SCARE,
972     MB_INDEX_CANCEL,
973
974     NUM_MB_INDICES
975 };
976
977 #define MB_MAX_DIEROLL 8 /* rolls above this aren't magical */
978 static const char *const mb_verb[2][NUM_MB_INDICES] = {
979 #if 0 /*JP*/
980     { "probe", "stun", "scare", "cancel" },
981     { "prod", "amaze", "tickle", "purge" },
982 #else
983     /* Mb_hit() \82Å "%s\82½"\82Ì\8c`\82Å\97\98\97p */
984     {"\92²\8d¸\82µ", "\82­\82ç\82­\82ç\82³\82¹", "\8b¯\82¦\82³\82¹", "\8fò\89»\82µ"},
985     { "\97ã\82Ü\82µ", "\8bÁ\82©\82¹", "\82­\82·\82®\82Á", "\90´\82ß" },
986 #endif
987 };
988
989 /* called when someone is being hit by Magicbane */
990 STATIC_OVL boolean
991 Mb_hit(magr, mdef, mb, dmgptr, dieroll, vis, hittee)
992 struct monst *magr, *mdef; /* attacker and defender */
993 struct obj *mb;            /* Magicbane */
994 int *dmgptr;               /* extra damage target will suffer */
995 int dieroll;               /* d20 that has already scored a hit */
996 boolean vis;               /* whether the action can be seen */
997 char *hittee;              /* target's name: "you" or mon_nam(mdef) */
998 {
999     struct permonst *old_uasmon;
1000 #if 0 /*JP*//* not used */
1001     const char *verb, *fakename;
1002 #else
1003     const char *verb;
1004 #endif
1005     boolean youattack = (magr == &youmonst), youdefend = (mdef == &youmonst),
1006             resisted = FALSE, do_stun, do_confuse, result;
1007     int attack_indx, scare_dieroll = MB_MAX_DIEROLL / 2;
1008
1009     result = FALSE; /* no message given yet */
1010     /* the most severe effects are less likely at higher enchantment */
1011     if (mb->spe >= 3)
1012         scare_dieroll /= (1 << (mb->spe / 3));
1013     /* if target successfully resisted the artifact damage bonus,
1014        reduce overall likelihood of the assorted special effects */
1015     if (!spec_dbon_applies)
1016         dieroll += 1;
1017
1018     /* might stun even when attempting a more severe effect, but
1019        in that case it will only happen if the other effect fails;
1020        extra damage will apply regardless; 3.4.1: sometimes might
1021        just probe even when it hasn't been enchanted */
1022     do_stun = (max(mb->spe, 0) < rn2(spec_dbon_applies ? 11 : 7));
1023
1024     /* the special effects also boost physical damage; increments are
1025        generally cumulative, but since the stun effect is based on a
1026        different criterium its damage might not be included; the base
1027        damage is either 1d4 (athame) or 2d4 (athame+spec_dbon) depending
1028        on target's resistance check against AD_STUN (handled by caller)
1029        [note that a successful save against AD_STUN doesn't actually
1030        prevent the target from ending up stunned] */
1031     attack_indx = MB_INDEX_PROBE;
1032     *dmgptr += rnd(4); /* (2..3)d4 */
1033     if (do_stun) {
1034         attack_indx = MB_INDEX_STUN;
1035         *dmgptr += rnd(4); /* (3..4)d4 */
1036     }
1037     if (dieroll <= scare_dieroll) {
1038         attack_indx = MB_INDEX_SCARE;
1039         *dmgptr += rnd(4); /* (3..5)d4 */
1040     }
1041     if (dieroll <= (scare_dieroll / 2)) {
1042         attack_indx = MB_INDEX_CANCEL;
1043         *dmgptr += rnd(4); /* (4..6)d4 */
1044     }
1045
1046     /* give the hit message prior to inflicting the effects */
1047     verb = mb_verb[!!Hallucination][attack_indx];
1048     if (youattack || youdefend || vis) {
1049         result = TRUE;
1050 #if 0 /*JP*/
1051         pline_The("magic-absorbing blade %s %s!",
1052                   vtense((const char *) 0, verb), hittee);
1053 #else
1054         pline("\96\82\97Í\82ð\8bz\82¢\82Æ\82é\90n\82ª%s\82ð%s\82½\81I",
1055                   hittee, verb);
1056 #endif
1057         /* assume probing has some sort of noticeable feedback
1058            even if it is being done by one monster to another */
1059         if (attack_indx == MB_INDEX_PROBE && !canspotmon(mdef))
1060             map_invisible(mdef->mx, mdef->my);
1061     }
1062
1063     /* now perform special effects */
1064     switch (attack_indx) {
1065     case MB_INDEX_CANCEL:
1066         old_uasmon = youmonst.data;
1067         /* No mdef->mcan check: even a cancelled monster can be polymorphed
1068          * into a golem, and the "cancel" effect acts as if some magical
1069          * energy remains in spellcasting defenders to be absorbed later.
1070          */
1071         if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
1072             resisted = TRUE;
1073         } else {
1074             do_stun = FALSE;
1075             if (youdefend) {
1076                 if (youmonst.data != old_uasmon)
1077                     *dmgptr = 0; /* rehumanized, so no more damage */
1078                 if (u.uenmax > 0) {
1079 /*JP
1080                     You("lose magical energy!");
1081 */
1082                     You("\96\82\96@\82Ì\83G\83l\83\8b\83M\81[\82ð\8e¸\82Á\82½\81I");
1083                     u.uenmax--;
1084                     if (u.uen > 0)
1085                         u.uen--;
1086                     context.botl = 1;
1087                 }
1088             } else {
1089                 if (mdef->data == &mons[PM_CLAY_GOLEM])
1090                     mdef->mhp = 1; /* cancelled clay golems will die */
1091                 if (youattack && attacktype(mdef->data, AT_MAGC)) {
1092 /*JP
1093                     You("absorb magical energy!");
1094 */
1095                     You("\96\82\96@\82Ì\83G\83l\83\8b\83M\81[\82ð\8bz\82¢\82Æ\82Á\82½\81I");
1096                     u.uenmax++;
1097                     u.uen++;
1098                     context.botl = 1;
1099                 }
1100             }
1101         }
1102         break;
1103
1104     case MB_INDEX_SCARE:
1105         if (youdefend) {
1106             if (Antimagic) {
1107                 resisted = TRUE;
1108             } else {
1109                 nomul(-3);
1110 /*JP
1111                 multi_reason = "being scared stiff";
1112 */
1113                 multi_reason = "\8b°\95|\82Å\98T\94\82\82µ\82½\8c\84\82É";
1114                 nomovemsg = "";
1115                 if (magr && magr == u.ustuck && sticks(youmonst.data)) {
1116                     u.ustuck = (struct monst *) 0;
1117 /*JP
1118                     You("release %s!", mon_nam(magr));
1119 */
1120                     You("%s\82ð\89ð\95ú\82µ\82½\81I", mon_nam(magr));
1121                 }
1122             }
1123         } else {
1124             if (rn2(2) && resist(mdef, WEAPON_CLASS, 0, NOTELL))
1125                 resisted = TRUE;
1126             else
1127                 monflee(mdef, 3, FALSE, (mdef->mhp > *dmgptr));
1128         }
1129         if (!resisted)
1130             do_stun = FALSE;
1131         break;
1132
1133     case MB_INDEX_STUN:
1134         do_stun = TRUE; /* (this is redundant...) */
1135         break;
1136
1137     case MB_INDEX_PROBE:
1138         if (youattack && (mb->spe == 0 || !rn2(3 * abs(mb->spe)))) {
1139 /*JP
1140             pline_The("%s is insightful.", verb);
1141 */
1142             pline("\91\8a\8eè\82ð%s\82½\81D", verb);
1143             /* pre-damage status */
1144             probe_monster(mdef);
1145         }
1146         break;
1147     }
1148     /* stun if that was selected and a worse effect didn't occur */
1149     if (do_stun) {
1150         if (youdefend)
1151             make_stunned(((HStun & TIMEOUT) + 3L), FALSE);
1152         else
1153             mdef->mstun = 1;
1154         /* avoid extra stun message below if we used mb_verb["stun"] above */
1155         if (attack_indx == MB_INDEX_STUN)
1156             do_stun = FALSE;
1157     }
1158     /* lastly, all this magic can be confusing... */
1159     do_confuse = !rn2(12);
1160     if (do_confuse) {
1161         if (youdefend)
1162             make_confused((HConfusion & TIMEOUT) + 4L, FALSE);
1163         else
1164             mdef->mconf = 1;
1165     }
1166
1167 #if 0 /*JP*//* not used */
1168     /* now give message(s) describing side-effects;
1169        don't let vtense() be fooled by assigned name ending in 's' */
1170     fakename = youdefend ? "you" : "mon";
1171 #endif
1172     if (youattack || youdefend || vis) {
1173         (void) upstart(hittee); /* capitalize */
1174         if (resisted) {
1175 /*JP
1176             pline("%s %s!", hittee, vtense(fakename, "resist"));
1177 */
1178             pline("%s\82Í\96h\82¢\82¾\81I", hittee);
1179             shieldeff(youdefend ? u.ux : mdef->mx,
1180                       youdefend ? u.uy : mdef->my);
1181         }
1182         if ((do_stun || do_confuse) && flags.verbose) {
1183             char buf[BUFSZ];
1184
1185             buf[0] = '\0';
1186 #if 0 /*JP:T*/
1187             if (do_stun)
1188                 Strcat(buf, "stunned");
1189             if (do_stun && do_confuse)
1190                 Strcat(buf, " and ");
1191             if (do_confuse)
1192                 Strcat(buf, "confused");
1193             pline("%s %s %s%c", hittee, vtense(fakename, "are"), buf,
1194                   (do_stun && do_confuse) ? '!' : '.');
1195 #else
1196             if (do_stun && do_confuse)
1197                 Strcat(buf, "\82æ\82ë\82ß\82¢\82Ä");
1198             else if (do_stun)
1199                 Strcat(buf, "\82æ\82ë\82ß\82¢\82½");
1200             if (do_confuse)
1201                 Strcat(buf, "\8d¬\97\90\82µ\82½");
1202             pline("%s\82Í%s%s", hittee,
1203                   buf, (do_stun && do_confuse) ? "\81I" : "\81D");
1204 #endif
1205         }
1206     }
1207
1208     return result;
1209 }
1210
1211 /* Function used when someone attacks someone else with an artifact
1212  * weapon.  Only adds the special (artifact) damage, and returns a 1 if it
1213  * did something special (in which case the caller won't print the normal
1214  * hit message).  This should be called once upon every artifact attack;
1215  * dmgval() no longer takes artifact bonuses into account.  Possible
1216  * extension: change the killer so that when an orc kills you with
1217  * Stormbringer it's "killed by Stormbringer" instead of "killed by an orc".
1218  */
1219 boolean
1220 artifact_hit(magr, mdef, otmp, dmgptr, dieroll)
1221 struct monst *magr, *mdef;
1222 struct obj *otmp;
1223 int *dmgptr;
1224 int dieroll; /* needed for Magicbane and vorpal blades */
1225 {
1226     boolean youattack = (magr == &youmonst);
1227     boolean youdefend = (mdef == &youmonst);
1228     boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
1229                   || (!youdefend && cansee(mdef->mx, mdef->my))
1230                   || (youattack && u.uswallow && mdef == u.ustuck && !Blind);
1231     boolean realizes_damage;
1232     const char *wepdesc;
1233 /*JP
1234     static const char you[] = "you";
1235 */
1236     static const char you[] = "\82 \82È\82½";
1237     char hittee[BUFSZ];
1238
1239     Strcpy(hittee, youdefend ? you : mon_nam(mdef));
1240
1241     /* The following takes care of most of the damage, but not all--
1242      * the exception being for level draining, which is specially
1243      * handled.  Messages are done in this function, however.
1244      */
1245     *dmgptr += spec_dbon(otmp, mdef, *dmgptr);
1246
1247     if (youattack && youdefend) {
1248         impossible("attacking yourself with weapon?");
1249         return FALSE;
1250     }
1251
1252     realizes_damage = (youdefend || vis
1253                        /* feel the effect even if not seen */
1254                        || (youattack && mdef == u.ustuck));
1255
1256     /* the four basic attacks: fire, cold, shock and missiles */
1257     if (attacks(AD_FIRE, otmp)) {
1258         if (realizes_damage)
1259 #if 0 /*JP*/
1260             pline_The("fiery blade %s %s%c",
1261                       !spec_dbon_applies
1262                           ? "hits"
1263                           : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1264                                 ? "vaporizes part of"
1265                                 : "burns",
1266                       hittee, !spec_dbon_applies ? '.' : '!');
1267 #else
1268             pline_The("\96Ò\89Î\82ª%s%s",
1269                       hittee,
1270                       !spec_dbon_applies
1271                           ? "\82É\96½\92\86\82µ\82½\81D"
1272                           : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1273                                 ? "\82Ì\88ê\95\94\82ð\8fÁ\96Å\82³\82¹\82½\81I"
1274                                 : "\82ð\8fÄ\82¢\82½\81I");
1275 #endif
1276         if (!rn2(4))
1277             (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1278         if (!rn2(4))
1279             (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1280         if (!rn2(7))
1281             (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1282         if (youdefend && Slimed)
1283             burn_away_slime();
1284         return realizes_damage;
1285     }
1286     if (attacks(AD_COLD, otmp)) {
1287         if (realizes_damage)
1288 #if 0 /*JP*/
1289             pline_The("ice-cold blade %s %s%c",
1290                       !spec_dbon_applies ? "hits" : "freezes", hittee,
1291                       !spec_dbon_applies ? '.' : '!');
1292 #else
1293             pline_The("\96Ò\90\81\90á\82ª%s%s",
1294                       hittee,
1295                       !spec_dbon_applies ? "\82É\96½\92\86\82µ\82½\81D" : "\82ð\8fP\82Á\82½\81I");
1296 #endif
1297         if (!rn2(4))
1298             (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1299         return realizes_damage;
1300     }
1301     if (attacks(AD_ELEC, otmp)) {
1302         if (realizes_damage)
1303 #if 0 /*JP*/
1304             pline_The("massive hammer hits%s %s%c",
1305                       !spec_dbon_applies ? "" : "!  Lightning strikes",
1306                       hittee, !spec_dbon_applies ? '.' : '!');
1307 #else
1308             pline("\8b\90\91å\82È\83n\83\93\83}\81[\82Í%s\82É\96½\92\86\82µ\82½%s", hittee,
1309                       !spec_dbon_applies ? "\81D" : "\81I\93d\8c\82\82ª\8fP\82Á\82½\81I");
1310 #endif
1311         if (!rn2(5))
1312             (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1313         if (!rn2(5))
1314             (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1315         return realizes_damage;
1316     }
1317     if (attacks(AD_MAGM, otmp)) {
1318         if (realizes_damage)
1319 #if 0 /*JP*/
1320             pline_The("imaginary widget hits%s %s%c",
1321                       !spec_dbon_applies
1322                           ? ""
1323                           : "!  A hail of magic missiles strikes",
1324                       hittee, !spec_dbon_applies ? '.' : '!');
1325 #else
1326             pline("\8eÀ\91Ì\82ð\8e\9d\82½\82È\82¢\95¨\91Ì\82ª%s\82ð\8dU\8c\82\82µ\82½%s",
1327                       hittee,
1328                       !spec_dbon_applies ? "\81D" :
1329                       "\81I\96\82\96@\82Ì\96î\82ª\89J\82 \82ç\82ê\82Æ\96½\92\86\82µ\82½\81I");
1330 #endif
1331         return realizes_damage;
1332     }
1333
1334     if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
1335         /* Magicbane's special attacks (possibly modifies hittee[]) */
1336         return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
1337     }
1338
1339     if (!spec_dbon_applies) {
1340         /* since damage bonus didn't apply, nothing more to do;
1341            no further attacks have side-effects on inventory */
1342         return FALSE;
1343     }
1344
1345     /* We really want "on a natural 20" but Nethack does it in */
1346     /* reverse from AD&D. */
1347     if (spec_ability(otmp, SPFX_BEHEAD)) {
1348         if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) {
1349 /*JP
1350             wepdesc = "The razor-sharp blade";
1351 */
1352             wepdesc = "\8ea\93S\8c\95";
1353             /* not really beheading, but so close, why add another SPFX */
1354             if (youattack && u.uswallow && mdef == u.ustuck) {
1355 /*JP
1356                 You("slice %s wide open!", mon_nam(mdef));
1357 */
1358                 You("%s\82ð\97Ö\90Ø\82è\82É\82µ\82½\81I", mon_nam(mdef));
1359                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1360                 return TRUE;
1361             }
1362             if (!youdefend) {
1363                 /* allow normal cutworm() call to add extra damage */
1364                 if (notonhead)
1365                     return FALSE;
1366
1367                 if (bigmonst(mdef->data)) {
1368                     if (youattack)
1369 /*JP
1370                         You("slice deeply into %s!", mon_nam(mdef));
1371 */
1372                         You("%s\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I",mon_nam(mdef));
1373                     else if (vis)
1374 #if 0 /*JP*/
1375                         pline("%s cuts deeply into %s!", Monnam(magr),
1376                               hittee);
1377 #else
1378                         pline("%s\82Í%s\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I", Monnam(magr),
1379                               hittee);
1380 #endif
1381                     *dmgptr *= 2;
1382                     return TRUE;
1383                 }
1384                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1385 /*JP
1386                 pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
1387 */
1388                 pline("%s\82ª%s\82ð\90^\82Á\93ñ\82Â\82É\82µ\82½\81I", wepdesc, mon_nam(mdef));
1389                 otmp->dknown = TRUE;
1390                 return TRUE;
1391             } else {
1392                 if (bigmonst(youmonst.data)) {
1393 /*JP
1394                     pline("%s cuts deeply into you!",
1395 */
1396                     pline("%s\82Í\82 \82È\82½\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I",
1397                           magr ? Monnam(magr) : wepdesc);
1398                     *dmgptr *= 2;
1399                     return TRUE;
1400                 }
1401
1402                 /* Players with negative AC's take less damage instead
1403                  * of just not getting hit.  We must add a large enough
1404                  * value to the damage so that this reduction in
1405                  * damage does not prevent death.
1406                  */
1407                 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1408 /*JP
1409                 pline("%s cuts you in half!", wepdesc);
1410 */
1411                 pline("%s\82ª\82 \82È\82½\82ð\90^\82Á\93ñ\82Â\82É\82µ\82½\81I", wepdesc);
1412                 otmp->dknown = TRUE;
1413                 return TRUE;
1414             }
1415         } else if (otmp->oartifact == ART_VORPAL_BLADE
1416                    && (dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) {
1417 #if 0 /*JP*/
1418             static const char *const behead_msg[2] = { "%s beheads %s!",
1419                                                        "%s decapitates %s!" };
1420 #else
1421             static const char *const behead_msg[2] = { "%s\82Í%s\82Ì\8eñ\82ð\90Ø\82Á\82½\81I",
1422                                                        "%s\82Í%s\82Ì\8eñ\82ð\90Ø\82è\97\8e\82µ\82½\81I" };
1423 #endif
1424
1425             if (youattack && u.uswallow && mdef == u.ustuck)
1426                 return FALSE;
1427             wepdesc = artilist[ART_VORPAL_BLADE].name;
1428             if (!youdefend) {
1429                 if (!has_head(mdef->data) || notonhead || u.uswallow) {
1430                     if (youattack)
1431 /*JP
1432                         pline("Somehow, you miss %s wildly.", mon_nam(mdef));
1433 */
1434                         pline("\82È\82º\82©\81C%s\82Ö\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D", mon_nam(mdef));
1435                     else if (vis)
1436 /*JP
1437                         pline("Somehow, %s misses wildly.", mon_nam(magr));
1438 */
1439                         pline("\82È\82º\82©\81C%s\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D", mon_nam(magr));
1440                     *dmgptr = 0;
1441                     return (boolean) (youattack || vis);
1442                 }
1443                 if (noncorporeal(mdef->data) || amorphous(mdef->data)) {
1444 #if 0 /*JP*/
1445                     pline("%s slices through %s %s.", wepdesc,
1446                           s_suffix(mon_nam(mdef)), mbodypart(mdef, NECK));
1447 #else
1448                     pline("%s\82Í%s\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
1449                           mon_nam(mdef), mbodypart(mdef, NECK));
1450 #endif
1451                     return TRUE;
1452                 }
1453                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1454                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc,
1455                       mon_nam(mdef));
1456                 if (Hallucination && !flags.female)
1457 /*JP
1458                     pline("Good job Henry, but that wasn't Anne.");
1459 */
1460                     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");
1461                 otmp->dknown = TRUE;
1462                 return TRUE;
1463             } else {
1464                 if (!has_head(youmonst.data)) {
1465 /*JP
1466                     pline("Somehow, %s misses you wildly.",
1467 */
1468                     pline("\82È\82º\82©\81C%s\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D",
1469                           magr ? mon_nam(magr) : wepdesc);
1470                     *dmgptr = 0;
1471                     return TRUE;
1472                 }
1473                 if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) {
1474 /*JP
1475                     pline("%s slices through your %s.", wepdesc,
1476 */
1477                     pline("%s\82Í\82 \82È\82½\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
1478                           body_part(NECK));
1479                     return TRUE;
1480                 }
1481                 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1482 /*JP
1483                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
1484 */
1485                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "\82 \82È\82½");
1486                 otmp->dknown = TRUE;
1487                 /* Should amulets fall off? */
1488                 return TRUE;
1489             }
1490         }
1491     }
1492     if (spec_ability(otmp, SPFX_DRLI)) {
1493         /* some non-living creatures (golems, vortices) are
1494            vulnerable to life drain effects */
1495 /*JP
1496         const char *life = nonliving(mdef->data) ? "animating force" : "life";
1497 */
1498         const char *life = nonliving(mdef->data) ? "\93®\8dì\97Í" : "\90\96½\97Í";
1499
1500         if (!youdefend) {
1501             if (vis) {
1502                 if (otmp->oartifact == ART_STORMBRINGER)
1503 #if 0 /*JP*/
1504                     pline_The("%s blade draws the %s from %s!",
1505                               hcolor(NH_BLACK), life, mon_nam(mdef));
1506 #else
1507                     pline("%s\90n\82ª%s\82Ì%s\82ð\92D\82Á\82½\81I",
1508                               hcolor(NH_BLACK), mon_nam(mdef), life);
1509 #endif
1510                 else
1511 #if 0 /*JP*/
1512                     pline("%s draws the %s from %s!",
1513                           The(distant_name(otmp, xname)), life,
1514                           mon_nam(mdef));
1515 #else
1516                     pline("%s\82Í%s\82Ì%s\82ð\92D\82Á\82½\81I",
1517                           The(distant_name(otmp, xname)),
1518                           mon_nam(mdef), life);
1519 #endif
1520             }
1521             if (mdef->m_lev == 0) {
1522                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1523             } else {
1524                 int drain = monhp_per_lvl(mdef);
1525
1526                 *dmgptr += drain;
1527                 mdef->mhpmax -= drain;
1528                 mdef->m_lev--;
1529                 drain /= 2;
1530                 if (drain)
1531                     healup(drain, 0, FALSE, FALSE);
1532             }
1533             return vis;
1534         } else { /* youdefend */
1535             int oldhpmax = u.uhpmax;
1536
1537             if (Blind)
1538 #if 0 /*JP*/
1539                 You_feel("an %s drain your %s!",
1540                          (otmp->oartifact == ART_STORMBRINGER)
1541                             ? "unholy blade"
1542                             : "object",
1543                          life);
1544 #else
1545                 pline("%s\82É%s\82ð\92D\82í\82ê\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I",
1546                          (otmp->oartifact == ART_STORMBRINGER)
1547                             ? "\95s\8fò\82È\90n"
1548                             : "\89½\82©",
1549                          life);
1550 #endif
1551             else if (otmp->oartifact == ART_STORMBRINGER)
1552 /*JP
1553                 pline_The("%s blade drains your %s!", hcolor(NH_BLACK), life);
1554 */
1555                 pline("%s\90n\82ª\82 \82È\82½\82Ì%s\82ð\92D\82Á\82½\81I", hcolor(NH_BLACK), life);
1556             else
1557 #if 0 /*JP*/
1558                 pline("%s drains your %s!", The(distant_name(otmp, xname)),
1559                       life);
1560 #else
1561                 pline("%s\82ª\82 \82È\82½\82Ì%s\82ð\92D\82Á\82½\81I", The(distant_name(otmp, xname)),
1562                       life);
1563 #endif
1564 /*JP
1565             losexp("life drainage");
1566 */
1567             losexp("\90\96½\97Í\82ð\8bz\8eû\82³\82ê\82Ä");
1568             if (magr && magr->mhp < magr->mhpmax) {
1569                 magr->mhp += (oldhpmax - u.uhpmax) / 2;
1570                 if (magr->mhp > magr->mhpmax)
1571                     magr->mhp = magr->mhpmax;
1572             }
1573             return TRUE;
1574         }
1575     }
1576     return FALSE;
1577 }
1578
1579 static NEARDATA const char recharge_type[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
1580 static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 };
1581 /* #invoke: an "ugly check" filters out most objects */
1582
1583 /* the #invoke command */
1584 int
1585 doinvoke()
1586 {
1587     struct obj *obj;
1588
1589     obj = getobj(invoke_types, "invoke");
1590     if (!obj)
1591         return 0;
1592     if (!retouch_object(&obj, FALSE))
1593         return 1;
1594     return arti_invoke(obj);
1595 }
1596
1597 STATIC_OVL int
1598 arti_invoke(obj)
1599 struct obj *obj;
1600 {
1601     register const struct artifact *oart = get_artifact(obj);
1602     if (!obj) {
1603         impossible("arti_invoke without obj");
1604         return 0;
1605     }
1606     if (!oart || !oart->inv_prop) {
1607         if (obj->otyp == CRYSTAL_BALL)
1608             use_crystal_ball(&obj);
1609         else
1610             pline1(nothing_happens);
1611         return 1;
1612     }
1613
1614     if (oart->inv_prop > LAST_PROP) {
1615         /* It's a special power, not "just" a property */
1616         if (obj->age > monstermoves) {
1617             /* the artifact is tired :-) */
1618 #if 0 /*JP:T*/
1619             You_feel("that %s %s ignoring you.", the(xname(obj)),
1620                      otense(obj, "are"));
1621 #else
1622             You_feel("%s\82ª\96³\8e\8b\82µ\82Ä\82¢\82é\82æ\82¤\82É\8a´\82\82½\81D", xname(obj));
1623 #endif
1624             /* and just got more so; patience is essential... */
1625             obj->age += (long) d(3, 10);
1626             return 1;
1627         }
1628         obj->age = monstermoves + rnz(100);
1629
1630         switch (oart->inv_prop) {
1631         case TAMING: {
1632             struct obj pseudo;
1633
1634             pseudo =
1635                 zeroobj; /* neither cursed nor blessed, zero oextra too */
1636             pseudo.otyp = SCR_TAMING;
1637             (void) seffects(&pseudo);
1638             break;
1639         }
1640         case HEALING: {
1641             int healamt = (u.uhpmax + 1 - u.uhp) / 2;
1642             long creamed = (long) u.ucreamed;
1643
1644             if (Upolyd)
1645                 healamt = (u.mhmax + 1 - u.mh) / 2;
1646             if (healamt || Sick || Slimed || Blinded > creamed)
1647 /*JP
1648                 You_feel("better.");
1649 */
1650                 You_feel("\8bC\95ª\82ª\82æ\82­\82È\82Á\82½\81D");
1651             else
1652                 goto nothing_special;
1653             if (healamt > 0) {
1654                 if (Upolyd)
1655                     u.mh += healamt;
1656                 else
1657                     u.uhp += healamt;
1658             }
1659             if (Sick)
1660                 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1661             if (Slimed)
1662                 make_slimed(0L, (char *) 0);
1663             if (Blinded > creamed)
1664                 make_blinded(creamed, FALSE);
1665             context.botl = 1;
1666             break;
1667         }
1668         case ENERGY_BOOST: {
1669             int epboost = (u.uenmax + 1 - u.uen) / 2;
1670             if (epboost > 120)
1671                 epboost = 120; /* arbitrary */
1672             else if (epboost < 12)
1673                 epboost = u.uenmax - u.uen;
1674             if (epboost) {
1675 /*JP
1676                 You_feel("re-energized.");
1677 */
1678                 You("\83G\83l\83\8b\83M\81[\82Å\96\9e\82½\82³\82ê\82½\81D");
1679                 u.uen += epboost;
1680                 context.botl = 1;
1681             } else
1682                 goto nothing_special;
1683             break;
1684         }
1685         case UNTRAP: {
1686             if (!untrap(TRUE)) {
1687                 obj->age = 0; /* don't charge for changing their mind */
1688                 return 0;
1689             }
1690             break;
1691         }
1692         case CHARGE_OBJ: {
1693             struct obj *otmp = getobj(recharge_type, "charge");
1694             boolean b_effect;
1695
1696             if (!otmp) {
1697                 obj->age = 0;
1698                 return 0;
1699             }
1700             b_effect = (obj->blessed && (oart->role == Role_switch
1701                                          || oart->role == NON_PM));
1702             recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
1703             update_inventory();
1704             break;
1705         }
1706         case LEV_TELE:
1707             level_tele();
1708             break;
1709         case CREATE_PORTAL: {
1710             int i, num_ok_dungeons, last_ok_dungeon = 0;
1711             d_level newlev;
1712             extern int n_dgns; /* from dungeon.c */
1713             winid tmpwin = create_nhwindow(NHW_MENU);
1714             anything any;
1715
1716             any = zeroany; /* set all bits to zero */
1717             start_menu(tmpwin);
1718             /* use index+1 (cant use 0) as identifier */
1719             for (i = num_ok_dungeons = 0; i < n_dgns; i++) {
1720                 if (!dungeons[i].dunlev_ureached)
1721                     continue;
1722                 any.a_int = i + 1;
1723                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1724                          dungeons[i].dname, MENU_UNSELECTED);
1725                 num_ok_dungeons++;
1726                 last_ok_dungeon = i;
1727             }
1728 /*JP
1729             end_menu(tmpwin, "Open a portal to which dungeon?");
1730 */
1731             end_menu(tmpwin, "\82Ç\82Ì\96À\8b{\82Ö\82Ì\96\82\96@\82Ì\93ü\8cû\82ð\8aJ\82«\82Ü\82·\82©\81H");
1732             if (num_ok_dungeons > 1) {
1733                 /* more than one entry; display menu for choices */
1734                 menu_item *selected;
1735                 int n;
1736
1737                 n = select_menu(tmpwin, PICK_ONE, &selected);
1738                 if (n <= 0) {
1739                     destroy_nhwindow(tmpwin);
1740                     goto nothing_special;
1741                 }
1742                 i = selected[0].item.a_int - 1;
1743                 free((genericptr_t) selected);
1744             } else
1745                 i = last_ok_dungeon; /* also first & only OK dungeon */
1746             destroy_nhwindow(tmpwin);
1747
1748             /*
1749              * i is now index into dungeon structure for the new dungeon.
1750              * Find the closest level in the given dungeon, open
1751              * a use-once portal to that dungeon and go there.
1752              * The closest level is either the entry or dunlev_ureached.
1753              */
1754             newlev.dnum = i;
1755             if (dungeons[i].depth_start >= depth(&u.uz))
1756                 newlev.dlevel = dungeons[i].entry_lev;
1757             else
1758                 newlev.dlevel = dungeons[i].dunlev_ureached;
1759
1760             if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
1761                 || newlev.dnum == u.uz.dnum || !next_to_u()) {
1762 /*JP
1763                 You_feel("very disoriented for a moment.");
1764 */
1765                 You("\88ê\8fu\95û\8cü\8a´\8ao\82ð\8e¸\82Á\82½\81D");
1766             } else {
1767                 if (!Blind)
1768 /*JP
1769                     You("are surrounded by a shimmering sphere!");
1770 */
1771                     You("\83`\83J\83`\83J\8cõ\82é\8b\85\91Ì\82É\95¢\82í\82ê\82½\81I");
1772                 else
1773 /*JP
1774                     You_feel("weightless for a moment.");
1775 */
1776                     You_feel("\88ê\8fu\81C\96³\8fd\97Í\8a´\82ð\8a´\82\82½\81D");
1777                 goto_level(&newlev, FALSE, FALSE, FALSE);
1778             }
1779             break;
1780         }
1781         case ENLIGHTENING:
1782             enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
1783             break;
1784         case CREATE_AMMO: {
1785             struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
1786
1787             if (!otmp)
1788                 goto nothing_special;
1789             otmp->blessed = obj->blessed;
1790             otmp->cursed = obj->cursed;
1791             otmp->bknown = obj->bknown;
1792             if (obj->blessed) {
1793                 if (otmp->spe < 0)
1794                     otmp->spe = 0;
1795                 otmp->quan += rnd(10);
1796             } else if (obj->cursed) {
1797                 if (otmp->spe > 0)
1798                     otmp->spe = 0;
1799             } else
1800                 otmp->quan += rnd(5);
1801             otmp->owt = weight(otmp);
1802 #if 0 /*JP*/
1803             otmp = hold_another_object(otmp, "Suddenly %s out.",
1804                                        aobjnam(otmp, "fall"), (char *) 0);
1805 #else
1806             otmp = hold_another_object(otmp, "\93Ë\91R%s\82ª\97\8e\82¿\82½\81D",
1807                                        xname(otmp), 0);
1808 #endif
1809             break;
1810         }
1811         }
1812     } else {
1813         long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
1814              iprop = u.uprops[oart->inv_prop].intrinsic;
1815         boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */
1816
1817         if (on && obj->age > monstermoves) {
1818             /* the artifact is tired :-) */
1819             u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
1820 #if 0 /*JP:T*/
1821             You_feel("that %s %s ignoring you.", the(xname(obj)),
1822                      otense(obj, "are"));
1823 #else
1824             You_feel("%s\82ª\96³\8e\8b\82µ\82Ä\82¢\82é\82æ\82¤\82É\8a´\82\82½\81D", xname(obj));
1825 #endif
1826             /* can't just keep repeatedly trying */
1827             obj->age += (long) d(3, 10);
1828             return 1;
1829         } else if (!on) {
1830             /* when turning off property, determine downtime */
1831             /* arbitrary for now until we can tune this -dlc */
1832             obj->age = monstermoves + rnz(100);
1833         }
1834
1835         if ((eprop & ~W_ARTI) || iprop) {
1836         nothing_special:
1837             /* you had the property from some other source too */
1838             if (carried(obj))
1839 /*JP
1840                 You_feel("a surge of power, but nothing seems to happen.");
1841 */
1842                 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");
1843             return 1;
1844         }
1845         switch (oart->inv_prop) {
1846         case CONFLICT:
1847             if (on)
1848 /*JP
1849                 You_feel("like a rabble-rouser.");
1850 */
1851                 You("\96¯\8fO\90î\93®\89Æ\82Ì\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
1852             else
1853 /*JP
1854                 You_feel("the tension decrease around you.");
1855 */
1856                 pline("\82Ü\82í\82è\82Ì\8bÙ\92£\8a´\82ª\82È\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
1857             break;
1858         case LEVITATION:
1859             if (on) {
1860                 float_up();
1861                 spoteffects(FALSE);
1862             } else
1863                 (void) float_down(I_SPECIAL | TIMEOUT, W_ARTI);
1864             break;
1865         case INVIS:
1866             if (BInvis || Blind)
1867                 goto nothing_special;
1868             newsym(u.ux, u.uy);
1869             if (on)
1870 #if 0 /*JP*/
1871                 Your("body takes on a %s transparency...",
1872                      Hallucination ? "normal" : "strange");
1873 #else
1874                 pline("%s\81C\91Ì\82Í\93§\89ß\90«\82ð\82à\82Á\82½\81D\81D\81D",
1875                       Hallucination ? "\82 \82½\82è\82Ü\82¦\82Ì\82±\82Æ\82¾\82ª" : "\8aï\96­\82È\82±\82Æ\82É");
1876 #endif
1877             else
1878 /*JP
1879                 Your("body seems to unfade...");
1880 */
1881                 Your("\91Ì\82Í\8e\9f\91æ\82É\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82Ä\82«\82½\81D\81D\81D");
1882             break;
1883         }
1884     }
1885
1886     return 1;
1887 }
1888
1889 /* will freeing this object from inventory cause levitation to end? */
1890 boolean
1891 finesse_ahriman(obj)
1892 struct obj *obj;
1893 {
1894     const struct artifact *oart;
1895     struct prop save_Lev;
1896     boolean result;
1897
1898     /* if we aren't levitating or this isn't an artifact which confers
1899        levitation via #invoke then freeinv() won't toggle levitation */
1900     if (!Levitation || (oart = get_artifact(obj)) == 0
1901         || oart->inv_prop != LEVITATION || !(ELevitation & W_ARTI))
1902         return FALSE;
1903
1904     /* arti_invoke(off) -> float_down() clears I_SPECIAL|TIMEOUT & W_ARTI;
1905        probe ahead to see whether that actually results in floating down;
1906        (this assumes that there aren't two simultaneously invoked artifacts
1907        both conferring levitation--safe, since if there were two of them,
1908        invoking the 2nd would negate the 1st rather than stack with it) */
1909     save_Lev = u.uprops[LEVITATION];
1910     HLevitation &= ~(I_SPECIAL | TIMEOUT);
1911     ELevitation &= ~W_ARTI;
1912     result = (boolean) !Levitation;
1913     u.uprops[LEVITATION] = save_Lev;
1914     return result;
1915 }
1916
1917 /* WAC return TRUE if artifact is always lit */
1918 boolean
1919 artifact_light(obj)
1920 struct obj *obj;
1921 {
1922     return (boolean) (get_artifact(obj) && obj->oartifact == ART_SUNSWORD);
1923 }
1924
1925 /* KMH -- Talking artifacts are finally implemented */
1926 void
1927 arti_speak(obj)
1928 struct obj *obj;
1929 {
1930     register const struct artifact *oart = get_artifact(obj);
1931     const char *line;
1932     char buf[BUFSZ];
1933
1934     /* Is this a speaking artifact? */
1935     if (!oart || !(oart->spfx & SPFX_SPEAK))
1936         return;
1937
1938     line = getrumor(bcsign(obj), buf, TRUE);
1939     if (!*line)
1940 /*JP
1941         line = "NetHack rumors file closed for renovation.";
1942 */
1943         line = "\89\\82Ì\90^\91\8a\82Í\90V\91\95\82Ì\82½\82ß\88ê\8e\9e\95Â\93X\81D";
1944 /*JP
1945     pline("%s:", Tobjnam(obj, "whisper"));
1946 */
1947     pline("%s\82Í\82³\82³\82â\82¢\82½\81F", xname(obj));
1948     verbalize1(line);
1949     return;
1950 }
1951
1952 boolean
1953 artifact_has_invprop(otmp, inv_prop)
1954 struct obj *otmp;
1955 uchar inv_prop;
1956 {
1957     const struct artifact *arti = get_artifact(otmp);
1958
1959     return (boolean) (arti && (arti->inv_prop == inv_prop));
1960 }
1961
1962 /* Return the price sold to the hero of a given artifact or unique item */
1963 long
1964 arti_cost(otmp)
1965 struct obj *otmp;
1966 {
1967     if (!otmp->oartifact)
1968         return (long) objects[otmp->otyp].oc_cost;
1969     else if (artilist[(int) otmp->oartifact].cost)
1970         return artilist[(int) otmp->oartifact].cost;
1971     else
1972         return (100L * (long) objects[otmp->otyp].oc_cost);
1973 }
1974
1975 STATIC_OVL uchar
1976 abil_to_adtyp(abil)
1977 long *abil;
1978 {
1979     struct abil2adtyp_tag {
1980         long *abil;
1981         uchar adtyp;
1982     } abil2adtyp[] = {
1983         { &EFire_resistance, AD_FIRE },
1984         { &ECold_resistance, AD_COLD },
1985         { &EShock_resistance, AD_ELEC },
1986         { &EAntimagic, AD_MAGM },
1987         { &EDisint_resistance, AD_DISN },
1988         { &EPoison_resistance, AD_DRST },
1989         { &EDrain_resistance, AD_DRLI },
1990     };
1991     int k;
1992
1993     for (k = 0; k < SIZE(abil2adtyp); k++) {
1994         if (abil2adtyp[k].abil == abil)
1995             return abil2adtyp[k].adtyp;
1996     }
1997     return 0;
1998 }
1999
2000 STATIC_OVL unsigned long
2001 abil_to_spfx(abil)
2002 long *abil;
2003 {
2004     static const struct abil2spfx_tag {
2005         long *abil;
2006         unsigned long spfx;
2007     } abil2spfx[] = {
2008         { &ESearching, SPFX_SEARCH },
2009         { &EHalluc_resistance, SPFX_HALRES },
2010         { &ETelepat, SPFX_ESP },
2011         { &EStealth, SPFX_STLTH },
2012         { &ERegeneration, SPFX_REGEN },
2013         { &ETeleport_control, SPFX_TCTRL },
2014         { &EWarn_of_mon, SPFX_WARN },
2015         { &EWarning, SPFX_WARN },
2016         { &EEnergy_regeneration, SPFX_EREGEN },
2017         { &EHalf_spell_damage, SPFX_HSPDAM },
2018         { &EHalf_physical_damage, SPFX_HPHDAM },
2019         { &EReflecting, SPFX_REFLECT },
2020     };
2021     int k;
2022
2023     for (k = 0; k < SIZE(abil2spfx); k++) {
2024         if (abil2spfx[k].abil == abil)
2025             return abil2spfx[k].spfx;
2026     }
2027     return 0L;
2028 }
2029
2030 /*
2031  * Return the first item that is conveying a particular intrinsic.
2032  */
2033 struct obj *
2034 what_gives(abil)
2035 long *abil;
2036 {
2037     struct obj *obj;
2038     uchar dtyp;
2039     unsigned long spfx;
2040     long wornbits;
2041     long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS
2042                      | W_ARMG | W_ARMF | W_ARMU
2043                      | W_AMUL | W_RINGL | W_RINGR | W_TOOL
2044                      | W_ART | W_ARTI);
2045
2046     if (u.twoweap)
2047         wornmask |= W_SWAPWEP;
2048     dtyp = abil_to_adtyp(abil);
2049     spfx = abil_to_spfx(abil);
2050     wornbits = (wornmask & *abil);
2051
2052     for (obj = invent; obj; obj = obj->nobj) {
2053         if (obj->oartifact
2054             && (abil != &EWarn_of_mon || context.warntype.obj)) {
2055             const struct artifact *art = get_artifact(obj);
2056
2057             if (art) {
2058                 if (dtyp) {
2059                     if (art->cary.adtyp == dtyp /* carried */
2060                         || (art->defn.adtyp == dtyp /* defends while worn */
2061                             && (obj->owornmask & ~(W_ART | W_ARTI))))
2062                         return obj;
2063                 }
2064                 if (spfx) {
2065                     /* property conferred when carried */
2066                     if ((art->cspfx & spfx) == spfx)
2067                         return obj;
2068                     /* property conferred when wielded or worn */
2069                     if ((art->spfx & spfx) == spfx && obj->owornmask)
2070                         return obj;
2071                 }
2072             }
2073         } else {
2074             if (wornbits && wornbits == (wornmask & obj->owornmask))
2075                 return obj;
2076         }
2077     }
2078     return (struct obj *) 0;
2079 }
2080
2081 #if 1 /*JP*/
2082 /*JP colornames\82Í\90Ý\92è\83t\83@\83C\83\8b\82Å\8eg\82¤\82Ì\82Å\96|\96ó\82¹\82¸\81A
2083      \93ú\96{\8cê\90ê\97p\82Ì\94z\97ñ\82ð\95Ê\82É\97p\88Ó\82·\82é\81B
2084 */
2085 static const struct {
2086     const char *name;
2087     const int color;
2088 } colornames2[] = {
2089     { "\8d\95\82¢", CLR_BLACK },
2090     { "\90Ô\82¢", CLR_RED },
2091     { "\97Î\90F\82Ì", CLR_GREEN },
2092     { "\92\83\90F\82¢", CLR_BROWN },
2093     { "\90Â\82¢", CLR_BLUE },
2094     { "\83}\83[\83\93\83^\90F\82Ì", CLR_MAGENTA },
2095     { "\83V\83A\83\93\90F\82Ì", CLR_CYAN },
2096     { "\8aD\90F\82Ì", CLR_GRAY },
2097     { "\8aD\90F\82Ì", CLR_GRAY },
2098     { "\83I\83\8c\83\93\83W\90F\82Ì", CLR_ORANGE },
2099     { "\92W\97Î\90F\82Ì", CLR_BRIGHT_GREEN },
2100     { "\89©\90F\82¢", CLR_YELLOW },
2101     { "\92W\90Â\90F\82Ì", CLR_BRIGHT_BLUE },
2102     { "\96¾\82é\82¢\83}\83[\83\93\83^\90F\82Ì", CLR_BRIGHT_MAGENTA },
2103     { "\96¾\82é\82¢\83V\83A\83\93\90F\82Ì", CLR_BRIGHT_CYAN },
2104     { "\94\92\82¢", CLR_WHITE }
2105 };
2106
2107 static const char *
2108 clr2colorname2(clr)
2109 int clr;
2110 {
2111     int i;
2112
2113     for (i = 0; i < SIZE(colornames2); i++)
2114         if (colornames2[i].color == clr)
2115             return colornames2[i].name;
2116     return (char *) 0;
2117 }
2118 #endif
2119
2120 const char *
2121 glow_color(arti_indx)
2122 int arti_indx;
2123 {
2124     int colornum = artilist[arti_indx].acolor;
2125 #if 0 /*JP*/
2126     const char *colorstr = clr2colorname(colornum);
2127 #else
2128     const char *colorstr = jconj_adj(clr2colorname2(colornum));
2129 #endif
2130
2131     return hcolor(colorstr);
2132 }
2133
2134 /* use for warning "glow" for Sting, Orcrist, and Grimtooth */
2135 void
2136 Sting_effects(orc_count)
2137 int orc_count; /* new count (warn_obj_cnt is old count); -1 is a flag value */
2138 {
2139     if (uwep
2140         && (uwep->oartifact == ART_STING
2141             || uwep->oartifact == ART_ORCRIST
2142             || uwep->oartifact == ART_GRIMTOOTH)) {
2143         if (orc_count == -1 && warn_obj_cnt > 0) {
2144             /* -1 means that blindness has just been toggled; give a
2145                'continue' message that eventual 'stop' message will match */
2146 #if 0 /*JP*/
2147             pline("%s is %s.", bare_artifactname(uwep),
2148                   !Blind ? "glowing" : "quivering");
2149 #else
2150             pline("%s\82Í%s\82Ä\82¢\82é\81D", bare_artifactname(uwep),
2151                   !Blind ? "\8bP\82¢" : "\90k\82¦");
2152 #endif
2153         } else if (orc_count > 0 && warn_obj_cnt == 0) {
2154             /* 'start' message */
2155             if (!Blind)
2156 #if 0 /*JP*/
2157                 pline("%s %s %s!", bare_artifactname(uwep),
2158                       otense(uwep, "glow"), glow_color(uwep->oartifact));
2159 #else
2160                 pline("%s\82Í%s\8bP\82¢\82½\81I", bare_artifactname(uwep),
2161                       glow_color(uwep->oartifact));
2162 #endif
2163             else
2164 /*JP
2165                 pline("%s quivers slightly.", bare_artifactname(uwep));
2166 */
2167                 pline("%s\82Í\8f­\82µ\90k\82¦\82½\81D", bare_artifactname(uwep));
2168         } else if (orc_count == 0 && warn_obj_cnt > 0) {
2169             /* 'stop' message */
2170 #if 0 /*JP*/
2171             pline("%s stops %s.", bare_artifactname(uwep),
2172                   !Blind ? "glowing" : "quivering");
2173 #else
2174             pline("%s\82Ì%s\82Í\8e~\82Ü\82Á\82½\81D", bare_artifactname(uwep),
2175                   !Blind ? "\8bP\82«" : "\90k\82¦");
2176 #endif
2177         }
2178     }
2179 }
2180
2181 /* called when hero is wielding/applying/invoking a carried item, or
2182    after undergoing a transformation (alignment change, lycanthropy,
2183    polymorph) which might affect item access */
2184 int
2185 retouch_object(objp, loseit)
2186 struct obj **objp; /* might be destroyed or unintentionally dropped */
2187 boolean loseit;    /* whether to drop it if hero can longer touch it */
2188 {
2189     struct obj *obj = *objp;
2190
2191     if (touch_artifact(obj, &youmonst)) {
2192         char buf[BUFSZ];
2193         int dmg = 0, tmp;
2194         boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver),
2195                 bane = bane_applies(get_artifact(obj), &youmonst);
2196
2197         /* nothing else to do if hero can successfully handle this object */
2198         if (!ag && !bane)
2199             return 1;
2200
2201         /* hero can't handle this object, but didn't get touch_artifact()'s
2202            "<obj> evades your grasp|control" message; give an alternate one */
2203 #if 0 /*JP*/
2204         You_cant("handle %s%s!", yname(obj),
2205                  obj->owornmask ? " anymore" : "");
2206 #else
2207         You_cant("%s%s\82ð\88µ\82¦\82È\82¢\81I", obj->owornmask ? "\82à\82¤" : "",
2208                  xname(obj));
2209 #endif
2210         /* also inflict damage unless touch_artifact() already did so */
2211         if (!touch_blasted) {
2212             /* damage is somewhat arbitrary; half the usual 1d20 physical
2213                for silver, 1d10 magical for <foo>bane, potentially both */
2214             if (ag)
2215                 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
2216             if (bane)
2217                 dmg += rnd(10);
2218 /*JP
2219             Sprintf(buf, "handling %s", killer_xname(obj));
2220 */
2221             Sprintf(buf, "%s\82ð\88µ\82Á\82Ä", killer_xname(obj));
2222             losehp(dmg, buf, KILLED_BY);
2223             exercise(A_CON, FALSE);
2224         }
2225     }
2226
2227     /* removing a worn item might result in loss of levitation,
2228        dropping the hero onto a polymorph trap or into water or
2229        lava and potentially dropping or destroying the item */
2230     if (obj->owornmask) {
2231         struct obj *otmp;
2232
2233         remove_worn_item(obj, FALSE);
2234         for (otmp = invent; otmp; otmp = otmp->nobj)
2235             if (otmp == obj)
2236                 break;
2237         if (!otmp)
2238             *objp = obj = 0;
2239     }
2240
2241     /* if we still have it and caller wants us to drop it, do so now */
2242     if (loseit && obj) {
2243         if (Levitation) {
2244             freeinv(obj);
2245             hitfloor(obj);
2246         } else {
2247             /* dropx gives a message iff item lands on an altar */
2248             if (!IS_ALTAR(levl[u.ux][u.uy].typ))
2249 #if 0 /*JP*/
2250                 pline("%s to the %s.", Tobjnam(obj, "fall"),
2251                       surface(u.ux, u.uy));
2252 #else
2253                 pline("%s\82Í%s\82É\97\8e\82¿\82½\81D", xname(obj),
2254                       surface(u.ux, u.uy));
2255 #endif
2256             dropx(obj);
2257         }
2258         *objp = obj = 0; /* no longer in inventory */
2259     }
2260     return 0;
2261 }
2262
2263 /* an item which is worn/wielded or an artifact which conveys
2264    something via being carried or which has an #invoke effect
2265    currently in operation undergoes a touch test; if it fails,
2266    it will be unworn/unwielded and revoked but not dropped */
2267 STATIC_OVL boolean
2268 untouchable(obj, drop_untouchable)
2269 struct obj *obj;
2270 boolean drop_untouchable;
2271 {
2272     struct artifact *art;
2273     boolean beingworn, carryeffect, invoked;
2274     long wearmask = ~(W_QUIVER | (u.twoweap ? 0L : W_SWAPWEP) | W_BALL);
2275
2276     beingworn = ((obj->owornmask & wearmask) != 0L
2277                  /* some items in use don't have any wornmask setting */
2278                  || (obj->oclass == TOOL_CLASS
2279                      && (obj->lamplit || (obj->otyp == LEASH && obj->leashmon)
2280                          || (Is_container(obj) && Has_contents(obj)))));
2281
2282     if ((art = get_artifact(obj)) != 0) {
2283         carryeffect = (art->cary.adtyp || art->cspfx);
2284         invoked = (art->inv_prop > 0 && art->inv_prop <= LAST_PROP
2285                    && (u.uprops[art->inv_prop].extrinsic & W_ARTI) != 0L);
2286     } else {
2287         carryeffect = invoked = FALSE;
2288     }
2289
2290     if (beingworn || carryeffect || invoked) {
2291         if (!retouch_object(&obj, drop_untouchable)) {
2292             /* "<artifact> is beyond your control" or "you can't handle
2293                <object>" has been given and it is now unworn/unwielded
2294                and possibly dropped (depending upon caller); if dropped,
2295                carried effect was turned off, else we leave that alone;
2296                we turn off invocation property here if still carried */
2297             if (invoked && obj)
2298                 arti_invoke(obj); /* reverse #invoke */
2299             return TRUE;
2300         }
2301     }
2302     return FALSE;
2303 }
2304
2305 /* check all items currently in use (mostly worn) for touchability */
2306 void
2307 retouch_equipment(dropflag)
2308 int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
2309 {
2310     static int nesting = 0; /* recursion control */
2311     struct obj *obj;
2312     boolean dropit, had_gloves = (uarmg != 0);
2313     int had_rings = (!!uleft + !!uright);
2314
2315     /*
2316      * We can potentially be called recursively if losing/unwearing
2317      * an item causes worn helm of opposite alignment to come off or
2318      * be destroyed.
2319      *
2320      * BUG: if the initial call was due to putting on a helm of
2321      * opposite alignment and it does come off to trigger recursion,
2322      * after the inner call executes, the outer call will finish
2323      * using the non-helm alignment rather than the helm alignment
2324      * which triggered this in the first place.
2325      */
2326     if (!nesting++)
2327         clear_bypasses(); /* init upon initial entry */
2328
2329     dropit = (dropflag > 0); /* drop all or drop weapon */
2330     /* check secondary weapon first, before possibly unwielding primary */
2331     if (u.twoweap) {
2332         bypass_obj(uswapwep); /* so loop below won't process it again */
2333         (void) untouchable(uswapwep, dropit);
2334     }
2335     /* check primary weapon next so that they're handled together */
2336     if (uwep) {
2337         bypass_obj(uwep); /* so loop below won't process it again */
2338         (void) untouchable(uwep, dropit);
2339     }
2340
2341     /* in case someone is daft enough to add artifact or silver saddle */
2342     if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
2343         /* untouchable() calls retouch_object() which expects an object in
2344            hero's inventory, but remove_worn_item() will be harmless for
2345            saddle and we're suppressing drop, so this works as intended */
2346         if (untouchable(obj, FALSE))
2347             dismount_steed(DISMOUNT_THROWN);
2348     }
2349     /*
2350      * TODO?  Force off gloves if either or both rings are going to
2351      * become unworn; force off cloak [suit] before suit [shirt].
2352      * The torso handling is hypothetical; the case for gloves is
2353      * not, due to the possibility of unwearing silver rings.
2354      */
2355
2356     dropit = (dropflag == 1); /* all untouchable items */
2357     /* loss of levitation (silver ring, or Heart of Ahriman invocation)
2358        might cause hero to lose inventory items (by dropping into lava,
2359        for instance), so inventory traversal needs to rescan the whole
2360        invent chain each time it moves on to another object; we use bypass
2361        handling to keep track of which items have already been processed */
2362     while ((obj = nxt_unbypassed_obj(invent)) != 0)
2363         (void) untouchable(obj, dropit);
2364
2365     if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
2366         uncurse(uarmg); /* temporary? hack for ring removal plausibility */
2367     if (had_gloves && !uarmg)
2368 /*JP
2369         selftouch("After losing your gloves, you");
2370 */
2371         selftouch("\8f¬\8eè\82ð\8e¸\82Á\82½\82 \82Æ\81C\82 \82È\82½\82Í");
2372
2373     if (!--nesting)
2374         clear_bypasses(); /* reset upon final exit */
2375 }
2376
2377 static int mkot_trap_warn_count = 0;
2378
2379 STATIC_OVL int
2380 count_surround_traps(x, y)
2381 int x, y;
2382 {
2383     struct rm *levp;
2384     struct obj *otmp;
2385     struct trap *ttmp;
2386     int dx, dy, glyph, ret = 0;
2387
2388     for (dx = x - 1; dx < x + 2; ++dx)
2389         for (dy = y - 1; dy < y + 2; ++dy) {
2390             if (!isok(dx, dy))
2391                 continue;
2392             /* If a trap is shown here, don't count it; the hero
2393              * should be expecting it.  But if there is a trap here
2394              * that's not shown, either undiscovered or covered by
2395              * something, do count it.
2396              */
2397             glyph = glyph_at(dx, dy);
2398             if (glyph_is_trap(glyph))
2399                 continue;
2400             if ((ttmp = t_at(dx, dy)) != 0) {
2401                 ++ret;
2402                 continue;
2403             }
2404             levp = &levl[dx][dy];
2405             if (IS_DOOR(levp->typ) && (levp->doormask & D_TRAPPED) != 0) {
2406                 ++ret;
2407                 continue;
2408             }
2409             for (otmp = level.objects[dx][dy]; otmp; otmp = otmp->nexthere)
2410                 if (Is_container(otmp) && otmp->otrapped) {
2411                     ++ret; /* we're counting locations, so just */
2412                     break; /* count the first one in a pile     */
2413                 }
2414         }
2415     /*
2416      * [Shouldn't we also check inventory for a trapped container?
2417      * Even if its trap has already been found, there's no 'tknown'
2418      * flag to help hero remember that so we have nothing comparable
2419      * to a shown glyph to justify skipping it.]
2420      */
2421     return ret;
2422 }
2423
2424 /* sense adjacent traps if wielding MKoT without wearing gloves */
2425 void
2426 mkot_trap_warn()
2427 {
2428 #if 0 /*JP*/
2429     static const char *const heat[7] = {
2430         "cool", "slightly warm", "warm", "very warm",
2431         "hot", "very hot", "like fire"
2432     };
2433 #else
2434     static const char *const heat[7] = {
2435         "\97â\82½\82­", "\8f­\82µ\89·\82©\82­", "\89·\82©\82­", "\82Æ\82Ä\82à\89·\82©\82­",
2436         "\94M\82­", "\82Æ\82Ä\82à\94M\82­", "\89\8a\82Ì\82æ\82¤\82É"
2437     };
2438 #endif
2439
2440     if (!uarmg && uwep && uwep->oartifact == ART_MASTER_KEY_OF_THIEVERY) {
2441         int idx, ntraps = count_surround_traps(u.ux, u.uy);
2442
2443         if (ntraps != mkot_trap_warn_count) {
2444             idx = min(ntraps, SIZE(heat) - 1);
2445 /*JP
2446             pline_The("Key feels %s%c", heat[idx], (ntraps > 3) ? '!' : '.');
2447 */
2448             pline_The("\8c®\82Í%s\8a´\82\82½%s", heat[idx], (ntraps > 3) ? "\81I" : "\81D");
2449         }
2450         mkot_trap_warn_count = ntraps;
2451     } else
2452         mkot_trap_warn_count = 0;
2453 }
2454
2455 /* Master Key is magic key if its bless/curse state meets our criteria:
2456    not cursed for rogues or blessed for non-rogues */
2457 boolean
2458 is_magic_key(mon, obj)
2459 struct monst *mon; /* if null, non-rogue is assumed */
2460 struct obj *obj;
2461 {
2462     if (((obj && obj->oartifact == ART_MASTER_KEY_OF_THIEVERY)
2463          && ((mon == &youmonst) ? Role_if(PM_ROGUE)
2464                                 : (mon && mon->data == &mons[PM_ROGUE])))
2465         ? !obj->cursed : obj->blessed)
2466         return TRUE;
2467     return FALSE;
2468 }
2469
2470 /* figure out whether 'mon' (usually youmonst) is carrying the magic key */
2471 struct obj *
2472 has_magic_key(mon)
2473 struct monst *mon; /* if null, hero assumed */
2474 {
2475     struct obj *o;
2476     short key = artilist[ART_MASTER_KEY_OF_THIEVERY].otyp;
2477
2478     if (!mon)
2479         mon = &youmonst;
2480     for (o = ((mon == &youmonst) ? invent : mon->minvent); o;
2481          o = nxtobj(o, key, FALSE)) {
2482         if (is_magic_key(mon, o))
2483             return o;
2484     }
2485     return (struct obj *) 0;
2486 }
2487
2488 /*artifact.c*/