OSDN Git Service

update year to 2019
[jnethack/source.git] / src / zap.c
1 /* NetHack 3.6  zap.c   $NHDT-Date: 1524470244 2018/04/23 07:57:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.275 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2013. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12
13 /* Disintegration rays have special treatment; corpses are never left.
14  * But the routine which calculates the damage is separate from the routine
15  * which kills the monster.  The damage routine returns this cookie to
16  * indicate that the monster should be disintegrated.
17  */
18 #define MAGIC_COOKIE 1000
19
20 static NEARDATA boolean obj_zapped;
21 static NEARDATA int poly_zapped;
22
23 extern boolean notonhead; /* for long worms */
24
25 /* kludge to use mondied instead of killed */
26 extern boolean m_using;
27
28 STATIC_DCL void FDECL(polyuse, (struct obj *, int, int));
29 STATIC_DCL void FDECL(create_polymon, (struct obj *, int));
30 STATIC_DCL int FDECL(stone_to_flesh_obj, (struct obj *));
31 STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
32 STATIC_DCL void FDECL(zhitu, (int, int, const char *, XCHAR_P, XCHAR_P));
33 STATIC_DCL void FDECL(revive_egg, (struct obj *));
34 STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
35 STATIC_DCL void FDECL(skiprange, (int, int *, int *));
36
37 STATIC_DCL int FDECL(zap_hit, (int, int));
38 STATIC_OVL void FDECL(disintegrate_mon, (struct monst *, int, const char *));
39 STATIC_DCL void FDECL(backfire, (struct obj *));
40 STATIC_DCL int FDECL(spell_hit_bonus, (int));
41
42 #define ZT_MAGIC_MISSILE (AD_MAGM - 1)
43 #define ZT_FIRE (AD_FIRE - 1)
44 #define ZT_COLD (AD_COLD - 1)
45 #define ZT_SLEEP (AD_SLEE - 1)
46 #define ZT_DEATH (AD_DISN - 1) /* or disintegration */
47 #define ZT_LIGHTNING (AD_ELEC - 1)
48 #define ZT_POISON_GAS (AD_DRST - 1)
49 #define ZT_ACID (AD_ACID - 1)
50 /* 8 and 9 are currently unassigned */
51
52 #define ZT_WAND(x) (x)
53 #define ZT_SPELL(x) (10 + (x))
54 #define ZT_BREATH(x) (20 + (x))
55
56 #define is_hero_spell(type) ((type) >= 10 && (type) < 20)
57
58 #define M_IN_WATER(ptr) \
59     ((ptr)->mlet == S_EEL || amphibious(ptr) || is_swimmer(ptr))
60
61 STATIC_VAR const char are_blinded_by_the_flash[] =
62 /*JP
63     "are blinded by the flash!";
64 */
65     "\82Ü\82Î\82ä\82¢\8cõ\82Å\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81I";
66
67 const char *const flash_types[] =       /* also used in buzzmu(mcastu.c) */
68     {
69 #if 0 /*JP*/
70         "magic missile", /* Wands must be 0-9 */
71         "bolt of fire", "bolt of cold", "sleep ray", "death ray",
72         "bolt of lightning", "", "", "", "",
73 #else
74         "\96\82\96@\82Ì\96î", /* Wands must be 0-9 */
75         "\89Î\82Ì\91M\8cõ",
76         "\95X\82Ì\91M\8cõ",
77         "\96°\82è\8cõ\90ü",
78         "\8e\80\82Ì\8cõ\90ü",
79         "\88î\8dÈ\82Ì\91M\8cõ",
80         "",
81         "",
82         "",
83         "",
84 #endif
85
86 #if 0 /*JP*/
87         "magic missile", /* Spell equivalents must be 10-19 */
88         "fireball", "cone of cold", "sleep ray", "finger of death",
89         "bolt of lightning", /* there is no spell, used for retribution */
90         "", "", "", "",
91 #else
92         "\96\82\96@\82Ì\96î", /* Spell equivalents must be 10-19 */
93         "\89Î\82Ì\8bÊ",
94         "\97â\8bC",
95         "\96°\82è\8cõ\90ü",
96         "\8e\80\82Ì\8ew",
97         "\88î\8dÈ\82Ì\91M\8cõ", /* There is no spell, used for retribution */
98         "",
99         "",
100         "",
101         "",
102 #endif
103
104 #if 0 /*JP*/
105         "blast of missiles", /* Dragon breath equivalents 20-29*/
106         "blast of fire", "blast of frost", "blast of sleep gas",
107         "blast of disintegration", "blast of lightning",
108         "blast of poison gas", "blast of acid", "", ""
109 #else
110         "\96\82\96@\82Ì\96î\82Ì\91§", /* Dragon breath equivalents 20-29*/
111         "\89Î\82Ì\91§",
112         "\95X\82Ì\91§",
113         "\90\87\96°\83K\83X\82Ì\91§",
114         "\95ª\89ð\82Ì\91§",
115         "\88î\8dÈ\82Ì\91§",
116         "\93Å\83K\83X\82Ì\91§",
117         "\8e_\82Ì\91§",
118         "",
119         ""
120 #endif
121     };
122
123 /*
124  * Recognizing unseen wands by zapping:  in 3.4.3 and earlier, zapping
125  * most wand types while blind would add that type to the discoveries
126  * list even if it had never been seen (ie, picked up while blinded
127  * and shown in inventory as simply "a wand").  This behavior has been
128  * changed; now such wands won't be discovered.  But if the type is
129  * already discovered, then the individual wand whose effect was just
130  * observed will be flagged as if seen.  [You already know wands of
131  * striking; you zap "a wand" and observe striking effect (presumably
132  * by sound or touch); it'll become shown in inventory as "a wand of
133  * striking".]
134  *
135  * Unfortunately, the new behavior isn't really correct either.  There
136  * should be an `eknown' bit for "effect known" added for wands (and
137  * for potions since quaffing one of a stack is similar) so that the
138  * particular wand which has been zapped would have its type become
139  * known (it would change from "a wand" to "a wand of striking", for
140  * example) without the type becoming discovered or other unknown wands
141  * of that type showing additional information.  When blindness ends,
142  * all objects in inventory with the eknown bit set would be discovered
143  * and other items of the same type would become known as such.
144  */
145
146 /* wand discovery gets special handling when hero is blinded */
147 void
148 learnwand(obj)
149 struct obj *obj;
150 {
151     /* For a wand (or wand-like tool) zapped by the player, if the
152        effect was observable (determined by caller; usually seen, but
153        possibly heard or felt if the hero is blinded) then discover the
154        object type provided that the object itself is known (as more
155        than just "a wand").  If object type is already discovered and
156        we observed the effect, mark the individual wand as having been
157        seen.  Suppress spells (which use fake spellbook object for `obj')
158        so that casting a spell won't re-discover its forgotten book. */
159     if (obj->oclass != SPBOOK_CLASS) {
160         /* if type already discovered, treat this item has having been seen
161            even if hero is currently blinded (skips redundant makeknown) */
162         if (objects[obj->otyp].oc_name_known) {
163             obj->dknown = 1; /* will usually be set already */
164
165         /* otherwise discover it if item itself has been or can be seen */
166         } else {
167             /* in case it was picked up while blind and then zapped without
168                examining inventory after regaining sight (bypassing xname) */
169             if (!Blind)
170                 obj->dknown = 1;
171             /* make the discovery iff we know what we're manipulating */
172             if (obj->dknown)
173                 makeknown(obj->otyp);
174         }
175     }
176 }
177
178 /* Routines for IMMEDIATE wands and spells. */
179 /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
180 int
181 bhitm(mtmp, otmp)
182 struct monst *mtmp;
183 struct obj *otmp;
184 {
185     boolean wake = TRUE; /* Most 'zaps' should wake monster */
186     boolean reveal_invis = FALSE, learn_it = FALSE;
187     boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
188     boolean helpful_gesture = FALSE;
189     int dmg, otyp = otmp->otyp;
190 /*JP
191     const char *zap_type_text = "spell";
192 */
193     const char *zap_type_text = "\96\82\96@";
194     struct obj *obj;
195     boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC
196                                && mtmp->m_ap_type != M_AP_NOTHING);
197
198     if (u.uswallow && mtmp == u.ustuck)
199         reveal_invis = FALSE;
200
201     notonhead = (mtmp->mx != bhitpos.x || mtmp->my != bhitpos.y);
202     switch (otyp) {
203     case WAN_STRIKING:
204 /*JP
205         zap_type_text = "wand";
206 */
207         zap_type_text = "\8fñ";
208     /* fall through */
209     case SPE_FORCE_BOLT:
210         reveal_invis = TRUE;
211         if (disguised_mimic)
212             seemimic(mtmp);
213         if (resists_magm(mtmp)) { /* match effect on player */
214             shieldeff(mtmp->mx, mtmp->my);
215 /*JP
216             pline("Boing!");
217 */
218             pline("\83{\83C\83\93\81I");
219             break; /* skip makeknown */
220         } else if (u.uswallow || rnd(20) < 10 + find_mac(mtmp)) {
221             dmg = d(2, 12);
222             if (dbldam)
223                 dmg *= 2;
224             if (otyp == SPE_FORCE_BOLT)
225                 dmg = spell_damage_bonus(dmg);
226             hit(zap_type_text, mtmp, exclam(dmg));
227             (void) resist(mtmp, otmp->oclass, dmg, TELL);
228         } else
229             miss(zap_type_text, mtmp);
230         learn_it = TRUE;
231         break;
232     case WAN_SLOW_MONSTER:
233     case SPE_SLOW_MONSTER:
234         if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
235             if (disguised_mimic)
236                 seemimic(mtmp);
237             mon_adjust_speed(mtmp, -1, otmp);
238             m_dowear(mtmp, FALSE); /* might want speed boots */
239             if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) {
240 /*JP
241                 You("disrupt %s!", mon_nam(mtmp));
242 */
243                 You("%s\82ð\83o\83\89\83o\83\89\82É\82µ\82½\81I", mon_nam(mtmp));
244 /*JP
245                 pline("A huge hole opens up...");
246 */
247                 pline("\92E\8fo\82Å\82«\82»\82¤\82È\8c\8a\82ª\8aJ\82¢\82½\81D\81D\81D");
248                 expels(mtmp, mtmp->data, TRUE);
249             }
250         }
251         break;
252     case WAN_SPEED_MONSTER:
253         if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
254             if (disguised_mimic)
255                 seemimic(mtmp);
256             mon_adjust_speed(mtmp, 1, otmp);
257             m_dowear(mtmp, FALSE); /* might want speed boots */
258         }
259         if (mtmp->mtame)
260             helpful_gesture = TRUE;
261         break;
262     case WAN_UNDEAD_TURNING:
263     case SPE_TURN_UNDEAD:
264         wake = FALSE;
265         if (unturn_dead(mtmp))
266             wake = TRUE;
267         if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
268             reveal_invis = TRUE;
269             wake = TRUE;
270             dmg = rnd(8);
271             if (dbldam)
272                 dmg *= 2;
273             if (otyp == SPE_TURN_UNDEAD)
274                 dmg = spell_damage_bonus(dmg);
275             context.bypasses = TRUE; /* for make_corpse() */
276             if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) {
277                 if (mtmp->mhp > 0)
278                     monflee(mtmp, 0, FALSE, TRUE);
279             }
280         }
281         break;
282     case WAN_POLYMORPH:
283     case SPE_POLYMORPH:
284     case POT_POLYMORPH:
285         if (resists_magm(mtmp)) {
286             /* magic resistance protects from polymorph traps, so make
287                it guard against involuntary polymorph attacks too... */
288             shieldeff(mtmp->mx, mtmp->my);
289         } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
290             boolean polyspot = (otyp != POT_POLYMORPH),
291                     give_msg = (!Hallucination
292                                 && (canseemon(mtmp)
293                                     || (u.uswallow && mtmp == u.ustuck)));
294
295             /* dropped inventory (due to death by system shock,
296                or loss of wielded weapon and/or worn armor due to
297                limitations of new shape) won't be hit by this zap */
298             if (polyspot)
299                 for (obj = mtmp->minvent; obj; obj = obj->nobj)
300                     bypass_obj(obj);
301             /* natural shapechangers aren't affected by system shock
302                (unless protection from shapechangers is interfering
303                with their metabolism...) */
304             if (mtmp->cham == NON_PM && !rn2(25)) {
305                 if (canseemon(mtmp)) {
306 /*JP
307                     pline("%s shudders!", Monnam(mtmp));
308 */
309                     pline("%s\82Í\90g\90k\82¢\82µ\82½\81I", Monnam(mtmp));
310                     learn_it = TRUE;
311                 }
312                 /* context.bypasses = TRUE; ## for make_corpse() */
313                 /* no corpse after system shock */
314                 xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
315             } else if (newcham(mtmp, (struct permonst *) 0,
316                                polyspot, give_msg) != 0
317                        /* if shapechange failed because there aren't
318                           enough eligible candidates (most likely for
319                           vampshifter), try reverting to original form */
320                        || (mtmp->cham >= LOW_PM
321                            && newcham(mtmp, &mons[mtmp->cham],
322                                       polyspot, give_msg) != 0)) {
323                 if (give_msg && (canspotmon(mtmp)
324                                  || (u.uswallow && mtmp == u.ustuck)))
325                     learn_it = TRUE;
326             }
327         }
328         break;
329     case WAN_CANCELLATION:
330     case SPE_CANCELLATION:
331         if (disguised_mimic)
332             seemimic(mtmp);
333         (void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
334         break;
335     case WAN_TELEPORTATION:
336     case SPE_TELEPORT_AWAY:
337         if (disguised_mimic)
338             seemimic(mtmp);
339         reveal_invis = !u_teleport_mon(mtmp, TRUE);
340         break;
341     case WAN_MAKE_INVISIBLE: {
342         int oldinvis = mtmp->minvis;
343         char nambuf[BUFSZ];
344
345         if (disguised_mimic)
346             seemimic(mtmp);
347         /* format monster's name before altering its visibility */
348         Strcpy(nambuf, Monnam(mtmp));
349         mon_set_minvis(mtmp);
350         if (!oldinvis && knowninvisible(mtmp)) {
351 /*JP
352             pline("%s turns transparent!", nambuf);
353 */
354             pline("%s\82Í\93§\96¾\82É\82È\82Á\82½\81I", nambuf);
355             reveal_invis = TRUE;
356             learn_it = TRUE;
357         }
358         break;
359     }
360     case WAN_LOCKING:
361     case SPE_WIZARD_LOCK:
362         wake = closeholdingtrap(mtmp, &learn_it);
363         break;
364     case WAN_PROBING:
365         wake = FALSE;
366         reveal_invis = TRUE;
367         probe_monster(mtmp);
368         learn_it = TRUE;
369         break;
370     case WAN_OPENING:
371     case SPE_KNOCK:
372         wake = FALSE; /* don't want immediate counterattack */
373         if (u.uswallow && mtmp == u.ustuck) {
374             if (is_animal(mtmp->data)) {
375                 if (Blind)
376 /*JP
377                     You_feel("a sudden rush of air!");
378 */
379                     You("\93Ë\91R\8c\83\82µ\82¢\8bó\8bC\82Ì\97¬\82ê\82ð\8a´\82\82½\81I");
380                 else
381 /*JP
382                     pline("%s opens its mouth!", Monnam(mtmp));
383 */
384                     pline("%s\82Í\8cû\82ð\8aJ\82¢\82½\81I", Monnam(mtmp));
385             }
386             expels(mtmp, mtmp->data, TRUE);
387             /* zap which hits steed will only release saddle if it
388                doesn't hit a holding or falling trap; playability
389                here overrides the more logical target ordering */
390         } else if (openholdingtrap(mtmp, &learn_it)) {
391             break;
392         } else if (openfallingtrap(mtmp, TRUE, &learn_it)) {
393             /* mtmp might now be on the migrating monsters list */
394             break;
395         } else if ((obj = which_armor(mtmp, W_SADDLE)) != 0) {
396             char buf[BUFSZ];
397
398 #if 0 /*JP*/
399             Sprintf(buf, "%s %s", s_suffix(Monnam(mtmp)),
400                     distant_name(obj, xname));
401 #else
402             Sprintf(buf, "%s\82Ì%s", Monnam(mtmp),
403                     distant_name(obj, xname));
404 #endif
405             if (cansee(mtmp->mx, mtmp->my)) {
406                 if (!canspotmon(mtmp))
407                     Strcpy(buf, An(distant_name(obj, xname)));
408 #if 0 /*JP*/
409                 pline("%s falls to the %s.", buf,
410                       surface(mtmp->mx, mtmp->my));
411 #else
412                 pline("%s\82Í%s\82É\97\8e\82¿\82½\81D", buf,
413                       surface(mtmp->mx, mtmp->my));
414 #endif
415             } else if (canspotmon(mtmp)) {
416 /*JP
417                 pline("%s falls off.", buf);
418 */
419                 pline("%s\82ª\97\8e\82¿\82½\81D", buf);
420             }
421             obj_extract_self(obj);
422             mdrop_obj(mtmp, obj, FALSE);
423         }
424         break;
425     case SPE_HEALING:
426     case SPE_EXTRA_HEALING:
427         reveal_invis = TRUE;
428         if (mtmp->data != &mons[PM_PESTILENCE]) {
429             wake = FALSE; /* wakeup() makes the target angry */
430             mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4);
431             if (mtmp->mhp > mtmp->mhpmax)
432                 mtmp->mhp = mtmp->mhpmax;
433             if (mtmp->mblinded) {
434                 mtmp->mblinded = 0;
435                 mtmp->mcansee = 1;
436             }
437             if (canseemon(mtmp)) {
438                 if (disguised_mimic) {
439                     if (is_obj_mappear(mtmp,STRANGE_OBJECT)) {
440                         /* it can do better now */
441                         set_mimic_sym(mtmp);
442                         newsym(mtmp->mx, mtmp->my);
443                     } else
444                         mimic_hit_msg(mtmp, otyp);
445                 } else
446 #if 0 /*JP*/
447                     pline("%s looks%s better.", Monnam(mtmp),
448                           otyp == SPE_EXTRA_HEALING ? " much" : "");
449 #else
450                     pline("%s\82Í%s\8c³\8bC\82É\82È\82Á\82½\82æ\82¤\82¾\81D", Monnam(mtmp),
451                           otyp == SPE_EXTRA_HEALING ? "\82Æ\82Ä\82à" : "" );
452 #endif
453             }
454             if (mtmp->mtame || mtmp->mpeaceful) {
455                 adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
456             }
457         } else { /* Pestilence */
458             /* Pestilence will always resist; damage is half of 3d{4,8} */
459             (void) resist(mtmp, otmp->oclass,
460                           d(3, otyp == SPE_EXTRA_HEALING ? 8 : 4), TELL);
461         }
462         break;
463     case WAN_LIGHT: /* (broken wand) */
464         if (flash_hits_mon(mtmp, otmp)) {
465             learn_it = TRUE;
466             reveal_invis = TRUE;
467         }
468         break;
469     case WAN_SLEEP: /* (broken wand) */
470         /* [wakeup() doesn't rouse victims of temporary sleep,
471            so it's okay to leave `wake' set to TRUE here] */
472         reveal_invis = TRUE;
473         if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS))
474             slept_monst(mtmp);
475         if (!Blind)
476             learn_it = TRUE;
477         break;
478     case SPE_STONE_TO_FLESH:
479         if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
480             char *name = Monnam(mtmp);
481
482             /* turn into flesh golem */
483             if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE, FALSE)) {
484                 if (canseemon(mtmp))
485 /*JP
486                     pline("%s turns to flesh!", name);
487 */
488                     pline("%s\82Ì\90Î\89»\82ª\89ð\82¯\82½\81I", name);
489             } else {
490                 if (canseemon(mtmp))
491 /*JP
492                     pline("%s looks rather fleshy for a moment.", name);
493 */
494                     pline("%s\82Í\88ê\8fu\90Î\89»\82ª\89ð\82¯\82½\81D", name);
495             }
496         } else
497             wake = FALSE;
498         break;
499     case SPE_DRAIN_LIFE:
500         if (disguised_mimic)
501             seemimic(mtmp);
502         dmg = monhp_per_lvl(mtmp);
503         if (dbldam)
504             dmg *= 2;
505         if (otyp == SPE_DRAIN_LIFE)
506             dmg = spell_damage_bonus(dmg);
507         if (resists_drli(mtmp)) {
508             shieldeff(mtmp->mx, mtmp->my);
509         } else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
510             mtmp->mhp -= dmg;
511             mtmp->mhpmax -= dmg;
512             /* die if already level 0, regardless of hit points */
513             if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) {
514                 killed(mtmp);
515             } else {
516                 mtmp->m_lev--;
517                 if (canseemon(mtmp))
518 /*JP
519                     pline("%s suddenly seems weaker!", Monnam(mtmp));
520 */
521                     pline("%s\82Í\82Æ\82Â\82º\82ñ\8eã\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", Monnam(mtmp));
522             }
523         }
524         break;
525     case WAN_NOTHING:
526         wake = FALSE;
527         break;
528     default:
529         impossible("What an interesting effect (%d)", otyp);
530         break;
531     }
532     if (wake) {
533         if (mtmp->mhp > 0) {
534             wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
535             m_respond(mtmp);
536             if (mtmp->isshk && !*u.ushops)
537                 hot_pursuit(mtmp);
538         } else if (mtmp->m_ap_type)
539             seemimic(mtmp); /* might unblock if mimicing a boulder/door */
540     }
541     /* note: bhitpos won't be set if swallowed, but that's okay since
542      * reveal_invis will be false.  We can't use mtmp->mx, my since it
543      * might be an invisible worm hit on the tail.
544      */
545     if (reveal_invis) {
546         if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y)
547             && !canspotmon(mtmp))
548             map_invisible(bhitpos.x, bhitpos.y);
549     }
550     /* if effect was observable then discover the wand type provided
551        that the wand itself has been seen */
552     if (learn_it)
553         learnwand(otmp);
554     return 0;
555 }
556
557 void
558 probe_monster(mtmp)
559 struct monst *mtmp;
560 {
561     struct obj *otmp;
562
563     mstatusline(mtmp);
564     if (notonhead)
565         return; /* don't show minvent for long worm tail */
566
567     if (mtmp->minvent) {
568         for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
569             otmp->dknown = 1; /* treat as "seen" */
570             if (Is_container(otmp) || otmp->otyp == STATUE) {
571                 otmp->lknown = 1;
572                 if (!SchroedingersBox(otmp))
573                     otmp->cknown = 1;
574             }
575         }
576         (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET | PICK_NONE,
577                                   (char *) 0);
578     } else {
579 #if 0 /*JP*/
580         pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
581               (u.uswallow && mtmp == u.ustuck) ? " besides you" : "");
582 #else
583         pline("%s\82Í%s\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", noit_Monnam(mtmp),
584               (u.uswallow && mtmp == u.ustuck) ? "\82 \82È\82½\88È\8aO\82É" : "");
585 #endif
586     }
587 }
588
589 /*
590  * Return the object's physical location.  This only makes sense for
591  * objects that are currently on the level (i.e. migrating objects
592  * are nowhere).  By default, only things that can be seen (in hero's
593  * inventory, monster's inventory, or on the ground) are reported.
594  * By adding BURIED_TOO and/or CONTAINED_TOO flags, you can also get
595  * the location of buried and contained objects.  Note that if an
596  * object is carried by a monster, its reported position may change
597  * from turn to turn.  This function returns FALSE if the position
598  * is not available or subject to the constraints above.
599  */
600 boolean
601 get_obj_location(obj, xp, yp, locflags)
602 struct obj *obj;
603 xchar *xp, *yp;
604 int locflags;
605 {
606     switch (obj->where) {
607     case OBJ_INVENT:
608         *xp = u.ux;
609         *yp = u.uy;
610         return TRUE;
611     case OBJ_FLOOR:
612         *xp = obj->ox;
613         *yp = obj->oy;
614         return TRUE;
615     case OBJ_MINVENT:
616         if (obj->ocarry->mx) {
617             *xp = obj->ocarry->mx;
618             *yp = obj->ocarry->my;
619             return TRUE;
620         }
621         break; /* !mx => migrating monster */
622     case OBJ_BURIED:
623         if (locflags & BURIED_TOO) {
624             *xp = obj->ox;
625             *yp = obj->oy;
626             return TRUE;
627         }
628         break;
629     case OBJ_CONTAINED:
630         if (locflags & CONTAINED_TOO)
631             return get_obj_location(obj->ocontainer, xp, yp, locflags);
632         break;
633     }
634     *xp = *yp = 0;
635     return FALSE;
636 }
637
638 boolean
639 get_mon_location(mon, xp, yp, locflags)
640 struct monst *mon;
641 xchar *xp, *yp;
642 int locflags; /* non-zero means get location even if monster is buried */
643 {
644     if (mon == &youmonst) {
645         *xp = u.ux;
646         *yp = u.uy;
647         return TRUE;
648     } else if (mon->mx > 0 && (!mon->mburied || locflags)) {
649         *xp = mon->mx;
650         *yp = mon->my;
651         return TRUE;
652     } else { /* migrating or buried */
653         *xp = *yp = 0;
654         return FALSE;
655     }
656 }
657
658 /* used by revive() and animate_statue() */
659 struct monst *
660 montraits(obj, cc)
661 struct obj *obj;
662 coord *cc;
663 {
664     struct monst *mtmp = (struct monst *) 0;
665     struct monst *mtmp2 = (struct monst *) 0;
666
667     if (has_omonst(obj))
668         mtmp2 = get_mtraits(obj, TRUE);
669     if (mtmp2) {
670         /* save_mtraits() validated mtmp2->mnum */
671         mtmp2->data = &mons[mtmp2->mnum];
672         if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
673             return (struct monst *) 0;
674         mtmp = makemon(mtmp2->data, cc->x, cc->y,
675                        NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
676         if (!mtmp)
677             return mtmp;
678
679         /* heal the monster */
680         if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data))
681             mtmp2->mhpmax = mtmp->mhpmax;
682         mtmp2->mhp = mtmp2->mhpmax;
683         /* Get these ones from mtmp */
684         mtmp2->minvent = mtmp->minvent; /*redundant*/
685         /* monster ID is available if the monster died in the current
686            game, but will be zero if the corpse was in a bones level
687            (we cleared it when loading bones) */
688         if (mtmp->m_id) {
689             mtmp2->m_id = mtmp->m_id;
690             /* might be bringing quest leader back to life */
691             if (quest_status.leader_is_dead
692                 /* leader_is_dead implies leader_m_id is valid */
693                 && mtmp2->m_id == quest_status.leader_m_id)
694                 quest_status.leader_is_dead = FALSE;
695         }
696         mtmp2->mx = mtmp->mx;
697         mtmp2->my = mtmp->my;
698         mtmp2->mux = mtmp->mux;
699         mtmp2->muy = mtmp->muy;
700         mtmp2->mw = mtmp->mw;
701         mtmp2->wormno = mtmp->wormno;
702         mtmp2->misc_worn_check = mtmp->misc_worn_check;
703         mtmp2->weapon_check = mtmp->weapon_check;
704         mtmp2->mtrapseen = mtmp->mtrapseen;
705         mtmp2->mflee = mtmp->mflee;
706         mtmp2->mburied = mtmp->mburied;
707         mtmp2->mundetected = mtmp->mundetected;
708         mtmp2->mfleetim = mtmp->mfleetim;
709         mtmp2->mlstmv = mtmp->mlstmv;
710         mtmp2->m_ap_type = mtmp->m_ap_type;
711         /* set these ones explicitly */
712         mtmp2->mrevived = 1;
713         mtmp2->mavenge = 0;
714         mtmp2->meating = 0;
715         mtmp2->mleashed = 0;
716         mtmp2->mtrapped = 0;
717         mtmp2->msleeping = 0;
718         mtmp2->mfrozen = 0;
719         mtmp2->mcanmove = 1;
720         /* most cancelled monsters return to normal,
721            but some need to stay cancelled */
722         if (!dmgtype(mtmp2->data, AD_SEDU)
723             && (!SYSOPT_SEDUCE || !dmgtype(mtmp2->data, AD_SSEX)))
724             mtmp2->mcan = 0;
725         mtmp2->mcansee = 1; /* set like in makemon */
726         mtmp2->mblinded = 0;
727         mtmp2->mstun = 0;
728         mtmp2->mconf = 0;
729         /* when traits are for a shopeekper, dummy monster 'mtmp' won't
730            have necessary eshk data for replmon() -> replshk() */
731         if (mtmp2->isshk) {
732             neweshk(mtmp);
733             *ESHK(mtmp) = *ESHK(mtmp2);
734             if (ESHK(mtmp2)->bill_p != 0
735                 && ESHK(mtmp2)->bill_p != (struct bill_x *) -1000)
736                 ESHK(mtmp)->bill_p = &(ESHK(mtmp)->bill[0]);
737             mtmp->isshk = 1;
738         }
739         replmon(mtmp, mtmp2);
740         newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
741
742         /* in case Protection_from_shape_changers is different
743            now than it was when the traits were stored */
744         restore_cham(mtmp2);
745     }
746     return mtmp2;
747 }
748
749 /*
750  * get_container_location() returns the following information
751  * about the outermost container:
752  * loc argument gets set to:
753  *      OBJ_INVENT      if in hero's inventory; return 0.
754  *      OBJ_FLOOR       if on the floor; return 0.
755  *      OBJ_BURIED      if buried; return 0.
756  *      OBJ_MINVENT     if in monster's inventory; return monster.
757  * container_nesting is updated with the nesting depth of the containers
758  * if applicable.
759  */
760 struct monst *
761 get_container_location(obj, loc, container_nesting)
762 struct obj *obj;
763 int *loc;
764 int *container_nesting;
765 {
766     if (!obj || !loc)
767         return 0;
768
769     if (container_nesting)
770         *container_nesting = 0;
771     while (obj && obj->where == OBJ_CONTAINED) {
772         if (container_nesting)
773             *container_nesting += 1;
774         obj = obj->ocontainer;
775     }
776     if (obj) {
777         *loc = obj->where; /* outermost container's location */
778         if (obj->where == OBJ_MINVENT)
779             return obj->ocarry;
780     }
781     return (struct monst *) 0;
782 }
783
784 /*
785  * Attempt to revive the given corpse, return the revived monster if
786  * successful.  Note: this does NOT use up the corpse if it fails.
787  * If corpse->quan is more than 1, only one corpse will be affected
788  * and only one monster will be resurrected.
789  */
790 struct monst *
791 revive(corpse, by_hero)
792 struct obj *corpse;
793 boolean by_hero;
794 {
795     struct monst *mtmp = 0;
796     struct permonst *mptr;
797     struct obj *container;
798     coord xy;
799     xchar x, y;
800     boolean one_of;
801     int montype, container_nesting = 0;
802
803     if (corpse->otyp != CORPSE) {
804         impossible("Attempting to revive %s?", xname(corpse));
805         return (struct monst *) 0;
806     }
807
808     x = y = 0;
809     if (corpse->where != OBJ_CONTAINED) {
810         /* only for invent, minvent, or floor */
811         container = 0;
812         (void) get_obj_location(corpse, &x, &y, 0);
813     } else {
814         /* deal with corpses in [possibly nested] containers */
815         struct monst *carrier;
816         int holder = OBJ_FREE;
817
818         container = corpse->ocontainer;
819         carrier =
820             get_container_location(container, &holder, &container_nesting);
821         switch (holder) {
822         case OBJ_MINVENT:
823             x = carrier->mx, y = carrier->my;
824             break;
825         case OBJ_INVENT:
826             x = u.ux, y = u.uy;
827             break;
828         case OBJ_FLOOR:
829             (void) get_obj_location(corpse, &x, &y, CONTAINED_TOO);
830             break;
831         default:
832             break; /* x,y are 0 */
833         }
834     }
835     if (!x || !y
836         /* Rules for revival from containers:
837          *  - the container cannot be locked
838          *  - the container cannot be heavily nested (>2 is arbitrary)
839          *  - the container cannot be a statue or bag of holding
840          *    (except in very rare cases for the latter)
841          */
842         || (container && (container->olocked || container_nesting > 2
843                           || container->otyp == STATUE
844                           || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
845         return (struct monst *) 0;
846
847     /* record the object's location now that we're sure where it is */
848     corpse->ox = x, corpse->oy = y;
849
850     /* prepare for the monster */
851     montype = corpse->corpsenm;
852     mptr = &mons[montype];
853     /* [should probably handle recorporealization first; if corpse and
854        ghost are at same location, revived creature shouldn't be bumped
855        to an adjacent spot by ghost which joins with it] */
856     if (MON_AT(x, y)) {
857         if (enexto(&xy, x, y, mptr))
858             x = xy.x, y = xy.y;
859     }
860
861     if ((mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ))
862         || (mons[montype].mlet == S_TROLL
863             && uwep && uwep->oartifact == ART_TROLLSBANE)) {
864         if (by_hero && cansee(x,y))
865 /*JP
866             pline("%s twitches feebly.",
867 */
868             pline("%s\82Í\82í\82¸\82©\82Éáz\9d¹\82µ\82½\81D",
869                 upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
870         return (struct monst *) 0;
871     }
872
873     if (cant_revive(&montype, TRUE, corpse)) {
874         /* make a zombie or doppelganger instead */
875         /* note: montype has changed; mptr keeps old value for newcham() */
876         mtmp = makemon(&mons[montype], x, y, NO_MINVENT | MM_NOWAIT);
877         if (mtmp) {
878             /* skip ghost handling */
879             if (has_omid(corpse))
880                 free_omid(corpse);
881             if (has_omonst(corpse))
882                 free_omonst(corpse);
883             if (mtmp->cham == PM_DOPPELGANGER) {
884                 /* change shape to match the corpse */
885                 (void) newcham(mtmp, mptr, FALSE, FALSE);
886             } else if (mtmp->data->mlet == S_ZOMBIE) {
887                 mtmp->mhp = mtmp->mhpmax = 100;
888                 mon_adjust_speed(mtmp, 2, (struct obj *) 0); /* MFAST */
889             }
890         }
891     } else if (has_omonst(corpse)) {
892         /* use saved traits */
893         xy.x = x, xy.y = y;
894         mtmp = montraits(corpse, &xy);
895         if (mtmp && mtmp->mtame && !mtmp->isminion)
896             wary_dog(mtmp, TRUE);
897     } else {
898         /* make a new monster */
899         mtmp = makemon(mptr, x, y, NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
900     }
901     if (!mtmp)
902         return (struct monst *) 0;
903
904     /* hiders shouldn't already be re-hidden when they revive */
905     if (mtmp->mundetected) {
906         mtmp->mundetected = 0;
907         newsym(mtmp->mx, mtmp->my);
908     }
909     if (mtmp->m_ap_type)
910         seemimic(mtmp);
911
912     one_of = (corpse->quan > 1L);
913     if (one_of)
914         corpse = splitobj(corpse, 1L);
915
916     /* if this is caused by the hero there might be a shop charge */
917     if (by_hero) {
918         struct monst *shkp = 0;
919
920         x = corpse->ox, y = corpse->oy;
921         if (costly_spot(x, y)
922             && (carried(corpse) ? corpse->unpaid : !corpse->no_charge))
923             shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
924
925         if (cansee(x, y)) {
926             char buf[BUFSZ];
927             unsigned pfx = CXN_PFX_THE;
928
929 #if 1 /*JP*//* \8e\80\91Ì\96¼\82Í\90æ\82É */
930             Strcpy(buf, corpse_xname(corpse, (const char *) 0, pfx));
931 #endif
932 #if 0 /*JP*/
933             Strcpy(buf, one_of ? "one of " : "");
934 #else /* \8cê\8f\87\82Í\95Ï\82í\82Á\82Ä\82¢\82é */
935             if (one_of) {
936                 Strcat(buf, "\82Ì\88ê\82Â");
937             }
938 #endif
939 #if 0 /*JP*//* \82±\82±\82Å\81u\82 \82È\82½\82Ì\81v\82Í\95s\8e©\91R */
940             if (carried(corpse) && !corpse->unpaid) {
941                 Strcat(buf, "your ");
942                 pfx = CXN_NO_PFX;
943             }
944 #endif
945             if (one_of)
946                 corpse->quan++; /* force plural */
947 #if 0 /*JP*//* \8aù\82É\90Ý\92è\8dÏ\82Ý */
948             Strcat(buf, corpse_xname(corpse, (const char *) 0, pfx));
949 #endif
950             if (one_of) /* could be simplified to ''corpse->quan = 1L;'' */
951                 corpse->quan--;
952 /*JP
953             pline("%s glows iridescently.", upstart(buf));
954 */
955             pline("%s\82Í\93ø\90F\82É\8bP\82¢\82½\81D", upstart(buf));
956         } else if (shkp) {
957             /* need some prior description of the corpse since
958                stolen_value() will refer to the object as "it" */
959 /*JP
960             pline("A corpse is resuscitated.");
961 */
962             pline("\8e\80\91Ì\82ª\91h\90\82µ\82½\81D");
963         }
964         /* don't charge for shopkeeper's own corpse if we just revived him */
965         if (shkp && mtmp != shkp)
966             (void) stolen_value(corpse, x, y, (boolean) shkp->mpeaceful,
967                                 FALSE);
968
969         /* [we don't give any comparable message about the corpse for
970            the !by_hero case because caller might have already done so] */
971     }
972
973     /* handle recorporealization of an active ghost */
974     if (has_omid(corpse)) {
975         unsigned m_id;
976         struct monst *ghost;
977         struct obj *otmp;
978
979         (void) memcpy((genericptr_t) &m_id, (genericptr_t) OMID(corpse),
980                       sizeof m_id);
981         ghost = find_mid(m_id, FM_FMON);
982         if (ghost && ghost->data == &mons[PM_GHOST]) {
983             if (canseemon(ghost))
984 #if 0 /*JP*/
985                 pline("%s is suddenly drawn into its former body!",
986 #else
987                 pline("%s\82Í\93Ë\91R\82à\82Æ\82Ì\91Ì\82É\88ø\82«\8d\9e\82Ü\82ê\82½\81I",
988 #endif
989                       Monnam(ghost));
990             /* transfer the ghost's inventory along with it */
991             while ((otmp = ghost->minvent) != 0) {
992                 obj_extract_self(otmp);
993                 add_to_minv(mtmp, otmp);
994             }
995             /* tame the revived monster if its ghost was tame */
996             if (ghost->mtame && !mtmp->mtame) {
997                 if (tamedog(mtmp, (struct obj *) 0)) {
998                     /* ghost's edog data is ignored */
999                     mtmp->mtame = ghost->mtame;
1000                 }
1001             }
1002             /* was ghost, now alive, it's all very confusing */
1003             mtmp->mconf = 1;
1004             /* separate ghost monster no longer exists */
1005             mongone(ghost);
1006         }
1007         free_omid(corpse);
1008     }
1009
1010     /* monster retains its name */
1011     if (has_oname(corpse) && !unique_corpstat(mtmp->data))
1012         mtmp = christen_monst(mtmp, ONAME(corpse));
1013     /* partially eaten corpse yields wounded monster */
1014     if (corpse->oeaten)
1015         mtmp->mhp = eaten_stat(mtmp->mhp, corpse);
1016     /* track that this monster was revived at least once */
1017     mtmp->mrevived = 1;
1018
1019     /* finally, get rid of the corpse--it's gone now */
1020     switch (corpse->where) {
1021     case OBJ_INVENT:
1022         useup(corpse);
1023         break;
1024     case OBJ_FLOOR:
1025         /* in case MON_AT+enexto for invisible mon */
1026         x = corpse->ox, y = corpse->oy;
1027         /* not useupf(), which charges */
1028         if (corpse->quan > 1L)
1029             corpse = splitobj(corpse, 1L);
1030         delobj(corpse);
1031         newsym(x, y);
1032         break;
1033     case OBJ_MINVENT:
1034         m_useup(corpse->ocarry, corpse);
1035         break;
1036     case OBJ_CONTAINED:
1037         obj_extract_self(corpse);
1038         obfree(corpse, (struct obj *) 0);
1039         break;
1040     default:
1041         panic("revive");
1042     }
1043
1044     return mtmp;
1045 }
1046
1047 STATIC_OVL void
1048 revive_egg(obj)
1049 struct obj *obj;
1050 {
1051     /*
1052      * Note: generic eggs with corpsenm set to NON_PM will never hatch.
1053      */
1054     if (obj->otyp != EGG)
1055         return;
1056     if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1057         attach_egg_hatch_timeout(obj, 0L);
1058 }
1059
1060 /* try to revive all corpses and eggs carried by `mon' */
1061 int
1062 unturn_dead(mon)
1063 struct monst *mon;
1064 {
1065     struct obj *otmp, *otmp2;
1066     struct monst *mtmp2;
1067     char owner[BUFSZ], corpse[BUFSZ];
1068     boolean youseeit;
1069     int res = 0;
1070
1071     youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
1072     otmp2 = (mon == &youmonst) ? invent : mon->minvent;
1073     owner[0] = corpse[0] = '\0'; /* lint suppression */
1074
1075     while ((otmp = otmp2) != 0) {
1076         otmp2 = otmp->nobj;
1077         if (otmp->otyp == EGG)
1078             revive_egg(otmp);
1079         if (otmp->otyp != CORPSE)
1080             continue;
1081         /* save the name; the object is liable to go away */
1082         if (youseeit) {
1083             Strcpy(corpse,
1084                    corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
1085             Shk_Your(owner, otmp); /* includes a trailing space */
1086         }
1087
1088         /* for a stack, only one is revived */
1089         if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
1090             ++res;
1091             if (youseeit)
1092 /*JP
1093                 pline("%s%s suddenly comes alive!", owner, corpse);
1094 */
1095                 pline("%s%s\82Í\93Ë\91R\90\96½\82ð\91Ñ\82Ñ\82½\81I", owner, corpse);
1096             else if (canseemon(mtmp2))
1097 /*JP
1098                 pline("%s suddenly appears!", Amonnam(mtmp2));
1099 */
1100                 pline("%s\82ª\93Ë\91R\8c»\82í\82ê\82½\81I", Amonnam(mtmp2));
1101         }
1102     }
1103     return res;
1104 }
1105
1106 /* cancel obj, possibly carried by you or a monster */
1107 void
1108 cancel_item(obj)
1109 register struct obj *obj;
1110 {
1111     boolean u_ring = (obj == uleft || obj == uright);
1112     int otyp = obj->otyp;
1113
1114     switch (otyp) {
1115     case RIN_GAIN_STRENGTH:
1116         if ((obj->owornmask & W_RING) && u_ring) {
1117             ABON(A_STR) -= obj->spe;
1118             context.botl = 1;
1119         }
1120         break;
1121     case RIN_GAIN_CONSTITUTION:
1122         if ((obj->owornmask & W_RING) && u_ring) {
1123             ABON(A_CON) -= obj->spe;
1124             context.botl = 1;
1125         }
1126         break;
1127     case RIN_ADORNMENT:
1128         if ((obj->owornmask & W_RING) && u_ring) {
1129             ABON(A_CHA) -= obj->spe;
1130             context.botl = 1;
1131         }
1132         break;
1133     case RIN_INCREASE_ACCURACY:
1134         if ((obj->owornmask & W_RING) && u_ring)
1135             u.uhitinc -= obj->spe;
1136         break;
1137     case RIN_INCREASE_DAMAGE:
1138         if ((obj->owornmask & W_RING) && u_ring)
1139             u.udaminc -= obj->spe;
1140         break;
1141     case GAUNTLETS_OF_DEXTERITY:
1142         if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1143             ABON(A_DEX) -= obj->spe;
1144             context.botl = 1;
1145         }
1146         break;
1147     case HELM_OF_BRILLIANCE:
1148         if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1149             ABON(A_INT) -= obj->spe;
1150             ABON(A_WIS) -= obj->spe;
1151             context.botl = 1;
1152         }
1153         break;
1154         /* case RIN_PROTECTION:  not needed */
1155     }
1156     if (objects[otyp].oc_magic
1157         || (obj->spe && (obj->oclass == ARMOR_CLASS
1158                          || obj->oclass == WEAPON_CLASS || is_weptool(obj)))
1159         || otyp == POT_ACID
1160         || otyp == POT_SICKNESS
1161         || (otyp == POT_WATER && (obj->blessed || obj->cursed))) {
1162         if (obj->spe != ((obj->oclass == WAND_CLASS) ? -1 : 0)
1163             && otyp != WAN_CANCELLATION /* can't cancel cancellation */
1164             && otyp != MAGIC_LAMP /* cancelling doesn't remove djinni */
1165             && otyp != CANDELABRUM_OF_INVOCATION) {
1166             costly_alteration(obj, COST_CANCEL);
1167             obj->spe = (obj->oclass == WAND_CLASS) ? -1 : 0;
1168         }
1169         switch (obj->oclass) {
1170         case SCROLL_CLASS:
1171             costly_alteration(obj, COST_CANCEL);
1172             obj->otyp = SCR_BLANK_PAPER;
1173             obj->spe = 0;
1174             break;
1175         case SPBOOK_CLASS:
1176             if (otyp != SPE_CANCELLATION && otyp != SPE_NOVEL
1177                 && otyp != SPE_BOOK_OF_THE_DEAD) {
1178                 costly_alteration(obj, COST_CANCEL);
1179                 obj->otyp = SPE_BLANK_PAPER;
1180             }
1181             break;
1182         case POTION_CLASS:
1183             costly_alteration(obj,
1184                               (otyp != POT_WATER)
1185                                   ? COST_CANCEL
1186                                   : obj->cursed ? COST_UNCURS : COST_UNBLSS);
1187             if (otyp == POT_SICKNESS || otyp == POT_SEE_INVISIBLE) {
1188                 /* sickness is "biologically contaminated" fruit juice;
1189                    cancel it and it just becomes fruit juice...
1190                    whereas see invisible tastes like "enchanted" fruit
1191                    juice, it similarly cancels */
1192                 obj->otyp = POT_FRUIT_JUICE;
1193             } else {
1194                 obj->otyp = POT_WATER;
1195                 obj->odiluted = 0; /* same as any other water */
1196             }
1197             break;
1198         }
1199     }
1200     unbless(obj);
1201     uncurse(obj);
1202     return;
1203 }
1204
1205 /* Remove a positive enchantment or charge from obj,
1206  * possibly carried by you or a monster
1207  */
1208 boolean
1209 drain_item(obj, by_you)
1210 struct obj *obj;
1211 boolean by_you;
1212 {
1213     boolean u_ring;
1214
1215     /* Is this a charged/enchanted object? */
1216     if (!obj
1217         || (!objects[obj->otyp].oc_charged && obj->oclass != WEAPON_CLASS
1218             && obj->oclass != ARMOR_CLASS && !is_weptool(obj))
1219         || obj->spe <= 0)
1220         return FALSE;
1221     if (defends(AD_DRLI, obj) || defends_when_carried(AD_DRLI, obj)
1222         || obj_resists(obj, 10, 90))
1223         return FALSE;
1224
1225     /* Charge for the cost of the object */
1226     if (by_you)
1227         costly_alteration(obj, COST_DRAIN);
1228
1229     /* Drain the object and any implied effects */
1230     obj->spe--;
1231     u_ring = (obj == uleft) || (obj == uright);
1232     switch (obj->otyp) {
1233     case RIN_GAIN_STRENGTH:
1234         if ((obj->owornmask & W_RING) && u_ring) {
1235             ABON(A_STR)--;
1236             context.botl = 1;
1237         }
1238         break;
1239     case RIN_GAIN_CONSTITUTION:
1240         if ((obj->owornmask & W_RING) && u_ring) {
1241             ABON(A_CON)--;
1242             context.botl = 1;
1243         }
1244         break;
1245     case RIN_ADORNMENT:
1246         if ((obj->owornmask & W_RING) && u_ring) {
1247             ABON(A_CHA)--;
1248             context.botl = 1;
1249         }
1250         break;
1251     case RIN_INCREASE_ACCURACY:
1252         if ((obj->owornmask & W_RING) && u_ring)
1253             u.uhitinc--;
1254         break;
1255     case RIN_INCREASE_DAMAGE:
1256         if ((obj->owornmask & W_RING) && u_ring)
1257             u.udaminc--;
1258         break;
1259     case RIN_PROTECTION:
1260         if (u_ring)
1261             context.botl = 1; /* bot() will recalc u.uac */
1262         break;
1263     case HELM_OF_BRILLIANCE:
1264         if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1265             ABON(A_INT)--;
1266             ABON(A_WIS)--;
1267             context.botl = 1;
1268         }
1269         break;
1270     case GAUNTLETS_OF_DEXTERITY:
1271         if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1272             ABON(A_DEX)--;
1273             context.botl = 1;
1274         }
1275         break;
1276     default:
1277         break;
1278     }
1279     if (context.botl)
1280         bot();
1281     if (carried(obj))
1282         update_inventory();
1283     return TRUE;
1284 }
1285
1286 boolean
1287 obj_resists(obj, ochance, achance)
1288 struct obj *obj;
1289 int ochance, achance; /* percent chance for ordinary objects, artifacts */
1290 {
1291     if (obj->otyp == AMULET_OF_YENDOR
1292         || obj->otyp == SPE_BOOK_OF_THE_DEAD
1293         || obj->otyp == CANDELABRUM_OF_INVOCATION
1294         || obj->otyp == BELL_OF_OPENING
1295         || (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm]))) {
1296         return TRUE;
1297     } else {
1298         int chance = rn2(100);
1299
1300         return (boolean) (chance < (obj->oartifact ? achance : ochance));
1301     }
1302 }
1303
1304 boolean
1305 obj_shudders(obj)
1306 struct obj *obj;
1307 {
1308     int zap_odds;
1309
1310     if (context.bypasses && obj->bypass)
1311         return FALSE;
1312
1313     if (obj->oclass == WAND_CLASS)
1314         zap_odds = 3; /* half-life = 2 zaps */
1315     else if (obj->cursed)
1316         zap_odds = 3; /* half-life = 2 zaps */
1317     else if (obj->blessed)
1318         zap_odds = 12; /* half-life = 8 zaps */
1319     else
1320         zap_odds = 8; /* half-life = 6 zaps */
1321
1322     /* adjust for "large" quantities of identical things */
1323     if (obj->quan > 4L)
1324         zap_odds /= 2;
1325
1326     return (boolean) !rn2(zap_odds);
1327 }
1328
1329 /* Use up at least minwt number of things made of material mat.
1330  * There's also a chance that other stuff will be used up.  Finally,
1331  * there's a random factor here to keep from always using the stuff
1332  * at the top of the pile.
1333  */
1334 STATIC_OVL void
1335 polyuse(objhdr, mat, minwt)
1336 struct obj *objhdr;
1337 int mat, minwt;
1338 {
1339     register struct obj *otmp, *otmp2;
1340
1341     for (otmp = objhdr; minwt > 0 && otmp; otmp = otmp2) {
1342         otmp2 = otmp->nexthere;
1343         if (context.bypasses && otmp->bypass)
1344             continue;
1345         if (otmp == uball || otmp == uchain)
1346             continue;
1347         if (obj_resists(otmp, 0, 0))
1348             continue; /* preserve unique objects */
1349 #ifdef MAIL
1350         if (otmp->otyp == SCR_MAIL)
1351             continue;
1352 #endif
1353
1354         if (((int) objects[otmp->otyp].oc_material == mat)
1355             == (rn2(minwt + 1) != 0)) {
1356             /* appropriately add damage to bill */
1357             if (costly_spot(otmp->ox, otmp->oy)) {
1358                 if (*u.ushops)
1359                     addtobill(otmp, FALSE, FALSE, FALSE);
1360                 else
1361                     (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE,
1362                                         FALSE);
1363             }
1364             if (otmp->quan < LARGEST_INT)
1365                 minwt -= (int) otmp->quan;
1366             else
1367                 minwt = 0;
1368             delobj(otmp);
1369         }
1370     }
1371 }
1372
1373 /*
1374  * Polymorph some of the stuff in this pile into a monster, preferably
1375  * a golem of the kind okind.
1376  */
1377 STATIC_OVL void
1378 create_polymon(obj, okind)
1379 struct obj *obj;
1380 int okind;
1381 {
1382     struct permonst *mdat = (struct permonst *) 0;
1383     struct monst *mtmp;
1384     const char *material;
1385     int pm_index;
1386
1387     if (context.bypasses) {
1388         /* this is approximate because the "no golems" !obj->nexthere
1389            check below doesn't understand bypassed objects; but it
1390            should suffice since bypassed objects always end up as a
1391            consecutive group at the top of their pile */
1392         while (obj && obj->bypass)
1393             obj = obj->nexthere;
1394     }
1395
1396     /* no golems if you zap only one object -- not enough stuff */
1397     if (!obj || (!obj->nexthere && obj->quan == 1L))
1398         return;
1399
1400     /* some of these choices are arbitrary */
1401     switch (okind) {
1402     case IRON:
1403     case METAL:
1404     case MITHRIL:
1405         pm_index = PM_IRON_GOLEM;
1406 /*JP
1407         material = "metal ";
1408 */
1409         material = "\8bà\91®";
1410         break;
1411     case COPPER:
1412     case SILVER:
1413     case PLATINUM:
1414     case GEMSTONE:
1415     case MINERAL:
1416         pm_index = rn2(2) ? PM_STONE_GOLEM : PM_CLAY_GOLEM;
1417 /*JP
1418         material = "lithic ";
1419 */
1420         material = "\8dz\95¨";
1421         break;
1422     case 0:
1423     case FLESH:
1424         /* there is no flesh type, but all food is type 0, so we use it */
1425         pm_index = PM_FLESH_GOLEM;
1426 /*JP
1427         material = "organic ";
1428 */
1429         material = "\97L\8b@\95¨";
1430         break;
1431     case WOOD:
1432         pm_index = PM_WOOD_GOLEM;
1433 /*JP
1434         material = "wood ";
1435 */
1436         material = "\96Ø\8dÞ";
1437         break;
1438     case LEATHER:
1439         pm_index = PM_LEATHER_GOLEM;
1440 /*JP
1441         material = "leather ";
1442 */
1443         material = "\8av";
1444         break;
1445     case CLOTH:
1446         pm_index = PM_ROPE_GOLEM;
1447 /*JP
1448         material = "cloth ";
1449 */
1450         material = "\95z";
1451         break;
1452     case BONE:
1453         pm_index = PM_SKELETON; /* nearest thing to "bone golem" */
1454 /*JP
1455         material = "bony ";
1456 */
1457         material = "\8d\9c";
1458         break;
1459     case GOLD:
1460         pm_index = PM_GOLD_GOLEM;
1461 /*JP
1462         material = "gold ";
1463 */
1464         material = "\8bà";
1465         break;
1466     case GLASS:
1467         pm_index = PM_GLASS_GOLEM;
1468 /*JP
1469         material = "glassy ";
1470 */
1471         material = "\83K\83\89\83X";
1472         break;
1473     case PAPER:
1474         pm_index = PM_PAPER_GOLEM;
1475 /*JP
1476         material = "paper ";
1477 */
1478         material = "\8e\86";
1479         break;
1480     default:
1481         /* if all else fails... */
1482         pm_index = PM_STRAW_GOLEM;
1483 #if 0 /*JP*/
1484         material = "";
1485 #else
1486         material = "\95¨\91Ì";
1487 #endif
1488         break;
1489     }
1490
1491     if (!(mvitals[pm_index].mvflags & G_GENOD))
1492         mdat = &mons[pm_index];
1493
1494     mtmp = makemon(mdat, obj->ox, obj->oy, NO_MM_FLAGS);
1495     polyuse(obj, okind, (int) mons[pm_index].cwt);
1496
1497     if (mtmp && cansee(mtmp->mx, mtmp->my)) {
1498 #if 0 /*JP*/
1499         pline("Some %sobjects meld, and %s arises from the pile!", material,
1500               a_monnam(mtmp));
1501 #else
1502         pline("\82¢\82­\82Â\82©\82Ì%s\82ª\97n\82¯\81C\82»\82Ì\8eR\82©\82ç%s\82ª\8c»\82í\82ê\82½\81I", material,
1503               a_monnam(mtmp));
1504 #endif
1505     }
1506 }
1507
1508 /* Assumes obj is on the floor. */
1509 void
1510 do_osshock(obj)
1511 struct obj *obj;
1512 {
1513     long i;
1514
1515 #ifdef MAIL
1516     if (obj->otyp == SCR_MAIL)
1517         return;
1518 #endif
1519     obj_zapped = TRUE;
1520
1521     if (poly_zapped < 0) {
1522         /* some may metamorphosize */
1523         for (i = obj->quan; i; i--)
1524             if (!rn2(Luck + 45)) {
1525                 poly_zapped = objects[obj->otyp].oc_material;
1526                 break;
1527             }
1528     }
1529
1530     /* if quan > 1 then some will survive intact */
1531     if (obj->quan > 1L) {
1532         if (obj->quan > LARGEST_INT)
1533             obj = splitobj(obj, (long) rnd(30000));
1534         else
1535             obj = splitobj(obj, (long) rnd((int) obj->quan - 1));
1536     }
1537
1538     /* appropriately add damage to bill */
1539     if (costly_spot(obj->ox, obj->oy)) {
1540         if (*u.ushops)
1541             addtobill(obj, FALSE, FALSE, FALSE);
1542         else
1543             (void) stolen_value(obj, obj->ox, obj->oy, FALSE, FALSE);
1544     }
1545
1546     /* zap the object */
1547     delobj(obj);
1548 }
1549
1550 /* classes of items whose current charge count carries over across polymorph
1551  */
1552 static const char charged_objs[] = { WAND_CLASS, WEAPON_CLASS, ARMOR_CLASS,
1553                                      '\0' };
1554
1555 /*
1556  * Polymorph the object to the given object ID.  If the ID is STRANGE_OBJECT
1557  * then pick random object from the source's class (this is the standard
1558  * "polymorph" case).  If ID is set to a specific object, inhibit fusing
1559  * n objects into 1.  This could have been added as a flag, but currently
1560  * it is tied to not being the standard polymorph case. The new polymorphed
1561  * object replaces obj in its link chains.  Return value is a pointer to
1562  * the new object.
1563  *
1564  * This should be safe to call for an object anywhere.
1565  */
1566 struct obj *
1567 poly_obj(obj, id)
1568 struct obj *obj;
1569 int id;
1570 {
1571     struct obj *otmp;
1572     xchar ox, oy;
1573     boolean can_merge = (id == STRANGE_OBJECT);
1574     int obj_location = obj->where;
1575
1576     if (obj->otyp == BOULDER)
1577         sokoban_guilt();
1578     if (id == STRANGE_OBJECT) { /* preserve symbol */
1579         int try_limit = 3;
1580         unsigned magic_obj = objects[obj->otyp].oc_magic;
1581
1582         if (obj->otyp == UNICORN_HORN && obj->degraded_horn)
1583             magic_obj = 0;
1584         /* Try up to 3 times to make the magic-or-not status of
1585            the new item be the same as it was for the old one. */
1586         otmp = (struct obj *) 0;
1587         do {
1588             if (otmp)
1589                 delobj(otmp);
1590             otmp = mkobj(obj->oclass, FALSE);
1591         } while (--try_limit > 0
1592                  && objects[otmp->otyp].oc_magic != magic_obj);
1593     } else {
1594         /* literally replace obj with this new thing */
1595         otmp = mksobj(id, FALSE, FALSE);
1596 /* Actually more things use corpsenm but they polymorph differently */
1597 #define USES_CORPSENM(typ) \
1598     ((typ) == CORPSE || (typ) == STATUE || (typ) == FIGURINE)
1599
1600         if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
1601             set_corpsenm(otmp, obj->corpsenm);
1602 #undef USES_CORPSENM
1603     }
1604
1605     /* preserve quantity */
1606     otmp->quan = obj->quan;
1607     /* preserve the shopkeepers (lack of) interest */
1608     otmp->no_charge = obj->no_charge;
1609     /* preserve inventory letter if in inventory */
1610     if (obj_location == OBJ_INVENT)
1611         otmp->invlet = obj->invlet;
1612 #ifdef MAIL
1613     /* You can't send yourself 100 mail messages and then
1614      * polymorph them into useful scrolls
1615      */
1616     if (obj->otyp == SCR_MAIL) {
1617         otmp->otyp = SCR_MAIL;
1618         otmp->spe = 1;
1619     }
1620 #endif
1621
1622     /* avoid abusing eggs laid by you */
1623     if (obj->otyp == EGG && obj->spe) {
1624         int mnum, tryct = 100;
1625
1626         /* first, turn into a generic egg */
1627         if (otmp->otyp == EGG)
1628             kill_egg(otmp);
1629         else {
1630             otmp->otyp = EGG;
1631             otmp->owt = weight(otmp);
1632         }
1633         otmp->corpsenm = NON_PM;
1634         otmp->spe = 0;
1635
1636         /* now change it into something laid by the hero */
1637         while (tryct--) {
1638             mnum = can_be_hatched(random_monster());
1639             if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
1640                 otmp->spe = 1;            /* laid by hero */
1641                 set_corpsenm(otmp, mnum); /* also sets hatch timer */
1642                 break;
1643             }
1644         }
1645     }
1646
1647     /* keep special fields (including charges on wands) */
1648     if (index(charged_objs, otmp->oclass))
1649         otmp->spe = obj->spe;
1650     otmp->recharged = obj->recharged;
1651
1652     otmp->cursed = obj->cursed;
1653     otmp->blessed = obj->blessed;
1654
1655     if (erosion_matters(otmp)) {
1656         if (is_flammable(otmp) || is_rustprone(otmp))
1657             otmp->oeroded = obj->oeroded;
1658         if (is_corrodeable(otmp) || is_rottable(otmp))
1659             otmp->oeroded2 = obj->oeroded2;
1660         if (is_damageable(otmp))
1661             otmp->oerodeproof = obj->oerodeproof;
1662     }
1663
1664     /* Keep chest/box traps and poisoned ammo if we may */
1665     if (obj->otrapped && Is_box(otmp))
1666         otmp->otrapped = TRUE;
1667
1668     if (obj->opoisoned && is_poisonable(otmp))
1669         otmp->opoisoned = TRUE;
1670
1671     if (id == STRANGE_OBJECT && obj->otyp == CORPSE) {
1672         /* turn crocodile corpses into shoes */
1673         if (obj->corpsenm == PM_CROCODILE) {
1674             otmp->otyp = LOW_BOOTS;
1675             otmp->oclass = ARMOR_CLASS;
1676             otmp->spe = 0;
1677             otmp->oeroded = 0;
1678             otmp->oerodeproof = TRUE;
1679             otmp->quan = 1L;
1680             otmp->cursed = FALSE;
1681         }
1682     }
1683
1684     /* no box contents --KAA */
1685     if (Has_contents(otmp))
1686         delete_contents(otmp);
1687
1688     /* 'n' merged objects may be fused into 1 object */
1689     if (otmp->quan > 1L && (!objects[otmp->otyp].oc_merge
1690                             || (can_merge && otmp->quan > (long) rn2(1000))))
1691         otmp->quan = 1L;
1692
1693     switch (otmp->oclass) {
1694     case TOOL_CLASS:
1695         if (otmp->otyp == MAGIC_LAMP) {
1696             otmp->otyp = OIL_LAMP;
1697             otmp->age = 1500L; /* "best" oil lamp possible */
1698         } else if (otmp->otyp == MAGIC_MARKER) {
1699             otmp->recharged = 1; /* degraded quality */
1700         }
1701         /* don't care about the recharge count of other tools */
1702         break;
1703
1704     case WAND_CLASS:
1705         while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
1706             otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
1707         /* altering the object tends to degrade its quality
1708            (analogous to spellbook `read count' handling) */
1709         if ((int) otmp->recharged < rn2(7)) /* recharge_limit */
1710             otmp->recharged++;
1711         break;
1712
1713     case POTION_CLASS:
1714         while (otmp->otyp == POT_POLYMORPH)
1715             otmp->otyp = rnd_class(POT_GAIN_ABILITY, POT_WATER);
1716         break;
1717
1718     case SPBOOK_CLASS:
1719         while (otmp->otyp == SPE_POLYMORPH)
1720             otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
1721         /* reduce spellbook abuse; non-blank books degrade */
1722         if (otmp->otyp != SPE_BLANK_PAPER) {
1723             otmp->spestudied = obj->spestudied + 1;
1724             if (otmp->spestudied > MAX_SPELL_STUDY) {
1725                 otmp->otyp = SPE_BLANK_PAPER;
1726                 /* writing a new book over it will yield an unstudied
1727                    one; re-polymorphing this one as-is may or may not
1728                    get something non-blank */
1729                 otmp->spestudied = rn2(otmp->spestudied);
1730             }
1731         }
1732         break;
1733
1734     case GEM_CLASS:
1735         if (otmp->quan > (long) rnd(4)
1736             && objects[obj->otyp].oc_material == MINERAL
1737             && objects[otmp->otyp].oc_material != MINERAL) {
1738             otmp->otyp = ROCK; /* transmutation backfired */
1739             otmp->quan /= 2L;  /* some material has been lost */
1740         }
1741         break;
1742     }
1743
1744     /* update the weight */
1745     otmp->owt = weight(otmp);
1746
1747     /* handle polymorph of worn item: stone-to-flesh cast on self can
1748        affect multiple objects at once, but their new forms won't
1749        produce any side-effects; a single worn item dipped into potion
1750        of polymorph can produce side-effects but those won't yield out
1751        of sequence messages because current polymorph is finished */
1752     if (obj_location == OBJ_INVENT && obj->owornmask) {
1753         long old_wornmask = obj->owornmask & ~(W_ART | W_ARTI),
1754              new_wornmask = wearslot(otmp);
1755         boolean was_twohanded = bimanual(obj), was_twoweap = u.twoweap;
1756
1757         remove_worn_item(obj, TRUE);
1758         /* if the new form can be worn in the same slot, make it so
1759            [possible extension:  if it could be worn in some other
1760            slot which is currently unfilled, wear it there instead] */
1761         if ((old_wornmask & W_QUIVER) != 0L) {
1762             setuqwep(otmp);
1763         } else if ((old_wornmask & W_SWAPWEP) != 0L) {
1764             if (was_twohanded || !bimanual(otmp))
1765                 setuswapwep(otmp);
1766             if (was_twoweap && uswapwep)
1767                 u.twoweap = TRUE;
1768         } else if ((old_wornmask & W_WEP) != 0L) {
1769             if (was_twohanded || !bimanual(otmp) || !uarms)
1770                 setuwep(otmp);
1771             if (was_twoweap && uwep && !bimanual(uwep))
1772                 u.twoweap = TRUE;
1773         } else if ((old_wornmask & new_wornmask) != 0L) {
1774             new_wornmask &= old_wornmask;
1775             setworn(otmp, new_wornmask);
1776             set_wear(otmp); /* Armor_on() for side-effects */
1777         }
1778     }
1779
1780     /* ** we are now done adjusting the object ** */
1781
1782     /* swap otmp for obj */
1783     replace_object(obj, otmp);
1784     if (obj_location == OBJ_INVENT) {
1785         /*
1786          * We may need to do extra adjustments for the hero if we're
1787          * messing with the hero's inventory.  The following calls are
1788          * equivalent to calling freeinv on obj and addinv on otmp,
1789          * while doing an in-place swap of the actual objects.
1790          */
1791         freeinv_core(obj);
1792         addinv_core1(otmp);
1793         addinv_core2(otmp);
1794     } else if (obj_location == OBJ_FLOOR) {
1795         ox = otmp->ox, oy = otmp->oy; /* set by replace_object() */
1796         if (obj->otyp == BOULDER && otmp->otyp != BOULDER
1797             && !does_block(ox, oy, &levl[ox][oy]))
1798             unblock_point(ox, oy);
1799         else if (obj->otyp != BOULDER && otmp->otyp == BOULDER)
1800             /* (checking does_block() here would be redundant) */
1801             block_point(ox, oy);
1802     }
1803
1804     if ((!carried(otmp) || obj->unpaid)
1805         && get_obj_location(otmp, &ox, &oy, BURIED_TOO | CONTAINED_TOO)
1806         && costly_spot(ox, oy)) {
1807         register struct monst *shkp =
1808             shop_keeper(*in_rooms(ox, oy, SHOPBASE));
1809
1810         if ((!obj->no_charge
1811              || (Has_contents(obj)
1812                  && (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L)))
1813             && inhishop(shkp)) {
1814             if (shkp->mpeaceful) {
1815                 if (*u.ushops
1816                     && *in_rooms(u.ux, u.uy, 0)
1817                            == *in_rooms(shkp->mx, shkp->my, 0)
1818                     && !costly_spot(u.ux, u.uy)) {
1819                     make_angry_shk(shkp, ox, oy);
1820                 } else {
1821 /*JP
1822                     pline("%s gets angry!", Monnam(shkp));
1823 */
1824                     pline("%s\82Í\8c\83\93{\82µ\82½\81I", Monnam(shkp));
1825                     hot_pursuit(shkp);
1826                 }
1827             } else
1828 /*JP
1829                 Norep("%s is furious!", Monnam(shkp));
1830 */
1831                 Norep("%s\82Í\93{\82Á\82½\81I", Monnam(shkp));
1832         }
1833     }
1834     delobj(obj);
1835     return otmp;
1836 }
1837
1838 /* stone-to-flesh spell hits and maybe transforms or animates obj */
1839 STATIC_OVL int
1840 stone_to_flesh_obj(obj)
1841 struct obj *obj;
1842 {
1843     int res = 1; /* affected object by default */
1844     struct permonst *ptr;
1845     struct monst *mon, *shkp;
1846     struct obj *item;
1847     xchar oox, ooy;
1848     boolean smell = FALSE, golem_xform = FALSE;
1849
1850     if (objects[obj->otyp].oc_material != MINERAL
1851         && objects[obj->otyp].oc_material != GEMSTONE)
1852         return 0;
1853     /* Heart of Ahriman usually resists; ordinary items rarely do */
1854     if (obj_resists(obj, 2, 98))
1855         return 0;
1856
1857     (void) get_obj_location(obj, &oox, &ooy, 0);
1858     /* add more if stone objects are added.. */
1859     switch (objects[obj->otyp].oc_class) {
1860     case ROCK_CLASS: /* boulders and statues */
1861     case TOOL_CLASS: /* figurines */
1862         if (obj->otyp == BOULDER) {
1863             obj = poly_obj(obj, HUGE_CHUNK_OF_MEAT);
1864             smell = TRUE;
1865         } else if (obj->otyp == STATUE || obj->otyp == FIGURINE) {
1866             ptr = &mons[obj->corpsenm];
1867             if (is_golem(ptr)) {
1868                 golem_xform = (ptr != &mons[PM_FLESH_GOLEM]);
1869             } else if (vegetarian(ptr)) {
1870                 /* Don't animate monsters that aren't flesh */
1871                 obj = poly_obj(obj, MEATBALL);
1872                 smell = TRUE;
1873                 break;
1874             }
1875             if (obj->otyp == STATUE) {
1876                 /* animate_statue() forces all golems to become flesh golems */
1877                 mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
1878             } else { /* (obj->otyp == FIGURINE) */
1879                 if (golem_xform)
1880                     ptr = &mons[PM_FLESH_GOLEM];
1881                 mon = makemon(ptr, oox, ooy, NO_MINVENT);
1882                 if (mon) {
1883                     if (costly_spot(oox, ooy)
1884                         && (carried(obj) ? obj->unpaid : !obj->no_charge)) {
1885                         shkp = shop_keeper(*in_rooms(oox, ooy, SHOPBASE));
1886                         stolen_value(obj, oox, ooy,
1887                                      (shkp && shkp->mpeaceful), FALSE);
1888                     }
1889                     if (obj->timed)
1890                         obj_stop_timers(obj);
1891                     if (carried(obj))
1892                         useup(obj);
1893                     else
1894                         delobj(obj);
1895                     if (cansee(mon->mx, mon->my))
1896 #if 0 /*JP*/
1897                         pline_The("figurine %sanimates!",
1898                                   golem_xform ? "turns to flesh and " : "");
1899 #else
1900                         pline_The("\90l\8c`\82Í%s\93®\82«\82¾\82µ\82½\81I",
1901                                   golem_xform ? "\90Î\89»\82ª\89ð\82¯\82Ä" : "");
1902 #endif
1903                 }
1904             }
1905             if (mon) {
1906                 ptr = mon->data;
1907                 /* this golem handling is redundant... */
1908                 if (is_golem(ptr) && ptr != &mons[PM_FLESH_GOLEM])
1909                     (void) newcham(mon, &mons[PM_FLESH_GOLEM], TRUE, FALSE);
1910             } else if ((ptr->geno & (G_NOCORPSE | G_UNIQ)) != 0) {
1911                 /* didn't revive but can't leave corpse either */
1912                 res = 0;
1913             } else {
1914                 /* unlikely to get here since genociding monsters also
1915                    sets the G_NOCORPSE flag; drop statue's contents */
1916                 while ((item = obj->cobj) != 0) {
1917                     bypass_obj(item); /* make stone-to-flesh miss it */
1918                     obj_extract_self(item);
1919                     place_object(item, oox, ooy);
1920                 }
1921                 obj = poly_obj(obj, CORPSE);
1922             }
1923         } else { /* miscellaneous tool or unexpected rock... */
1924             res = 0;
1925         }
1926         break;
1927     /* maybe add weird things to become? */
1928     case RING_CLASS: /* some of the rings are stone */
1929         obj = poly_obj(obj, MEAT_RING);
1930         smell = TRUE;
1931         break;
1932     case WAND_CLASS: /* marble wand */
1933         obj = poly_obj(obj, MEAT_STICK);
1934         smell = TRUE;
1935         break;
1936     case GEM_CLASS: /* stones & gems */
1937         obj = poly_obj(obj, MEATBALL);
1938         smell = TRUE;
1939         break;
1940     case WEAPON_CLASS: /* crysknife */
1941         /*FALLTHRU*/
1942     default:
1943         res = 0;
1944         break;
1945     }
1946
1947     if (smell) {
1948         /* non-meat eaters smell meat, meat eaters smell its flavor;
1949            monks are considered non-meat eaters regardless of behavior;
1950            other roles are non-meat eaters if they haven't broken
1951            vegetarian conduct yet (or if poly'd into non-carnivorous/
1952            non-omnivorous form, regardless of whether it's herbivorous,
1953            non-eating, or something stranger) */
1954         if (Role_if(PM_MONK) || !u.uconduct.unvegetarian
1955             || !carnivorous(youmonst.data))
1956 /*JP
1957             Norep("You smell the odor of meat.");
1958 */
1959             Norep("\93÷\82Ì\88«\8fL\82ª\95Y\82Á\82½\81D");
1960         else
1961 /*JP
1962             Norep("You smell a delicious smell.");
1963 */
1964             Norep("\82·\82Î\82ç\82µ\82¢\8d\81\82è\82¾\81I");
1965     }
1966     newsym(oox, ooy);
1967     return res;
1968 }
1969
1970 /*
1971  * Object obj was hit by the effect of the wand/spell otmp.  Return
1972  * non-zero if the wand/spell had any effect.
1973  */
1974 int
1975 bhito(obj, otmp)
1976 struct obj *obj, *otmp;
1977 {
1978     int res = 1; /* affected object by default */
1979     boolean learn_it = FALSE, maybelearnit;
1980
1981     /* fundamental: a wand effect hitting itself doesn't do anything;
1982        otherwise we need to guard against accessing otmp after something
1983        strange has happened to it (along the lines of polymorph or
1984        stone-to-flesh [which aren't good examples since polymorph wands
1985        aren't affected by polymorph zaps and stone-to-flesh isn't
1986        available in wand form, but the concept still applies...]) */
1987     if (obj == otmp)
1988         return 0;
1989
1990     if (obj->bypass) {
1991         /* The bypass bit is currently only used as follows:
1992          *
1993          * POLYMORPH - When a monster being polymorphed drops something
1994          *             from its inventory as a result of the change.
1995          *             If the items fall to the floor, they are not
1996          *             subject to direct subsequent polymorphing
1997          *             themselves on that same zap. This makes it
1998          *             consistent with items that remain in the
1999          *             monster's inventory. They are not polymorphed
2000          *             either.
2001          * UNDEAD_TURNING - When an undead creature gets killed via
2002          *             undead turning, prevent its corpse from being
2003          *             immediately revived by the same effect.
2004          * STONE_TO_FLESH - If a statue can't be revived, its
2005          *             contents get dropped before turning it into
2006          *             meat; prevent those contents from being hit.
2007          * retouch_equipment() - bypass flag is used to track which
2008          *             items have been handled (bhito isn't involved).
2009          * menu_drop(), askchain() - inventory traversal where multiple
2010          *             Drop can alter the invent chain while traversal
2011          *             is in progress (bhito isn't involved).
2012          *
2013          * The bypass bit on all objects is reset each turn, whenever
2014          * context.bypasses is set.
2015          *
2016          * We check the obj->bypass bit above AND context.bypasses
2017          * as a safeguard against any stray occurrence left in an obj
2018          * struct someplace, although that should never happen.
2019          */
2020         if (context.bypasses) {
2021             return 0;
2022         } else {
2023             debugpline1("%s for a moment.", Tobjnam(obj, "pulsate"));
2024             obj->bypass = 0;
2025         }
2026     }
2027
2028     /*
2029      * Some parts of this function expect the object to be on the floor
2030      * obj->{ox,oy} to be valid.  The exception to this (so far) is
2031      * for the STONE_TO_FLESH spell.
2032      */
2033     if (!(obj->where == OBJ_FLOOR || otmp->otyp == SPE_STONE_TO_FLESH))
2034         impossible("bhito: obj is not floor or Stone To Flesh spell");
2035
2036     if (obj == uball) {
2037         res = 0;
2038     } else if (obj == uchain) {
2039         if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
2040             learn_it = TRUE;
2041             unpunish();
2042         } else
2043             res = 0;
2044     } else
2045         switch (otmp->otyp) {
2046         case WAN_POLYMORPH:
2047         case SPE_POLYMORPH:
2048             if (obj->otyp == WAN_POLYMORPH || obj->otyp == SPE_POLYMORPH
2049                 || obj->otyp == POT_POLYMORPH || obj_resists(obj, 5, 95)) {
2050                 res = 0;
2051                 break;
2052             }
2053             /* KMH, conduct */
2054             u.uconduct.polypiles++;
2055             /* any saved lock context will be dangerously obsolete */
2056             if (Is_box(obj))
2057                 (void) boxlock(obj, otmp);
2058
2059             if (obj_shudders(obj)) {
2060                 boolean cover =
2061                     ((obj == level.objects[u.ux][u.uy]) && u.uundetected
2062                      && hides_under(youmonst.data));
2063
2064                 if (cansee(obj->ox, obj->oy))
2065                     learn_it = TRUE;
2066                 do_osshock(obj);
2067                 /* eek - your cover might have been blown */
2068                 if (cover)
2069                     (void) hideunder(&youmonst);
2070                 break;
2071             }
2072             obj = poly_obj(obj, STRANGE_OBJECT);
2073             newsym(obj->ox, obj->oy);
2074             break;
2075         case WAN_PROBING:
2076             res = !obj->dknown;
2077             /* target object has now been "seen (up close)" */
2078             obj->dknown = 1;
2079             if (Is_container(obj) || obj->otyp == STATUE) {
2080                 obj->cknown = obj->lknown = 1;
2081                 if (!obj->cobj) {
2082                     boolean catbox = SchroedingersBox(obj);
2083
2084                     /* we don't want to force alive vs dead
2085                        determination for Schroedinger's Cat here,
2086                        so just make probing be inconclusive for it */
2087                     if (catbox)
2088                         obj->cknown = 0;
2089 /*JP
2090                     pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
2091 */
2092                     pline("%s\82Í\8bó\82Á\82Û%s\82¾\81D", xname(obj), catbox ? "\82Ì\82æ\82¤" : "");
2093                 } else {
2094                     struct obj *o;
2095                     /* view contents (not recursively) */
2096                     for (o = obj->cobj; o; o = o->nobj)
2097                         o->dknown = 1; /* "seen", even if blind */
2098                     (void) display_cinventory(obj);
2099                 }
2100                 res = 1;
2101             }
2102             if (res)
2103                 learn_it = TRUE;
2104             break;
2105         case WAN_STRIKING:
2106         case SPE_FORCE_BOLT:
2107             /* learn the type if you see or hear something break
2108                (the sound could be implicit) */
2109             maybelearnit = cansee(obj->ox, obj->oy) || !Deaf;
2110             if (obj->otyp == BOULDER) {
2111                 if (cansee(obj->ox, obj->oy))
2112 /*JP
2113                     pline_The("boulder falls apart.");
2114 */
2115                     pline_The("\8aâ\82Í\82Î\82ç\82Î\82ç\82É\82È\82Á\82½\81D");
2116                 else
2117 /*JP
2118                     You_hear("a crumbling sound.");
2119 */
2120                     You_hear("\89½\82©\82ª\8dÓ\82¯\82é\89¹\82ð\95·\82¢\82½\81D");
2121                 fracture_rock(obj);
2122             } else if (obj->otyp == STATUE) {
2123                 if (break_statue(obj)) {
2124                     if (cansee(obj->ox, obj->oy)) {
2125                         if (Hallucination)
2126 /*JP
2127                             pline_The("%s shatters.", rndmonnam(NULL));
2128 */
2129                             pline_The("%s\82Í\95²\81X\82É\82È\82Á\82½\81D", rndmonnam(NULL));
2130                         else
2131 /*JP
2132                             pline_The("statue shatters.");
2133 */
2134                             pline_The("\90Î\91\9c\82Í\95²\81X\82É\82È\82Á\82½\81D");
2135                     } else
2136 /*JP
2137                         You_hear("a crumbling sound.");
2138 */
2139                         You_hear("\89½\82©\82ª\8dÓ\82¯\82é\89¹\82ð\95·\82¢\82½\81D");
2140                 }
2141             } else {
2142                 int oox = obj->ox;
2143                 int ooy = obj->oy;
2144                 if (context.mon_moving
2145                         ? !breaks(obj, obj->ox, obj->oy)
2146                         : !hero_breaks(obj, obj->ox, obj->oy, FALSE))
2147                     maybelearnit = FALSE; /* nothing broke */
2148                 else
2149                     newsym_force(oox,ooy);
2150                 res = 0;
2151             }
2152             if (maybelearnit)
2153                 learn_it = TRUE;
2154             break;
2155         case WAN_CANCELLATION:
2156         case SPE_CANCELLATION:
2157             cancel_item(obj);
2158 #ifdef TEXTCOLOR
2159             newsym(obj->ox, obj->oy); /* might change color */
2160 #endif
2161             break;
2162         case SPE_DRAIN_LIFE:
2163             (void) drain_item(obj, TRUE);
2164             break;
2165         case WAN_TELEPORTATION:
2166         case SPE_TELEPORT_AWAY:
2167             (void) rloco(obj);
2168             break;
2169         case WAN_MAKE_INVISIBLE:
2170             break;
2171         case WAN_UNDEAD_TURNING:
2172         case SPE_TURN_UNDEAD:
2173             if (obj->otyp == EGG) {
2174                 revive_egg(obj);
2175             } else if (obj->otyp == CORPSE) {
2176                 int corpsenm = corpse_revive_type(obj);
2177
2178                 res = !!revive(obj, TRUE);
2179                 if (res && Role_if(PM_HEALER)) {
2180                     if (Hallucination && !Deaf) {
2181 /*JP
2182                         You_hear("the sound of a defibrillator.");
2183 */
2184                         You_hear("\8f\9c\8d×\93®\8aí\82Ì\89¹\82ð\95·\82¢\82½\81D");
2185                         learn_it = TRUE;
2186                     } else if (!Blind) {
2187 #if 0 /*JP*/
2188                         You("observe %s %s change dramatically.",
2189                             s_suffix(an(mons[corpsenm].mname)),
2190                             nonliving(&mons[corpsenm]) ? "motility"
2191                                                        : "health");
2192 #else
2193                         You("%s\82Ì%s\82ª\8c\80\93I\82É\95Ï\89»\82·\82é\82Ì\82ð\8c©\82½\81D",
2194                             mons[corpsenm].mname,
2195                             nonliving(&mons[corpsenm]) ? "\89^\93®\90«"
2196                                                        : "\8c\92\8dN");
2197 #endif
2198                         learn_it = TRUE;
2199                     }
2200                     if (learn_it)
2201                         exercise(A_WIS, TRUE);
2202                 }
2203             }
2204             break;
2205         case WAN_OPENING:
2206         case SPE_KNOCK:
2207         case WAN_LOCKING:
2208         case SPE_WIZARD_LOCK:
2209             if (Is_box(obj))
2210                 res = boxlock(obj, otmp);
2211             else
2212                 res = 0;
2213             if (res)
2214                 learn_it = TRUE;
2215             break;
2216         case WAN_SLOW_MONSTER: /* no effect on objects */
2217         case SPE_SLOW_MONSTER:
2218         case WAN_SPEED_MONSTER:
2219         case WAN_NOTHING:
2220         case SPE_HEALING:
2221         case SPE_EXTRA_HEALING:
2222             res = 0;
2223             break;
2224         case SPE_STONE_TO_FLESH:
2225             res = stone_to_flesh_obj(obj);
2226             break;
2227         default:
2228             impossible("What an interesting effect (%d)", otmp->otyp);
2229             break;
2230         }
2231     /* if effect was observable then discover the wand type provided
2232        that the wand itself has been seen */
2233     if (learn_it)
2234         learnwand(otmp);
2235     return res;
2236 }
2237
2238 /* returns nonzero if something was hit */
2239 int
2240 bhitpile(obj, fhito, tx, ty, zz)
2241 struct obj *obj;
2242 int FDECL((*fhito), (OBJ_P, OBJ_P));
2243 int tx, ty;
2244 schar zz;
2245 {
2246     int hitanything = 0;
2247     register struct obj *otmp, *next_obj;
2248
2249     if (obj->otyp == SPE_FORCE_BOLT || obj->otyp == WAN_STRIKING) {
2250         struct trap *t = t_at(tx, ty);
2251
2252         /* We can't settle for the default calling sequence of
2253            bhito(otmp) -> break_statue(otmp) -> activate_statue_trap(ox,oy)
2254            because that last call might end up operating on our `next_obj'
2255            (below), rather than on the current object, if it happens to
2256            encounter a statue which mustn't become animated. */
2257         if (t && t->ttyp == STATUE_TRAP
2258             && activate_statue_trap(t, tx, ty, TRUE))
2259             learnwand(obj);
2260     }
2261
2262     poly_zapped = -1;
2263     for (otmp = level.objects[tx][ty]; otmp; otmp = next_obj) {
2264         next_obj = otmp->nexthere;
2265         /* for zap downwards, don't hit object poly'd hero is hiding under */
2266         if (zz > 0 && u.uundetected && otmp == level.objects[u.ux][u.uy]
2267             && hides_under(youmonst.data))
2268             continue;
2269
2270         hitanything += (*fhito)(otmp, obj);
2271     }
2272     if (poly_zapped >= 0)
2273         create_polymon(level.objects[tx][ty], poly_zapped);
2274
2275     return hitanything;
2276 }
2277
2278 /*
2279  * zappable - returns 1 if zap is available, 0 otherwise.
2280  *            it removes a charge from the wand if zappable.
2281  * added by GAN 11/03/86
2282  */
2283 int
2284 zappable(wand)
2285 register struct obj *wand;
2286 {
2287     if (wand->spe < 0 || (wand->spe == 0 && rn2(121)))
2288         return 0;
2289     if (wand->spe == 0)
2290 /*JP
2291         You("wrest one last charge from the worn-out wand.");
2292 */
2293         You("\8eg\82¢\82«\82Á\82½\8fñ\82©\82ç\8dÅ\8cã\82Ì\97Í\82ð\82µ\82Ú\82è\82Æ\82Á\82½\81D");
2294     wand->spe--;
2295     return 1;
2296 }
2297
2298 /*
2299  * zapnodir - zaps a NODIR wand/spell.
2300  * added by GAN 11/03/86
2301  */
2302 void
2303 zapnodir(obj)
2304 register struct obj *obj;
2305 {
2306     boolean known = FALSE;
2307
2308     switch (obj->otyp) {
2309     case WAN_LIGHT:
2310     case SPE_LIGHT:
2311         litroom(TRUE, obj);
2312         if (!Blind)
2313             known = TRUE;
2314         if (lightdamage(obj, TRUE, 5))
2315             known = TRUE;
2316         break;
2317     case WAN_SECRET_DOOR_DETECTION:
2318     case SPE_DETECT_UNSEEN:
2319         if (!findit())
2320             return;
2321         if (!Blind)
2322             known = TRUE;
2323         break;
2324     case WAN_CREATE_MONSTER:
2325         known = create_critters(rn2(23) ? 1 : rn1(7, 2),
2326                                 (struct permonst *) 0, FALSE);
2327         break;
2328     case WAN_WISHING:
2329         known = TRUE;
2330         if (Luck + rn2(5) < 0) {
2331 /*JP
2332             pline("Unfortunately, nothing happens.");
2333 */
2334             pline("\8ec\94O\82È\82ª\82ç\81C\89½\82à\8bN\82«\82È\82©\82Á\82½\81D");
2335             break;
2336         }
2337         makewish();
2338         break;
2339     case WAN_ENLIGHTENMENT:
2340         known = TRUE;
2341 /*JP
2342         You_feel("self-knowledgeable...");
2343 */
2344         You("\8e©\95ª\8e©\90g\82ª\94»\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D\81D\81D");
2345         display_nhwindow(WIN_MESSAGE, FALSE);
2346         enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
2347 /*JP
2348         pline_The("feeling subsides.");
2349 */
2350         pline("\82»\82Ì\8a´\82\82Í\82È\82­\82È\82Á\82½\81D");
2351         exercise(A_WIS, TRUE);
2352         break;
2353     }
2354     if (known) {
2355         if (!objects[obj->otyp].oc_name_known)
2356             more_experienced(0, 10);
2357         /* effect was observable; discover the wand type provided
2358            that the wand itself has been seen */
2359         learnwand(obj);
2360     }
2361 }
2362
2363 STATIC_OVL void
2364 backfire(otmp)
2365 struct obj *otmp;
2366 {
2367     int dmg;
2368
2369     otmp->in_use = TRUE; /* in case losehp() is fatal */
2370 /*JP
2371     pline("%s suddenly explodes!", The(xname(otmp)));
2372 */
2373     pline("%s\82Í\93Ë\91R\94\9a\94­\82µ\82½\81I", xname(otmp));
2374     dmg = d(otmp->spe + 2, 6);
2375 /*JP
2376     losehp(Maybe_Half_Phys(dmg), "exploding wand", KILLED_BY_AN);
2377 */
2378     losehp(Maybe_Half_Phys(dmg), "\8fñ\82Ì\94\9a\94­\82Å", KILLED_BY_AN);
2379     useup(otmp);
2380 }
2381
2382 static NEARDATA const char zap_syms[] = { WAND_CLASS, 0 };
2383
2384 /* 'z' command (or 'y' if numbed_pad==-1) */
2385 int
2386 dozap()
2387 {
2388     register struct obj *obj;
2389     int damage;
2390
2391     if (check_capacity((char *) 0))
2392         return 0;
2393     obj = getobj(zap_syms, "zap");
2394     if (!obj)
2395         return 0;
2396
2397     check_unpaid(obj);
2398
2399     /* zappable addition done by GAN 11/03/86 */
2400     if (!zappable(obj))
2401         pline1(nothing_happens);
2402     else if (obj->cursed && !rn2(WAND_BACKFIRE_CHANCE)) {
2403         backfire(obj); /* the wand blows up in your face! */
2404         exercise(A_STR, FALSE);
2405         return 1;
2406     } else if (!(objects[obj->otyp].oc_dir == NODIR) && !getdir((char *) 0)) {
2407         if (!Blind)
2408 /*JP
2409             pline("%s glows and fades.", The(xname(obj)));
2410 */
2411             pline("%s\82Í\88ê\8fu\8bP\82¢\82½\81D", The(xname(obj)));
2412         /* make him pay for knowing !NODIR */
2413     } else if (!u.dx && !u.dy && !u.dz
2414                && !(objects[obj->otyp].oc_dir == NODIR)) {
2415         if ((damage = zapyourself(obj, TRUE)) != 0) {
2416 #if 0 /*JP*/
2417             char buf[BUFSZ];
2418
2419             Sprintf(buf, "zapped %sself with a wand", uhim());
2420             losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
2421 #else
2422             losehp(Maybe_Half_Phys(damage),
2423                 "\8e©\95ª\8e©\90g\82Ì\8fñ\82Ì\97Í\82ð\97\81\82Ñ\82Ä", KILLED_BY);
2424 #endif
2425         }
2426     } else {
2427         /*      Are we having fun yet?
2428          * weffects -> buzz(obj->otyp) -> zhitm (temple priest) ->
2429          * attack -> hitum -> known_hitum -> ghod_hitsu ->
2430          * buzz(AD_ELEC) -> destroy_item(WAND_CLASS) ->
2431          * useup -> obfree -> dealloc_obj -> free(obj)
2432          */
2433         current_wand = obj;
2434         weffects(obj);
2435         obj = current_wand;
2436         current_wand = 0;
2437     }
2438     if (obj && obj->spe < 0) {
2439 /*JP
2440         pline("%s to dust.", Tobjnam(obj, "turn"));
2441 */
2442         pline("%s\82Í\82¿\82è\82Æ\82È\82Á\82½\81D", xname(obj));
2443         useup(obj);
2444     }
2445     update_inventory(); /* maybe used a charge */
2446     return 1;
2447 }
2448
2449 int
2450 zapyourself(obj, ordinary)
2451 struct obj *obj;
2452 boolean ordinary;
2453 {
2454     boolean learn_it = FALSE;
2455     int damage = 0;
2456
2457     switch (obj->otyp) {
2458     case WAN_STRIKING:
2459     case SPE_FORCE_BOLT:
2460         learn_it = TRUE;
2461         if (Antimagic) {
2462             shieldeff(u.ux, u.uy);
2463 /*JP
2464             pline("Boing!");
2465 */
2466             pline("\83{\83C\83\93\81I");
2467         } else {
2468             if (ordinary) {
2469 /*JP
2470                 You("bash yourself!");
2471 */
2472                 You("\8e©\95ª\8e©\90g\82ð\91Å\82¿\82Â\82¯\82½\81I");
2473                 damage = d(2, 12);
2474             } else
2475                 damage = d(1 + obj->spe, 6);
2476             exercise(A_STR, FALSE);
2477         }
2478         break;
2479
2480     case WAN_LIGHTNING:
2481         learn_it = TRUE;
2482         if (!Shock_resistance) {
2483 /*JP
2484             You("shock yourself!");
2485 */
2486             You("\93d\8c\82\82ð\82¤\82¯\82½\81I");
2487             damage = d(12, 6);
2488             exercise(A_CON, FALSE);
2489         } else {
2490             shieldeff(u.ux, u.uy);
2491 /*JP
2492             You("zap yourself, but seem unharmed.");
2493 */
2494             You("\8e©\95ª\82É\8fñ\82ð\82Ó\82è\82©\82´\82µ\82½\82ª\81C\89ö\89ä\82Í\82µ\82È\82©\82Á\82½\82æ\82¤\82¾\81D");
2495             ugolemeffects(AD_ELEC, d(12, 6));
2496         }
2497         destroy_item(WAND_CLASS, AD_ELEC);
2498         destroy_item(RING_CLASS, AD_ELEC);
2499         (void) flashburn((long) rnd(100));
2500         break;
2501
2502     case SPE_FIREBALL:
2503 /*JP
2504         You("explode a fireball on top of yourself!");
2505 */
2506         Your("\93ª\8fã\82Å\89Î\82Ì\8bÊ\82ª\94\9a\94­\82µ\82½\81I");
2507         explode(u.ux, u.uy, 11, d(6, 6), WAND_CLASS, EXPL_FIERY);
2508         break;
2509     case WAN_FIRE:
2510     case FIRE_HORN:
2511         learn_it = TRUE;
2512         if (Fire_resistance) {
2513             shieldeff(u.ux, u.uy);
2514 /*JP
2515             You_feel("rather warm.");
2516 */
2517             You("\82¿\82å\82Á\82Æ\92g\82©\82­\8a´\82\82½\81D");
2518             ugolemeffects(AD_FIRE, d(12, 6));
2519         } else {
2520 /*JP
2521             pline("You've set yourself afire!");
2522 */
2523             You("\89\8a\82É\82Â\82Â\82Ü\82ê\82½\81I");
2524             damage = d(12, 6);
2525         }
2526         burn_away_slime();
2527         (void) burnarmor(&youmonst);
2528         destroy_item(SCROLL_CLASS, AD_FIRE);
2529         destroy_item(POTION_CLASS, AD_FIRE);
2530         destroy_item(SPBOOK_CLASS, AD_FIRE);
2531         destroy_item(FOOD_CLASS, AD_FIRE); /* only slime for now */
2532         break;
2533
2534     case WAN_COLD:
2535     case SPE_CONE_OF_COLD:
2536     case FROST_HORN:
2537         learn_it = TRUE;
2538         if (Cold_resistance) {
2539             shieldeff(u.ux, u.uy);
2540 /*JP
2541             You_feel("a little chill.");
2542 */
2543             You("\82¿\82å\82Á\82Æ\97â\82½\82­\8a´\82\82½\81D");
2544             ugolemeffects(AD_COLD, d(12, 6));
2545         } else {
2546 /*JP
2547             You("imitate a popsicle!");
2548 */
2549             You("\83A\83C\83X\83L\83\83\83\93\83f\81[\82Ì\82æ\82¤\82É\82È\82Á\82½\81I");
2550             damage = d(12, 6);
2551         }
2552         destroy_item(POTION_CLASS, AD_COLD);
2553         break;
2554
2555     case WAN_MAGIC_MISSILE:
2556     case SPE_MAGIC_MISSILE:
2557         learn_it = TRUE;
2558         if (Antimagic) {
2559             shieldeff(u.ux, u.uy);
2560 /*JP
2561             pline_The("missiles bounce!");
2562 */
2563             pline("\96\82\96@\82Ì\96î\82Í\82Í\82Ë\82©\82¦\82Á\82½\81I");
2564         } else {
2565             damage = d(4, 6);
2566 /*JP
2567             pline("Idiot!  You've shot yourself!");
2568 */
2569             pline("\89½\82â\82Á\82Ä\82ñ\82¾\81I\82 \82È\82½\82Í\8e©\95ª\8e©\90g\82ð\8c\82\82Á\82½\81I");
2570         }
2571         break;
2572
2573     case WAN_POLYMORPH:
2574     case SPE_POLYMORPH:
2575         if (!Unchanging) {
2576             learn_it = TRUE;
2577             polyself(0);
2578         }
2579         break;
2580
2581     case WAN_CANCELLATION:
2582     case SPE_CANCELLATION:
2583         (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
2584         break;
2585
2586     case SPE_DRAIN_LIFE:
2587         if (!Drain_resistance) {
2588             learn_it = TRUE; /* (no effect for spells...) */
2589 /*JP
2590             losexp("life drainage");
2591 */
2592             losexp("\90\96½\97Í\82ð\8bz\8eû\82³\82ê\82Ä");
2593         }
2594         damage = 0; /* No additional damage */
2595         break;
2596
2597     case WAN_MAKE_INVISIBLE: {
2598         /* have to test before changing HInvis but must change
2599          * HInvis before doing newsym().
2600          */
2601         int msg = !Invis && !Blind && !BInvis;
2602
2603         if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
2604             /* A mummy wrapping absorbs it and protects you */
2605 /*JP
2606             You_feel("rather itchy under %s.", yname(uarmc));
2607 */
2608             You("%s\82Ì\89º\82ª\83\80\83Y\83\80\83Y\82µ\82½\81D", xname(uarmc));
2609             break;
2610         }
2611         if (ordinary || !rn2(10)) { /* permanent */
2612             HInvis |= FROMOUTSIDE;
2613         } else { /* temporary */
2614             incr_itimeout(&HInvis, d(obj->spe, 250));
2615         }
2616         if (msg) {
2617             learn_it = TRUE;
2618             newsym(u.ux, u.uy);
2619             self_invis_message();
2620         }
2621         break;
2622     }
2623
2624     case WAN_SPEED_MONSTER:
2625         if (!(HFast & INTRINSIC)) {
2626             learn_it = TRUE;
2627             if (!Fast)
2628 /*JP
2629                 You("speed up.");
2630 */
2631                 You("\93®\82«\82ª\91¬\82­\82È\82Á\82½\81D");
2632             else
2633 /*JP
2634                 Your("quickness feels more natural.");
2635 */
2636                 You("\91¬\82³\82É\8aµ\82ê\82Ä\82«\82½\81D");
2637             exercise(A_DEX, TRUE);
2638         }
2639         HFast |= FROMOUTSIDE;
2640         break;
2641
2642     case WAN_SLEEP:
2643     case SPE_SLEEP:
2644         learn_it = TRUE;
2645         if (Sleep_resistance) {
2646             shieldeff(u.ux, u.uy);
2647 /*JP
2648             You("don't feel sleepy!");
2649 */
2650             You("\96°\82­\82È\82ç\82È\82¢\81I");
2651         } else {
2652 /*JP
2653             pline_The("sleep ray hits you!");
2654 */
2655             pline("\96°\82è\8cõ\90ü\82ª\82 \82È\82½\82É\96½\92\86\82µ\82½\81I");
2656             fall_asleep(-rnd(50), TRUE);
2657         }
2658         break;
2659
2660     case WAN_SLOW_MONSTER:
2661     case SPE_SLOW_MONSTER:
2662         if (HFast & (TIMEOUT | INTRINSIC)) {
2663             learn_it = TRUE;
2664             u_slow_down();
2665         }
2666         break;
2667
2668     case WAN_TELEPORTATION:
2669     case SPE_TELEPORT_AWAY:
2670         tele();
2671         /* same criteria as when mounted (zap_steed) */
2672         if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2673             || distu(u.ux0, u.uy0) >= 16)
2674             learn_it = TRUE;
2675         break;
2676
2677     case WAN_DEATH:
2678     case SPE_FINGER_OF_DEATH:
2679         if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
2680             pline((obj->otyp == WAN_DEATH)
2681 /*JP
2682                       ? "The wand shoots an apparently harmless beam at you."
2683 */
2684                       ? "\8fñ\82Ì\8cõ\90ü\82Í\82Ç\82¤\82â\82ç\82 \82È\82½\82É\89e\8b¿\82ð\97^\82¦\82È\82¢\82à\82Ì\82Ì\82æ\82¤\82¾\81D"
2685 /*JP
2686                       : "You seem no deader than before.");
2687 */
2688                       : "\82 \82È\82½\82Í\82±\82ê\88È\8fã\8e\80\82Ë\82È\82¢\82æ\82¤\82¾\81D");
2689             break;
2690         }
2691         learn_it = TRUE;
2692 #if 0 /*JP*/
2693         Sprintf(killer.name, "shot %sself with a death ray", uhim());
2694         killer.format = NO_KILLER_PREFIX;
2695 #else
2696         Strcpy(killer.name, "\8e©\95ª\82ª\8c\82\82Á\82½\8e\80\82Ì\8cõ\90ü\82É\82æ\82Á\82Ä");
2697         killer.format = KILLED_BY;
2698 #endif
2699 /*JP
2700         You("irradiate yourself with pure energy!");
2701 */
2702         You("\83G\83l\83\8b\83M\81[\82ð\8e©\95ª\8e©\90g\82É\8fÆ\8eË\82µ\82½\81D");
2703 /*JP
2704         You("die.");
2705 */
2706         pline("\82 \82È\82½\82Í\8e\80\82É\82Ü\82µ\82½\81D");
2707         /* They might survive with an amulet of life saving */
2708         done(DIED);
2709         break;
2710     case WAN_UNDEAD_TURNING:
2711     case SPE_TURN_UNDEAD:
2712         learn_it = TRUE;
2713         (void) unturn_dead(&youmonst);
2714         if (is_undead(youmonst.data)) {
2715 #if 0 /*JP*/
2716             You_feel("frightened and %sstunned.",
2717                      Stunned ? "even more " : "");
2718 #else
2719             You("\8b°\95|\82µ%s\82­\82ç\82­\82ç\82µ\82½\81D",
2720                 Stunned ? "\82³\82ç\82É" : "");
2721 #endif
2722             make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
2723         } else
2724 /*JP
2725             You("shudder in dread.");
2726 */
2727             You("\8b°\95|\82Å\90k\82¦\82½\81D");
2728         break;
2729     case SPE_HEALING:
2730     case SPE_EXTRA_HEALING:
2731         learn_it = TRUE; /* (no effect for spells...) */
2732         healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE,
2733                (obj->otyp == SPE_EXTRA_HEALING));
2734 /*JP
2735         You_feel("%sbetter.", obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
2736 */
2737         You("%s\8bC\95ª\82ª\82æ\82­\82È\82Á\82½\81D", obj->otyp == SPE_EXTRA_HEALING ? "\82Æ\82Ä\82à" : "");
2738         break;
2739     case WAN_LIGHT: /* (broken wand) */
2740         /* assert( !ordinary ); */
2741         damage = d(obj->spe, 25);
2742         /*FALLTHRU*/
2743     case EXPENSIVE_CAMERA:
2744         if (!damage)
2745             damage = 5;
2746         damage = lightdamage(obj, ordinary, damage);
2747         damage += rnd(25);
2748         if (flashburn((long) damage))
2749             learn_it = TRUE;
2750         damage = 0; /* reset */
2751         break;
2752     case WAN_OPENING:
2753     case SPE_KNOCK:
2754         if (Punished) {
2755             learn_it = TRUE;
2756             unpunish();
2757         }
2758         if (u.utrap) { /* escape web or bear trap */
2759             (void) openholdingtrap(&youmonst, &learn_it);
2760         } else {
2761             struct obj *otmp;
2762             /* unlock carried boxes */
2763             for (otmp = invent; otmp; otmp = otmp->nobj)
2764                 if (Is_box(otmp))
2765                     (void) boxlock(otmp, obj);
2766             /* trigger previously escaped trapdoor */
2767             (void) openfallingtrap(&youmonst, TRUE, &learn_it);
2768         }
2769         break;
2770     case WAN_LOCKING:
2771     case SPE_WIZARD_LOCK:
2772         if (!u.utrap) {
2773             (void) closeholdingtrap(&youmonst, &learn_it);
2774         }
2775         break;
2776     case WAN_DIGGING:
2777     case SPE_DIG:
2778     case SPE_DETECT_UNSEEN:
2779     case WAN_NOTHING:
2780         break;
2781     case WAN_PROBING: {
2782         struct obj *otmp;
2783
2784         for (otmp = invent; otmp; otmp = otmp->nobj) {
2785             otmp->dknown = 1;
2786             if (Is_container(otmp) || otmp->otyp == STATUE) {
2787                 otmp->lknown = 1;
2788                 if (!SchroedingersBox(otmp))
2789                     otmp->cknown = 1;
2790             }
2791         }
2792         learn_it = TRUE;
2793         ustatusline();
2794         break;
2795     }
2796     case SPE_STONE_TO_FLESH: {
2797         struct obj *otmp, *onxt;
2798         boolean didmerge;
2799
2800         if (u.umonnum == PM_STONE_GOLEM) {
2801             learn_it = TRUE;
2802             (void) polymon(PM_FLESH_GOLEM);
2803         }
2804         if (Stoned) {
2805             learn_it = TRUE;
2806             fix_petrification(); /* saved! */
2807         }
2808         /* but at a cost.. */
2809         for (otmp = invent; otmp; otmp = onxt) {
2810             onxt = otmp->nobj;
2811             if (bhito(otmp, obj))
2812                 learn_it = TRUE;
2813         }
2814         /*
2815          * It is possible that we can now merge some inventory.
2816          * Do a highly paranoid merge.  Restart from the beginning
2817          * until no merges.
2818          */
2819         do {
2820             didmerge = FALSE;
2821             for (otmp = invent; !didmerge && otmp; otmp = otmp->nobj)
2822                 for (onxt = otmp->nobj; onxt; onxt = onxt->nobj)
2823                     if (merged(&otmp, &onxt)) {
2824                         didmerge = TRUE;
2825                         break;
2826                     }
2827         } while (didmerge);
2828         break;
2829     }
2830     default:
2831         impossible("zapyourself: object %d used?", obj->otyp);
2832         break;
2833     }
2834     /* if effect was observable then discover the wand type provided
2835        that the wand itself has been seen */
2836     if (learn_it)
2837         learnwand(obj);
2838     return damage;
2839 }
2840
2841 /* called when poly'd hero uses breath attack against self */
2842 void
2843 ubreatheu(mattk)
2844 struct attack *mattk;
2845 {
2846     int dtyp = 20 + mattk->adtyp - 1;      /* breath by hero */
2847     const char *fltxt = flash_types[dtyp]; /* blast of <something> */
2848
2849     zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
2850 }
2851
2852 /* light damages hero in gremlin form */
2853 int
2854 lightdamage(obj, ordinary, amt)
2855 struct obj *obj;  /* item making light (fake book if spell) */
2856 boolean ordinary; /* wand/camera zap vs wand destruction */
2857 int amt;          /* pseudo-damage used to determine blindness duration */
2858 {
2859     char buf[BUFSZ];
2860     const char *how;
2861     int dmg = amt;
2862
2863     if (dmg && youmonst.data == &mons[PM_GREMLIN]) {
2864         /* reduce high values (from destruction of wand with many charges) */
2865         dmg = rnd(dmg);
2866         if (dmg > 10)
2867             dmg = 10 + rnd(dmg - 10);
2868         if (dmg > 20)
2869             dmg = 20;
2870 /*JP
2871         pline("Ow, that light hurts%c", (dmg > 2 || u.mh <= 5) ? '!' : '.');
2872 */
2873         pline("\82¨\82í\81C\8cõ\82ª\92É\82¢%s", (dmg > 2 || u.mh <= 5) ? "\81I" : "\81D");
2874         /* [composing killer/reason is superfluous here; if fatal, cause
2875            of death will always be "killed while stuck in creature form"] */
2876 #if 0 /*JP*/
2877         if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2878             ordinary = FALSE; /* say blasted rather than zapped */
2879 #endif
2880         how = (obj->oclass != SPBOOK_CLASS)
2881                   ? (const char *) ansimpleoname(obj)
2882 /*JP
2883                   : "spell of light";
2884 */
2885                   : "\8cõ\82Ì\96\82\96@";
2886 #if 0 /*JP*/
2887         Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2888                 uhim(), how);
2889 #else
2890         Sprintf(buf, "\8e©\95ª\82Å%s\82ð\97\81\82Ñ\82Ä", how);
2891 #endif
2892         /* might rehumanize(); could be fatal, but only for Unchanging */
2893 #if 0 /*JP*/
2894         losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2895 #else
2896         losehp(Maybe_Half_Phys(dmg), buf, KILLED_BY);
2897 #endif
2898     }
2899     return dmg;
2900 }
2901
2902 /* light[ning] causes blindness */
2903 boolean
2904 flashburn(duration)
2905 long duration;
2906 {
2907     if (!resists_blnd(&youmonst)) {
2908         You(are_blinded_by_the_flash);
2909         make_blinded(duration, FALSE);
2910         if (!Blind)
2911             Your1(vision_clears);
2912         return TRUE;
2913     }
2914     return FALSE;
2915 }
2916
2917 /* you've zapped a wand downwards while riding
2918  * Return TRUE if the steed was hit by the wand.
2919  * Return FALSE if the steed was not hit by the wand.
2920  */
2921 STATIC_OVL boolean
2922 zap_steed(obj)
2923 struct obj *obj; /* wand or spell */
2924 {
2925     int steedhit = FALSE;
2926
2927     bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
2928     notonhead = FALSE;
2929     switch (obj->otyp) {
2930     /*
2931      * Wands that are allowed to hit the steed
2932      * Carefully test the results of any that are
2933      * moved here from the bottom section.
2934      */
2935     case WAN_PROBING:
2936         probe_monster(u.usteed);
2937         learnwand(obj);
2938         steedhit = TRUE;
2939         break;
2940     case WAN_TELEPORTATION:
2941     case SPE_TELEPORT_AWAY:
2942         /* you go together */
2943         tele();
2944         /* same criteria as when unmounted (zapyourself) */
2945         if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2946             || distu(u.ux0, u.uy0) >= 16)
2947             learnwand(obj);
2948         steedhit = TRUE;
2949         break;
2950
2951     /* Default processing via bhitm() for these */
2952     case SPE_CURE_SICKNESS:
2953     case WAN_MAKE_INVISIBLE:
2954     case WAN_CANCELLATION:
2955     case SPE_CANCELLATION:
2956     case WAN_POLYMORPH:
2957     case SPE_POLYMORPH:
2958     case WAN_STRIKING:
2959     case SPE_FORCE_BOLT:
2960     case WAN_SLOW_MONSTER:
2961     case SPE_SLOW_MONSTER:
2962     case WAN_SPEED_MONSTER:
2963     case SPE_HEALING:
2964     case SPE_EXTRA_HEALING:
2965     case SPE_DRAIN_LIFE:
2966     case WAN_OPENING:
2967     case SPE_KNOCK:
2968         (void) bhitm(u.usteed, obj);
2969         steedhit = TRUE;
2970         break;
2971
2972     default:
2973         steedhit = FALSE;
2974         break;
2975     }
2976     return steedhit;
2977 }
2978
2979 /*
2980  * cancel a monster (possibly the hero).  inventory is cancelled only
2981  * if the monster is zapping itself directly, since otherwise the
2982  * effect is too strong.  currently non-hero monsters do not zap
2983  * themselves with cancellation.
2984  */
2985 boolean
2986 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2987 register struct monst *mdef;
2988 register struct obj *obj;
2989 boolean youattack, allow_cancel_kill, self_cancel;
2990 {
2991     boolean youdefend = (mdef == &youmonst);
2992     static const char writing_vanishes[] =
2993 /*JP
2994         "Some writing vanishes from %s head!";
2995 */
2996         "\89½\82©\82Ì\95\8e\9a\82ª%s\82Ì\93ª\82©\82ç\8fÁ\82¦\82½\81I";
2997 #if 0 /*JP:T*/
2998     static const char your[] = "your"; /* should be extern */
2999 #else
3000     static const char your[] = "\82 \82È\82½"; /* should be extern */
3001 #endif
3002
3003     if (youdefend ? (!youattack && Antimagic)
3004                   : resist(mdef, obj->oclass, 0, NOTELL))
3005         return FALSE; /* resisted cancellation */
3006
3007     if (self_cancel) { /* 1st cancel inventory */
3008         struct obj *otmp;
3009
3010         for (otmp = (youdefend ? invent : mdef->minvent); otmp;
3011              otmp = otmp->nobj)
3012             cancel_item(otmp);
3013         if (youdefend) {
3014             context.botl = 1; /* potential AC change */
3015             find_ac();
3016         }
3017     }
3018
3019     /* now handle special cases */
3020     if (youdefend) {
3021         if (Upolyd) {
3022             if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
3023                 pline(writing_vanishes, your);
3024
3025             if (Unchanging)
3026 /*JP
3027                 Your("amulet grows hot for a moment, then cools.");
3028 */
3029                 Your("\96\82\8f\9c\82¯\82Í\82µ\82Î\82ç\82­\94M\82­\82È\82è\81C\82â\82ª\82Ä\8c³\82É\96ß\82Á\82½\81D");
3030             else
3031                 rehumanize();
3032         }
3033     } else {
3034         mdef->mcan = TRUE;
3035
3036         if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
3037             were_change(mdef);
3038
3039         if (mdef->data == &mons[PM_CLAY_GOLEM]) {
3040             if (canseemon(mdef))
3041 #if 0 /*JP*/
3042                 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
3043 #else
3044                 pline(writing_vanishes, mon_nam(mdef));
3045 #endif
3046
3047             if (allow_cancel_kill) {
3048                 if (youattack)
3049                     killed(mdef);
3050                 else
3051                     monkilled(mdef, "", AD_SPEL);
3052             }
3053         }
3054     }
3055     return TRUE;
3056 }
3057
3058 /* you've zapped an immediate type wand up or down */
3059 STATIC_OVL boolean
3060 zap_updown(obj)
3061 struct obj *obj; /* wand or spell */
3062 {
3063     boolean striking = FALSE, disclose = FALSE;
3064     int x, y, xx, yy, ptmp;
3065     struct obj *otmp;
3066     struct engr *e;
3067     struct trap *ttmp;
3068     char buf[BUFSZ];
3069
3070     /* some wands have special effects other than normal bhitpile */
3071     /* drawbridge might change <u.ux,u.uy> */
3072     x = xx = u.ux;     /* <x,y> is zap location */
3073     y = yy = u.uy;     /* <xx,yy> is drawbridge (portcullis) position */
3074     ttmp = t_at(x, y); /* trap if there is one */
3075
3076     switch (obj->otyp) {
3077     case WAN_PROBING:
3078         ptmp = 0;
3079         if (u.dz < 0) {
3080 /*JP
3081             You("probe towards the %s.", ceiling(x, y));
3082 */
3083             You("\8fã\95û\82Ì%s\82ð\92²\82×\82½\81D", ceiling(x,y));
3084         } else {
3085             ptmp += bhitpile(obj, bhito, x, y, u.dz);
3086 /*JP
3087             You("probe beneath the %s.", surface(x, y));
3088 */
3089             You("\89º\95û\82Ì%s\82ð\92²\82×\82½\81D", surface(x,y));
3090             ptmp += display_binventory(x, y, TRUE);
3091         }
3092         if (!ptmp)
3093 /*JP
3094             Your("probe reveals nothing.");
3095 */
3096             pline("\92²\8d¸\82Ì\8c\8b\89Ê\89½\82à\82Å\82Ä\82±\82È\82©\82Á\82½\81D");
3097         return TRUE; /* we've done our own bhitpile */
3098     case WAN_OPENING:
3099     case SPE_KNOCK:
3100         /* up or down, but at closed portcullis only */
3101         if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
3102             open_drawbridge(xx, yy);
3103             disclose = TRUE;
3104         } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
3105                    /* can't use the stairs down to quest level 2 until
3106                       leader "unlocks" them; give feedback if you try */
3107                    && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
3108 /*JP
3109             pline_The("stairs seem to ripple momentarily.");
3110 */
3111             pline("\8aK\92i\82ª\88ê\8fu\97h\82ê\82½\82æ\82¤\82É\8c©\82¦\82½\81D");
3112             disclose = TRUE;
3113         }
3114         /* down will release you from bear trap or web */
3115         if (u.dz > 0 && u.utrap) {
3116             (void) openholdingtrap(&youmonst, &disclose);
3117             /* down will trigger trapdoor, hole, or [spiked-] pit */
3118         } else if (u.dz > 0 && !u.utrap) {
3119             (void) openfallingtrap(&youmonst, FALSE, &disclose);
3120         }
3121         break;
3122     case WAN_STRIKING:
3123     case SPE_FORCE_BOLT:
3124         striking = TRUE;
3125         /*FALLTHRU*/
3126     case WAN_LOCKING:
3127     case SPE_WIZARD_LOCK:
3128         /* down at open bridge or up or down at open portcullis */
3129         if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
3130                  ? (u.dz > 0)
3131                  : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
3132             && find_drawbridge(&xx, &yy)) {
3133             if (!striking)
3134                 close_drawbridge(xx, yy);
3135             else
3136                 destroy_drawbridge(xx, yy);
3137             disclose = TRUE;
3138         } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
3139                    && !Is_waterlevel(&u.uz) && !Underwater
3140                    && !Is_qstart(&u.uz)) {
3141             int dmg;
3142             /* similar to zap_dig() */
3143 #if 0 /*JP*/
3144             pline("A rock is dislodged from the %s and falls on your %s.",
3145                   ceiling(x, y), body_part(HEAD));
3146 #else
3147             pline("%s\82©\82ç\8aâ\82ª\97\8e\82¿\82Ä\82 \82È\82½\82Ì%s\82É\96½\92\86\82µ\82½\81D",
3148                   ceiling(x, y), body_part(HEAD));
3149 #endif
3150             dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
3151 /*JP
3152             losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
3153 */
3154             losehp(Maybe_Half_Phys(dmg), "\97\8e\8aâ\82Å", KILLED_BY_AN);
3155             if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
3156                 (void) xname(otmp); /* set dknown, maybe bknown */
3157                 stackobj(otmp);
3158             }
3159             newsym(x, y);
3160         } else if (u.dz > 0 && ttmp) {
3161             if (!striking && closeholdingtrap(&youmonst, &disclose)) {
3162                 ; /* now stuck in web or bear trap */
3163             } else if (striking && ttmp->ttyp == TRAPDOOR) {
3164                 /* striking transforms trapdoor into hole */
3165                 if (Blind && !ttmp->tseen) {
3166 /*JP
3167                     pline("%s beneath you shatters.", Something);
3168 */
3169                     pline("\82 \82È\82½\82Ì\89º\82É\82 \82é\89½\82©\82ª\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
3170                 } else if (!ttmp->tseen) { /* => !Blind */
3171 /*JP
3172                     pline("There's a trapdoor beneath you; it shatters.");
3173 */
3174                     pline("\82 \82È\82½\82Ì\89º\82É\82Í\97\8e\82µ\94à\82ª\82 \82Á\82½\81G\82»\82ê\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
3175                 } else {
3176 /*JP
3177                     pline("The trapdoor beneath you shatters.");
3178 */
3179                     pline("\82 \82È\82½\82Ì\89º\82É\82 \82é\97\8e\82µ\94à\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
3180                     disclose = TRUE;
3181                 }
3182                 ttmp->ttyp = HOLE;
3183                 ttmp->tseen = 1;
3184                 newsym(x, y);
3185                 /* might fall down hole */
3186                 dotrap(ttmp, 0);
3187             } else if (!striking && ttmp->ttyp == HOLE) {
3188                 /* locking transforms hole into trapdoor */
3189                 ttmp->ttyp = TRAPDOOR;
3190                 if (Blind || !ttmp->tseen) {
3191 #if 0 /*JP*/
3192                     pline("Some %s swirls beneath you.",
3193                           is_ice(x, y) ? "frost" : "dust");
3194 #else
3195                     pline("\82 \82È\82½\82Ì\89º\82Å%s\82ª\82¤\82¸\82ð\8aª\82­\82Ì\82ª\8c©\82¦\82½\81D",
3196                           is_ice(x,y) ? "\91\9a" : "\82Ù\82±\82è");
3197 #endif
3198                 } else {
3199                     ttmp->tseen = 1;
3200                     newsym(x, y);
3201 /*JP
3202                     pline("A trapdoor appears beneath you.");
3203 */
3204                     pline("\82 \82È\82½\82Ì\89º\82É\97\8e\82µ\94à\82ª\82 \82ç\82í\82ê\82½\81D");
3205                     disclose = TRUE;
3206                 }
3207                 /* hadn't fallen down hole; won't fall now */
3208             }
3209         }
3210         break;
3211     case SPE_STONE_TO_FLESH:
3212         if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3213             || (Is_qstart(&u.uz) && u.dz < 0)) {
3214             pline1(nothing_happens);
3215         } else if (u.dz < 0) { /* we should do more... */
3216 /*JP
3217             pline("Blood drips on your %s.", body_part(FACE));
3218 */
3219             pline("\8c\8c\82ª\82 \82È\82½\82Ì%s\82Ö\82µ\82½\82½\82è\97\8e\82¿\82Ä\82«\82½\81D", body_part(FACE));
3220         } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3221             /*
3222             Print this message only if there wasn't an engraving
3223             affected here.  If water or ice, act like waterlevel case.
3224             */
3225             e = engr_at(u.ux, u.uy);
3226             if (!(e && e->engr_type == ENGRAVE)) {
3227                 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3228                     pline1(nothing_happens);
3229                 else
3230 #if 0 /*JP:T*/
3231                     pline("Blood %ss %s your %s.",
3232                           is_lava(u.ux, u.uy) ? "boil" : "pool",
3233                           Levitation ? "beneath" : "at",
3234                           makeplural(body_part(FOOT)));
3235 #else
3236                     pline("%s%s%s\81D",
3237                           makeplural(body_part(FOOT)),
3238                           Levitation ? "\82Ì\89º" : "\8c³",
3239                           is_lava(u.ux, u.uy) ?
3240                           "\82Å\8c\8c\82ª\95¦\93«\82µ\82½" : "\82É\8c\8c\82¾\82Ü\82è\82ª\8fo\97\88\82½");
3241 #endif
3242             }
3243         }
3244         break;
3245     default:
3246         break;
3247     }
3248
3249     if (u.dz > 0) {
3250         /* zapping downward */
3251         (void) bhitpile(obj, bhito, x, y, u.dz);
3252
3253         /* subset of engraving effects; none sets `disclose' */
3254         if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3255             switch (obj->otyp) {
3256             case WAN_POLYMORPH:
3257             case SPE_POLYMORPH:
3258                 del_engr(e);
3259                 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3260                 break;
3261             case WAN_CANCELLATION:
3262             case SPE_CANCELLATION:
3263             case WAN_MAKE_INVISIBLE:
3264                 del_engr(e);
3265                 break;
3266             case WAN_TELEPORTATION:
3267             case SPE_TELEPORT_AWAY:
3268                 rloc_engr(e);
3269                 break;
3270             case SPE_STONE_TO_FLESH:
3271                 if (e->engr_type == ENGRAVE) {
3272                     /* only affects things in stone */
3273 #if 0 /*JP*/
3274                     pline_The(Hallucination
3275                                   ? "floor runs like butter!"
3276                                   : "edges on the floor get smoother.");
3277 #else
3278                     pline(Hallucination
3279                                   ? "\8f°\82ª\83o\83^\81[\82Ì\82æ\82¤\82É\91\96\82Á\82Ä\82¢\82Á\82½\81I"
3280                                   : "\8f°\82Ì\89\8f\82ª\82È\82ß\82ç\82©\82É\82È\82Á\82½\81D");
3281 #endif
3282                     wipe_engr_at(x, y, d(2, 4), TRUE);
3283                 }
3284                 break;
3285             case WAN_STRIKING:
3286             case SPE_FORCE_BOLT:
3287                 wipe_engr_at(x, y, d(2, 4), TRUE);
3288                 break;
3289             default:
3290                 break;
3291             }
3292         }
3293     } else if (u.dz < 0) {
3294         /* zapping upward */
3295
3296         /* game flavor: if you're hiding under "something"
3297          * a zap upward should hit that "something".
3298          */
3299         if (u.uundetected && hides_under(youmonst.data)) {
3300             int hitit = 0;
3301             otmp = level.objects[u.ux][u.uy];
3302
3303             if (otmp)
3304                 hitit = bhito(otmp, obj);
3305             if (hitit) {
3306                 (void) hideunder(&youmonst);
3307                 disclose = TRUE;
3308             }
3309         }
3310     }
3311
3312     return disclose;
3313 }
3314
3315 /* used by do_break_wand() was well as by weffects() */
3316 void
3317 zapsetup()
3318 {
3319     obj_zapped = FALSE;
3320 }
3321
3322 void
3323 zapwrapup()
3324 {
3325     /* if do_osshock() set obj_zapped while polying, give a message now */
3326     if (obj_zapped)
3327 /*JP
3328         You_feel("shuddering vibrations.");
3329 */
3330         You("\82¼\82Á\82Æ\82·\82é\90U\93®\82ð\8a´\82\82½\81D"); 
3331     obj_zapped = FALSE;
3332 }
3333
3334 /* called for various wand and spell effects - M. Stephenson */
3335 void
3336 weffects(obj)
3337 struct obj *obj;
3338 {
3339     int otyp = obj->otyp;
3340     boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3341
3342     exercise(A_WIS, TRUE);
3343     if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3344         && (u.dz > 0) && zap_steed(obj)) {
3345         disclose = TRUE;
3346     } else if (objects[otyp].oc_dir == IMMEDIATE) {
3347         zapsetup(); /* reset obj_zapped */
3348         if (u.uswallow) {
3349             (void) bhitm(u.ustuck, obj);
3350             /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3351         } else if (u.dz) {
3352             disclose = zap_updown(obj);
3353         } else {
3354             (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3355                         &obj);
3356         }
3357         zapwrapup(); /* give feedback for obj_zapped */
3358
3359     } else if (objects[otyp].oc_dir == NODIR) {
3360         zapnodir(obj);
3361
3362     } else {
3363         /* neither immediate nor directionless */
3364
3365         if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3366             zap_dig();
3367         else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3368             buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3369                  u.dx, u.dy);
3370         else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3371             buzz(otyp - WAN_MAGIC_MISSILE,
3372                  (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3373         else
3374             impossible("weffects: unexpected spell or wand");
3375         disclose = TRUE;
3376     }
3377     if (disclose) {
3378         learnwand(obj);
3379         if (was_unkn)
3380             more_experienced(0, 10);
3381     }
3382     return;
3383 }
3384
3385 /* augment damage for a spell dased on the hero's intelligence (and level) */
3386 int
3387 spell_damage_bonus(dmg)
3388 int dmg; /* base amount to be adjusted by bonus or penalty */
3389 {
3390     int intell = ACURR(A_INT);
3391
3392     /* Punish low intelligence before low level else low intelligence
3393        gets punished only when high level */
3394     if (intell <= 9) {
3395         /* -3 penalty, but never reduce combined amount below 1
3396            (if dmg is 0 for some reason, we're careful to leave it there) */
3397         if (dmg > 1)
3398             dmg = (dmg <= 3) ? 1 : dmg - 3;
3399     } else if (intell <= 13 || u.ulevel < 5)
3400         ; /* no bonus or penalty; dmg remains same */
3401     else if (intell <= 18)
3402         dmg += 1;
3403     else if (intell <= 24 || u.ulevel < 14)
3404         dmg += 2;
3405     else
3406         dmg += 3; /* Int 25 */
3407
3408     return dmg;
3409 }
3410
3411 /*
3412  * Generate the to hit bonus for a spell.  Based on the hero's skill in
3413  * spell class and dexterity.
3414  */
3415 STATIC_OVL int
3416 spell_hit_bonus(skill)
3417 int skill;
3418 {
3419     int hit_bon = 0;
3420     int dex = ACURR(A_DEX);
3421
3422     switch (P_SKILL(spell_skilltype(skill))) {
3423     case P_ISRESTRICTED:
3424     case P_UNSKILLED:
3425         hit_bon = -4;
3426         break;
3427     case P_BASIC:
3428         hit_bon = 0;
3429         break;
3430     case P_SKILLED:
3431         hit_bon = 2;
3432         break;
3433     case P_EXPERT:
3434         hit_bon = 3;
3435         break;
3436     }
3437
3438     if (dex < 4)
3439         hit_bon -= 3;
3440     else if (dex < 6)
3441         hit_bon -= 2;
3442     else if (dex < 8)
3443         hit_bon -= 1;
3444     else if (dex < 14)
3445         /* Will change when print stuff below removed */
3446         hit_bon -= 0;
3447     else
3448         /* Even increment for dextrous heroes (see weapon.c abon) */
3449         hit_bon += dex - 14;
3450
3451     return hit_bon;
3452 }
3453
3454 const char *
3455 exclam(force)
3456 int force;
3457 {
3458     /* force == 0 occurs e.g. with sleep ray */
3459     /* note that large force is usual with wands so that !! would
3460             require information about hand/weapon/wand */
3461 /*JP
3462     return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3463 */
3464     return (const char *) ((force < 0) ? "\81H" : (force <= 4) ? "\81D" : "\81I");
3465 }
3466
3467 void
3468 hit(str, mtmp, force)
3469 const char *str;
3470 struct monst *mtmp;
3471 const char *force; /* usually either "." or "!" */
3472 {
3473     if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3474          && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3475 /*JP
3476         pline("%s %s it.", The(str), vtense(str, "hit"));
3477 */
3478         pline("%s\82Í\89½\82©\82É\96½\92\86\82µ\82½\81D", str);
3479     else
3480 #if 0 /*JP*/
3481         pline("%s %s %s%s", The(str), vtense(str, "hit"),
3482               mon_nam(mtmp), force);
3483 #else
3484         pline("%s\82Í%s\82É\96½\92\86\82µ\82½%s", str,
3485               mon_nam(mtmp), force);
3486 #endif
3487 }
3488
3489 void
3490 miss(str, mtmp)
3491 register const char *str;
3492 register struct monst *mtmp;
3493 {
3494 #if 0 /*JP*/
3495     pline(
3496         "%s %s %s.", The(str), vtense(str, "miss"),
3497         ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3498             ? mon_nam(mtmp)
3499             : "it");
3500 #else
3501     pline(
3502         "%s\82Ì%s\82Ö\82Ì\8dU\8c\82\82Í\82Í\82¸\82ê\82½\81D", str,
3503         ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3504             ? mon_nam(mtmp)
3505             : "\89½\8eÒ\82©");
3506 #endif
3507 }
3508
3509 STATIC_OVL void
3510 skiprange(range, skipstart, skipend)
3511 int range, *skipstart, *skipend;
3512 {
3513     int tr = (range / 4);
3514     int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3515
3516     *skipstart = tmp;
3517     *skipend = tmp - ((tmp / 4) * rnd(3));
3518     if (*skipend >= tmp)
3519         *skipend = tmp - 1;
3520 }
3521
3522 /*
3523  *  Called for the following distance effects:
3524  *      when a weapon is thrown (weapon == THROWN_WEAPON)
3525  *      when an object is kicked (KICKED_WEAPON)
3526  *      when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3527  *      when a light beam is flashed (FLASHED_LIGHT)
3528  *      when a mirror is applied (INVIS_BEAM)
3529  *  A thrown/kicked object falls down at end of its range or when a monster
3530  *  is hit.  The variable 'bhitpos' is set to the final position of the weapon
3531  *  thrown/zapped.  The ray of a wand may affect (by calling a provided
3532  *  function) several objects and monsters on its path.  The return value
3533  *  is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3534  *
3535  * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3536  * destroyed and *pobj set to NULL to indicate this.
3537  *
3538  *  Check !u.uswallow before calling bhit().
3539  *  This function reveals the absence of a remembered invisible monster in
3540  *  necessary cases (throwing or kicking weapons).  The presence of a real
3541  *  one is revealed for a weapon, but if not a weapon is left up to fhitm().
3542  */
3543 struct monst *
3544 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3545 register int ddx, ddy, range;          /* direction and range */
3546 int weapon;                            /* see values in hack.h */
3547 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3548     FDECL((*fhito), (OBJ_P, OBJ_P));
3549 struct obj **pobj; /* object tossed/used, set to NULL
3550                     * if object is destroyed */
3551 {
3552     struct monst *mtmp;
3553     struct obj *obj = *pobj;
3554     uchar typ;
3555     boolean shopdoor = FALSE, point_blank = TRUE;
3556     boolean in_skip = FALSE, allow_skip = FALSE;
3557     int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3558
3559     if (weapon == KICKED_WEAPON) {
3560         /* object starts one square in front of player */
3561         bhitpos.x = u.ux + ddx;
3562         bhitpos.y = u.uy + ddy;
3563         range--;
3564     } else {
3565         bhitpos.x = u.ux;
3566         bhitpos.y = u.uy;
3567     }
3568
3569     if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3570         skiprange(range, &skiprange_start, &skiprange_end);
3571         allow_skip = !rn2(3);
3572     }
3573
3574     if (weapon == FLASHED_LIGHT) {
3575         tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3576     } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3577         tmp_at(DISP_FLASH, obj_to_glyph(obj));
3578
3579     while (range-- > 0) {
3580         int x, y;
3581
3582         bhitpos.x += ddx;
3583         bhitpos.y += ddy;
3584         x = bhitpos.x;
3585         y = bhitpos.y;
3586
3587         if (!isok(x, y)) {
3588             bhitpos.x -= ddx;
3589             bhitpos.y -= ddy;
3590             break;
3591         }
3592
3593         if (is_pick(obj) && inside_shop(x, y)
3594             && (mtmp = shkcatch(obj, x, y)) != 0) {
3595             tmp_at(DISP_END, 0);
3596             return mtmp;
3597         }
3598
3599         typ = levl[bhitpos.x][bhitpos.y].typ;
3600
3601         /* iron bars will block anything big enough */
3602         if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3603             && typ == IRONBARS
3604             && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
3605                          point_blank ? 0 : !rn2(5), 1)) {
3606             /* caveat: obj might now be null... */
3607             obj = *pobj;
3608             bhitpos.x -= ddx;
3609             bhitpos.y -= ddy;
3610             break;
3611         }
3612
3613         if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3614             boolean learn_it = FALSE;
3615
3616             switch (obj->otyp) {
3617             case WAN_OPENING:
3618             case SPE_KNOCK:
3619                 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3620                     if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3621                         learn_it = TRUE;
3622                     open_drawbridge(x, y);
3623                 }
3624                 break;
3625             case WAN_LOCKING:
3626             case SPE_WIZARD_LOCK:
3627                 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3628                     && levl[x][y].typ == DRAWBRIDGE_DOWN)
3629                     learn_it = TRUE;
3630                 close_drawbridge(x, y);
3631                 break;
3632             case WAN_STRIKING:
3633             case SPE_FORCE_BOLT:
3634                 if (typ != DRAWBRIDGE_UP)
3635                     destroy_drawbridge(x, y);
3636                 learn_it = TRUE;
3637                 break;
3638             }
3639             if (learn_it)
3640                 learnwand(obj);
3641         }
3642
3643         mtmp = m_at(bhitpos.x, bhitpos.y);
3644
3645         /*
3646          * skipping rocks
3647          *
3648          * skiprange_start is only set if this is a thrown rock
3649          */
3650         if (skiprange_start && (range == skiprange_start) && allow_skip) {
3651             if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3652                 in_skip = TRUE;
3653                 if (!Blind)
3654 #if 0 /*JP*/
3655                     pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3656                           skipcount ? " again" : "");
3657 #else
3658                     pline("%s\82Í%s\92µ\82Ë\82½\81D", Yname2(obj),
3659                           skipcount ? "\8dÄ\82Ñ" : "");
3660 #endif
3661                 else
3662 /*JP
3663                     You_hear("%s skip.", yname(obj));
3664 */
3665                     You_hear("%s\82ª\92µ\82Ë\82é\89¹\82ð\95·\82¢\82½\81D", yname(obj));
3666                 skipcount++;
3667             } else if (skiprange_start > skiprange_end + 1) {
3668                 --skiprange_start;
3669             }
3670         }
3671         if (in_skip) {
3672             if (range <= skiprange_end) {
3673                 in_skip = FALSE;
3674                 if (range > 3) /* another bounce? */
3675                     skiprange(range, &skiprange_start, &skiprange_end);
3676             } else if (mtmp && M_IN_WATER(mtmp->data)) {
3677                 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3678 #if 0 /*JP*/
3679                     pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3680                           mon_nam(mtmp));
3681 #else
3682                     pline("%s\82Í%s\82ð\94ò\82Ñ\89z\82¦\82½\81D", Yname2(obj),
3683                           mon_nam(mtmp));
3684 #endif
3685             }
3686         }
3687
3688         if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3689             notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3690             if (weapon == FLASHED_LIGHT) {
3691                 /* FLASHED_LIGHT hitting invisible monster should
3692                    pass through instead of stop so we call
3693                    flash_hits_mon() directly rather than returning
3694                    mtmp back to caller.  That allows the flash to
3695                    keep on going.  Note that we use mtmp->minvis
3696                    not canspotmon() because it makes no difference
3697                    whether the hero can see the monster or not. */
3698                 if (mtmp->minvis) {
3699                     obj->ox = u.ux, obj->oy = u.uy;
3700                     (void) flash_hits_mon(mtmp, obj);
3701                 } else {
3702                     tmp_at(DISP_END, 0);
3703                     return mtmp; /* caller will call flash_hits_mon */
3704                 }
3705             } else if (weapon == INVIS_BEAM) {
3706                 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3707                    through invisible targets; unlike it, we aren't
3708                    prepared for multiple hits so just get first one
3709                    that's either visible or could see its invisible
3710                    self.  [No tmp_at() cleanup is needed here.] */
3711                 if (!mtmp->minvis || perceives(mtmp->data))
3712                     return mtmp;
3713             } else if (weapon != ZAPPED_WAND) {
3714                 /* THROWN_WEAPON, KICKED_WEAPON */
3715                 tmp_at(DISP_END, 0);
3716                 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3717                     map_invisible(bhitpos.x, bhitpos.y);
3718                 return mtmp;
3719             } else {
3720                 /* ZAPPED_WAND */
3721                 (*fhitm)(mtmp, obj);
3722                 range -= 3;
3723             }
3724         } else {
3725             if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3726                 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3727                 unmap_object(bhitpos.x, bhitpos.y);
3728                 newsym(x, y);
3729             }
3730         }
3731         if (fhito) {
3732             if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3733                 range--;
3734         } else {
3735             if (weapon == KICKED_WEAPON
3736                 && ((obj->oclass == COIN_CLASS
3737                      && OBJ_AT(bhitpos.x, bhitpos.y))
3738                     || ship_object(obj, bhitpos.x, bhitpos.y,
3739                                    costly_spot(bhitpos.x, bhitpos.y)))) {
3740                 tmp_at(DISP_END, 0);
3741                 return (struct monst *) 0;
3742             }
3743         }
3744         if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3745             switch (obj->otyp) {
3746             case WAN_OPENING:
3747             case WAN_LOCKING:
3748             case WAN_STRIKING:
3749             case SPE_KNOCK:
3750             case SPE_WIZARD_LOCK:
3751             case SPE_FORCE_BOLT:
3752                 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3753                     if (cansee(bhitpos.x, bhitpos.y)
3754                         || (obj->otyp == WAN_STRIKING && !Deaf))
3755                         learnwand(obj);
3756                     if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3757                         && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3758                         shopdoor = TRUE;
3759                         add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
3760                     }
3761                 }
3762                 break;
3763             }
3764         }
3765         if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3766             bhitpos.x -= ddx;
3767             bhitpos.y -= ddy;
3768             break;
3769         }
3770         if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3771             /* 'I' present but no monster: erase */
3772             /* do this before the tmp_at() */
3773             if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3774                 && cansee(x, y)) {
3775                 unmap_object(bhitpos.x, bhitpos.y);
3776                 newsym(x, y);
3777             }
3778             tmp_at(bhitpos.x, bhitpos.y);
3779             delay_output();
3780             /* kicked objects fall in pools */
3781             if ((weapon == KICKED_WEAPON)
3782                 && (is_pool(bhitpos.x, bhitpos.y)
3783                     || is_lava(bhitpos.x, bhitpos.y)))
3784                 break;
3785             if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3786                 break; /* physical objects fall onto sink */
3787         }
3788         /* limit range of ball so hero won't make an invalid move */
3789         if (weapon == THROWN_WEAPON && range > 0
3790             && obj->otyp == HEAVY_IRON_BALL) {
3791             struct obj *bobj;
3792             struct trap *t;
3793
3794             if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3795                 if (cansee(x, y))
3796 #if 0 /*JP*/
3797                     pline("%s hits %s.", The(distant_name(obj, xname)),
3798                           an(xname(bobj)));
3799 #else
3800                     pline("%s\82Í%s\82É\96½\92\86\82µ\82½\81D", distant_name(obj, xname),
3801                           xname(bobj));
3802 #endif
3803                 range = 0;
3804             } else if (obj == uball) {
3805                 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3806                     /* nb: it didn't hit anything directly */
3807                     if (cansee(x, y))
3808 #if 0 /*JP*/
3809                         pline("%s jerks to an abrupt halt.",
3810                               The(distant_name(obj, xname))); /* lame */
3811 #else
3812                         pline("%s\82Í\82Æ\82Â\82º\82ñ\83K\83N\83\93\82Æ\8e~\82Ü\82Á\82½\81D",
3813                               distant_name(obj, xname)); /* lame */
3814 #endif
3815                     range = 0;
3816                 } else if (Sokoban && (t = t_at(x, y)) != 0
3817                            && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3818                                || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3819                     /* hero falls into the trap, so ball stops */
3820                     range = 0;
3821                 }
3822             }
3823         }
3824
3825         /* thrown/kicked missile has moved away from its starting spot */
3826         point_blank = FALSE; /* affects passing through iron bars */
3827     }
3828
3829     if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3830         tmp_at(DISP_END, 0);
3831
3832     if (shopdoor)
3833 /*JP
3834         pay_for_damage("destroy", FALSE);
3835 */
3836         pay_for_damage("\94j\89ó\82·\82é", FALSE);
3837
3838     return (struct monst *) 0;
3839 }
3840
3841 /* process thrown boomerang, which travels a curving path...
3842  * A multi-shot volley ought to have all missiles in flight at once,
3843  * but we're called separately for each one.  We terminate the volley
3844  * early on a failed catch since continuing to throw after being hit
3845  * is too obviously silly.
3846  */
3847 struct monst *
3848 boomhit(obj, dx, dy)
3849 struct obj *obj;
3850 int dx, dy;
3851 {
3852     register int i, ct;
3853     int boom; /* showsym[] index  */
3854     struct monst *mtmp;
3855     boolean counterclockwise = TRUE; /* right-handed throw */
3856
3857     /* counterclockwise traversal patterns:
3858      *  ..........................54.................................
3859      *  ..................43.....6..3....765.........................
3860      *  ..........32.....5..2...7...2...8...4....87..................
3861      *  .........4..1....6..1...8..1....9...3...9..6.....98..........
3862      *  ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3863      *  .3...9....6..9....89.....................1..4...1..6....1..8.
3864      *  .4...8.....78.............................23....2..5...2...7.
3865      *  ..567............................................34....3..6..
3866      *  ........................................................45...
3867      * (invert rows for corresponding clockwise patterns)
3868      */
3869
3870     bhitpos.x = u.ux;
3871     bhitpos.y = u.uy;
3872     boom = counterclockwise ? S_boomleft : S_boomright;
3873     for (i = 0; i < 8; i++)
3874         if (xdir[i] == dx && ydir[i] == dy)
3875             break;
3876     tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3877     for (ct = 0; ct < 10; ct++) {
3878         i = (i + 8) % 8;                          /* 0..7 (8 -> 0, -1 -> 7) */
3879         boom = (S_boomleft + S_boomright - boom); /* toggle */
3880         tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3881         dx = xdir[i];
3882         dy = ydir[i];
3883         bhitpos.x += dx;
3884         bhitpos.y += dy;
3885         if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3886             m_respond(mtmp);
3887             tmp_at(DISP_END, 0);
3888             return mtmp;
3889         }
3890         if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3891             || closed_door(bhitpos.x, bhitpos.y)) {
3892             bhitpos.x -= dx;
3893             bhitpos.y -= dy;
3894             break;
3895         }
3896         if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3897             if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3898                 /* we hit ourselves */
3899                 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
3900 /*JP
3901                              "boomerang");
3902 */
3903                              "\83u\81[\83\81\83\89\83\93");
3904                 endmultishot(TRUE);
3905                 break;
3906             } else { /* we catch it */
3907                 tmp_at(DISP_END, 0);
3908 /*JP
3909                 You("skillfully catch the boomerang.");
3910 */
3911                 You("\8fã\8eè\82É\83u\81[\83\81\83\89\83\93\82ð\92Í\82Ü\82¦\82½\81D");
3912                 return &youmonst;
3913             }
3914         }
3915         tmp_at(bhitpos.x, bhitpos.y);
3916         delay_output();
3917         if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3918             if (!Deaf)
3919 /*JP
3920                 pline("Klonk!");
3921 */
3922                 pline("\83J\83\89\83\93\81I");
3923             break; /* boomerang falls on sink */
3924         }
3925         /* ct==0, initial position, we want next delta to be same;
3926            ct==5, opposite position, repeat delta undoes first one */
3927         if (ct % 5 != 0)
3928             i += (counterclockwise ? -1 : 1);
3929     }
3930     tmp_at(DISP_END, 0); /* do not leave last symbol */
3931     return (struct monst *) 0;
3932 }
3933
3934 /* used by buzz(); also used by munslime(muse.c); returns damage applied
3935    to mon; note: caller is responsible for killing mon if damage is fatal */
3936 int
3937 zhitm(mon, type, nd, ootmp)
3938 register struct monst *mon;
3939 register int type, nd;
3940 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3941 {
3942     register int tmp = 0;
3943     register int abstype = abs(type) % 10;
3944     boolean sho_shieldeff = FALSE;
3945     boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3946
3947     *ootmp = (struct obj *) 0;
3948     switch (abstype) {
3949     case ZT_MAGIC_MISSILE:
3950         if (resists_magm(mon)) {
3951             sho_shieldeff = TRUE;
3952             break;
3953         }
3954         tmp = d(nd, 6);
3955         if (spellcaster)
3956             tmp = spell_damage_bonus(tmp);
3957         break;
3958     case ZT_FIRE:
3959         if (resists_fire(mon)) {
3960             sho_shieldeff = TRUE;
3961             break;
3962         }
3963         tmp = d(nd, 6);
3964         if (resists_cold(mon))
3965             tmp += 7;
3966         if (spellcaster)
3967             tmp = spell_damage_bonus(tmp);
3968         if (burnarmor(mon)) {
3969             if (!rn2(3))
3970                 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3971             if (!rn2(3))
3972                 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3973             if (!rn2(5))
3974                 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3975             destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3976         }
3977         break;
3978     case ZT_COLD:
3979         if (resists_cold(mon)) {
3980             sho_shieldeff = TRUE;
3981             break;
3982         }
3983         tmp = d(nd, 6);
3984         if (resists_fire(mon))
3985             tmp += d(nd, 3);
3986         if (spellcaster)
3987             tmp = spell_damage_bonus(tmp);
3988         if (!rn2(3))
3989             (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3990         break;
3991     case ZT_SLEEP:
3992         tmp = 0;
3993         (void) sleep_monst(mon, d(nd, 25),
3994                            type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3995         break;
3996     case ZT_DEATH:                              /* death/disintegration */
3997         if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3998             if (mon->data == &mons[PM_DEATH]) {
3999                 mon->mhpmax += mon->mhpmax / 2;
4000                 if (mon->mhpmax >= MAGIC_COOKIE)
4001                     mon->mhpmax = MAGIC_COOKIE - 1;
4002                 mon->mhp = mon->mhpmax;
4003                 tmp = 0;
4004                 break;
4005             }
4006             if (nonliving(mon->data) || is_demon(mon->data)
4007                 || is_vampshifter(mon) || resists_magm(mon)) {
4008                 /* similar to player */
4009                 sho_shieldeff = TRUE;
4010                 break;
4011             }
4012             type = -1; /* so they don't get saving throws */
4013         } else {
4014             struct obj *otmp2;
4015
4016             if (resists_disint(mon)) {
4017                 sho_shieldeff = TRUE;
4018             } else if (mon->misc_worn_check & W_ARMS) {
4019                 /* destroy shield; victim survives */
4020                 *ootmp = which_armor(mon, W_ARMS);
4021             } else if (mon->misc_worn_check & W_ARM) {
4022                 /* destroy body armor, also cloak if present */
4023                 *ootmp = which_armor(mon, W_ARM);
4024                 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4025                     m_useup(mon, otmp2);
4026             } else {
4027                 /* no body armor, victim dies; destroy cloak
4028                    and shirt now in case target gets life-saved */
4029                 tmp = MAGIC_COOKIE;
4030                 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4031                     m_useup(mon, otmp2);
4032                 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
4033                     m_useup(mon, otmp2);
4034             }
4035             type = -1; /* no saving throw wanted */
4036             break;     /* not ordinary damage */
4037         }
4038         tmp = mon->mhp + 1;
4039         break;
4040     case ZT_LIGHTNING:
4041         if (resists_elec(mon)) {
4042             sho_shieldeff = TRUE;
4043             tmp = 0;
4044             /* can still blind the monster */
4045         } else
4046             tmp = d(nd, 6);
4047         if (spellcaster)
4048             tmp = spell_damage_bonus(tmp);
4049         if (!resists_blnd(mon)
4050             && !(type > 0 && u.uswallow && mon == u.ustuck)) {
4051             register unsigned rnd_tmp = rnd(50);
4052             mon->mcansee = 0;
4053             if ((mon->mblinded + rnd_tmp) > 127)
4054                 mon->mblinded = 127;
4055             else
4056                 mon->mblinded += rnd_tmp;
4057         }
4058         if (!rn2(3))
4059             (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
4060         /* not actually possible yet */
4061         if (!rn2(3))
4062             (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
4063         break;
4064     case ZT_POISON_GAS:
4065         if (resists_poison(mon)) {
4066             sho_shieldeff = TRUE;
4067             break;
4068         }
4069         tmp = d(nd, 6);
4070         break;
4071     case ZT_ACID:
4072         if (resists_acid(mon)) {
4073             sho_shieldeff = TRUE;
4074             break;
4075         }
4076         tmp = d(nd, 6);
4077         if (!rn2(6))
4078             acid_damage(MON_WEP(mon));
4079         if (!rn2(6))
4080             erode_armor(mon, ERODE_CORRODE);
4081         break;
4082     }
4083     if (sho_shieldeff)
4084         shieldeff(mon->mx, mon->my);
4085     if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
4086         tmp *= 2;
4087     if (tmp > 0 && type >= 0
4088         && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
4089         tmp /= 2;
4090     if (tmp < 0)
4091         tmp = 0; /* don't allow negative damage */
4092     debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
4093                 mon->mhp, tmp);
4094     mon->mhp -= tmp;
4095     return tmp;
4096 }
4097
4098 STATIC_OVL void
4099 zhitu(type, nd, fltxt, sx, sy)
4100 int type, nd;
4101 const char *fltxt;
4102 xchar sx, sy;
4103 {
4104     int dam = 0, abstyp = abs(type);
4105 #if 1 /*JP*/
4106     char buf[BUFSZ];
4107
4108     Sprintf(buf, "%s\82É\82æ\82Á\82Ä", fltxt);
4109     fltxt = buf;
4110 #endif
4111
4112     switch (abstyp % 10) {
4113     case ZT_MAGIC_MISSILE:
4114         if (Antimagic) {
4115             shieldeff(sx, sy);
4116 /*JP
4117             pline_The("missiles bounce off!");
4118 */
4119             pline("\96\82\96@\82Ì\96î\82Í\94½\8eË\82µ\82½\81I");
4120         } else {
4121             dam = d(nd, 6);
4122             exercise(A_STR, FALSE);
4123         }
4124         break;
4125     case ZT_FIRE:
4126         if (Fire_resistance) {
4127             shieldeff(sx, sy);
4128 /*JP
4129             You("don't feel hot!");
4130 */
4131             You("\94M\82³\82ð\8a´\82\82È\82¢\81I");
4132             ugolemeffects(AD_FIRE, d(nd, 6));
4133         } else {
4134             dam = d(nd, 6);
4135         }
4136         burn_away_slime();
4137         if (burnarmor(&youmonst)) { /* "body hit" */
4138             if (!rn2(3))
4139                 destroy_item(POTION_CLASS, AD_FIRE);
4140             if (!rn2(3))
4141                 destroy_item(SCROLL_CLASS, AD_FIRE);
4142             if (!rn2(5))
4143                 destroy_item(SPBOOK_CLASS, AD_FIRE);
4144             destroy_item(FOOD_CLASS, AD_FIRE);
4145         }
4146         break;
4147     case ZT_COLD:
4148         if (Cold_resistance) {
4149             shieldeff(sx, sy);
4150 /*JP
4151             You("don't feel cold.");
4152 */
4153             You("\97â\82½\82³\82ð\8a´\82\82È\82¢\81D");
4154             ugolemeffects(AD_COLD, d(nd, 6));
4155         } else {
4156             dam = d(nd, 6);
4157         }
4158         if (!rn2(3))
4159             destroy_item(POTION_CLASS, AD_COLD);
4160         break;
4161     case ZT_SLEEP:
4162         if (Sleep_resistance) {
4163             shieldeff(u.ux, u.uy);
4164 /*JP
4165             You("don't feel sleepy.");
4166 */
4167             You("\96°\82­\82È\82ç\82È\82¢\81D");
4168         } else {
4169             fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
4170         }
4171         break;
4172     case ZT_DEATH:
4173         if (abstyp == ZT_BREATH(ZT_DEATH)) {
4174             if (Disint_resistance) {
4175 /*JP
4176                 You("are not disintegrated.");
4177 */
4178                 You("\95ª\89ð\82³\82ê\82È\82¢\81D");
4179                 break;
4180             } else if (uarms) {
4181                 /* destroy shield; other possessions are safe */
4182                 (void) destroy_arm(uarms);
4183                 break;
4184             } else if (uarm) {
4185                 /* destroy suit; if present, cloak goes too */
4186                 if (uarmc)
4187                     (void) destroy_arm(uarmc);
4188                 (void) destroy_arm(uarm);
4189                 break;
4190             }
4191             /* no shield or suit, you're dead; wipe out cloak
4192                and/or shirt in case of life-saving or bones */
4193             if (uarmc)
4194                 (void) destroy_arm(uarmc);
4195             if (uarmu)
4196                 (void) destroy_arm(uarmu);
4197         } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4198             shieldeff(sx, sy);
4199 /*JP
4200             You("seem unaffected.");
4201 */
4202             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
4203             break;
4204         } else if (Antimagic) {
4205             shieldeff(sx, sy);
4206 /*JP
4207             You("aren't affected.");
4208 */
4209             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D");
4210             break;
4211         }
4212         killer.format = KILLED_BY_AN;
4213         Strcpy(killer.name, fltxt ? fltxt : "");
4214         /* when killed by disintegration breath, don't leave corpse */
4215         u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4216         done(DIED);
4217         return; /* lifesaved */
4218     case ZT_LIGHTNING:
4219         if (Shock_resistance) {
4220             shieldeff(sx, sy);
4221 /*JP
4222             You("aren't affected.");
4223 */
4224             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D");
4225             ugolemeffects(AD_ELEC, d(nd, 6));
4226         } else {
4227             dam = d(nd, 6);
4228             exercise(A_CON, FALSE);
4229         }
4230         if (!rn2(3))
4231             destroy_item(WAND_CLASS, AD_ELEC);
4232         if (!rn2(3))
4233             destroy_item(RING_CLASS, AD_ELEC);
4234         break;
4235     case ZT_POISON_GAS:
4236 /*JP
4237         poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4238 */
4239         poisoned("\91§", A_DEX, "\93Å\82Ì\91§", 15, FALSE);
4240         break;
4241     case ZT_ACID:
4242         if (Acid_resistance) {
4243 /*JP
4244             pline_The("%s doesn't hurt.", hliquid("acid"));
4245 */
4246             pline_The("%s\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D", hliquid("\8e_"));
4247             dam = 0;
4248         } else {
4249 /*JP
4250             pline_The("%s burns!", hliquid("acid"));
4251 */
4252             pline_The("%s\82Å\8fÄ\82¯\82½\81I", hliquid("\8e_"));
4253             dam = d(nd, 6);
4254             exercise(A_STR, FALSE);
4255         }
4256         /* using two weapons at once makes both of them more vulnerable */
4257         if (!rn2(u.twoweap ? 3 : 6))
4258             acid_damage(uwep);
4259         if (u.twoweap && !rn2(3))
4260             acid_damage(uswapwep);
4261         if (!rn2(6))
4262             erode_armor(&youmonst, ERODE_CORRODE);
4263         break;
4264     }
4265
4266     /* Half_spell_damage protection yields half-damage for wands & spells,
4267        including hero's own ricochets; breath attacks do full damage */
4268     if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4269         dam = (dam + 1) / 2;
4270     losehp(dam, fltxt, KILLED_BY_AN);
4271     return;
4272 }
4273
4274 /*
4275  * burn objects (such as scrolls and spellbooks) on floor
4276  * at position x,y; return the number of objects burned
4277  */
4278 int
4279 burn_floor_objects(x, y, give_feedback, u_caused)
4280 int x, y;
4281 boolean give_feedback; /* caller needs to decide about visibility checks */
4282 boolean u_caused;
4283 {
4284     struct obj *obj, *obj2;
4285     long i, scrquan, delquan;
4286     char buf1[BUFSZ], buf2[BUFSZ];
4287     int cnt = 0;
4288
4289     for (obj = level.objects[x][y]; obj; obj = obj2) {
4290         obj2 = obj->nexthere;
4291         if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4292             || (obj->oclass == FOOD_CLASS
4293                 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4294             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4295                 || obj_resists(obj, 2, 100))
4296                 continue;
4297             scrquan = obj->quan; /* number present */
4298             delquan = 0L;        /* number to destroy */
4299             for (i = scrquan; i > 0L; i--)
4300                 if (!rn2(3))
4301                     delquan++;
4302             if (delquan) {
4303                 /* save name before potential delobj() */
4304                 if (give_feedback) {
4305                     obj->quan = 1L;
4306                     Strcpy(buf1, (x == u.ux && y == u.uy)
4307                                      ? xname(obj)
4308                                      : distant_name(obj, xname));
4309                     obj->quan = 2L;
4310                     Strcpy(buf2, (x == u.ux && y == u.uy)
4311                                      ? xname(obj)
4312                                      : distant_name(obj, xname));
4313                     obj->quan = scrquan;
4314                 }
4315                 /* useupf(), which charges, only if hero caused damage */
4316                 if (u_caused)
4317                     useupf(obj, delquan);
4318                 else if (delquan < scrquan)
4319                     obj->quan -= delquan;
4320                 else
4321                     delobj(obj);
4322                 cnt += delquan;
4323                 if (give_feedback) {
4324                     if (delquan > 1L)
4325 #if 0 /*JP*/
4326                         pline("%ld %s burn.", delquan, buf2);
4327 #else
4328                         pline("%ld%s\82Ì%s\82ª\94R\82¦\82½\81D", 
4329                               delquan, 
4330                               obj->oclass == SCROLL_CLASS ? "\96\87" : "\8dû",
4331                               buf2);
4332 #endif
4333                     else
4334 /*JP
4335                         pline("%s burns.", An(buf1));
4336 */
4337                         pline("%s\82Í\94R\82¦\82½\81D", buf1);
4338                 }
4339             }
4340         }
4341     }
4342     return cnt;
4343 }
4344
4345 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4346 STATIC_OVL int
4347 zap_hit(ac, type)
4348 int ac;
4349 int type; /* either hero cast spell type or 0 */
4350 {
4351     int chance = rn2(20);
4352     int spell_bonus = type ? spell_hit_bonus(type) : 0;
4353
4354     /* small chance for naked target to avoid being hit */
4355     if (!chance)
4356         return rnd(10) < ac + spell_bonus;
4357
4358     /* very high armor protection does not achieve invulnerability */
4359     ac = AC_VALUE(ac);
4360
4361     return (3 - chance < ac + spell_bonus);
4362 }
4363
4364 STATIC_OVL void
4365 disintegrate_mon(mon, type, fltxt)
4366 struct monst *mon;
4367 int type; /* hero vs other */
4368 const char *fltxt;
4369 {
4370     struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4371
4372     if (canseemon(mon)) {
4373         if (!m_amulet)
4374 /*JP
4375             pline("%s is disintegrated!", Monnam(mon));
4376 */
4377             pline("%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I", Monnam(mon));
4378         else
4379 /*JP
4380             hit(fltxt, mon, "!");
4381 */
4382             hit(fltxt, mon, "\81I");
4383     }
4384
4385 /* note: worn amulet of life saving must be preserved in order to operate */
4386 #define oresist_disintegration(obj)                                       \
4387     (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4388      || is_quest_artifact(obj) || obj == m_amulet)
4389
4390     for (otmp = mon->minvent; otmp; otmp = otmp2) {
4391         otmp2 = otmp->nobj;
4392         if (!oresist_disintegration(otmp)) {
4393             if (otmp->owornmask) {
4394                 /* in case monster's life gets saved */
4395                 mon->misc_worn_check &= ~otmp->owornmask;
4396                 if (otmp->owornmask & W_WEP)
4397                     setmnotwielded(mon, otmp);
4398                 /* also dismounts hero if this object is steed's saddle */
4399                 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4400                 otmp->owornmask = 0L;
4401             }
4402             obj_extract_self(otmp);
4403             obfree(otmp, (struct obj *) 0);
4404         }
4405     }
4406
4407 #undef oresist_disintegration
4408
4409     if (type < 0)
4410         monkilled(mon, (char *) 0, -AD_RBRE);
4411     else
4412         xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
4413 }
4414
4415 void
4416 buzz(type, nd, sx, sy, dx, dy)
4417 int type, nd;
4418 xchar sx, sy;
4419 int dx, dy;
4420 {
4421     dobuzz(type, nd, sx, sy, dx, dy, TRUE);
4422 }
4423
4424 /*
4425  * type ==   0 to   9 : you shooting a wand
4426  * type ==  10 to  19 : you casting a spell
4427  * type ==  20 to  29 : you breathing as a monster
4428  * type == -10 to -19 : monster casting spell
4429  * type == -20 to -29 : monster breathing at you
4430  * type == -30 to -39 : monster shooting a wand
4431  * called with dx = dy = 0 with vertical bolts
4432  */
4433 void
4434 dobuzz(type, nd, sx, sy, dx, dy, say)
4435 register int type, nd;
4436 register xchar sx, sy;
4437 register int dx, dy;
4438 boolean say; /* Announce out of sight hit/miss events if true */
4439 {
4440     int range, abstype = abs(type) % 10;
4441     register xchar lsx, lsy;
4442     struct monst *mon;
4443     coord save_bhitpos;
4444     boolean shopdamage = FALSE;
4445     const char *fltxt;
4446     struct obj *otmp;
4447     int spell_type;
4448
4449     /* if its a Hero Spell then get its SPE_TYPE */
4450     spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4451
4452     fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4453     if (u.uswallow) {
4454         register int tmp;
4455
4456         if (type < 0)
4457             return;
4458         tmp = zhitm(u.ustuck, type, nd, &otmp);
4459         if (!u.ustuck)
4460             u.uswallow = 0;
4461         else
4462 #if 0 /*JP*/
4463             pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4464                   exclam(tmp));
4465 #else
4466             pline("%s\82Í%s\82ð\82Ð\82«\82³\82¢\82½%s", fltxt, mon_nam(u.ustuck),
4467                   exclam(tmp));
4468 #endif
4469         /* Using disintegration from the inside only makes a hole... */
4470         if (tmp == MAGIC_COOKIE)
4471             u.ustuck->mhp = 0;
4472         if (u.ustuck->mhp < 1)
4473             killed(u.ustuck);
4474         return;
4475     }
4476     if (type < 0)
4477         newsym(u.ux, u.uy);
4478     range = rn1(7, 7);
4479     if (dx == 0 && dy == 0)
4480         range = 1;
4481     save_bhitpos = bhitpos;
4482
4483     tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4484     while (range-- > 0) {
4485         lsx = sx;
4486         sx += dx;
4487         lsy = sy;
4488         sy += dy;
4489         if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
4490             goto make_bounce;
4491
4492         mon = m_at(sx, sy);
4493         if (cansee(sx, sy)) {
4494             /* reveal/unreveal invisible monsters before tmp_at() */
4495             if (mon && !canspotmon(mon))
4496                 map_invisible(sx, sy);
4497             else if (!mon)
4498                 (void) unmap_invisible(sx, sy);
4499             if (ZAP_POS(levl[sx][sy].typ)
4500                 || (isok(lsx, lsy) && cansee(lsx, lsy)))
4501                 tmp_at(sx, sy);
4502             delay_output(); /* wait a little */
4503         }
4504
4505         /* hit() and miss() need bhitpos to match the target */
4506         bhitpos.x = sx, bhitpos.y = sy;
4507         /* Fireballs only damage when they explode */
4508         if (type != ZT_SPELL(ZT_FIRE))
4509             range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4510
4511         if (mon) {
4512             if (type == ZT_SPELL(ZT_FIRE))
4513                 break;
4514             if (type >= 0)
4515                 mon->mstrategy &= ~STRAT_WAITMASK;
4516         buzzmonst:
4517             notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
4518             if (zap_hit(find_mac(mon), spell_type)) {
4519                 if (mon_reflects(mon, (char *) 0)) {
4520                     if (cansee(mon->mx, mon->my)) {
4521                         hit(fltxt, mon, exclam(0));
4522                         shieldeff(mon->mx, mon->my);
4523 #if 0 /*JP*/
4524                         (void) mon_reflects(mon,
4525                                             "But it reflects from %s %s!");
4526 #else
4527                         (void) mon_reflects(mon,
4528                                             "\82µ\82©\82µ\82»\82ê\82Í%s\82Ì%s\82Å\94½\8eË\82µ\82½\81I");
4529 #endif
4530                     }
4531                     dx = -dx;
4532                     dy = -dy;
4533                 } else {
4534                     boolean mon_could_move = mon->mcanmove;
4535                     int tmp = zhitm(mon, type, nd, &otmp);
4536
4537                     if (is_rider(mon->data)
4538                         && abs(type) == ZT_BREATH(ZT_DEATH)) {
4539                         if (canseemon(mon)) {
4540 /*JP
4541                             hit(fltxt, mon, ".");
4542 */
4543                             hit(fltxt, mon, "\81D");
4544 /*JP
4545                             pline("%s disintegrates.", Monnam(mon));
4546 */
4547                             pline("%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D", Monnam(mon));
4548 #if 0 /*JP*/
4549                             pline("%s body reintegrates before your %s!",
4550                                   s_suffix(Monnam(mon)),
4551                                   (eyecount(youmonst.data) == 1)
4552                                       ? body_part(EYE)
4553                                       : makeplural(body_part(EYE)));
4554 #else
4555                             pline("%s\82Ì\91Ì\82Í\82 \82È\82½\82Ì\96Ú\82Ì\91O\82Å\8dÄ\8c\8b\8d\87\82µ\82½\81I",
4556                                   Monnam(mon));
4557 #endif
4558 /*JP
4559                             pline("%s resurrects!", Monnam(mon));
4560 */
4561                             pline("%s\82Í\91h\82Á\82½\81I", Monnam(mon));
4562                         }
4563                         mon->mhp = mon->mhpmax;
4564                         break; /* Out of while loop */
4565                     }
4566                     if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4567                         if (canseemon(mon)) {
4568 /*JP
4569                             hit(fltxt, mon, ".");
4570 */
4571                             hit(fltxt, mon, "\81D");
4572 #if 0 /*JP*/
4573                             pline("%s absorbs the deadly %s!", Monnam(mon),
4574                                   type == ZT_BREATH(ZT_DEATH) ? "blast"
4575                                                               : "ray");
4576 #else
4577                             pline("%s\82Í\8e\80\82Ì%s\82ð\8bz\8eû\82µ\82½\81I", Monnam(mon),
4578                                   type == ZT_BREATH(ZT_DEATH) ? "\91§"
4579                                                               : "\8cõ\90ü");
4580 #endif
4581 /*JP
4582                             pline("It seems even stronger than before.");
4583 */
4584                             pline("\82³\82ç\82É\8b­\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82³\82¦\82·\82é\81D");
4585                         }
4586                         break; /* Out of while loop */
4587                     }
4588
4589                     if (tmp == MAGIC_COOKIE) { /* disintegration */
4590                         disintegrate_mon(mon, type, fltxt);
4591                     } else if (mon->mhp < 1) {
4592                         if (type < 0) {
4593                             /* mon has just been killed by another monster */
4594                             monkilled(mon, fltxt, AD_RBRE);
4595                         } else {
4596                             int xkflags = XKILL_GIVEMSG; /* killed(mon); */
4597
4598                             /* killed by hero; we know 'type' isn't negative;
4599                                if it's fire, highly flammable monsters leave
4600                                no corpse; don't bother reporting that they
4601                                "burn completely" -- unnecessary verbosity */
4602                             if ((type % 10 == ZT_FIRE)
4603                                 /* paper golem or straw golem */
4604                                 && completelyburns(mon->data))
4605                                 xkflags |= XKILL_NOCORPSE;
4606                             xkilled(mon, xkflags);
4607                         }
4608                     } else {
4609                         if (!otmp) {
4610                             /* normal non-fatal hit */
4611                             if (say || canseemon(mon))
4612                                 hit(fltxt, mon, exclam(tmp));
4613                         } else {
4614                             /* some armor was destroyed; no damage done */
4615                             if (canseemon(mon))
4616 #if 0 /*JP*/
4617                                 pline("%s %s is disintegrated!",
4618                                       s_suffix(Monnam(mon)),
4619                                       distant_name(otmp, xname));
4620 #else
4621                                 pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
4622                                       Monnam(mon),
4623                                       distant_name(otmp, xname));
4624 #endif
4625                             m_useup(mon, otmp);
4626                         }
4627                         if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4628                             slept_monst(mon);
4629                     }
4630                 }
4631                 range -= 2;
4632             } else {
4633                 if (say || canseemon(mon))
4634                     miss(fltxt, mon);
4635             }
4636         } else if (sx == u.ux && sy == u.uy && range >= 0) {
4637             nomul(0);
4638             if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4639                 mon = u.usteed;
4640                 goto buzzmonst;
4641             } else if (zap_hit((int) u.uac, 0)) {
4642                 range -= 2;
4643 /*JP
4644                 pline("%s hits you!", The(fltxt));
4645 */
4646                 pline("%s\82Í\82 \82È\82½\82É\96½\92\86\82µ\82½\81I", fltxt);
4647                 if (Reflecting) {
4648                     if (!Blind) {
4649 #if 0 /*JP*/
4650                         (void) ureflects("But %s reflects from your %s!",
4651                                          "it");
4652 #else
4653                         (void) ureflects("\82µ\82©\82µ\81C%s\82Í\82 \82È\82½\82Ì%s\82É\82æ\82Á\82Ä\94½\8eË\82µ\82½\81D",
4654                                          "\82»\82ê");
4655 #endif
4656                     } else
4657 /*JP
4658                         pline("For some reason you are not affected.");
4659 */
4660                         pline("\82È\82º\82©\82 \82È\82½\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D");
4661                     dx = -dx;
4662                     dy = -dy;
4663                     shieldeff(sx, sy);
4664                 } else {
4665                     zhitu(type, nd, fltxt, sx, sy);
4666                 }
4667             } else if (!Blind) {
4668 /*JP
4669                 pline("%s whizzes by you!", The(fltxt));
4670 */
4671                 pline("%s\82Í\82 \82È\82½\82Ì\82»\82Î\82ð\82©\82·\82ß\82½\81I", fltxt);
4672             } else if (abstype == ZT_LIGHTNING) {
4673 /*JP
4674                 Your("%s tingles.", body_part(ARM));
4675 */
4676                 Your("%s\82Í\83q\83\8a\83q\83\8a\82µ\82½\81D", body_part(ARM));
4677             }
4678             if (abstype == ZT_LIGHTNING)
4679                 (void) flashburn((long) d(nd, 50));
4680             stop_occupation();
4681             nomul(0);
4682         }
4683
4684         if (!ZAP_POS(levl[sx][sy].typ)
4685             || (closed_door(sx, sy) && range >= 0)) {
4686             int bounce, bchance;
4687             uchar rmn;
4688             boolean fireball;
4689
4690         make_bounce:
4691             bchance = (levl[sx][sy].typ == STONE) ? 10
4692                 : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
4693                 : 75;
4694             bounce = 0;
4695             fireball = (type == ZT_SPELL(ZT_FIRE));
4696             if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
4697                 || fireball) {
4698                 if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
4699 /*JP
4700                     pline_The("%s vanishes into the aether!", fltxt);
4701 */
4702                     pline_The("%s\82Í\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½\81I", fltxt);
4703                     if (fireball)
4704                         type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
4705                     break;
4706                 } else if (fireball) {
4707                     sx = lsx;
4708                     sy = lsy;
4709                     break; /* fireballs explode before the obstacle */
4710                 } else
4711 /*JP
4712                     pline_The("%s bounces!", fltxt);
4713 */
4714                     pline_The("%s\82Í\94½\8eË\82µ\82½\81I", fltxt);
4715             }
4716             if (!dx || !dy || !rn2(bchance)) {
4717                 dx = -dx;
4718                 dy = -dy;
4719             } else {
4720                 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4721                     && !closed_door(sx, lsy)
4722                     && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4723                                          && ZAP_POS(levl[sx + dx][lsy].typ))))
4724                     bounce = 1;
4725                 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4726                     && !closed_door(lsx, sy)
4727                     && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4728                                          && ZAP_POS(levl[lsx][sy + dy].typ))))
4729                     if (!bounce || rn2(2))
4730                         bounce = 2;
4731
4732                 switch (bounce) {
4733                 case 0:
4734                     dx = -dx;
4735                     /*FALLTHRU*/
4736                 case 1:
4737                     dy = -dy;
4738                     break;
4739                 case 2:
4740                     dx = -dx;
4741                     break;
4742                 }
4743                 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4744             }
4745         }
4746     }
4747     tmp_at(DISP_END, 0);
4748     if (type == ZT_SPELL(ZT_FIRE))
4749         explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4750     if (shopdamage)
4751 #if 0 /*JP*/
4752         pay_for_damage(abstype == ZT_FIRE
4753                           ? "burn away"
4754                           : abstype == ZT_COLD
4755                              ? "shatter"
4756                              /* "damage" indicates wall rather than door */
4757                              : abstype == ZT_ACID
4758                                 ? "damage"
4759                                 : abstype == ZT_DEATH
4760                                    ? "disintegrate"
4761                                    : "destroy",
4762                        FALSE);
4763 #else
4764         pay_for_damage(abstype == ZT_FIRE
4765                        ? "\94R\82â\82·"
4766                        : abstype == ZT_COLD
4767                           ? "\95²\81X\82É\82·\82é"
4768                           : abstype == ZT_ACID
4769                           ? "\8f\9d\82Â\82¯\82é"
4770                              : abstype == ZT_DEATH
4771                                 ? "\95²\8dÓ\82·\82é"
4772                                 : "\94j\89ó\82·\82é",
4773                        FALSE);
4774 #endif
4775     bhitpos = save_bhitpos;
4776 }
4777
4778 void
4779 melt_ice(x, y, msg)
4780 xchar x, y;
4781 const char *msg;
4782 {
4783     struct rm *lev = &levl[x][y];
4784     struct obj *otmp;
4785
4786     if (!msg)
4787 /*JP
4788         msg = "The ice crackles and melts.";
4789 */
4790         msg = "\95X\82Í\83s\83L\83s\83L\96Â\82è\81C\97n\82¯\82½\81D";
4791     if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
4792         lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4793     } else { /* lev->typ == ICE */
4794 #ifdef STUPID
4795         if (lev->icedpool == ICED_POOL)
4796             lev->typ = POOL;
4797         else
4798             lev->typ = MOAT;
4799 #else
4800         lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4801 #endif
4802         lev->icedpool = 0;
4803     }
4804     spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4805     obj_ice_effects(x, y, FALSE);
4806     unearth_objs(x, y);
4807     if (Underwater)
4808         vision_recalc(1);
4809     newsym(x, y);
4810     if (cansee(x, y))
4811         Norep("%s", msg);
4812     if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4813         if (cansee(x, y))
4814 /*JP
4815             pline("%s settles...", An(xname(otmp)));
4816 */
4817             pline("%s\82Í\82Í\82Ü\82Á\82½\81D\81D\81D", xname(otmp));
4818         do {
4819             obj_extract_self(otmp); /* boulder isn't being pushed */
4820             if (!boulder_hits_pool(otmp, x, y, FALSE))
4821                 impossible("melt_ice: no pool?");
4822             /* try again if there's another boulder and pool didn't fill */
4823         } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4824         newsym(x, y);
4825     }
4826     if (x == u.ux && y == u.uy)
4827         spoteffects(TRUE); /* possibly drown, notice objects */
4828 }
4829
4830 #define MIN_ICE_TIME 50
4831 #define MAX_ICE_TIME 2000
4832 /*
4833  * Usually start a melt_ice timer; sometimes the ice will become
4834  * permanent instead.
4835  */
4836 void
4837 start_melt_ice_timeout(x, y, min_time)
4838 xchar x, y;
4839 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4840 {
4841     int when;
4842     long where;
4843
4844     when = (int) min_time;
4845     if (when < MIN_ICE_TIME - 1)
4846         when = MIN_ICE_TIME - 1;
4847
4848     /* random timeout; surrounding ice locations ought to be a factor... */
4849     while (++when <= MAX_ICE_TIME)
4850         if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4851             break;
4852
4853     /* if we're within MAX_ICE_TIME, install a melt timer;
4854        otherwise, omit it to leave this ice permanent */
4855     if (when <= MAX_ICE_TIME) {
4856         where = ((long) x << 16) | (long) y;
4857         (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4858                            long_to_any(where));
4859     }
4860 }
4861 #undef MIN_ICE_TIME
4862 #undef MAX_ICE_TIME
4863
4864 /*
4865  * Called when ice has melted completely away.
4866  */
4867 void
4868 melt_ice_away(arg, timeout)
4869 anything *arg;
4870 long timeout UNUSED;
4871 {
4872     xchar x, y;
4873     long where = arg->a_long;
4874
4875     y = (xchar) (where & 0xFFFF);
4876     x = (xchar) ((where >> 16) & 0xFFFF);
4877     /* melt_ice does newsym when appropriate */
4878 /*JP
4879     melt_ice(x, y, "Some ice melts away.");
4880 */
4881     melt_ice(x, y, "\95X\82ª\8f­\82µ\97n\82¯\82½\81D");
4882 }
4883
4884 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4885  * Used both for normal bolts of fire, cold, etc... and for fireballs.
4886  * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4887  * amount by which range is reduced (the latter is just ignored by fireballs)
4888  */
4889 int
4890 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4891 xchar x, y;
4892 int type;
4893 boolean *shopdamage;
4894 short exploding_wand_typ;
4895 {
4896     const char *zapverb;
4897     struct monst *mon;
4898     struct trap *t;
4899     struct rm *lev = &levl[x][y];
4900     boolean see_it = cansee(x, y), yourzap;
4901     int rangemod = 0, abstype = abs(type) % 10;
4902
4903     switch (abstype) {
4904     case ZT_FIRE:
4905         t = t_at(x, y);
4906         if (t && t->ttyp == WEB) {
4907             /* a burning web is too flimsy to notice if you can't see it */
4908             if (see_it)
4909 /*JP
4910                 Norep("A web bursts into flames!");
4911 */
4912                 Norep("\82­\82à\82Ì\91\83\82Í\89\8a\82É\95ï\82Ü\82ê\82½\81I");
4913             (void) delfloortrap(t);
4914             if (see_it)
4915                 newsym(x, y);
4916         }
4917         if (is_ice(x, y)) {
4918             melt_ice(x, y, (char *) 0);
4919         } else if (is_pool(x, y)) {
4920 /*JP
4921             const char *msgtxt = "You hear hissing gas.";
4922 */
4923             const char *msgtxt = "\82µ\82ã\81[\82Á\82Æ\82¢\82¤\83K\83X\82Ì\89¹\82ð\95·\82¢\82½\81D";
4924
4925             if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4926                 if (see_it)
4927 /*JP
4928                     msgtxt = "Some water evaporates.";
4929 */
4930                     msgtxt = "\82·\82±\82µ\90\85\82ª\8fö\94­\82µ\82½\81D";
4931             } else {
4932                 rangemod -= 3;
4933                 lev->typ = ROOM;
4934                 t = maketrap(x, y, PIT);
4935                 if (t)
4936                     t->tseen = 1;
4937                 if (see_it)
4938 /*JP
4939                     msgtxt = "The water evaporates.";
4940 */
4941                     msgtxt = "\90\85\82ª\8fö\94­\82µ\82½\81D";
4942             }
4943             Norep("%s", msgtxt);
4944             if (lev->typ == ROOM)
4945                 newsym(x, y);
4946         } else if (IS_FOUNTAIN(lev->typ)) {
4947             if (see_it)
4948 /*JP
4949                 pline("Steam billows from the fountain.");
4950 */
4951                 pline("\90ò\82©\82ç\8fö\8bC\82ª\97§\82¿\82Ì\82Ú\82Á\82½\81D");
4952             rangemod -= 1;
4953             dryup(x, y, type > 0);
4954         }
4955         break; /* ZT_FIRE */
4956
4957     case ZT_COLD:
4958         if (is_pool(x, y) || is_lava(x, y)) {
4959             boolean lava = is_lava(x, y),
4960                     moat = is_moat(x, y);
4961
4962             if (lev->typ == WATER) {
4963                 /* For now, don't let WATER freeze. */
4964                 if (see_it)
4965 /*JP
4966                     pline_The("%s freezes for a moment.", hliquid("water"));
4967 */
4968                     pline_The("%s\82Í\88ê\8fu\93\80\82Á\82½\81D", hliquid("\90\85"));
4969                 else
4970 /*JP
4971                     You_hear("a soft crackling.");
4972 */
4973                     You_hear("\83s\83L\81I\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
4974                 rangemod -= 1000; /* stop */
4975             } else {
4976                 char buf[BUFSZ];
4977
4978                 Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
4979                 rangemod -= 3;
4980                 if (lev->typ == DRAWBRIDGE_UP) {
4981                     lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4982                     lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4983                 } else {
4984                     if (!lava)
4985                         lev->icedpool = (lev->typ == POOL) ? ICED_POOL
4986                                                            : ICED_MOAT;
4987                     lev->typ = lava ? ROOM : ICE;
4988                 }
4989                 bury_objs(x, y);
4990                 if (see_it) {
4991                     if (lava)
4992 /*JP
4993                         Norep("The %s cools and solidifies.", hliquid("lava"));
4994 */
4995                         Norep("%s\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D", hliquid("lava"));
4996                     else if (moat)
4997 /*JP
4998                         Norep("The %s is bridged with ice!", buf);
4999 */
5000                         Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I", buf);
5001                     else
5002 /*JP
5003                         Norep("The %s freezes.", hliquid("water"));
5004 */
5005                         Norep("%s\82Í\93\80\82Á\82½\81D", hliquid("\95X"));
5006                     newsym(x, y);
5007                 } else if (!lava)
5008 /*JP
5009                     You_hear("a crackling sound.");
5010 */
5011                     You_hear("\83s\83L\83s\83L\83b\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
5012
5013                 if (x == u.ux && y == u.uy) {
5014                     if (u.uinwater) { /* not just `if (Underwater)' */
5015                         /* leave the no longer existent water */
5016                         u.uinwater = 0;
5017                         u.uundetected = 0;
5018                         docrt();
5019                         vision_full_recalc = 1;
5020                     } else if (u.utrap && u.utraptype == TT_LAVA) {
5021                         if (Passes_walls) {
5022                             u.utrap = 0;
5023 /*JP
5024                             You("pass through the now-solid rock.");
5025 */
5026                             You("\82¢\82Ü\8cÅ\82­\82È\82Á\82½\82Î\82©\82è\82Ì\90Î\82Ì\92\86\82ð\82·\82è\94²\82¯\82½\81D");
5027                         } else {
5028                             u.utrap = rn1(50, 20);
5029                             u.utraptype = TT_INFLOOR;
5030 /*JP
5031                             You("are firmly stuck in the cooling rock.");
5032 */
5033                             You("\97â\82¦\82½\8aâ\82Ì\82È\82©\82É\82µ\82Á\82©\82è\82Æ\96\84\82Ü\82Á\82½\81D");
5034                         }
5035                     }
5036                 } else if ((mon = m_at(x, y)) != 0) {
5037                     /* probably ought to do some hefty damage to any
5038                        non-ice creature caught in freezing water;
5039                        at a minimum, eels are forced out of hiding */
5040                     if (is_swimmer(mon->data) && mon->mundetected) {
5041                         mon->mundetected = 0;
5042                         newsym(x, y);
5043                     }
5044                 }
5045                 if (!lava) {
5046                     start_melt_ice_timeout(x, y, 0L);
5047                     obj_ice_effects(x, y, TRUE);
5048                 }
5049             } /* ?WATER */
5050
5051         } else if (is_ice(x, y)) {
5052             long melt_time;
5053
5054             /* Already ice here, so just firm it up. */
5055             /* Now ensure that only ice that is already timed is affected */
5056             if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
5057                 spot_stop_timers(x, y, MELT_ICE_AWAY);
5058                 start_melt_ice_timeout(x, y, melt_time);
5059             }
5060         }
5061         break; /* ZT_COLD */
5062
5063     case ZT_POISON_GAS:
5064         (void) create_gas_cloud(x, y, 1, 8);
5065         break;
5066
5067     case ZT_ACID:
5068         if (lev->typ == IRONBARS) {
5069             if ((lev->wall_info & W_NONDIGGABLE) != 0) {
5070                 if (see_it)
5071 /*JP
5072                     Norep("The %s corrode somewhat but remain intact.",
5073 */
5074                     Norep("%s\82Í\8f­\82µ\92É\82ñ\82¾\82ª\82Ü\82¾\82µ\82Á\82©\82è\82µ\82Ä\82¢\82é\81D",
5075                           defsyms[S_bars].explanation);
5076                 /* but nothing actually happens... */
5077             } else {
5078                 rangemod -= 3;
5079                 if (see_it)
5080 /*JP
5081                     Norep("The %s melt.", defsyms[S_bars].explanation);
5082 */
5083                     Norep("%s\82ª\97n\82¯\82½\81D", defsyms[S_bars].explanation);
5084                 if (*in_rooms(x, y, SHOPBASE)) {
5085                     /* in case we ever have a shop bounded by bars */
5086                     lev->typ = ROOM;
5087                     if (see_it)
5088                         newsym(x, y);
5089                     add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
5090                     if (type >= 0)
5091                         *shopdamage = TRUE;
5092                 } else {
5093                     lev->typ = DOOR;
5094                     lev->doormask = D_NODOOR;
5095                     if (see_it)
5096                         newsym(x, y);
5097                 }
5098             }
5099         }
5100         break; /* ZT_ACID */
5101
5102     default:
5103         break;
5104     }
5105
5106     /* set up zap text for possible door feedback; for exploding wand, we
5107        want "the blast" rather than "your blast" even if hero caused it */
5108     yourzap = (type >= 0 && !exploding_wand_typ);
5109 #if 0 /*JP*/
5110     zapverb = "blast"; /* breath attack or wand explosion */
5111 #else
5112     zapverb = "\8fÕ\8c\82"; /* breath attack or wand explosion */
5113 #endif
5114     if (!exploding_wand_typ) {
5115         if (abs(type) < ZT_SPELL(0))
5116 #if 0 /*JP*/
5117             zapverb = "bolt"; /* wand zap */
5118 #else
5119             zapverb = "\8cõ\90ü"; /* wand zap */
5120 #endif
5121         else if (abs(type) < ZT_BREATH(0))
5122 /*JP
5123             zapverb = "spell";
5124 */
5125             zapverb = "\8eô\95¶";
5126     }
5127
5128     /* secret door gets revealed, converted into regular door */
5129     if (levl[x][y].typ == SDOOR) {
5130         cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
5131         /* target spot will now pass closed_door() test below
5132            (except on rogue level) */
5133         newsym(x, y);
5134         if (see_it)
5135 #if 0 /*JP*/
5136             pline("%s %s reveals a secret door.",
5137                   yourzap ? "Your" : "The", zapverb);
5138 #else
5139             pline("%s\82Å\89B\82µ\94à\82ª\96¾\82ç\82©\82É\82È\82Á\82½\81D", zapverb);
5140 #endif
5141         else if (Is_rogue_level(&u.uz))
5142             draft_message(FALSE); /* "You feel a draft." (open doorway) */
5143     }
5144
5145     /* regular door absorbs remaining zap range, possibly gets destroyed */
5146     if (closed_door(x, y)) {
5147         int new_doormask = -1;
5148         const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
5149
5150         rangemod = -1000;
5151         switch (abstype) {
5152         case ZT_FIRE:
5153             new_doormask = D_NODOOR;
5154 /*JP
5155             see_txt = "The door is consumed in flames!";
5156 */
5157             see_txt = "\94à\82Í\89\8a\82Å\8fÄ\82«\82Â\82­\82³\82ê\82½\81I";
5158 /*JP
5159             sense_txt = "smell smoke.";
5160 */
5161             sense_txt = "\89\8c\82Ì\93õ\82¢\82ª\82µ\82½\81D";
5162             break;
5163         case ZT_COLD:
5164             new_doormask = D_NODOOR;
5165 /*JP
5166             see_txt = "The door freezes and shatters!";
5167 */
5168             see_txt = "\94à\82Í\93\80\82è\81C\82±\82È\82²\82È\82É\82È\82Á\82½\81I";
5169 /*JP
5170             sense_txt = "feel cold.";
5171 */
5172             sense_txt = "\97â\8bC\82ð\8a´\82\82½\81D";
5173             break;
5174         case ZT_DEATH:
5175             /* death spells/wands don't disintegrate */
5176             if (abs(type) != ZT_BREATH(ZT_DEATH))
5177                 goto def_case;
5178             new_doormask = D_NODOOR;
5179 /*JP
5180             see_txt = "The door disintegrates!";
5181 */
5182             see_txt = "\94à\82Í\95²\8dÓ\82³\82ê\82½\81I";
5183 /*JP
5184             hear_txt = "crashing wood.";
5185 */
5186             hear_txt = "\96Ø\82Ì\89ó\82ê\82é\89¹\82ð\95·\82¢\82½\81D";
5187             break;
5188         case ZT_LIGHTNING:
5189             new_doormask = D_BROKEN;
5190 /*JP
5191             see_txt = "The door splinters!";
5192 */
5193             see_txt = "\94à\82Í\82¸\82½\82¸\82½\82É\82È\82Á\82½\81I";
5194 /*JP
5195             hear_txt = "crackling.";
5196 */
5197             hear_txt = "\83s\83L\83s\83L\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D";
5198             break;
5199         default:
5200         def_case:
5201             if (exploding_wand_typ > 0) {
5202                 /* Magical explosion from misc exploding wand */
5203                 if (exploding_wand_typ == WAN_STRIKING) {
5204                     new_doormask = D_BROKEN;
5205 /*JP
5206                     see_txt = "The door crashes open!";
5207 */
5208                     see_txt = "\94à\82Í\89ó\82ê\82Ä\8aJ\82¢\82½\81I";
5209 /*JP
5210                     sense_txt = "feel a burst of cool air.";
5211 */
5212                     sense_txt = "\97â\8bC\82Ì\8f[\96\9e\82ð\8a´\82\82½\81D";
5213                     break;
5214                 }
5215             }
5216             if (see_it) {
5217                 /* "the door absorbs the blast" would be
5218                    inaccurate for an exploding wand since
5219                    other adjacent locations still get hit */
5220                 if (exploding_wand_typ)
5221 /*JP
5222                     pline_The("door remains intact.");
5223 */
5224                     pline_The("\94à\82Í\96³\8f\9d\82¾\81D");
5225                 else
5226 #if 0 /*JP*/
5227                     pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
5228                               zapverb);
5229 #else
5230                     pline_The("\94à\82Í%s%s\82ð\8bz\8eû\82µ\82½\81I", yourzap ? "\82 \82È\82½\82ª\95ú\82Á\82½" : "",
5231                               zapverb);
5232 #endif
5233             } else
5234 /*JP
5235                 You_feel("vibrations.");
5236 */
5237                 You("\90U\93®\82ð\8a´\82\82½\81D");
5238             break;
5239         }
5240         if (new_doormask >= 0) { /* door gets broken */
5241             if (*in_rooms(x, y, SHOPBASE)) {
5242                 if (type >= 0) {
5243                     add_damage(x, y, SHOP_DOOR_COST);
5244                     *shopdamage = TRUE;
5245                 } else /* caused by monster */
5246                     add_damage(x, y, 0L);
5247             }
5248             lev->doormask = new_doormask;
5249             unblock_point(x, y); /* vision */
5250             if (see_it) {
5251                 pline1(see_txt);
5252                 newsym(x, y);
5253             } else if (sense_txt) {
5254 #if 0 /*JP*//*\81u\82 \82È\82½\82Í\81v\82ª\95s\93K\90Ø\82È\95\82à\82 \82é*/
5255                 You1(sense_txt);
5256 #else
5257                 pline1(sense_txt);
5258 #endif
5259             } else if (hear_txt)
5260                 You_hear1(hear_txt);
5261             if (picking_at(x, y)) {
5262                 stop_occupation();
5263                 reset_pick();
5264             }
5265         }
5266     }
5267
5268     if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5269         if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5270             newsym(x, y);
5271 /*JP
5272             You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5273 */
5274             pline("%s\81D", !Blind ? "\82Û\82í\82Á\82Æ\89\8c\82ª\82 \82ª\82Á\82½" : "\89\8c\82Ì\83v\83\93\82Æ\82¢\82¤\93õ\82¢\82ª\82µ\82½");
5275         }
5276     if ((mon = m_at(x, y)) != 0) {
5277         wakeup(mon, FALSE);
5278         if (type >= 0) {
5279             setmangry(mon, TRUE);
5280             if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5281                 ghod_hitsu(mon);
5282             if (mon->isshk && !*u.ushops)
5283                 hot_pursuit(mon);
5284         }
5285     }
5286     return rangemod;
5287 }
5288
5289 /* fractured by pick-axe or wand of striking */
5290 void
5291 fracture_rock(obj)
5292 register struct obj *obj; /* no texts here! */
5293 {
5294     xchar x, y;
5295     boolean by_you = !context.mon_moving;
5296
5297     if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5298         struct monst *shkp = 0;
5299         char objroom = *in_rooms(x, y, SHOPBASE);
5300
5301         if (billable(&shkp, obj, objroom, FALSE)) {
5302             /* shop message says "you owe <shk> <$> for it!" so we need
5303                to precede that with a message explaining what "it" is */
5304 /*JP
5305             You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5306 */
5307             You("%s\82Ì%s\82ð\89ó\82µ\82½\81D", shkname(shkp), xname(obj));
5308             breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5309         }
5310     }
5311     if (by_you && obj->otyp == BOULDER)
5312         sokoban_guilt();
5313
5314     obj->otyp = ROCK;
5315     obj->oclass = GEM_CLASS;
5316     obj->quan = (long) rn1(60, 7);
5317     obj->owt = weight(obj);
5318     obj->dknown = obj->bknown = obj->rknown = 0;
5319     obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5320     dealloc_oextra(obj);
5321
5322     if (obj->where == OBJ_FLOOR) {
5323         obj_extract_self(obj); /* move rocks back on top */
5324         place_object(obj, obj->ox, obj->oy);
5325         if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5326             unblock_point(obj->ox, obj->oy);
5327         if (cansee(obj->ox, obj->oy))
5328             newsym(obj->ox, obj->oy);
5329     }
5330 }
5331
5332 /* handle statue hit by striking/force bolt/pick-axe */
5333 boolean
5334 break_statue(obj)
5335 register struct obj *obj;
5336 {
5337     /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5338     struct trap *trap = t_at(obj->ox, obj->oy);
5339     struct obj *item;
5340     boolean by_you = !context.mon_moving;
5341
5342     if (trap && trap->ttyp == STATUE_TRAP
5343         && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5344         return FALSE;
5345     /* drop any objects contained inside the statue */
5346     while ((item = obj->cobj) != 0) {
5347         obj_extract_self(item);
5348         place_object(item, obj->ox, obj->oy);
5349     }
5350     if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5351 /*JP
5352         You_feel("guilty about damaging such a historic statue.");
5353 */
5354         You_feel("\82±\82Ì\82æ\82¤\82È\97ð\8ej\93I\82È\92¤\91\9c\82É\8f\9d\82ð\82Â\82¯\82é\82Ì\82Í\8dß\90[\82¢\82±\82Æ\82¾\82Æ\8ev\82Á\82½\81D");
5355         adjalign(-1);
5356     }
5357     obj->spe = 0;
5358     fracture_rock(obj);
5359     return TRUE;
5360 }
5361
5362 /*
5363  * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5364  *      [0] freezing potion
5365  *      [1] boiling potion other than oil
5366  *      [2] boiling potion of oil
5367  *      [3] burning scroll
5368  *      [4] burning spellbook
5369  *      [5] shocked ring
5370  *      [6] shocked wand
5371  * (books, rings, and wands don't stack so don't need plural form;
5372  *  crumbling ring doesn't do damage so doesn't need killer reason)
5373  */
5374 const char *const destroy_strings[][3] = {
5375     /* also used in trap.c */
5376 /*JP
5377     { "freezes and shatters", "freeze and shatter", "shattered potion" },
5378 */
5379     { "\93\80\8c\8b\82µ\82Ä\8dÓ\82¯\82½", "\93\80\8c\8b\82µ\82Ä\8dÓ\82¯\82½", "\8dÓ\82¯\82½\96ò\95r\82Å" },
5380 /*JP
5381     { "boils and explodes", "boil and explode", "boiling potion" },
5382 */
5383     { "\95¦\93«\82µ\82Ä\94\9a\94­\82µ\82½", "\95¦\93«\82µ\82Ä\94\9a\94­\82µ\82½", "\95¦\93«\82µ\82½\96ò\82Å" },
5384 /*JP
5385     { "ignites and explodes", "ignite and explode", "exploding potion" },
5386 */
5387     { "\89Î\82ª\82Â\82¢\82Ä\94\9a\94­\82µ\82½", "\89Î\82ª\82Â\82¢\82Ä\94\9a\94­\82µ\82½", "\94\9a\94­\82µ\82½\96ò\82Å" },
5388 /*JP
5389     { "catches fire and burns", "catch fire and burn", "burning scroll" },
5390 */
5391     { "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\94R\82¦\82½\8aª\95¨\82Å" },
5392 /*JP
5393     { "catches fire and burns", "", "burning book" },
5394 */
5395     { "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\94R\82¦\82½\96\82\96@\8f\91\82Å" },
5396 /*JP
5397     { "turns to dust and vanishes", "", "" },
5398 */
5399     { "\90o\82É\82È\82Á\82Ä\8fÁ\82¦\82½", "\90o\82É\82È\82Á\82Ä\8fÁ\82¦\82½", "" },
5400 /*JP
5401     { "breaks apart and explodes", "", "exploding wand" },
5402 */
5403     { "\82Î\82ç\82Î\82ç\82É\89ó\82ê\82Ä\94\9a\94­\82µ\82½", "\82Î\82ç\82Î\82ç\82É\89ó\82ê\82Ä\94\9a\94­\82µ\82½", "\8fñ\82Ì\94\9a\94­\82Å" },
5404 };
5405
5406 void
5407 destroy_item(osym, dmgtyp)
5408 register int osym, dmgtyp;
5409 {
5410     register struct obj *obj, *obj2;
5411     int dmg, xresist, skip;
5412     long i, cnt, quan;
5413     int dindx;
5414     const char *mult;
5415     boolean physical_damage;
5416
5417     for (obj = invent; obj; obj = obj2) {
5418         obj2 = obj->nobj;
5419         physical_damage = FALSE;
5420         if (obj->oclass != osym)
5421             continue; /* test only objs of type osym */
5422         if (obj->oartifact)
5423             continue; /* don't destroy artifacts */
5424         if (obj->in_use && obj->quan == 1L)
5425             continue; /* not available */
5426         xresist = skip = 0;
5427         /* lint suppression */
5428         dmg = dindx = 0;
5429         quan = 0L;
5430
5431         switch (dmgtyp) {
5432         case AD_COLD:
5433             if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5434                 quan = obj->quan;
5435                 dindx = 0;
5436                 dmg = rnd(4);
5437             } else
5438                 skip++;
5439             break;
5440         case AD_FIRE:
5441             xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5442                        && obj->otyp != GLOB_OF_GREEN_SLIME);
5443
5444             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5445                 skip++;
5446             if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5447                 skip++;
5448                 if (!Blind)
5449 #if 0 /*JP:T*/
5450                     pline("%s glows a strange %s, but remains intact.",
5451                           The(xname(obj)), hcolor("dark red"));
5452 #else
5453                     pline("%s\82Í\8aï\96­\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
5454                           xname(obj), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
5455 #endif
5456
5457             }
5458             quan = obj->quan;
5459             switch (osym) {
5460             case POTION_CLASS:
5461                 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5462                 dmg = rnd(6);
5463                 break;
5464             case SCROLL_CLASS:
5465                 dindx = 3;
5466                 dmg = 1;
5467                 break;
5468             case SPBOOK_CLASS:
5469                 dindx = 4;
5470                 dmg = 1;
5471                 break;
5472             case FOOD_CLASS:
5473                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5474                     dindx = 1; /* boil and explode */
5475                     dmg = (obj->owt + 19) / 20;
5476                 } else {
5477                     skip++;
5478                 }
5479                 break;
5480             default:
5481                 skip++;
5482                 break;
5483             }
5484             break;
5485         case AD_ELEC:
5486             xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5487             quan = obj->quan;
5488             switch (osym) {
5489             case RING_CLASS:
5490                 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5491                     skip++;
5492                     break;
5493                 }
5494                 dindx = 5;
5495                 dmg = 0;
5496                 break;
5497             case WAND_CLASS:
5498                 if (obj->otyp == WAN_LIGHTNING) {
5499                     skip++;
5500                     break;
5501                 }
5502 #if 0
5503                 if (obj == current_wand) {  skip++;  break;  }
5504 #endif
5505                 dindx = 6;
5506                 dmg = rnd(10);
5507                 break;
5508             default:
5509                 skip++;
5510                 break;
5511             }
5512             break;
5513         default:
5514             skip++;
5515             break;
5516         }
5517         if (!skip) {
5518             if (obj->in_use)
5519                 --quan; /* one will be used up elsewhere */
5520             for (i = cnt = 0L; i < quan; i++)
5521                 if (!rn2(3))
5522                     cnt++;
5523
5524             if (!cnt)
5525                 continue;
5526 #if 0 /*JP*/
5527             mult = (cnt == 1L)
5528                    ? (quan == 1L) ? "Your"                        /* 1 of 1 */
5529                                   : "One of your"                 /* 1 of N */
5530                    : (cnt < quan) ? "Some of your"                /* n of N */
5531                                   : (quan == 2L) ? "Both of your" /* 2 of 2 */
5532                                                  : "All of your"; /* N of N */
5533 #else
5534             mult = (cnt == quan)
5535                    ? ""
5536                    : (cnt == 1L) ? "\82Ì\82Ð\82Æ\82Â" : "\82Ì\82¢\82­\82Â\82©";
5537 #endif
5538 #if 0 /*JP*/
5539             pline("%s %s %s!", mult, xname(obj),
5540                   destroy_strings[dindx][(cnt > 1L)]);
5541 #else
5542             pline("\82 \82È\82½\82Ì%s%s\82Í%s\81I", xname(obj), mult, 
5543                   destroy_strings[dindx][(cnt > 1L)]);
5544 #endif
5545             if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5546                 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5547                     potionbreathe(obj);
5548             }
5549             if (obj->owornmask) {
5550                 if (obj->owornmask & W_RING) /* ring being worn */
5551                     Ring_gone(obj);
5552                 else
5553                     setnotworn(obj);
5554             }
5555             if (obj == current_wand)
5556                 current_wand = 0; /* destroyed */
5557             for (i = 0; i < cnt; i++)
5558                 useup(obj);
5559             if (dmg) {
5560                 if (xresist)
5561 /*JP
5562                     You("aren't hurt!");
5563 */
5564                     You("\8f\9d\82Â\82©\82È\82¢\81I");
5565                 else {
5566                     const char *how = destroy_strings[dindx][2];
5567                     boolean one = (cnt == 1L);
5568
5569                     if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
5570 /*JP
5571                         how = "exploding glob of slime";
5572 */
5573                         how = "\83X\83\89\83C\83\80\82Ì\82Ë\82Î\82Ë\82Î\82Ì\94\9a\94­\82Å";
5574                     if (physical_damage)
5575                         dmg = Maybe_Half_Phys(dmg);
5576                     losehp(dmg, one ? how : (const char *) makeplural(how),
5577                            one ? KILLED_BY_AN : KILLED_BY);
5578                     exercise(A_STR, FALSE);
5579                 }
5580             }
5581         }
5582     }
5583     return;
5584 }
5585
5586 int
5587 destroy_mitem(mtmp, osym, dmgtyp)
5588 struct monst *mtmp;
5589 int osym, dmgtyp;
5590 {
5591     struct obj *obj, *obj2;
5592     int skip, tmp = 0;
5593     long i, cnt, quan;
5594     int dindx;
5595     boolean vis;
5596
5597     if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5598         destroy_item(osym, dmgtyp);
5599         return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5600     }
5601
5602     vis = canseemon(mtmp);
5603     for (obj = mtmp->minvent; obj; obj = obj2) {
5604         obj2 = obj->nobj;
5605         if (obj->oclass != osym)
5606             continue; /* test only objs of type osym */
5607         skip = 0;
5608         quan = 0L;
5609         dindx = 0;
5610
5611         switch (dmgtyp) {
5612         case AD_COLD:
5613             if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5614                 quan = obj->quan;
5615                 dindx = 0;
5616                 tmp++;
5617             } else
5618                 skip++;
5619             break;
5620         case AD_FIRE:
5621             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5622                 skip++;
5623             if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5624                 skip++;
5625                 if (vis)
5626 #if 0 /*JP*/
5627                     pline("%s glows a strange %s, but remains intact.",
5628                           The(distant_name(obj, xname)), hcolor("dark red"));
5629 #else
5630                     pline("%s\82Í\8aï\96­\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
5631                           The(distant_name(obj, xname)), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
5632 #endif
5633             }
5634             quan = obj->quan;
5635             switch (osym) {
5636             case POTION_CLASS:
5637                 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5638                 tmp++;
5639                 break;
5640             case SCROLL_CLASS:
5641                 dindx = 3;
5642                 tmp++;
5643                 break;
5644             case SPBOOK_CLASS:
5645                 dindx = 4;
5646                 tmp++;
5647                 break;
5648             case FOOD_CLASS:
5649                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5650                     dindx = 1; /* boil and explode */
5651                     tmp += (obj->owt + 19) / 20;
5652                 } else {
5653                     skip++;
5654                 }
5655                 break;
5656             default:
5657                 skip++;
5658                 break;
5659             }
5660             break;
5661         case AD_ELEC:
5662             quan = obj->quan;
5663             switch (osym) {
5664             case RING_CLASS:
5665                 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5666                     skip++;
5667                     break;
5668                 }
5669                 dindx = 5;
5670                 break;
5671             case WAND_CLASS:
5672                 if (obj->otyp == WAN_LIGHTNING) {
5673                     skip++;
5674                     break;
5675                 }
5676                 dindx = 6;
5677                 tmp++;
5678                 break;
5679             default:
5680                 skip++;
5681                 break;
5682             }
5683             break;
5684         default:
5685             skip++;
5686             break;
5687         }
5688         if (!skip) {
5689             for (i = cnt = 0L; i < quan; i++)
5690                 if (!rn2(3))
5691                     cnt++;
5692
5693             if (!cnt)
5694                 continue;
5695             if (vis)
5696 #if 0 /*JP*/
5697                 pline("%s%s %s!",
5698                       (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5699                                                            : "One of ",
5700                       (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5701                       destroy_strings[dindx][(cnt > 1L)]);
5702 #else
5703                 pline("%s%s\82Í%s\81I",
5704                       (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5705                       (cnt == obj->quan) ? "" : (cnt > 1L) ? "\82Ì\82¢\82­\82Â\82©"
5706                                                            : "\82Ì\82Ð\82Æ\82Â",
5707                       destroy_strings[dindx][(cnt > 1L)]);
5708 #endif
5709             for (i = 0; i < cnt; i++)
5710                 m_useup(mtmp, obj);
5711         }
5712     }
5713     return tmp;
5714 }
5715
5716 int
5717 resist(mtmp, oclass, damage, tell)
5718 struct monst *mtmp;
5719 char oclass;
5720 int damage, tell;
5721 {
5722     int resisted;
5723     int alev, dlev;
5724
5725     /* attack level */
5726     switch (oclass) {
5727     case WAND_CLASS:
5728         alev = 12;
5729         break;
5730     case TOOL_CLASS:
5731         alev = 10;
5732         break; /* instrument */
5733     case WEAPON_CLASS:
5734         alev = 10;
5735         break; /* artifact */
5736     case SCROLL_CLASS:
5737         alev = 9;
5738         break;
5739     case POTION_CLASS:
5740         alev = 6;
5741         break;
5742     case RING_CLASS:
5743         alev = 5;
5744         break;
5745     default:
5746         alev = u.ulevel;
5747         break; /* spell */
5748     }
5749     /* defense level */
5750     dlev = (int) mtmp->m_lev;
5751     if (dlev > 50)
5752         dlev = 50;
5753     else if (dlev < 1)
5754         dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5755
5756     resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5757     if (resisted) {
5758         if (tell) {
5759             shieldeff(mtmp->mx, mtmp->my);
5760 /*JP
5761             pline("%s resists!", Monnam(mtmp));
5762 */
5763             pline("%s\82Í\96h\82¢\82¾\81I", Monnam(mtmp));
5764         }
5765         damage = (damage + 1) / 2;
5766     }
5767
5768     if (damage) {
5769         mtmp->mhp -= damage;
5770         if (mtmp->mhp < 1) {
5771             if (m_using)
5772                 monkilled(mtmp, "", AD_RBRE);
5773             else
5774                 killed(mtmp);
5775         }
5776     }
5777     return resisted;
5778 }
5779
5780 #define MAXWISHTRY 5
5781
5782 STATIC_OVL void
5783 wishcmdassist(triesleft)
5784 int triesleft;
5785 {
5786     static NEARDATA const char *
5787         wishinfo[] = {
5788   "Wish details:",
5789   "",
5790   "Enter the name of an object, such as \"potion of monster detection\",",
5791   "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5792   "(without the quotes).",
5793   "",
5794   "For object types which come in stacks, you may specify a plural name",
5795   "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5796   "pieces\", although that aspect of your wish might not be granted.",
5797   "",
5798   "You may also specify various prefix values which might be used to",
5799   "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5800   "Most modifiers shown when viewing your inventory can be specified.",
5801   "",
5802   "You may specify 'nothing' to explicitly decline this wish.",
5803   0,
5804     },
5805         preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5806         retry_info[] =
5807                     "If you specify an unrecognized object name %s%s time%s,",
5808         retry_too[] = "a randomly chosen item will be granted.",
5809         suppress_cmdassist[] =
5810             "(Suppress this assistance with !cmdassist in your config file.)",
5811         *cardinals[] = { "zero",  "one",  "two", "three", "four", "five" },
5812         too_many[] = "too many";
5813     int i;
5814     winid win;
5815     char buf[BUFSZ];
5816
5817     win = create_nhwindow(NHW_TEXT);
5818     if (!win)
5819         return;
5820     for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5821         putstr(win, 0, wishinfo[i]);
5822     if (!u.uconduct.wishes)
5823         putstr(win, 0, preserve_wishless);
5824     putstr(win, 0, "");
5825     Sprintf(buf, retry_info,
5826             (triesleft >= 0 && triesleft < SIZE(cardinals))
5827                ? cardinals[triesleft]
5828                : too_many,
5829             (triesleft < MAXWISHTRY) ? " more" : "",
5830             plur(triesleft));
5831     putstr(win, 0, buf);
5832     putstr(win, 0, retry_too);
5833     putstr(win, 0, "");
5834     if (iflags.cmdassist)
5835         putstr(win, 0, suppress_cmdassist);
5836     display_nhwindow(win, FALSE);
5837     destroy_nhwindow(win);
5838 }
5839
5840 void
5841 makewish()
5842 {
5843     static char buf[BUFSZ] = DUMMY;
5844     char promptbuf[BUFSZ];
5845     struct obj *otmp, nothing;
5846     int tries = 0;
5847
5848     promptbuf[0] = '\0';
5849     nothing = zeroobj; /* lint suppression; only its address matters */
5850     if (flags.verbose)
5851 /*JP
5852         You("may wish for an object.");
5853 */
5854         You("\96]\82Ý\82Ì\82à\82Ì\82ð\8eè\82É\93ü\82ê\82ç\82ê\82é\81D");
5855 retry:
5856 /*JP
5857     Strcpy(promptbuf, "For what do you wish");
5858 */
5859     Strcpy(promptbuf, "(\93ú\96{\8cê\82Å)\89½\82ð\82¨\96]\82Ý");
5860     if (iflags.cmdassist && tries > 0)
5861 /*JP
5862         Strcat(promptbuf, " (enter 'help' for assistance)");
5863 */
5864         Strcat(promptbuf, " (\8f\95\82¯\82ª\95K\97v\82È\82ç 'help' \82Æ\93ü\97Í)");
5865 /*JP
5866     Strcat(promptbuf, "?");
5867 */
5868     Strcat(promptbuf, "\81H");
5869     getlin(promptbuf, buf);
5870     (void) mungspaces(buf);
5871     if (buf[0] == '\033') {
5872         buf[0] = '\0';
5873     } else if (!strcmpi(buf, "help")) {
5874         wishcmdassist(MAXWISHTRY - tries);
5875         goto retry;
5876     }
5877     /*
5878      *  Note: if they wished for and got a non-object successfully,
5879      *  otmp == &zeroobj.  That includes gold, or an artifact that
5880      *  has been denied.  Wishing for "nothing" requires a separate
5881      *  value to remain distinct.
5882      */
5883     otmp = readobjnam(buf, &nothing);
5884     if (!otmp) {
5885 /*JP
5886         pline("Nothing fitting that description exists in the game.");
5887 */
5888         pline("\82¤\81[\82ñ\81D\82»\82ñ\82È\82à\82Ì\82Í\91\8dÝ\82µ\82È\82¢\82æ\82¤\82¾\81D");
5889         if (++tries < MAXWISHTRY)
5890             goto retry;
5891         pline1(thats_enough_tries);
5892         otmp = readobjnam((char *) 0, (struct obj *) 0);
5893         if (!otmp)
5894             return; /* for safety; should never happen */
5895     } else if (otmp == &nothing) {
5896         /* explicitly wished for "nothing", presumably attempting
5897            to retain wishless conduct */
5898         return;
5899     }
5900
5901     /* KMH, conduct */
5902     u.uconduct.wishes++;
5903
5904     if (otmp != &zeroobj) {
5905         const char
5906 /*JP
5907             *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5908 */
5909             *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "\8a\8a\82è\97\8e\82¿\82½" : "\97\8e\82¿\82½"),
5910 #if 0 /*JP*/
5911             *oops_msg = (u.uswallow
5912                          ? "Oops!  %s out of your reach!"
5913                          : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5914                             || levl[u.ux][u.uy].typ < IRONBARS
5915                             || levl[u.ux][u.uy].typ >= ICE)
5916                             ? "Oops!  %s away from you!"
5917                             : "Oops!  %s to the floor!");
5918
5919         /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5920         (void) hold_another_object(otmp, oops_msg,
5921                                    The(aobjnam(otmp, verb)),
5922                                    (const char *) 0);
5923 #else
5924             *oops_msg = (u.uswallow
5925                          ? "\82¨\82Á\82Æ\81C%%s\82ª\93Í\82©\82È\82¢\82Æ\82±\82ë\82É%s\81I"
5926                          : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5927                             || levl[u.ux][u.uy].typ < IRONBARS
5928                             || levl[u.ux][u.uy].typ >= ICE)
5929                             ? "\82¨\82Á\82Æ\81C%%s\82ª\8eè\82©\82ç%s\81I"
5930                             : "\82¨\82Á\82Æ\81C%%s\82ª\8f°\82É%s\81I");
5931         char oopsbuf[BUFSZ];
5932         Sprintf(oopsbuf, oops_msg, verb);
5933
5934         (void) hold_another_object(otmp, oopsbuf,
5935                                    xname(otmp),
5936                                    (const char *) 0);
5937 #endif
5938         u.ublesscnt += rn1(100, 50); /* the gods take notice */
5939     }
5940 }
5941
5942 /*zap.c*/