OSDN Git Service

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