OSDN Git Service

update year to 2020
[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-2020            */
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 #if 0 /*JP*/
1005     int attack_indx, fakeidx, scare_dieroll = MB_MAX_DIEROLL / 2;
1006 #else
1007     int attack_indx, scare_dieroll = MB_MAX_DIEROLL / 2;
1008 #endif
1009
1010     result = FALSE; /* no message given yet */
1011     /* the most severe effects are less likely at higher enchantment */
1012     if (mb->spe >= 3)
1013         scare_dieroll /= (1 << (mb->spe / 3));
1014     /* if target successfully resisted the artifact damage bonus,
1015        reduce overall likelihood of the assorted special effects */
1016     if (!spec_dbon_applies)
1017         dieroll += 1;
1018
1019     /* might stun even when attempting a more severe effect, but
1020        in that case it will only happen if the other effect fails;
1021        extra damage will apply regardless; 3.4.1: sometimes might
1022        just probe even when it hasn't been enchanted */
1023     do_stun = (max(mb->spe, 0) < rn2(spec_dbon_applies ? 11 : 7));
1024
1025     /* the special effects also boost physical damage; increments are
1026        generally cumulative, but since the stun effect is based on a
1027        different criterium its damage might not be included; the base
1028        damage is either 1d4 (athame) or 2d4 (athame+spec_dbon) depending
1029        on target's resistance check against AD_STUN (handled by caller)
1030        [note that a successful save against AD_STUN doesn't actually
1031        prevent the target from ending up stunned] */
1032     attack_indx = MB_INDEX_PROBE;
1033     *dmgptr += rnd(4); /* (2..3)d4 */
1034     if (do_stun) {
1035         attack_indx = MB_INDEX_STUN;
1036         *dmgptr += rnd(4); /* (3..4)d4 */
1037     }
1038     if (dieroll <= scare_dieroll) {
1039         attack_indx = MB_INDEX_SCARE;
1040         *dmgptr += rnd(4); /* (3..5)d4 */
1041     }
1042     if (dieroll <= (scare_dieroll / 2)) {
1043         attack_indx = MB_INDEX_CANCEL;
1044         *dmgptr += rnd(4); /* (4..6)d4 */
1045     }
1046
1047     /* give the hit message prior to inflicting the effects */
1048     verb = mb_verb[!!Hallucination][attack_indx];
1049     if (youattack || youdefend || vis) {
1050         result = TRUE;
1051 #if 0 /*JP*/
1052         pline_The("magic-absorbing blade %s %s!",
1053                   vtense((const char *) 0, verb), hittee);
1054 #else
1055         pline("\96\82\97Í\82ð\8bz\82¢\82Æ\82é\90n\82ª%s\82ð%s\82½\81I",
1056                   hittee, verb);
1057 #endif
1058         /* assume probing has some sort of noticeable feedback
1059            even if it is being done by one monster to another */
1060         if (attack_indx == MB_INDEX_PROBE && !canspotmon(mdef))
1061             map_invisible(mdef->mx, mdef->my);
1062     }
1063
1064     /* now perform special effects */
1065     switch (attack_indx) {
1066     case MB_INDEX_CANCEL:
1067         old_uasmon = youmonst.data;
1068         /* No mdef->mcan check: even a cancelled monster can be polymorphed
1069          * into a golem, and the "cancel" effect acts as if some magical
1070          * energy remains in spellcasting defenders to be absorbed later.
1071          */
1072         if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
1073             resisted = TRUE;
1074         } else {
1075             do_stun = FALSE;
1076             if (youdefend) {
1077                 if (youmonst.data != old_uasmon)
1078                     *dmgptr = 0; /* rehumanized, so no more damage */
1079                 if (u.uenmax > 0) {
1080                     u.uenmax--;
1081                     if (u.uen > 0)
1082                         u.uen--;
1083                     context.botl = TRUE;
1084 /*JP
1085                     You("lose magical energy!");
1086 */
1087                     You("\96\82\96@\82Ì\83G\83l\83\8b\83M\81[\82ð\8e¸\82Á\82½\81I");
1088                 }
1089             } else {
1090                 if (mdef->data == &mons[PM_CLAY_GOLEM])
1091                     mdef->mhp = 1; /* cancelled clay golems will die */
1092                 if (youattack && attacktype(mdef->data, AT_MAGC)) {
1093                     u.uenmax++;
1094                     u.uen++;
1095                     context.botl = TRUE;
1096 /*JP
1097                     You("absorb magical energy!");
1098 */
1099                     You("\96\82\96@\82Ì\83G\83l\83\8b\83M\81[\82ð\8bz\82¢\82Æ\82Á\82½\81I");
1100                 }
1101             }
1102         }
1103         break;
1104
1105     case MB_INDEX_SCARE:
1106         if (youdefend) {
1107             if (Antimagic) {
1108                 resisted = TRUE;
1109             } else {
1110                 nomul(-3);
1111 /*JP
1112                 multi_reason = "being scared stiff";
1113 */
1114                 multi_reason = "\8b°\95|\82Å\98T\94\82\82µ\82½\8c\84\82É";
1115                 nomovemsg = "";
1116                 if (magr && magr == u.ustuck && sticks(youmonst.data)) {
1117                     u.ustuck = (struct monst *) 0;
1118 /*JP
1119                     You("release %s!", mon_nam(magr));
1120 */
1121                     You("%s\82ð\89ð\95ú\82µ\82½\81I", mon_nam(magr));
1122                 }
1123             }
1124         } else {
1125             if (rn2(2) && resist(mdef, WEAPON_CLASS, 0, NOTELL))
1126                 resisted = TRUE;
1127             else
1128                 monflee(mdef, 3, FALSE, (mdef->mhp > *dmgptr));
1129         }
1130         if (!resisted)
1131             do_stun = FALSE;
1132         break;
1133
1134     case MB_INDEX_STUN:
1135         do_stun = TRUE; /* (this is redundant...) */
1136         break;
1137
1138     case MB_INDEX_PROBE:
1139         if (youattack && (mb->spe == 0 || !rn2(3 * abs(mb->spe)))) {
1140 /*JP
1141             pline_The("%s is insightful.", verb);
1142 */
1143             pline("\91\8a\8eè\82ð%s\82½\81D", verb);
1144             /* pre-damage status */
1145             probe_monster(mdef);
1146         }
1147         break;
1148     }
1149     /* stun if that was selected and a worse effect didn't occur */
1150     if (do_stun) {
1151         if (youdefend)
1152             make_stunned(((HStun & TIMEOUT) + 3L), FALSE);
1153         else
1154             mdef->mstun = 1;
1155         /* avoid extra stun message below if we used mb_verb["stun"] above */
1156         if (attack_indx == MB_INDEX_STUN)
1157             do_stun = FALSE;
1158     }
1159     /* lastly, all this magic can be confusing... */
1160     do_confuse = !rn2(12);
1161     if (do_confuse) {
1162         if (youdefend)
1163             make_confused((HConfusion & TIMEOUT) + 4L, FALSE);
1164         else
1165             mdef->mconf = 1;
1166     }
1167
1168     /* now give message(s) describing side-effects; Use fakename
1169        so vtense() won't be fooled by assigned name ending in 's' */
1170 #if 0 /*JP*/
1171     fakeidx = youdefend ? 1 : 0;
1172 #endif
1173     if (youattack || youdefend || vis) {
1174         (void) upstart(hittee); /* capitalize */
1175         if (resisted) {
1176 /*JP
1177             pline("%s %s!", hittee, vtense(fakename[fakeidx], "resist"));
1178 */
1179             pline("%s\82Í\96h\82¢\82¾\81I", hittee);
1180             shieldeff(youdefend ? u.ux : mdef->mx,
1181                       youdefend ? u.uy : mdef->my);
1182         }
1183         if ((do_stun || do_confuse) && flags.verbose) {
1184             char buf[BUFSZ];
1185
1186             buf[0] = '\0';
1187 #if 0 /*JP*/
1188             if (do_stun)
1189                 Strcat(buf, "stunned");
1190             if (do_stun && do_confuse)
1191                 Strcat(buf, " and ");
1192             if (do_confuse)
1193                 Strcat(buf, "confused");
1194             pline("%s %s %s%c", hittee, vtense(fakename[fakeidx], "are"), buf,
1195                   (do_stun && do_confuse) ? '!' : '.');
1196 #else
1197             if (do_stun && do_confuse)
1198                 Strcat(buf, "\82æ\82ë\82ß\82¢\82Ä");
1199             else if (do_stun)
1200                 Strcat(buf, "\82æ\82ë\82ß\82¢\82½");
1201             if (do_confuse)
1202                 Strcat(buf, "\8d¬\97\90\82µ\82½");
1203             pline("%s\82Í%s%s", hittee,
1204                   buf, (do_stun && do_confuse) ? "\81I" : "\81D");
1205 #endif
1206         }
1207     }
1208
1209     return result;
1210 }
1211
1212 /* Function used when someone attacks someone else with an artifact
1213  * weapon.  Only adds the special (artifact) damage, and returns a 1 if it
1214  * did something special (in which case the caller won't print the normal
1215  * hit message).  This should be called once upon every artifact attack;
1216  * dmgval() no longer takes artifact bonuses into account.  Possible
1217  * extension: change the killer so that when an orc kills you with
1218  * Stormbringer it's "killed by Stormbringer" instead of "killed by an orc".
1219  */
1220 boolean
1221 artifact_hit(magr, mdef, otmp, dmgptr, dieroll)
1222 struct monst *magr, *mdef;
1223 struct obj *otmp;
1224 int *dmgptr;
1225 int dieroll; /* needed for Magicbane and vorpal blades */
1226 {
1227     boolean youattack = (magr == &youmonst);
1228     boolean youdefend = (mdef == &youmonst);
1229     boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
1230                   || (!youdefend && cansee(mdef->mx, mdef->my))
1231                   || (youattack && u.uswallow && mdef == u.ustuck && !Blind);
1232     boolean realizes_damage;
1233     const char *wepdesc;
1234 /*JP
1235     static const char you[] = "you";
1236 */
1237     static const char you[] = "\82 \82È\82½";
1238     char hittee[BUFSZ];
1239
1240     Strcpy(hittee, youdefend ? you : mon_nam(mdef));
1241
1242     /* The following takes care of most of the damage, but not all--
1243      * the exception being for level draining, which is specially
1244      * handled.  Messages are done in this function, however.
1245      */
1246     *dmgptr += spec_dbon(otmp, mdef, *dmgptr);
1247
1248     if (youattack && youdefend) {
1249         impossible("attacking yourself with weapon?");
1250         return FALSE;
1251     }
1252
1253     realizes_damage = (youdefend || vis
1254                        /* feel the effect even if not seen */
1255                        || (youattack && mdef == u.ustuck));
1256
1257     /* the four basic attacks: fire, cold, shock and missiles */
1258     if (attacks(AD_FIRE, otmp)) {
1259         if (realizes_damage)
1260 #if 0 /*JP*/
1261             pline_The("fiery blade %s %s%c",
1262                       !spec_dbon_applies
1263                           ? "hits"
1264                           : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1265                                 ? "vaporizes part of"
1266                                 : "burns",
1267                       hittee, !spec_dbon_applies ? '.' : '!');
1268 #else
1269             pline_The("\96Ò\89Î\82ª%s%s",
1270                       hittee,
1271                       !spec_dbon_applies
1272                           ? "\82É\96½\92\86\82µ\82½\81D"
1273                           : (mdef->data == &mons[PM_WATER_ELEMENTAL])
1274                                 ? "\82Ì\88ê\95\94\82ð\8fÁ\96Å\82³\82¹\82½\81I"
1275                                 : "\82ð\8fÄ\82¢\82½\81I");
1276 #endif
1277         if (!rn2(4))
1278             (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1279         if (!rn2(4))
1280             (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1281         if (!rn2(7))
1282             (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1283         if (youdefend && Slimed)
1284             burn_away_slime();
1285         return realizes_damage;
1286     }
1287     if (attacks(AD_COLD, otmp)) {
1288         if (realizes_damage)
1289 #if 0 /*JP*/
1290             pline_The("ice-cold blade %s %s%c",
1291                       !spec_dbon_applies ? "hits" : "freezes", hittee,
1292                       !spec_dbon_applies ? '.' : '!');
1293 #else
1294             pline_The("\96Ò\90\81\90á\82ª%s%s",
1295                       hittee,
1296                       !spec_dbon_applies ? "\82É\96½\92\86\82µ\82½\81D" : "\82ð\8fP\82Á\82½\81I");
1297 #endif
1298         if (!rn2(4))
1299             (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1300         return realizes_damage;
1301     }
1302     if (attacks(AD_ELEC, otmp)) {
1303         if (realizes_damage)
1304 #if 0 /*JP*/
1305             pline_The("massive hammer hits%s %s%c",
1306                       !spec_dbon_applies ? "" : "!  Lightning strikes",
1307                       hittee, !spec_dbon_applies ? '.' : '!');
1308 #else
1309             pline("\8b\90\91å\82È\83n\83\93\83}\81[\82Í%s\82É\96½\92\86\82µ\82½%s", hittee,
1310                       !spec_dbon_applies ? "\81D" : "\81I\93d\8c\82\82ª\8fP\82Á\82½\81I");
1311 #endif
1312         if (spec_dbon_applies)
1313             wake_nearto(mdef->mx, mdef->my, 4 * 4);
1314         if (!rn2(5))
1315             (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1316         if (!rn2(5))
1317             (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1318         return realizes_damage;
1319     }
1320     if (attacks(AD_MAGM, otmp)) {
1321         if (realizes_damage)
1322 #if 0 /*JP*/
1323             pline_The("imaginary widget hits%s %s%c",
1324                       !spec_dbon_applies
1325                           ? ""
1326                           : "!  A hail of magic missiles strikes",
1327                       hittee, !spec_dbon_applies ? '.' : '!');
1328 #else
1329             pline("\8eÀ\91Ì\82ð\8e\9d\82½\82È\82¢\95¨\91Ì\82ª%s\82ð\8dU\8c\82\82µ\82½%s",
1330                       hittee,
1331                       !spec_dbon_applies ? "\81D" :
1332                       "\81I\96\82\96@\82Ì\96î\82ª\89J\82 \82ç\82ê\82Æ\96½\92\86\82µ\82½\81I");
1333 #endif
1334         return realizes_damage;
1335     }
1336
1337     if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
1338         /* Magicbane's special attacks (possibly modifies hittee[]) */
1339         return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
1340     }
1341
1342     if (!spec_dbon_applies) {
1343         /* since damage bonus didn't apply, nothing more to do;
1344            no further attacks have side-effects on inventory */
1345         return FALSE;
1346     }
1347
1348     /* We really want "on a natural 20" but Nethack does it in */
1349     /* reverse from AD&D. */
1350     if (spec_ability(otmp, SPFX_BEHEAD)) {
1351         if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) {
1352 /*JP
1353             wepdesc = "The razor-sharp blade";
1354 */
1355             wepdesc = "\8ea\93S\8c\95";
1356             /* not really beheading, but so close, why add another SPFX */
1357             if (youattack && u.uswallow && mdef == u.ustuck) {
1358 /*JP
1359                 You("slice %s wide open!", mon_nam(mdef));
1360 */
1361                 You("%s\82ð\97Ö\90Ø\82è\82É\82µ\82½\81I", mon_nam(mdef));
1362                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1363                 return TRUE;
1364             }
1365             if (!youdefend) {
1366                 /* allow normal cutworm() call to add extra damage */
1367                 if (notonhead)
1368                     return FALSE;
1369
1370                 if (bigmonst(mdef->data)) {
1371                     if (youattack)
1372 /*JP
1373                         You("slice deeply into %s!", mon_nam(mdef));
1374 */
1375                         You("%s\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I",mon_nam(mdef));
1376                     else if (vis)
1377 #if 0 /*JP*/
1378                         pline("%s cuts deeply into %s!", Monnam(magr),
1379                               hittee);
1380 #else
1381                         pline("%s\82Í%s\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I", Monnam(magr),
1382                               hittee);
1383 #endif
1384                     *dmgptr *= 2;
1385                     return TRUE;
1386                 }
1387                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1388 /*JP
1389                 pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
1390 */
1391                 pline("%s\82ª%s\82ð\90^\82Á\93ñ\82Â\82É\82µ\82½\81I", wepdesc, mon_nam(mdef));
1392                 otmp->dknown = TRUE;
1393                 return TRUE;
1394             } else {
1395                 if (bigmonst(youmonst.data)) {
1396 /*JP
1397                     pline("%s cuts deeply into you!",
1398 */
1399                     pline("%s\82Í\82 \82È\82½\82É\90[\82­\8ea\82è\82Â\82¯\82½\81I",
1400                           magr ? Monnam(magr) : wepdesc);
1401                     *dmgptr *= 2;
1402                     return TRUE;
1403                 }
1404
1405                 /* Players with negative AC's take less damage instead
1406                  * of just not getting hit.  We must add a large enough
1407                  * value to the damage so that this reduction in
1408                  * damage does not prevent death.
1409                  */
1410                 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1411 /*JP
1412                 pline("%s cuts you in half!", wepdesc);
1413 */
1414                 pline("%s\82ª\82 \82È\82½\82ð\90^\82Á\93ñ\82Â\82É\82µ\82½\81I", wepdesc);
1415                 otmp->dknown = TRUE;
1416                 return TRUE;
1417             }
1418         } else if (otmp->oartifact == ART_VORPAL_BLADE
1419                    && (dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) {
1420 #if 0 /*JP*/
1421             static const char *const behead_msg[2] = { "%s beheads %s!",
1422                                                        "%s decapitates %s!" };
1423 #else
1424             static const char *const behead_msg[2] = { "%s\82Í%s\82Ì\8eñ\82ð\90Ø\82Á\82½\81I",
1425                                                        "%s\82Í%s\82Ì\8eñ\82ð\90Ø\82è\97\8e\82µ\82½\81I" };
1426 #endif
1427
1428             if (youattack && u.uswallow && mdef == u.ustuck)
1429                 return FALSE;
1430             wepdesc = artilist[ART_VORPAL_BLADE].name;
1431             if (!youdefend) {
1432                 if (!has_head(mdef->data) || notonhead || u.uswallow) {
1433                     if (youattack)
1434 /*JP
1435                         pline("Somehow, you miss %s wildly.", mon_nam(mdef));
1436 */
1437                         pline("\82È\82º\82©\81C%s\82Ö\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D", mon_nam(mdef));
1438                     else if (vis)
1439 /*JP
1440                         pline("Somehow, %s misses wildly.", mon_nam(magr));
1441 */
1442                         pline("\82È\82º\82©\81C%s\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D", mon_nam(magr));
1443                     *dmgptr = 0;
1444                     return (boolean) (youattack || vis);
1445                 }
1446                 if (noncorporeal(mdef->data) || amorphous(mdef->data)) {
1447 #if 0 /*JP*/
1448                     pline("%s slices through %s %s.", wepdesc,
1449                           s_suffix(mon_nam(mdef)), mbodypart(mdef, NECK));
1450 #else
1451                     pline("%s\82Í%s\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
1452                           mon_nam(mdef), mbodypart(mdef, NECK));
1453 #endif
1454                     return TRUE;
1455                 }
1456                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1457                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc,
1458                       mon_nam(mdef));
1459                 if (Hallucination && !flags.female)
1460 /*JP
1461                     pline("Good job Henry, but that wasn't Anne.");
1462 */
1463                     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");
1464                 otmp->dknown = TRUE;
1465                 return TRUE;
1466             } else {
1467                 if (!has_head(youmonst.data)) {
1468 /*JP
1469                     pline("Somehow, %s misses you wildly.",
1470 */
1471                     pline("\82È\82º\82©\81C%s\82Ì\8dU\8c\82\82Í\91å\82«\82­\82Í\82¸\82ê\82½\81D",
1472                           magr ? mon_nam(magr) : wepdesc);
1473                     *dmgptr = 0;
1474                     return TRUE;
1475                 }
1476                 if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) {
1477 /*JP
1478                     pline("%s slices through your %s.", wepdesc,
1479 */
1480                     pline("%s\82Í\82 \82È\82½\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
1481                           body_part(NECK));
1482                     return TRUE;
1483                 }
1484                 *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
1485 /*JP
1486                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
1487 */
1488                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "\82 \82È\82½");
1489                 otmp->dknown = TRUE;
1490                 /* Should amulets fall off? */
1491                 return TRUE;
1492             }
1493         }
1494     }
1495     if (spec_ability(otmp, SPFX_DRLI)) {
1496         /* some non-living creatures (golems, vortices) are
1497            vulnerable to life drain effects */
1498 /*JP
1499         const char *life = nonliving(mdef->data) ? "animating force" : "life";
1500 */
1501         const char *life = nonliving(mdef->data) ? "\93®\8dì\97Í" : "\90\96½\97Í";
1502
1503         if (!youdefend) {
1504             if (vis) {
1505                 if (otmp->oartifact == ART_STORMBRINGER)
1506 #if 0 /*JP*/
1507                     pline_The("%s blade draws the %s from %s!",
1508                               hcolor(NH_BLACK), life, mon_nam(mdef));
1509 #else
1510                     pline("%s\90n\82ª%s\82Ì%s\82ð\92D\82Á\82½\81I",
1511                               hcolor(NH_BLACK), mon_nam(mdef), life);
1512 #endif
1513                 else
1514 #if 0 /*JP*/
1515                     pline("%s draws the %s from %s!",
1516                           The(distant_name(otmp, xname)), life,
1517                           mon_nam(mdef));
1518 #else
1519                     pline("%s\82Í%s\82Ì%s\82ð\92D\82Á\82½\81I",
1520                           The(distant_name(otmp, xname)),
1521                           mon_nam(mdef), life);
1522 #endif
1523             }
1524             if (mdef->m_lev == 0) {
1525                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
1526             } else {
1527                 int drain = monhp_per_lvl(mdef);
1528
1529                 *dmgptr += drain;
1530                 mdef->mhpmax -= drain;
1531                 mdef->m_lev--;
1532                 drain /= 2;
1533                 if (drain)
1534                     healup(drain, 0, FALSE, FALSE);
1535             }
1536             return vis;
1537         } else { /* youdefend */
1538             int oldhpmax = u.uhpmax;
1539
1540             if (Blind)
1541 #if 0 /*JP*/
1542                 You_feel("an %s drain your %s!",
1543                          (otmp->oartifact == ART_STORMBRINGER)
1544                             ? "unholy blade"
1545                             : "object",
1546                          life);
1547 #else
1548                 pline("%s\82É%s\82ð\92D\82í\82ê\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I",
1549                          (otmp->oartifact == ART_STORMBRINGER)
1550                             ? "\95s\8fò\82È\90n"
1551                             : "\89½\82©",
1552                          life);
1553 #endif
1554             else if (otmp->oartifact == ART_STORMBRINGER)
1555 /*JP
1556                 pline_The("%s blade drains your %s!", hcolor(NH_BLACK), life);
1557 */
1558                 pline("%s\90n\82ª\82 \82È\82½\82Ì%s\82ð\92D\82Á\82½\81I", hcolor(NH_BLACK), life);
1559             else
1560 #if 0 /*JP*/
1561                 pline("%s drains your %s!", The(distant_name(otmp, xname)),
1562                       life);
1563 #else
1564                 pline("%s\82ª\82 \82È\82½\82Ì%s\82ð\92D\82Á\82½\81I", The(distant_name(otmp, xname)),
1565                       life);
1566 #endif
1567 /*JP
1568             losexp("life drainage");
1569 */
1570             losexp("\90\96½\97Í\82ð\8bz\8eû\82³\82ê\82Ä");
1571             if (magr && magr->mhp < magr->mhpmax) {
1572                 magr->mhp += (oldhpmax - u.uhpmax) / 2;
1573                 if (magr->mhp > magr->mhpmax)
1574                     magr->mhp = magr->mhpmax;
1575             }
1576             return TRUE;
1577         }
1578     }
1579     return FALSE;
1580 }
1581
1582 static NEARDATA const char recharge_type[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
1583 static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 };
1584 /* #invoke: an "ugly check" filters out most objects */
1585
1586 /* the #invoke command */
1587 int
1588 doinvoke()
1589 {
1590     struct obj *obj;
1591
1592     obj = getobj(invoke_types, "invoke");
1593     if (!obj)
1594         return 0;
1595     if (!retouch_object(&obj, FALSE))
1596         return 1;
1597     return arti_invoke(obj);
1598 }
1599
1600 STATIC_OVL int
1601 arti_invoke(obj)
1602 struct obj *obj;
1603 {
1604     register const struct artifact *oart = get_artifact(obj);
1605     if (!obj) {
1606         impossible("arti_invoke without obj");
1607         return 0;
1608     }
1609     if (!oart || !oart->inv_prop) {
1610         if (obj->otyp == CRYSTAL_BALL)
1611             use_crystal_ball(&obj);
1612         else
1613             pline1(nothing_happens);
1614         return 1;
1615     }
1616
1617     if (oart->inv_prop > LAST_PROP) {
1618         /* It's a special power, not "just" a property */
1619         if (obj->age > monstermoves) {
1620             /* the artifact is tired :-) */
1621 #if 0 /*JP:T*/
1622             You_feel("that %s %s ignoring you.", the(xname(obj)),
1623                      otense(obj, "are"));
1624 #else
1625             You_feel("%s\82ª\96³\8e\8b\82µ\82Ä\82¢\82é\82æ\82¤\82É\8a´\82\82½\81D", xname(obj));
1626 #endif
1627             /* and just got more so; patience is essential... */
1628             obj->age += (long) d(3, 10);
1629             return 1;
1630         }
1631         obj->age = monstermoves + rnz(100);
1632
1633         switch (oart->inv_prop) {
1634         case TAMING: {
1635             struct obj pseudo;
1636
1637             pseudo =
1638                 zeroobj; /* neither cursed nor blessed, zero oextra too */
1639             pseudo.otyp = SCR_TAMING;
1640             (void) seffects(&pseudo);
1641             break;
1642         }
1643         case HEALING: {
1644             int healamt = (u.uhpmax + 1 - u.uhp) / 2;
1645             long creamed = (long) u.ucreamed;
1646
1647             if (Upolyd)
1648                 healamt = (u.mhmax + 1 - u.mh) / 2;
1649             if (healamt || Sick || Slimed || Blinded > creamed)
1650 /*JP
1651                 You_feel("better.");
1652 */
1653                 You_feel("\8bC\95ª\82ª\82æ\82­\82È\82Á\82½\81D");
1654             else
1655                 goto nothing_special;
1656             if (healamt > 0) {
1657                 if (Upolyd)
1658                     u.mh += healamt;
1659                 else
1660                     u.uhp += healamt;
1661             }
1662             if (Sick)
1663                 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1664             if (Slimed)
1665                 make_slimed(0L, (char *) 0);
1666             if (Blinded > creamed)
1667                 make_blinded(creamed, FALSE);
1668             context.botl = TRUE;
1669             break;
1670         }
1671         case ENERGY_BOOST: {
1672             int epboost = (u.uenmax + 1 - u.uen) / 2;
1673
1674             if (epboost > 120)
1675                 epboost = 120; /* arbitrary */
1676             else if (epboost < 12)
1677                 epboost = u.uenmax - u.uen;
1678             if (epboost) {
1679                 u.uen += epboost;
1680                 context.botl = TRUE;
1681 /*JP
1682                 You_feel("re-energized.");
1683 */
1684                 You("\83G\83l\83\8b\83M\81[\82Å\96\9e\82½\82³\82ê\82½\81D");
1685             } else
1686                 goto nothing_special;
1687             break;
1688         }
1689         case UNTRAP: {
1690             if (!untrap(TRUE)) {
1691                 obj->age = 0; /* don't charge for changing their mind */
1692                 return 0;
1693             }
1694             break;
1695         }
1696         case CHARGE_OBJ: {
1697             struct obj *otmp = getobj(recharge_type, "charge");
1698             boolean b_effect;
1699
1700             if (!otmp) {
1701                 obj->age = 0;
1702                 return 0;
1703             }
1704             b_effect = (obj->blessed && (oart->role == Role_switch
1705                                          || oart->role == NON_PM));
1706             recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
1707             update_inventory();
1708             break;
1709         }
1710         case LEV_TELE:
1711             level_tele();
1712             break;
1713         case CREATE_PORTAL: {
1714             int i, num_ok_dungeons, last_ok_dungeon = 0;
1715             d_level newlev;
1716             extern int n_dgns; /* from dungeon.c */
1717             winid tmpwin = create_nhwindow(NHW_MENU);
1718             anything any;
1719
1720             any = zeroany; /* set all bits to zero */
1721             start_menu(tmpwin);
1722             /* use index+1 (cant use 0) as identifier */
1723             for (i = num_ok_dungeons = 0; i < n_dgns; i++) {
1724                 if (!dungeons[i].dunlev_ureached)
1725                     continue;
1726                 any.a_int = i + 1;
1727                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1728                          dungeons[i].dname, MENU_UNSELECTED);
1729                 num_ok_dungeons++;
1730                 last_ok_dungeon = i;
1731             }
1732 /*JP
1733             end_menu(tmpwin, "Open a portal to which dungeon?");
1734 */
1735             end_menu(tmpwin, "\82Ç\82Ì\96À\8b{\82Ö\82Ì\96\82\96@\82Ì\93ü\8cû\82ð\8aJ\82«\82Ü\82·\82©\81H");
1736             if (num_ok_dungeons > 1) {
1737                 /* more than one entry; display menu for choices */
1738                 menu_item *selected;
1739                 int n;
1740
1741                 n = select_menu(tmpwin, PICK_ONE, &selected);
1742                 if (n <= 0) {
1743                     destroy_nhwindow(tmpwin);
1744                     goto nothing_special;
1745                 }
1746                 i = selected[0].item.a_int - 1;
1747                 free((genericptr_t) selected);
1748             } else
1749                 i = last_ok_dungeon; /* also first & only OK dungeon */
1750             destroy_nhwindow(tmpwin);
1751
1752             /*
1753              * i is now index into dungeon structure for the new dungeon.
1754              * Find the closest level in the given dungeon, open
1755              * a use-once portal to that dungeon and go there.
1756              * The closest level is either the entry or dunlev_ureached.
1757              */
1758             newlev.dnum = i;
1759             if (dungeons[i].depth_start >= depth(&u.uz))
1760                 newlev.dlevel = dungeons[i].entry_lev;
1761             else
1762                 newlev.dlevel = dungeons[i].dunlev_ureached;
1763
1764             if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
1765                 || newlev.dnum == u.uz.dnum || !next_to_u()) {
1766 /*JP
1767                 You_feel("very disoriented for a moment.");
1768 */
1769                 You("\88ê\8fu\95û\8cü\8a´\8ao\82ð\8e¸\82Á\82½\81D");
1770             } else {
1771                 if (!Blind)
1772 /*JP
1773                     You("are surrounded by a shimmering sphere!");
1774 */
1775                     You("\83`\83J\83`\83J\8cõ\82é\8b\85\91Ì\82É\95¢\82í\82ê\82½\81I");
1776                 else
1777 /*JP
1778                     You_feel("weightless for a moment.");
1779 */
1780                     You_feel("\88ê\8fu\81C\96³\8fd\97Í\8a´\82ð\8a´\82\82½\81D");
1781                 goto_level(&newlev, FALSE, FALSE, FALSE);
1782             }
1783             break;
1784         }
1785         case ENLIGHTENING:
1786             enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
1787             break;
1788         case CREATE_AMMO: {
1789             struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
1790
1791             if (!otmp)
1792                 goto nothing_special;
1793             otmp->blessed = obj->blessed;
1794             otmp->cursed = obj->cursed;
1795             otmp->bknown = obj->bknown;
1796             if (obj->blessed) {
1797                 if (otmp->spe < 0)
1798                     otmp->spe = 0;
1799                 otmp->quan += rnd(10);
1800             } else if (obj->cursed) {
1801                 if (otmp->spe > 0)
1802                     otmp->spe = 0;
1803             } else
1804                 otmp->quan += rnd(5);
1805             otmp->owt = weight(otmp);
1806 #if 0 /*JP*/
1807             otmp = hold_another_object(otmp, "Suddenly %s out.",
1808                                        aobjnam(otmp, "fall"), (char *) 0);
1809 #else
1810             otmp = hold_another_object(otmp, "\93Ë\91R%s\82ª\97\8e\82¿\82½\81D",
1811                                        xname(otmp), 0);
1812 #endif
1813             nhUse(otmp);
1814             break;
1815         }
1816         }
1817     } else {
1818         long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
1819              iprop = u.uprops[oart->inv_prop].intrinsic;
1820         boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */
1821
1822         if (on && obj->age > monstermoves) {
1823             /* the artifact is tired :-) */
1824             u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
1825 #if 0 /*JP:T*/
1826             You_feel("that %s %s ignoring you.", the(xname(obj)),
1827                      otense(obj, "are"));
1828 #else
1829             You_feel("%s\82ª\96³\8e\8b\82µ\82Ä\82¢\82é\82æ\82¤\82É\8a´\82\82½\81D", xname(obj));
1830 #endif
1831             /* can't just keep repeatedly trying */
1832             obj->age += (long) d(3, 10);
1833             return 1;
1834         } else if (!on) {
1835             /* when turning off property, determine downtime */
1836             /* arbitrary for now until we can tune this -dlc */
1837             obj->age = monstermoves + rnz(100);
1838         }
1839
1840         if ((eprop & ~W_ARTI) || iprop) {
1841  nothing_special:
1842             /* you had the property from some other source too */
1843             if (carried(obj))
1844 /*JP
1845                 You_feel("a surge of power, but nothing seems to happen.");
1846 */
1847                 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");
1848             return 1;
1849         }
1850         switch (oart->inv_prop) {
1851         case CONFLICT:
1852             if (on)
1853 /*JP
1854                 You_feel("like a rabble-rouser.");
1855 */
1856                 You("\96¯\8fO\90î\93®\89Æ\82Ì\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
1857             else
1858 /*JP
1859                 You_feel("the tension decrease around you.");
1860 */
1861                 pline("\82Ü\82í\82è\82Ì\8bÙ\92£\8a´\82ª\82È\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
1862             break;
1863         case LEVITATION:
1864             if (on) {
1865                 float_up();
1866                 spoteffects(FALSE);
1867             } else
1868                 (void) float_down(I_SPECIAL | TIMEOUT, W_ARTI);
1869             break;
1870         case INVIS:
1871             if (BInvis || Blind)
1872                 goto nothing_special;
1873             newsym(u.ux, u.uy);
1874             if (on)
1875 #if 0 /*JP*/
1876                 Your("body takes on a %s transparency...",
1877                      Hallucination ? "normal" : "strange");
1878 #else
1879                 pline("%s\81C\91Ì\82Í\93§\89ß\90«\82ð\82à\82Á\82½\81D\81D\81D",
1880                       Hallucination ? "\82 \82½\82è\82Ü\82¦\82Ì\82±\82Æ\82¾\82ª" : "\8aï\96­\82È\82±\82Æ\82É");
1881 #endif
1882             else
1883 /*JP
1884                 Your("body seems to unfade...");
1885 */
1886                 Your("\91Ì\82Í\8e\9f\91æ\82É\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82Ä\82«\82½\81D\81D\81D");
1887             break;
1888         }
1889     }
1890
1891     return 1;
1892 }
1893
1894 /* will freeing this object from inventory cause levitation to end? */
1895 boolean
1896 finesse_ahriman(obj)
1897 struct obj *obj;
1898 {
1899     const struct artifact *oart;
1900     struct prop save_Lev;
1901     boolean result;
1902
1903     /* if we aren't levitating or this isn't an artifact which confers
1904        levitation via #invoke then freeinv() won't toggle levitation */
1905     if (!Levitation || (oart = get_artifact(obj)) == 0
1906         || oart->inv_prop != LEVITATION || !(ELevitation & W_ARTI))
1907         return FALSE;
1908
1909     /* arti_invoke(off) -> float_down() clears I_SPECIAL|TIMEOUT & W_ARTI;
1910        probe ahead to see whether that actually results in floating down;
1911        (this assumes that there aren't two simultaneously invoked artifacts
1912        both conferring levitation--safe, since if there were two of them,
1913        invoking the 2nd would negate the 1st rather than stack with it) */
1914     save_Lev = u.uprops[LEVITATION];
1915     HLevitation &= ~(I_SPECIAL | TIMEOUT);
1916     ELevitation &= ~W_ARTI;
1917     result = (boolean) !Levitation;
1918     u.uprops[LEVITATION] = save_Lev;
1919     return result;
1920 }
1921
1922 /* WAC return TRUE if artifact is always lit */
1923 boolean
1924 artifact_light(obj)
1925 struct obj *obj;
1926 {
1927     return (boolean) (get_artifact(obj) && obj->oartifact == ART_SUNSWORD);
1928 }
1929
1930 /* KMH -- Talking artifacts are finally implemented */
1931 void
1932 arti_speak(obj)
1933 struct obj *obj;
1934 {
1935     register const struct artifact *oart = get_artifact(obj);
1936     const char *line;
1937     char buf[BUFSZ];
1938
1939     /* Is this a speaking artifact? */
1940     if (!oart || !(oart->spfx & SPFX_SPEAK))
1941         return;
1942
1943     line = getrumor(bcsign(obj), buf, TRUE);
1944     if (!*line)
1945 /*JP
1946         line = "NetHack rumors file closed for renovation.";
1947 */
1948         line = "\89\\82Ì\90^\91\8a\82Í\90V\91\95\82Ì\82½\82ß\88ê\8e\9e\95Â\93X\81D";
1949 /*JP
1950     pline("%s:", Tobjnam(obj, "whisper"));
1951 */
1952     pline("%s\82Í\82³\82³\82â\82¢\82½\81F", xname(obj));
1953     verbalize1(line);
1954     return;
1955 }
1956
1957 boolean
1958 artifact_has_invprop(otmp, inv_prop)
1959 struct obj *otmp;
1960 uchar inv_prop;
1961 {
1962     const struct artifact *arti = get_artifact(otmp);
1963
1964     return (boolean) (arti && (arti->inv_prop == inv_prop));
1965 }
1966
1967 /* Return the price sold to the hero of a given artifact or unique item */
1968 long
1969 arti_cost(otmp)
1970 struct obj *otmp;
1971 {
1972     if (!otmp->oartifact)
1973         return (long) objects[otmp->otyp].oc_cost;
1974     else if (artilist[(int) otmp->oartifact].cost)
1975         return artilist[(int) otmp->oartifact].cost;
1976     else
1977         return (100L * (long) objects[otmp->otyp].oc_cost);
1978 }
1979
1980 STATIC_OVL uchar
1981 abil_to_adtyp(abil)
1982 long *abil;
1983 {
1984     struct abil2adtyp_tag {
1985         long *abil;
1986         uchar adtyp;
1987     } abil2adtyp[] = {
1988         { &EFire_resistance, AD_FIRE },
1989         { &ECold_resistance, AD_COLD },
1990         { &EShock_resistance, AD_ELEC },
1991         { &EAntimagic, AD_MAGM },
1992         { &EDisint_resistance, AD_DISN },
1993         { &EPoison_resistance, AD_DRST },
1994         { &EDrain_resistance, AD_DRLI },
1995     };
1996     int k;
1997
1998     for (k = 0; k < SIZE(abil2adtyp); k++) {
1999         if (abil2adtyp[k].abil == abil)
2000             return abil2adtyp[k].adtyp;
2001     }
2002     return 0;
2003 }
2004
2005 STATIC_OVL unsigned long
2006 abil_to_spfx(abil)
2007 long *abil;
2008 {
2009     static const struct abil2spfx_tag {
2010         long *abil;
2011         unsigned long spfx;
2012     } abil2spfx[] = {
2013         { &ESearching, SPFX_SEARCH },
2014         { &EHalluc_resistance, SPFX_HALRES },
2015         { &ETelepat, SPFX_ESP },
2016         { &EStealth, SPFX_STLTH },
2017         { &ERegeneration, SPFX_REGEN },
2018         { &ETeleport_control, SPFX_TCTRL },
2019         { &EWarn_of_mon, SPFX_WARN },
2020         { &EWarning, SPFX_WARN },
2021         { &EEnergy_regeneration, SPFX_EREGEN },
2022         { &EHalf_spell_damage, SPFX_HSPDAM },
2023         { &EHalf_physical_damage, SPFX_HPHDAM },
2024         { &EReflecting, SPFX_REFLECT },
2025     };
2026     int k;
2027
2028     for (k = 0; k < SIZE(abil2spfx); k++) {
2029         if (abil2spfx[k].abil == abil)
2030             return abil2spfx[k].spfx;
2031     }
2032     return 0L;
2033 }
2034
2035 /*
2036  * Return the first item that is conveying a particular intrinsic.
2037  */
2038 struct obj *
2039 what_gives(abil)
2040 long *abil;
2041 {
2042     struct obj *obj;
2043     uchar dtyp;
2044     unsigned long spfx;
2045     long wornbits;
2046     long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS
2047                      | W_ARMG | W_ARMF | W_ARMU
2048                      | W_AMUL | W_RINGL | W_RINGR | W_TOOL
2049                      | W_ART | W_ARTI);
2050
2051     if (u.twoweap)
2052         wornmask |= W_SWAPWEP;
2053     dtyp = abil_to_adtyp(abil);
2054     spfx = abil_to_spfx(abil);
2055     wornbits = (wornmask & *abil);
2056
2057     for (obj = invent; obj; obj = obj->nobj) {
2058         if (obj->oartifact
2059             && (abil != &EWarn_of_mon || context.warntype.obj)) {
2060             const struct artifact *art = get_artifact(obj);
2061
2062             if (art) {
2063                 if (dtyp) {
2064                     if (art->cary.adtyp == dtyp /* carried */
2065                         || (art->defn.adtyp == dtyp /* defends while worn */
2066                             && (obj->owornmask & ~(W_ART | W_ARTI))))
2067                         return obj;
2068                 }
2069                 if (spfx) {
2070                     /* property conferred when carried */
2071                     if ((art->cspfx & spfx) == spfx)
2072                         return obj;
2073                     /* property conferred when wielded or worn */
2074                     if ((art->spfx & spfx) == spfx && obj->owornmask)
2075                         return obj;
2076                 }
2077             }
2078         } else {
2079             if (wornbits && wornbits == (wornmask & obj->owornmask))
2080                 return obj;
2081         }
2082     }
2083     return (struct obj *) 0;
2084 }
2085
2086 #if 1 /*JP*/
2087 /*JP colornames\82Í\90Ý\92è\83t\83@\83C\83\8b\82Å\8eg\82¤\82Ì\82Å\96|\96ó\82¹\82¸\81A
2088      \93ú\96{\8cê\90ê\97p\82Ì\94z\97ñ\82ð\95Ê\82É\97p\88Ó\82·\82é\81B
2089 */
2090 static const struct {
2091     const char *name;
2092     const int color;
2093 } colornames2[] = {
2094     { "\8d\95\82¢", CLR_BLACK },
2095     { "\90Ô\82¢", CLR_RED },
2096     { "\97Î\90F\82Ì", CLR_GREEN },
2097     { "\92\83\90F\82¢", CLR_BROWN },
2098     { "\90Â\82¢", CLR_BLUE },
2099     { "\83}\83[\83\93\83^\90F\82Ì", CLR_MAGENTA },
2100     { "\83V\83A\83\93\90F\82Ì", CLR_CYAN },
2101     { "\8aD\90F\82Ì", CLR_GRAY },
2102     { "\8aD\90F\82Ì", CLR_GRAY },
2103     { "\83I\83\8c\83\93\83W\90F\82Ì", CLR_ORANGE },
2104     { "\92W\97Î\90F\82Ì", CLR_BRIGHT_GREEN },
2105     { "\89©\90F\82¢", CLR_YELLOW },
2106     { "\92W\90Â\90F\82Ì", CLR_BRIGHT_BLUE },
2107     { "\96¾\82é\82¢\83}\83[\83\93\83^\90F\82Ì", CLR_BRIGHT_MAGENTA },
2108     { "\96¾\82é\82¢\83V\83A\83\93\90F\82Ì", CLR_BRIGHT_CYAN },
2109     { "\94\92\82¢", CLR_WHITE }
2110 };
2111
2112 static const char *
2113 clr2colorname2(clr)
2114 int clr;
2115 {
2116     int i;
2117
2118     for (i = 0; i < SIZE(colornames2); i++)
2119         if (colornames2[i].color == clr)
2120             return colornames2[i].name;
2121     return (char *) 0;
2122 }
2123 #endif
2124
2125 const char *
2126 glow_color(arti_indx)
2127 int arti_indx;
2128 {
2129     int colornum = artilist[arti_indx].acolor;
2130 #if 0 /*JP*/
2131     const char *colorstr = clr2colorname(colornum);
2132 #else
2133     const char *colorstr = jconj_adj(clr2colorname2(colornum));
2134 #endif
2135
2136     return hcolor(colorstr);
2137 }
2138
2139 /* glow verb; [0] holds the value used when blind */
2140 static const char *glow_verbs[] = {
2141 /*JP
2142     "quiver", "flicker", "glimmer", "gleam"
2143 */
2144     "\90k\82¦\82é", "\82Ü\82½\82½\82­", "\8cõ\82é", "\8bP\82­"
2145 };
2146
2147 /* relative strength that Sting is glowing (0..3), to select verb */
2148 STATIC_OVL int
2149 glow_strength(count)
2150 int count;
2151 {
2152     /* glow strength should also be proportional to proximity and
2153        probably difficulty, but we don't have that information and
2154        gathering it is more trouble than this would be worth */
2155     return (count > 12) ? 3 : (count > 4) ? 2 : (count > 0);
2156 }
2157
2158 const char *
2159 glow_verb(count, ingsfx)
2160 int count; /* 0 means blind rather than no applicable creatures */
2161 boolean ingsfx;
2162 {
2163     static char resbuf[20];
2164
2165     Strcpy(resbuf, glow_verbs[glow_strength(count)]);
2166     /* ing_suffix() will double the last consonant for all the words
2167        we're using and none of them should have that, so bypass it */
2168 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8eg\82í\82È\82¢*/
2169     if (ingsfx)
2170         Strcat(resbuf, "ing");
2171 #endif
2172     return resbuf;
2173 }
2174
2175 /* use for warning "glow" for Sting, Orcrist, and Grimtooth */
2176 void
2177 Sting_effects(orc_count)
2178 int orc_count; /* new count (warn_obj_cnt is old count); -1 is a flag value */
2179 {
2180     if (uwep
2181         && (uwep->oartifact == ART_STING
2182             || uwep->oartifact == ART_ORCRIST
2183             || uwep->oartifact == ART_GRIMTOOTH)) {
2184         int oldstr = glow_strength(warn_obj_cnt),
2185             newstr = glow_strength(orc_count);
2186
2187         if (orc_count == -1 && warn_obj_cnt > 0) {
2188             /* -1 means that blindness has just been toggled; give a
2189                'continue' message that eventual 'stop' message will match */
2190 #if 0 /*JP*/
2191             pline("%s is %s.", bare_artifactname(uwep),
2192                   glow_verb(Blind ? 0 : warn_obj_cnt, TRUE));
2193 #else
2194             pline("%s\82Í%s\82¢\82é\81D", bare_artifactname(uwep),
2195                   jconj(glow_verb(Blind ? 0 : warn_obj_cnt, TRUE), "\82Ä"));
2196 #endif
2197         } else if (newstr > 0 && newstr != oldstr) {
2198             /* 'start' message */
2199             if (!Blind)
2200 #if 0 /*JP*/
2201                 pline("%s %s %s%c", bare_artifactname(uwep),
2202                       otense(uwep, glow_verb(orc_count, FALSE)),
2203                       glow_color(uwep->oartifact),
2204                       (newstr > oldstr) ? '!' : '.');
2205 #else
2206                 pline("%s\82Í%s%s%s", bare_artifactname(uwep),
2207                       jconj_adj(glow_color(uwep->oartifact)),
2208                       jconj(glow_verb(orc_count, FALSE), "\82½"),
2209                       (newstr > oldstr) ? "\81I" : "\81D");
2210 #endif
2211             else if (oldstr == 0) /* quivers */
2212 #if 0 /*JP*/
2213                 pline("%s %s slightly.", bare_artifactname(uwep),
2214                       otense(uwep, glow_verb(0, FALSE)));
2215 #else
2216                 pline("%s\82Í\8f­\82µ\90k\82¦\82½\81D", bare_artifactname(uwep));
2217 #endif
2218         } else if (orc_count == 0 && warn_obj_cnt > 0) {
2219             /* 'stop' message */
2220 #if 0 /*JP*/
2221             pline("%s stops %s.", bare_artifactname(uwep),
2222                   glow_verb(Blind ? 0 : warn_obj_cnt, TRUE));
2223 #else
2224             pline("%s\82Í%s\82Ì\82ð\82â\82ß\82½\81D", bare_artifactname(uwep),
2225                   glow_verb(Blind ? 0 : warn_obj_cnt, TRUE));
2226 #endif
2227         }
2228     }
2229 }
2230
2231 /* called when hero is wielding/applying/invoking a carried item, or
2232    after undergoing a transformation (alignment change, lycanthropy,
2233    polymorph) which might affect item access */
2234 int
2235 retouch_object(objp, loseit)
2236 struct obj **objp; /* might be destroyed or unintentionally dropped */
2237 boolean loseit;    /* whether to drop it if hero can longer touch it */
2238 {
2239     struct obj *obj = *objp;
2240
2241     if (touch_artifact(obj, &youmonst)) {
2242         char buf[BUFSZ];
2243         int dmg = 0, tmp;
2244         boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver),
2245                 bane = bane_applies(get_artifact(obj), &youmonst);
2246
2247         /* nothing else to do if hero can successfully handle this object */
2248         if (!ag && !bane)
2249             return 1;
2250
2251         /* hero can't handle this object, but didn't get touch_artifact()'s
2252            "<obj> evades your grasp|control" message; give an alternate one */
2253 #if 0 /*JP*/
2254         You_cant("handle %s%s!", yname(obj),
2255                  obj->owornmask ? " anymore" : "");
2256 #else
2257         You_cant("%s%s\82ð\88µ\82¦\82È\82¢\81I", obj->owornmask ? "\82à\82¤" : "",
2258                  xname(obj));
2259 #endif
2260         /* also inflict damage unless touch_artifact() already did so */
2261         if (!touch_blasted) {
2262             /* damage is somewhat arbitrary; half the usual 1d20 physical
2263                for silver, 1d10 magical for <foo>bane, potentially both */
2264             if (ag)
2265                 tmp = rnd(10), dmg += Maybe_Half_Phys(tmp);
2266             if (bane)
2267                 dmg += rnd(10);
2268 /*JP
2269             Sprintf(buf, "handling %s", killer_xname(obj));
2270 */
2271             Sprintf(buf, "%s\82ð\88µ\82Á\82Ä", killer_xname(obj));
2272             losehp(dmg, buf, KILLED_BY);
2273             exercise(A_CON, FALSE);
2274         }
2275     }
2276
2277     /* removing a worn item might result in loss of levitation,
2278        dropping the hero onto a polymorph trap or into water or
2279        lava and potentially dropping or destroying the item */
2280     if (obj->owornmask) {
2281         struct obj *otmp;
2282
2283         remove_worn_item(obj, FALSE);
2284         for (otmp = invent; otmp; otmp = otmp->nobj)
2285             if (otmp == obj)
2286                 break;
2287         if (!otmp)
2288             *objp = obj = 0;
2289     }
2290
2291     /* if we still have it and caller wants us to drop it, do so now */
2292     if (loseit && obj) {
2293         if (Levitation) {
2294             freeinv(obj);
2295             hitfloor(obj, TRUE);
2296         } else {
2297             /* dropx gives a message iff item lands on an altar */
2298             if (!IS_ALTAR(levl[u.ux][u.uy].typ))
2299 #if 0 /*JP*/
2300                 pline("%s to the %s.", Tobjnam(obj, "fall"),
2301                       surface(u.ux, u.uy));
2302 #else
2303                 pline("%s\82Í%s\82É\97\8e\82¿\82½\81D", xname(obj),
2304                       surface(u.ux, u.uy));
2305 #endif
2306             dropx(obj);
2307         }
2308         *objp = obj = 0; /* no longer in inventory */
2309     }
2310     return 0;
2311 }
2312
2313 /* an item which is worn/wielded or an artifact which conveys
2314    something via being carried or which has an #invoke effect
2315    currently in operation undergoes a touch test; if it fails,
2316    it will be unworn/unwielded and revoked but not dropped */
2317 STATIC_OVL boolean
2318 untouchable(obj, drop_untouchable)
2319 struct obj *obj;
2320 boolean drop_untouchable;
2321 {
2322     struct artifact *art;
2323     boolean beingworn, carryeffect, invoked;
2324     long wearmask = ~(W_QUIVER | (u.twoweap ? 0L : W_SWAPWEP) | W_BALL);
2325
2326     beingworn = ((obj->owornmask & wearmask) != 0L
2327                  /* some items in use don't have any wornmask setting */
2328                  || (obj->oclass == TOOL_CLASS
2329                      && (obj->lamplit || (obj->otyp == LEASH && obj->leashmon)
2330                          || (Is_container(obj) && Has_contents(obj)))));
2331
2332     if ((art = get_artifact(obj)) != 0) {
2333         carryeffect = (art->cary.adtyp || art->cspfx);
2334         invoked = (art->inv_prop > 0 && art->inv_prop <= LAST_PROP
2335                    && (u.uprops[art->inv_prop].extrinsic & W_ARTI) != 0L);
2336     } else {
2337         carryeffect = invoked = FALSE;
2338     }
2339
2340     if (beingworn || carryeffect || invoked) {
2341         if (!retouch_object(&obj, drop_untouchable)) {
2342             /* "<artifact> is beyond your control" or "you can't handle
2343                <object>" has been given and it is now unworn/unwielded
2344                and possibly dropped (depending upon caller); if dropped,
2345                carried effect was turned off, else we leave that alone;
2346                we turn off invocation property here if still carried */
2347             if (invoked && obj)
2348                 arti_invoke(obj); /* reverse #invoke */
2349             return TRUE;
2350         }
2351     }
2352     return FALSE;
2353 }
2354
2355 /* check all items currently in use (mostly worn) for touchability */
2356 void
2357 retouch_equipment(dropflag)
2358 int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
2359 {
2360     static int nesting = 0; /* recursion control */
2361     struct obj *obj;
2362     boolean dropit, had_gloves = (uarmg != 0);
2363     int had_rings = (!!uleft + !!uright);
2364
2365     /*
2366      * We can potentially be called recursively if losing/unwearing
2367      * an item causes worn helm of opposite alignment to come off or
2368      * be destroyed.
2369      *
2370      * BUG: if the initial call was due to putting on a helm of
2371      * opposite alignment and it does come off to trigger recursion,
2372      * after the inner call executes, the outer call will finish
2373      * using the non-helm alignment rather than the helm alignment
2374      * which triggered this in the first place.
2375      */
2376     if (!nesting++)
2377         clear_bypasses(); /* init upon initial entry */
2378
2379     dropit = (dropflag > 0); /* drop all or drop weapon */
2380     /* check secondary weapon first, before possibly unwielding primary */
2381     if (u.twoweap) {
2382         bypass_obj(uswapwep); /* so loop below won't process it again */
2383         (void) untouchable(uswapwep, dropit);
2384     }
2385     /* check primary weapon next so that they're handled together */
2386     if (uwep) {
2387         bypass_obj(uwep); /* so loop below won't process it again */
2388         (void) untouchable(uwep, dropit);
2389     }
2390
2391     /* in case someone is daft enough to add artifact or silver saddle */
2392     if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
2393         /* untouchable() calls retouch_object() which expects an object in
2394            hero's inventory, but remove_worn_item() will be harmless for
2395            saddle and we're suppressing drop, so this works as intended */
2396         if (untouchable(obj, FALSE))
2397             dismount_steed(DISMOUNT_THROWN);
2398     }
2399     /*
2400      * TODO?  Force off gloves if either or both rings are going to
2401      * become unworn; force off cloak [suit] before suit [shirt].
2402      * The torso handling is hypothetical; the case for gloves is
2403      * not, due to the possibility of unwearing silver rings.
2404      */
2405
2406     dropit = (dropflag == 1); /* all untouchable items */
2407     /* loss of levitation (silver ring, or Heart of Ahriman invocation)
2408        might cause hero to lose inventory items (by dropping into lava,
2409        for instance), so inventory traversal needs to rescan the whole
2410        invent chain each time it moves on to another object; we use bypass
2411        handling to keep track of which items have already been processed */
2412     while ((obj = nxt_unbypassed_obj(invent)) != 0)
2413         (void) untouchable(obj, dropit);
2414
2415     if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
2416         uncurse(uarmg); /* temporary? hack for ring removal plausibility */
2417     if (had_gloves && !uarmg)
2418 /*JP
2419         selftouch("After losing your gloves, you");
2420 */
2421         selftouch("\8f¬\8eè\82ð\8e¸\82Á\82½\82 \82Æ\81C\82 \82È\82½\82Í");
2422
2423     if (!--nesting)
2424         clear_bypasses(); /* reset upon final exit */
2425 }
2426
2427 static int mkot_trap_warn_count = 0;
2428
2429 STATIC_OVL int
2430 count_surround_traps(x, y)
2431 int x, y;
2432 {
2433     struct rm *levp;
2434     struct obj *otmp;
2435     struct trap *ttmp;
2436     int dx, dy, glyph, ret = 0;
2437
2438     for (dx = x - 1; dx < x + 2; ++dx)
2439         for (dy = y - 1; dy < y + 2; ++dy) {
2440             if (!isok(dx, dy))
2441                 continue;
2442             /* If a trap is shown here, don't count it; the hero
2443              * should be expecting it.  But if there is a trap here
2444              * that's not shown, either undiscovered or covered by
2445              * something, do count it.
2446              */
2447             glyph = glyph_at(dx, dy);
2448             if (glyph_is_trap(glyph))
2449                 continue;
2450             if ((ttmp = t_at(dx, dy)) != 0) {
2451                 ++ret;
2452                 continue;
2453             }
2454             levp = &levl[dx][dy];
2455             if (IS_DOOR(levp->typ) && (levp->doormask & D_TRAPPED) != 0) {
2456                 ++ret;
2457                 continue;
2458             }
2459             for (otmp = level.objects[dx][dy]; otmp; otmp = otmp->nexthere)
2460                 if (Is_container(otmp) && otmp->otrapped) {
2461                     ++ret; /* we're counting locations, so just */
2462                     break; /* count the first one in a pile     */
2463                 }
2464         }
2465     /*
2466      * [Shouldn't we also check inventory for a trapped container?
2467      * Even if its trap has already been found, there's no 'tknown'
2468      * flag to help hero remember that so we have nothing comparable
2469      * to a shown glyph to justify skipping it.]
2470      */
2471     return ret;
2472 }
2473
2474 /* sense adjacent traps if wielding MKoT without wearing gloves */
2475 void
2476 mkot_trap_warn()
2477 {
2478 #if 0 /*JP*/
2479     static const char *const heat[7] = {
2480         "cool", "slightly warm", "warm", "very warm",
2481         "hot", "very hot", "like fire"
2482     };
2483 #else
2484     static const char *const heat[7] = {
2485         "\97â\82½\82­", "\8f­\82µ\89·\82©\82­", "\89·\82©\82­", "\82Æ\82Ä\82à\89·\82©\82­",
2486         "\94M\82­", "\82Æ\82Ä\82à\94M\82­", "\89\8a\82Ì\82æ\82¤\82É"
2487     };
2488 #endif
2489
2490     if (!uarmg && uwep && uwep->oartifact == ART_MASTER_KEY_OF_THIEVERY) {
2491         int idx, ntraps = count_surround_traps(u.ux, u.uy);
2492
2493         if (ntraps != mkot_trap_warn_count) {
2494             idx = min(ntraps, SIZE(heat) - 1);
2495 /*JP
2496             pline_The("Key feels %s%c", heat[idx], (ntraps > 3) ? '!' : '.');
2497 */
2498             pline_The("\8c®\82Í%s\8a´\82\82½%s", heat[idx], (ntraps > 3) ? "\81I" : "\81D");
2499         }
2500         mkot_trap_warn_count = ntraps;
2501     } else
2502         mkot_trap_warn_count = 0;
2503 }
2504
2505 /* Master Key is magic key if its bless/curse state meets our criteria:
2506    not cursed for rogues or blessed for non-rogues */
2507 boolean
2508 is_magic_key(mon, obj)
2509 struct monst *mon; /* if null, non-rogue is assumed */
2510 struct obj *obj;
2511 {
2512     if (((obj && obj->oartifact == ART_MASTER_KEY_OF_THIEVERY)
2513          && ((mon == &youmonst) ? Role_if(PM_ROGUE)
2514                                 : (mon && mon->data == &mons[PM_ROGUE])))
2515         ? !obj->cursed : obj->blessed)
2516         return TRUE;
2517     return FALSE;
2518 }
2519
2520 /* figure out whether 'mon' (usually youmonst) is carrying the magic key */
2521 struct obj *
2522 has_magic_key(mon)
2523 struct monst *mon; /* if null, hero assumed */
2524 {
2525     struct obj *o;
2526     short key = artilist[ART_MASTER_KEY_OF_THIEVERY].otyp;
2527
2528     if (!mon)
2529         mon = &youmonst;
2530     for (o = ((mon == &youmonst) ? invent : mon->minvent); o;
2531          o = nxtobj(o, key, FALSE)) {
2532         if (is_magic_key(mon, o))
2533             return o;
2534     }
2535     return (struct obj *) 0;
2536 }
2537
2538 /*artifact.c*/