OSDN Git Service

update year to 2018
[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-2018            */
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             Strcat(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 (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2877             ordinary = FALSE; /* say blasted rather than zapped */
2878         how = (obj->oclass != SPBOOK_CLASS)
2879                   ? (const char *) ansimpleoname(obj)
2880 /*JP
2881                   : "spell of light";
2882 */
2883                   : "\8cõ\82Ì\96\82\96@";
2884 #if 0 /*JP*/
2885         Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2886                 uhim(), how);
2887 #else
2888         Sprintf(buf, "\8e©\95ª\82Å%s\82ð\97\81\82Ñ\82Ä", how);
2889 #endif
2890         /* might rehumanize(); could be fatal, but only for Unchanging */
2891 #if 0 /*JP*/
2892         losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2893 #else
2894         losehp(Maybe_Half_Phys(dmg), buf, KILLED_BY);
2895 #endif
2896     }
2897     return dmg;
2898 }
2899
2900 /* light[ning] causes blindness */
2901 boolean
2902 flashburn(duration)
2903 long duration;
2904 {
2905     if (!resists_blnd(&youmonst)) {
2906         You(are_blinded_by_the_flash);
2907         make_blinded(duration, FALSE);
2908         if (!Blind)
2909             Your1(vision_clears);
2910         return TRUE;
2911     }
2912     return FALSE;
2913 }
2914
2915 /* you've zapped a wand downwards while riding
2916  * Return TRUE if the steed was hit by the wand.
2917  * Return FALSE if the steed was not hit by the wand.
2918  */
2919 STATIC_OVL boolean
2920 zap_steed(obj)
2921 struct obj *obj; /* wand or spell */
2922 {
2923     int steedhit = FALSE;
2924
2925     bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
2926     notonhead = FALSE;
2927     switch (obj->otyp) {
2928     /*
2929      * Wands that are allowed to hit the steed
2930      * Carefully test the results of any that are
2931      * moved here from the bottom section.
2932      */
2933     case WAN_PROBING:
2934         probe_monster(u.usteed);
2935         learnwand(obj);
2936         steedhit = TRUE;
2937         break;
2938     case WAN_TELEPORTATION:
2939     case SPE_TELEPORT_AWAY:
2940         /* you go together */
2941         tele();
2942         /* same criteria as when unmounted (zapyourself) */
2943         if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2944             || distu(u.ux0, u.uy0) >= 16)
2945             learnwand(obj);
2946         steedhit = TRUE;
2947         break;
2948
2949     /* Default processing via bhitm() for these */
2950     case SPE_CURE_SICKNESS:
2951     case WAN_MAKE_INVISIBLE:
2952     case WAN_CANCELLATION:
2953     case SPE_CANCELLATION:
2954     case WAN_POLYMORPH:
2955     case SPE_POLYMORPH:
2956     case WAN_STRIKING:
2957     case SPE_FORCE_BOLT:
2958     case WAN_SLOW_MONSTER:
2959     case SPE_SLOW_MONSTER:
2960     case WAN_SPEED_MONSTER:
2961     case SPE_HEALING:
2962     case SPE_EXTRA_HEALING:
2963     case SPE_DRAIN_LIFE:
2964     case WAN_OPENING:
2965     case SPE_KNOCK:
2966         (void) bhitm(u.usteed, obj);
2967         steedhit = TRUE;
2968         break;
2969
2970     default:
2971         steedhit = FALSE;
2972         break;
2973     }
2974     return steedhit;
2975 }
2976
2977 /*
2978  * cancel a monster (possibly the hero).  inventory is cancelled only
2979  * if the monster is zapping itself directly, since otherwise the
2980  * effect is too strong.  currently non-hero monsters do not zap
2981  * themselves with cancellation.
2982  */
2983 boolean
2984 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2985 register struct monst *mdef;
2986 register struct obj *obj;
2987 boolean youattack, allow_cancel_kill, self_cancel;
2988 {
2989     boolean youdefend = (mdef == &youmonst);
2990     static const char writing_vanishes[] =
2991 /*JP
2992         "Some writing vanishes from %s head!";
2993 */
2994         "\89½\82©\82Ì\95\8e\9a\82ª%s\82Ì\93ª\82©\82ç\8fÁ\82¦\82½\81I";
2995 #if 0 /*JP:T*/
2996     static const char your[] = "your"; /* should be extern */
2997 #else
2998     static const char your[] = "\82 \82È\82½"; /* should be extern */
2999 #endif
3000
3001     if (youdefend ? (!youattack && Antimagic)
3002                   : resist(mdef, obj->oclass, 0, NOTELL))
3003         return FALSE; /* resisted cancellation */
3004
3005     if (self_cancel) { /* 1st cancel inventory */
3006         struct obj *otmp;
3007
3008         for (otmp = (youdefend ? invent : mdef->minvent); otmp;
3009              otmp = otmp->nobj)
3010             cancel_item(otmp);
3011         if (youdefend) {
3012             context.botl = 1; /* potential AC change */
3013             find_ac();
3014         }
3015     }
3016
3017     /* now handle special cases */
3018     if (youdefend) {
3019         if (Upolyd) {
3020             if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
3021                 pline(writing_vanishes, your);
3022
3023             if (Unchanging)
3024 /*JP
3025                 Your("amulet grows hot for a moment, then cools.");
3026 */
3027                 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");
3028             else
3029                 rehumanize();
3030         }
3031     } else {
3032         mdef->mcan = TRUE;
3033
3034         if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
3035             were_change(mdef);
3036
3037         if (mdef->data == &mons[PM_CLAY_GOLEM]) {
3038             if (canseemon(mdef))
3039 #if 0 /*JP*/
3040                 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
3041 #else
3042                 pline(writing_vanishes, mon_nam(mdef));
3043 #endif
3044
3045             if (allow_cancel_kill) {
3046                 if (youattack)
3047                     killed(mdef);
3048                 else
3049                     monkilled(mdef, "", AD_SPEL);
3050             }
3051         }
3052     }
3053     return TRUE;
3054 }
3055
3056 /* you've zapped an immediate type wand up or down */
3057 STATIC_OVL boolean
3058 zap_updown(obj)
3059 struct obj *obj; /* wand or spell */
3060 {
3061     boolean striking = FALSE, disclose = FALSE;
3062     int x, y, xx, yy, ptmp;
3063     struct obj *otmp;
3064     struct engr *e;
3065     struct trap *ttmp;
3066     char buf[BUFSZ];
3067
3068     /* some wands have special effects other than normal bhitpile */
3069     /* drawbridge might change <u.ux,u.uy> */
3070     x = xx = u.ux;     /* <x,y> is zap location */
3071     y = yy = u.uy;     /* <xx,yy> is drawbridge (portcullis) position */
3072     ttmp = t_at(x, y); /* trap if there is one */
3073
3074     switch (obj->otyp) {
3075     case WAN_PROBING:
3076         ptmp = 0;
3077         if (u.dz < 0) {
3078 /*JP
3079             You("probe towards the %s.", ceiling(x, y));
3080 */
3081             You("\8fã\95û\82Ì%s\82ð\92²\82×\82½\81D", ceiling(x,y));
3082         } else {
3083             ptmp += bhitpile(obj, bhito, x, y, u.dz);
3084 /*JP
3085             You("probe beneath the %s.", surface(x, y));
3086 */
3087             You("\89º\95û\82Ì%s\82ð\92²\82×\82½\81D", surface(x,y));
3088             ptmp += display_binventory(x, y, TRUE);
3089         }
3090         if (!ptmp)
3091 /*JP
3092             Your("probe reveals nothing.");
3093 */
3094             pline("\92²\8d¸\82Ì\8c\8b\89Ê\89½\82à\82Å\82Ä\82±\82È\82©\82Á\82½\81D");
3095         return TRUE; /* we've done our own bhitpile */
3096     case WAN_OPENING:
3097     case SPE_KNOCK:
3098         /* up or down, but at closed portcullis only */
3099         if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
3100             open_drawbridge(xx, yy);
3101             disclose = TRUE;
3102         } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
3103                    /* can't use the stairs down to quest level 2 until
3104                       leader "unlocks" them; give feedback if you try */
3105                    && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
3106 /*JP
3107             pline_The("stairs seem to ripple momentarily.");
3108 */
3109             pline("\8aK\92i\82ª\88ê\8fu\97h\82ê\82½\82æ\82¤\82É\8c©\82¦\82½\81D");
3110             disclose = TRUE;
3111         }
3112         /* down will release you from bear trap or web */
3113         if (u.dz > 0 && u.utrap) {
3114             (void) openholdingtrap(&youmonst, &disclose);
3115             /* down will trigger trapdoor, hole, or [spiked-] pit */
3116         } else if (u.dz > 0 && !u.utrap) {
3117             (void) openfallingtrap(&youmonst, FALSE, &disclose);
3118         }
3119         break;
3120     case WAN_STRIKING:
3121     case SPE_FORCE_BOLT:
3122         striking = TRUE;
3123         /*FALLTHRU*/
3124     case WAN_LOCKING:
3125     case SPE_WIZARD_LOCK:
3126         /* down at open bridge or up or down at open portcullis */
3127         if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
3128                  ? (u.dz > 0)
3129                  : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
3130             && find_drawbridge(&xx, &yy)) {
3131             if (!striking)
3132                 close_drawbridge(xx, yy);
3133             else
3134                 destroy_drawbridge(xx, yy);
3135             disclose = TRUE;
3136         } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
3137                    && !Is_waterlevel(&u.uz) && !Underwater
3138                    && !Is_qstart(&u.uz)) {
3139             int dmg;
3140             /* similar to zap_dig() */
3141 #if 0 /*JP*/
3142             pline("A rock is dislodged from the %s and falls on your %s.",
3143                   ceiling(x, y), body_part(HEAD));
3144 #else
3145             pline("%s\82©\82ç\8aâ\82ª\97\8e\82¿\82Ä\82 \82È\82½\82Ì%s\82É\96½\92\86\82µ\82½\81D",
3146                   ceiling(x, y), body_part(HEAD));
3147 #endif
3148             dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
3149 /*JP
3150             losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
3151 */
3152             losehp(Maybe_Half_Phys(dmg), "\97\8e\8aâ\82Å", KILLED_BY_AN);
3153             if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
3154                 (void) xname(otmp); /* set dknown, maybe bknown */
3155                 stackobj(otmp);
3156             }
3157             newsym(x, y);
3158         } else if (u.dz > 0 && ttmp) {
3159             if (!striking && closeholdingtrap(&youmonst, &disclose)) {
3160                 ; /* now stuck in web or bear trap */
3161             } else if (striking && ttmp->ttyp == TRAPDOOR) {
3162                 /* striking transforms trapdoor into hole */
3163                 if (Blind && !ttmp->tseen) {
3164 /*JP
3165                     pline("%s beneath you shatters.", Something);
3166 */
3167                     pline("\82 \82È\82½\82Ì\89º\82É\82 \82é\89½\82©\82ª\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
3168                 } else if (!ttmp->tseen) { /* => !Blind */
3169 /*JP
3170                     pline("There's a trapdoor beneath you; it shatters.");
3171 */
3172                     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");
3173                 } else {
3174 /*JP
3175                     pline("The trapdoor beneath you shatters.");
3176 */
3177                     pline("\82 \82È\82½\82Ì\89º\82É\82 \82é\97\8e\82µ\94à\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
3178                     disclose = TRUE;
3179                 }
3180                 ttmp->ttyp = HOLE;
3181                 ttmp->tseen = 1;
3182                 newsym(x, y);
3183                 /* might fall down hole */
3184                 dotrap(ttmp, 0);
3185             } else if (!striking && ttmp->ttyp == HOLE) {
3186                 /* locking transforms hole into trapdoor */
3187                 ttmp->ttyp = TRAPDOOR;
3188                 if (Blind || !ttmp->tseen) {
3189 #if 0 /*JP*/
3190                     pline("Some %s swirls beneath you.",
3191                           is_ice(x, y) ? "frost" : "dust");
3192 #else
3193                     pline("\82 \82È\82½\82Ì\89º\82Å%s\82ª\82¤\82¸\82ð\8aª\82­\82Ì\82ª\8c©\82¦\82½\81D",
3194                           is_ice(x,y) ? "\91\9a" : "\82Ù\82±\82è");
3195 #endif
3196                 } else {
3197                     ttmp->tseen = 1;
3198                     newsym(x, y);
3199 /*JP
3200                     pline("A trapdoor appears beneath you.");
3201 */
3202                     pline("\82 \82È\82½\82Ì\89º\82É\97\8e\82µ\94à\82ª\82 \82ç\82í\82ê\82½\81D");
3203                     disclose = TRUE;
3204                 }
3205                 /* hadn't fallen down hole; won't fall now */
3206             }
3207         }
3208         break;
3209     case SPE_STONE_TO_FLESH:
3210         if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3211             || (Is_qstart(&u.uz) && u.dz < 0)) {
3212             pline1(nothing_happens);
3213         } else if (u.dz < 0) { /* we should do more... */
3214 /*JP
3215             pline("Blood drips on your %s.", body_part(FACE));
3216 */
3217             pline("\8c\8c\82ª\82 \82È\82½\82Ì%s\82Ö\82µ\82½\82½\82è\97\8e\82¿\82Ä\82«\82½\81D", body_part(FACE));
3218         } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3219             /*
3220             Print this message only if there wasn't an engraving
3221             affected here.  If water or ice, act like waterlevel case.
3222             */
3223             e = engr_at(u.ux, u.uy);
3224             if (!(e && e->engr_type == ENGRAVE)) {
3225                 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3226                     pline1(nothing_happens);
3227                 else
3228 #if 0 /*JP:T*/
3229                     pline("Blood %ss %s your %s.",
3230                           is_lava(u.ux, u.uy) ? "boil" : "pool",
3231                           Levitation ? "beneath" : "at",
3232                           makeplural(body_part(FOOT)));
3233 #else
3234                     pline("%s%s%s\81D",
3235                           makeplural(body_part(FOOT)),
3236                           Levitation ? "\82Ì\89º" : "\8c³",
3237                           is_lava(u.ux, u.uy) ?
3238                           "\82Å\8c\8c\82ª\95¦\93«\82µ\82½" : "\82É\8c\8c\82¾\82Ü\82è\82ª\8fo\97\88\82½");
3239 #endif
3240             }
3241         }
3242         break;
3243     default:
3244         break;
3245     }
3246
3247     if (u.dz > 0) {
3248         /* zapping downward */
3249         (void) bhitpile(obj, bhito, x, y, u.dz);
3250
3251         /* subset of engraving effects; none sets `disclose' */
3252         if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3253             switch (obj->otyp) {
3254             case WAN_POLYMORPH:
3255             case SPE_POLYMORPH:
3256                 del_engr(e);
3257                 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3258                 break;
3259             case WAN_CANCELLATION:
3260             case SPE_CANCELLATION:
3261             case WAN_MAKE_INVISIBLE:
3262                 del_engr(e);
3263                 break;
3264             case WAN_TELEPORTATION:
3265             case SPE_TELEPORT_AWAY:
3266                 rloc_engr(e);
3267                 break;
3268             case SPE_STONE_TO_FLESH:
3269                 if (e->engr_type == ENGRAVE) {
3270                     /* only affects things in stone */
3271 #if 0 /*JP*/
3272                     pline_The(Hallucination
3273                                   ? "floor runs like butter!"
3274                                   : "edges on the floor get smoother.");
3275 #else
3276                     pline(Hallucination
3277                                   ? "\8f°\82ª\83o\83^\81[\82Ì\82æ\82¤\82É\91\96\82Á\82Ä\82¢\82Á\82½\81I"
3278                                   : "\8f°\82Ì\89\8f\82ª\82È\82ß\82ç\82©\82É\82È\82Á\82½\81D");
3279 #endif
3280                     wipe_engr_at(x, y, d(2, 4), TRUE);
3281                 }
3282                 break;
3283             case WAN_STRIKING:
3284             case SPE_FORCE_BOLT:
3285                 wipe_engr_at(x, y, d(2, 4), TRUE);
3286                 break;
3287             default:
3288                 break;
3289             }
3290         }
3291     } else if (u.dz < 0) {
3292         /* zapping upward */
3293
3294         /* game flavor: if you're hiding under "something"
3295          * a zap upward should hit that "something".
3296          */
3297         if (u.uundetected && hides_under(youmonst.data)) {
3298             int hitit = 0;
3299             otmp = level.objects[u.ux][u.uy];
3300
3301             if (otmp)
3302                 hitit = bhito(otmp, obj);
3303             if (hitit) {
3304                 (void) hideunder(&youmonst);
3305                 disclose = TRUE;
3306             }
3307         }
3308     }
3309
3310     return disclose;
3311 }
3312
3313 /* used by do_break_wand() was well as by weffects() */
3314 void
3315 zapsetup()
3316 {
3317     obj_zapped = FALSE;
3318 }
3319
3320 void
3321 zapwrapup()
3322 {
3323     /* if do_osshock() set obj_zapped while polying, give a message now */
3324     if (obj_zapped)
3325 /*JP
3326         You_feel("shuddering vibrations.");
3327 */
3328         You("\82¼\82Á\82Æ\82·\82é\90U\93®\82ð\8a´\82\82½\81D"); 
3329     obj_zapped = FALSE;
3330 }
3331
3332 /* called for various wand and spell effects - M. Stephenson */
3333 void
3334 weffects(obj)
3335 struct obj *obj;
3336 {
3337     int otyp = obj->otyp;
3338     boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3339
3340     exercise(A_WIS, TRUE);
3341     if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3342         && (u.dz > 0) && zap_steed(obj)) {
3343         disclose = TRUE;
3344     } else if (objects[otyp].oc_dir == IMMEDIATE) {
3345         zapsetup(); /* reset obj_zapped */
3346         if (u.uswallow) {
3347             (void) bhitm(u.ustuck, obj);
3348             /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3349         } else if (u.dz) {
3350             disclose = zap_updown(obj);
3351         } else {
3352             (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3353                         &obj);
3354         }
3355         zapwrapup(); /* give feedback for obj_zapped */
3356
3357     } else if (objects[otyp].oc_dir == NODIR) {
3358         zapnodir(obj);
3359
3360     } else {
3361         /* neither immediate nor directionless */
3362
3363         if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3364             zap_dig();
3365         else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3366             buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3367                  u.dx, u.dy);
3368         else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3369             buzz(otyp - WAN_MAGIC_MISSILE,
3370                  (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3371         else
3372             impossible("weffects: unexpected spell or wand");
3373         disclose = TRUE;
3374     }
3375     if (disclose) {
3376         learnwand(obj);
3377         if (was_unkn)
3378             more_experienced(0, 10);
3379     }
3380     return;
3381 }
3382
3383 /* augment damage for a spell dased on the hero's intelligence (and level) */
3384 int
3385 spell_damage_bonus(dmg)
3386 int dmg; /* base amount to be adjusted by bonus or penalty */
3387 {
3388     int intell = ACURR(A_INT);
3389
3390     /* Punish low intelligence before low level else low intelligence
3391        gets punished only when high level */
3392     if (intell <= 9) {
3393         /* -3 penalty, but never reduce combined amount below 1
3394            (if dmg is 0 for some reason, we're careful to leave it there) */
3395         if (dmg > 1)
3396             dmg = (dmg <= 3) ? 1 : dmg - 3;
3397     } else if (intell <= 13 || u.ulevel < 5)
3398         ; /* no bonus or penalty; dmg remains same */
3399     else if (intell <= 18)
3400         dmg += 1;
3401     else if (intell <= 24 || u.ulevel < 14)
3402         dmg += 2;
3403     else
3404         dmg += 3; /* Int 25 */
3405
3406     return dmg;
3407 }
3408
3409 /*
3410  * Generate the to hit bonus for a spell.  Based on the hero's skill in
3411  * spell class and dexterity.
3412  */
3413 STATIC_OVL int
3414 spell_hit_bonus(skill)
3415 int skill;
3416 {
3417     int hit_bon = 0;
3418     int dex = ACURR(A_DEX);
3419
3420     switch (P_SKILL(spell_skilltype(skill))) {
3421     case P_ISRESTRICTED:
3422     case P_UNSKILLED:
3423         hit_bon = -4;
3424         break;
3425     case P_BASIC:
3426         hit_bon = 0;
3427         break;
3428     case P_SKILLED:
3429         hit_bon = 2;
3430         break;
3431     case P_EXPERT:
3432         hit_bon = 3;
3433         break;
3434     }
3435
3436     if (dex < 4)
3437         hit_bon -= 3;
3438     else if (dex < 6)
3439         hit_bon -= 2;
3440     else if (dex < 8)
3441         hit_bon -= 1;
3442     else if (dex < 14)
3443         /* Will change when print stuff below removed */
3444         hit_bon -= 0;
3445     else
3446         /* Even increment for dextrous heroes (see weapon.c abon) */
3447         hit_bon += dex - 14;
3448
3449     return hit_bon;
3450 }
3451
3452 const char *
3453 exclam(force)
3454 int force;
3455 {
3456     /* force == 0 occurs e.g. with sleep ray */
3457     /* note that large force is usual with wands so that !! would
3458             require information about hand/weapon/wand */
3459 /*JP
3460     return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3461 */
3462     return (const char *) ((force < 0) ? "\81H" : (force <= 4) ? "\81D" : "\81I");
3463 }
3464
3465 void
3466 hit(str, mtmp, force)
3467 const char *str;
3468 struct monst *mtmp;
3469 const char *force; /* usually either "." or "!" */
3470 {
3471     if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3472          && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3473 /*JP
3474         pline("%s %s it.", The(str), vtense(str, "hit"));
3475 */
3476         pline("%s\82Í\89½\82©\82É\96½\92\86\82µ\82½\81D", str);
3477     else
3478 #if 0 /*JP*/
3479         pline("%s %s %s%s", The(str), vtense(str, "hit"),
3480               mon_nam(mtmp), force);
3481 #else
3482         pline("%s\82Í%s\82É\96½\92\86\82µ\82½%s", str,
3483               mon_nam(mtmp), force);
3484 #endif
3485 }
3486
3487 void
3488 miss(str, mtmp)
3489 register const char *str;
3490 register struct monst *mtmp;
3491 {
3492 #if 0 /*JP*/
3493     pline(
3494         "%s %s %s.", The(str), vtense(str, "miss"),
3495         ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3496             ? mon_nam(mtmp)
3497             : "it");
3498 #else
3499     pline(
3500         "%s\82Ì%s\82Ö\82Ì\8dU\8c\82\82Í\82Í\82¸\82ê\82½\81D", str,
3501         ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3502             ? mon_nam(mtmp)
3503             : "\89½\8eÒ\82©");
3504 #endif
3505 }
3506
3507 STATIC_OVL void
3508 skiprange(range, skipstart, skipend)
3509 int range, *skipstart, *skipend;
3510 {
3511     int tr = (range / 4);
3512     int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3513
3514     *skipstart = tmp;
3515     *skipend = tmp - ((tmp / 4) * rnd(3));
3516     if (*skipend >= tmp)
3517         *skipend = tmp - 1;
3518 }
3519
3520 /*
3521  *  Called for the following distance effects:
3522  *      when a weapon is thrown (weapon == THROWN_WEAPON)
3523  *      when an object is kicked (KICKED_WEAPON)
3524  *      when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3525  *      when a light beam is flashed (FLASHED_LIGHT)
3526  *      when a mirror is applied (INVIS_BEAM)
3527  *  A thrown/kicked object falls down at end of its range or when a monster
3528  *  is hit.  The variable 'bhitpos' is set to the final position of the weapon
3529  *  thrown/zapped.  The ray of a wand may affect (by calling a provided
3530  *  function) several objects and monsters on its path.  The return value
3531  *  is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3532  *
3533  * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3534  * destroyed and *pobj set to NULL to indicate this.
3535  *
3536  *  Check !u.uswallow before calling bhit().
3537  *  This function reveals the absence of a remembered invisible monster in
3538  *  necessary cases (throwing or kicking weapons).  The presence of a real
3539  *  one is revealed for a weapon, but if not a weapon is left up to fhitm().
3540  */
3541 struct monst *
3542 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3543 register int ddx, ddy, range;          /* direction and range */
3544 int weapon;                            /* see values in hack.h */
3545 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3546     FDECL((*fhito), (OBJ_P, OBJ_P));
3547 struct obj **pobj; /* object tossed/used, set to NULL
3548                     * if object is destroyed */
3549 {
3550     struct monst *mtmp;
3551     struct obj *obj = *pobj;
3552     uchar typ;
3553     boolean shopdoor = FALSE, point_blank = TRUE;
3554     boolean in_skip = FALSE, allow_skip = FALSE;
3555     int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3556
3557     if (weapon == KICKED_WEAPON) {
3558         /* object starts one square in front of player */
3559         bhitpos.x = u.ux + ddx;
3560         bhitpos.y = u.uy + ddy;
3561         range--;
3562     } else {
3563         bhitpos.x = u.ux;
3564         bhitpos.y = u.uy;
3565     }
3566
3567     if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3568         skiprange(range, &skiprange_start, &skiprange_end);
3569         allow_skip = !rn2(3);
3570     }
3571
3572     if (weapon == FLASHED_LIGHT) {
3573         tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3574     } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3575         tmp_at(DISP_FLASH, obj_to_glyph(obj));
3576
3577     while (range-- > 0) {
3578         int x, y;
3579
3580         bhitpos.x += ddx;
3581         bhitpos.y += ddy;
3582         x = bhitpos.x;
3583         y = bhitpos.y;
3584
3585         if (!isok(x, y)) {
3586             bhitpos.x -= ddx;
3587             bhitpos.y -= ddy;
3588             break;
3589         }
3590
3591         if (is_pick(obj) && inside_shop(x, y)
3592             && (mtmp = shkcatch(obj, x, y)) != 0) {
3593             tmp_at(DISP_END, 0);
3594             return mtmp;
3595         }
3596
3597         typ = levl[bhitpos.x][bhitpos.y].typ;
3598
3599         /* iron bars will block anything big enough */
3600         if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3601             && typ == IRONBARS
3602             && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
3603                          point_blank ? 0 : !rn2(5), 1)) {
3604             /* caveat: obj might now be null... */
3605             obj = *pobj;
3606             bhitpos.x -= ddx;
3607             bhitpos.y -= ddy;
3608             break;
3609         }
3610
3611         if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3612             boolean learn_it = FALSE;
3613
3614             switch (obj->otyp) {
3615             case WAN_OPENING:
3616             case SPE_KNOCK:
3617                 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3618                     if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3619                         learn_it = TRUE;
3620                     open_drawbridge(x, y);
3621                 }
3622                 break;
3623             case WAN_LOCKING:
3624             case SPE_WIZARD_LOCK:
3625                 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3626                     && levl[x][y].typ == DRAWBRIDGE_DOWN)
3627                     learn_it = TRUE;
3628                 close_drawbridge(x, y);
3629                 break;
3630             case WAN_STRIKING:
3631             case SPE_FORCE_BOLT:
3632                 if (typ != DRAWBRIDGE_UP)
3633                     destroy_drawbridge(x, y);
3634                 learn_it = TRUE;
3635                 break;
3636             }
3637             if (learn_it)
3638                 learnwand(obj);
3639         }
3640
3641         mtmp = m_at(bhitpos.x, bhitpos.y);
3642
3643         /*
3644          * skipping rocks
3645          *
3646          * skiprange_start is only set if this is a thrown rock
3647          */
3648         if (skiprange_start && (range == skiprange_start) && allow_skip) {
3649             if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3650                 in_skip = TRUE;
3651                 if (!Blind)
3652 #if 0 /*JP*/
3653                     pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3654                           skipcount ? " again" : "");
3655 #else
3656                     pline("%s\82Í%s\92µ\82Ë\82½\81D", Yname2(obj),
3657                           skipcount ? "\8dÄ\82Ñ" : "");
3658 #endif
3659                 else
3660 /*JP
3661                     You_hear("%s skip.", yname(obj));
3662 */
3663                     You_hear("%s\82ª\92µ\82Ë\82é\89¹\82ð\95·\82¢\82½\81D", yname(obj));
3664                 skipcount++;
3665             } else if (skiprange_start > skiprange_end + 1) {
3666                 --skiprange_start;
3667             }
3668         }
3669         if (in_skip) {
3670             if (range <= skiprange_end) {
3671                 in_skip = FALSE;
3672                 if (range > 3) /* another bounce? */
3673                     skiprange(range, &skiprange_start, &skiprange_end);
3674             } else if (mtmp && M_IN_WATER(mtmp->data)) {
3675                 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3676 #if 0 /*JP*/
3677                     pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3678                           mon_nam(mtmp));
3679 #else
3680                     pline("%s\82Í%s\82ð\94ò\82Ñ\89z\82¦\82½\81D", Yname2(obj),
3681                           mon_nam(mtmp));
3682 #endif
3683             }
3684         }
3685
3686         if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3687             notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3688             if (weapon == FLASHED_LIGHT) {
3689                 /* FLASHED_LIGHT hitting invisible monster should
3690                    pass through instead of stop so we call
3691                    flash_hits_mon() directly rather than returning
3692                    mtmp back to caller.  That allows the flash to
3693                    keep on going.  Note that we use mtmp->minvis
3694                    not canspotmon() because it makes no difference
3695                    whether the hero can see the monster or not. */
3696                 if (mtmp->minvis) {
3697                     obj->ox = u.ux, obj->oy = u.uy;
3698                     (void) flash_hits_mon(mtmp, obj);
3699                 } else {
3700                     tmp_at(DISP_END, 0);
3701                     return mtmp; /* caller will call flash_hits_mon */
3702                 }
3703             } else if (weapon == INVIS_BEAM) {
3704                 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3705                    through invisible targets; unlike it, we aren't
3706                    prepared for multiple hits so just get first one
3707                    that's either visible or could see its invisible
3708                    self.  [No tmp_at() cleanup is needed here.] */
3709                 if (!mtmp->minvis || perceives(mtmp->data))
3710                     return mtmp;
3711             } else if (weapon != ZAPPED_WAND) {
3712                 /* THROWN_WEAPON, KICKED_WEAPON */
3713                 tmp_at(DISP_END, 0);
3714                 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3715                     map_invisible(bhitpos.x, bhitpos.y);
3716                 return mtmp;
3717             } else {
3718                 /* ZAPPED_WAND */
3719                 (*fhitm)(mtmp, obj);
3720                 range -= 3;
3721             }
3722         } else {
3723             if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3724                 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3725                 unmap_object(bhitpos.x, bhitpos.y);
3726                 newsym(x, y);
3727             }
3728         }
3729         if (fhito) {
3730             if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3731                 range--;
3732         } else {
3733             if (weapon == KICKED_WEAPON
3734                 && ((obj->oclass == COIN_CLASS
3735                      && OBJ_AT(bhitpos.x, bhitpos.y))
3736                     || ship_object(obj, bhitpos.x, bhitpos.y,
3737                                    costly_spot(bhitpos.x, bhitpos.y)))) {
3738                 tmp_at(DISP_END, 0);
3739                 return (struct monst *) 0;
3740             }
3741         }
3742         if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3743             switch (obj->otyp) {
3744             case WAN_OPENING:
3745             case WAN_LOCKING:
3746             case WAN_STRIKING:
3747             case SPE_KNOCK:
3748             case SPE_WIZARD_LOCK:
3749             case SPE_FORCE_BOLT:
3750                 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3751                     if (cansee(bhitpos.x, bhitpos.y)
3752                         || (obj->otyp == WAN_STRIKING && !Deaf))
3753                         learnwand(obj);
3754                     if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3755                         && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3756                         shopdoor = TRUE;
3757                         add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
3758                     }
3759                 }
3760                 break;
3761             }
3762         }
3763         if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3764             bhitpos.x -= ddx;
3765             bhitpos.y -= ddy;
3766             break;
3767         }
3768         if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3769             /* 'I' present but no monster: erase */
3770             /* do this before the tmp_at() */
3771             if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3772                 && cansee(x, y)) {
3773                 unmap_object(bhitpos.x, bhitpos.y);
3774                 newsym(x, y);
3775             }
3776             tmp_at(bhitpos.x, bhitpos.y);
3777             delay_output();
3778             /* kicked objects fall in pools */
3779             if ((weapon == KICKED_WEAPON)
3780                 && (is_pool(bhitpos.x, bhitpos.y)
3781                     || is_lava(bhitpos.x, bhitpos.y)))
3782                 break;
3783             if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3784                 break; /* physical objects fall onto sink */
3785         }
3786         /* limit range of ball so hero won't make an invalid move */
3787         if (weapon == THROWN_WEAPON && range > 0
3788             && obj->otyp == HEAVY_IRON_BALL) {
3789             struct obj *bobj;
3790             struct trap *t;
3791
3792             if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3793                 if (cansee(x, y))
3794 #if 0 /*JP*/
3795                     pline("%s hits %s.", The(distant_name(obj, xname)),
3796                           an(xname(bobj)));
3797 #else
3798                     pline("%s\82Í%s\82É\96½\92\86\82µ\82½\81D", distant_name(obj, xname),
3799                           xname(bobj));
3800 #endif
3801                 range = 0;
3802             } else if (obj == uball) {
3803                 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3804                     /* nb: it didn't hit anything directly */
3805                     if (cansee(x, y))
3806 #if 0 /*JP*/
3807                         pline("%s jerks to an abrupt halt.",
3808                               The(distant_name(obj, xname))); /* lame */
3809 #else
3810                         pline("%s\82Í\82Æ\82Â\82º\82ñ\83K\83N\83\93\82Æ\8e~\82Ü\82Á\82½\81D",
3811                               distant_name(obj, xname)); /* lame */
3812 #endif
3813                     range = 0;
3814                 } else if (Sokoban && (t = t_at(x, y)) != 0
3815                            && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3816                                || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3817                     /* hero falls into the trap, so ball stops */
3818                     range = 0;
3819                 }
3820             }
3821         }
3822
3823         /* thrown/kicked missile has moved away from its starting spot */
3824         point_blank = FALSE; /* affects passing through iron bars */
3825     }
3826
3827     if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3828         tmp_at(DISP_END, 0);
3829
3830     if (shopdoor)
3831 /*JP
3832         pay_for_damage("destroy", FALSE);
3833 */
3834         pay_for_damage("\94j\89ó\82·\82é", FALSE);
3835
3836     return (struct monst *) 0;
3837 }
3838
3839 /* process thrown boomerang, which travels a curving path...
3840  * A multi-shot volley ought to have all missiles in flight at once,
3841  * but we're called separately for each one.  We terminate the volley
3842  * early on a failed catch since continuing to throw after being hit
3843  * is too obviously silly.
3844  */
3845 struct monst *
3846 boomhit(obj, dx, dy)
3847 struct obj *obj;
3848 int dx, dy;
3849 {
3850     register int i, ct;
3851     int boom; /* showsym[] index  */
3852     struct monst *mtmp;
3853     boolean counterclockwise = TRUE; /* right-handed throw */
3854
3855     /* counterclockwise traversal patterns:
3856      *  ..........................54.................................
3857      *  ..................43.....6..3....765.........................
3858      *  ..........32.....5..2...7...2...8...4....87..................
3859      *  .........4..1....6..1...8..1....9...3...9..6.....98..........
3860      *  ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3861      *  .3...9....6..9....89.....................1..4...1..6....1..8.
3862      *  .4...8.....78.............................23....2..5...2...7.
3863      *  ..567............................................34....3..6..
3864      *  ........................................................45...
3865      * (invert rows for corresponding clockwise patterns)
3866      */
3867
3868     bhitpos.x = u.ux;
3869     bhitpos.y = u.uy;
3870     boom = counterclockwise ? S_boomleft : S_boomright;
3871     for (i = 0; i < 8; i++)
3872         if (xdir[i] == dx && ydir[i] == dy)
3873             break;
3874     tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3875     for (ct = 0; ct < 10; ct++) {
3876         i = (i + 8) % 8;                          /* 0..7 (8 -> 0, -1 -> 7) */
3877         boom = (S_boomleft + S_boomright - boom); /* toggle */
3878         tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3879         dx = xdir[i];
3880         dy = ydir[i];
3881         bhitpos.x += dx;
3882         bhitpos.y += dy;
3883         if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3884             m_respond(mtmp);
3885             tmp_at(DISP_END, 0);
3886             return mtmp;
3887         }
3888         if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3889             || closed_door(bhitpos.x, bhitpos.y)) {
3890             bhitpos.x -= dx;
3891             bhitpos.y -= dy;
3892             break;
3893         }
3894         if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3895             if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3896                 /* we hit ourselves */
3897                 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
3898 /*JP
3899                              "boomerang");
3900 */
3901                              "\83u\81[\83\81\83\89\83\93");
3902                 endmultishot(TRUE);
3903                 break;
3904             } else { /* we catch it */
3905                 tmp_at(DISP_END, 0);
3906 /*JP
3907                 You("skillfully catch the boomerang.");
3908 */
3909                 You("\8fã\8eè\82É\83u\81[\83\81\83\89\83\93\82ð\92Í\82Ü\82¦\82½\81D");
3910                 return &youmonst;
3911             }
3912         }
3913         tmp_at(bhitpos.x, bhitpos.y);
3914         delay_output();
3915         if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3916             if (!Deaf)
3917 /*JP
3918                 pline("Klonk!");
3919 */
3920                 pline("\83J\83\89\83\93\81I");
3921             break; /* boomerang falls on sink */
3922         }
3923         /* ct==0, initial position, we want next delta to be same;
3924            ct==5, opposite position, repeat delta undoes first one */
3925         if (ct % 5 != 0)
3926             i += (counterclockwise ? -1 : 1);
3927     }
3928     tmp_at(DISP_END, 0); /* do not leave last symbol */
3929     return (struct monst *) 0;
3930 }
3931
3932 /* used by buzz(); also used by munslime(muse.c); returns damage applied
3933    to mon; note: caller is responsible for killing mon if damage is fatal */
3934 int
3935 zhitm(mon, type, nd, ootmp)
3936 register struct monst *mon;
3937 register int type, nd;
3938 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3939 {
3940     register int tmp = 0;
3941     register int abstype = abs(type) % 10;
3942     boolean sho_shieldeff = FALSE;
3943     boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3944
3945     *ootmp = (struct obj *) 0;
3946     switch (abstype) {
3947     case ZT_MAGIC_MISSILE:
3948         if (resists_magm(mon)) {
3949             sho_shieldeff = TRUE;
3950             break;
3951         }
3952         tmp = d(nd, 6);
3953         if (spellcaster)
3954             tmp = spell_damage_bonus(tmp);
3955         break;
3956     case ZT_FIRE:
3957         if (resists_fire(mon)) {
3958             sho_shieldeff = TRUE;
3959             break;
3960         }
3961         tmp = d(nd, 6);
3962         if (resists_cold(mon))
3963             tmp += 7;
3964         if (spellcaster)
3965             tmp = spell_damage_bonus(tmp);
3966         if (burnarmor(mon)) {
3967             if (!rn2(3))
3968                 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3969             if (!rn2(3))
3970                 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3971             if (!rn2(5))
3972                 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3973             destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3974         }
3975         break;
3976     case ZT_COLD:
3977         if (resists_cold(mon)) {
3978             sho_shieldeff = TRUE;
3979             break;
3980         }
3981         tmp = d(nd, 6);
3982         if (resists_fire(mon))
3983             tmp += d(nd, 3);
3984         if (spellcaster)
3985             tmp = spell_damage_bonus(tmp);
3986         if (!rn2(3))
3987             (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3988         break;
3989     case ZT_SLEEP:
3990         tmp = 0;
3991         (void) sleep_monst(mon, d(nd, 25),
3992                            type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3993         break;
3994     case ZT_DEATH:                              /* death/disintegration */
3995         if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3996             if (mon->data == &mons[PM_DEATH]) {
3997                 mon->mhpmax += mon->mhpmax / 2;
3998                 if (mon->mhpmax >= MAGIC_COOKIE)
3999                     mon->mhpmax = MAGIC_COOKIE - 1;
4000                 mon->mhp = mon->mhpmax;
4001                 tmp = 0;
4002                 break;
4003             }
4004             if (nonliving(mon->data) || is_demon(mon->data)
4005                 || is_vampshifter(mon) || resists_magm(mon)) {
4006                 /* similar to player */
4007                 sho_shieldeff = TRUE;
4008                 break;
4009             }
4010             type = -1; /* so they don't get saving throws */
4011         } else {
4012             struct obj *otmp2;
4013
4014             if (resists_disint(mon)) {
4015                 sho_shieldeff = TRUE;
4016             } else if (mon->misc_worn_check & W_ARMS) {
4017                 /* destroy shield; victim survives */
4018                 *ootmp = which_armor(mon, W_ARMS);
4019             } else if (mon->misc_worn_check & W_ARM) {
4020                 /* destroy body armor, also cloak if present */
4021                 *ootmp = which_armor(mon, W_ARM);
4022                 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4023                     m_useup(mon, otmp2);
4024             } else {
4025                 /* no body armor, victim dies; destroy cloak
4026                    and shirt now in case target gets life-saved */
4027                 tmp = MAGIC_COOKIE;
4028                 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4029                     m_useup(mon, otmp2);
4030                 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
4031                     m_useup(mon, otmp2);
4032             }
4033             type = -1; /* no saving throw wanted */
4034             break;     /* not ordinary damage */
4035         }
4036         tmp = mon->mhp + 1;
4037         break;
4038     case ZT_LIGHTNING:
4039         if (resists_elec(mon)) {
4040             sho_shieldeff = TRUE;
4041             tmp = 0;
4042             /* can still blind the monster */
4043         } else
4044             tmp = d(nd, 6);
4045         if (spellcaster)
4046             tmp = spell_damage_bonus(tmp);
4047         if (!resists_blnd(mon)
4048             && !(type > 0 && u.uswallow && mon == u.ustuck)) {
4049             register unsigned rnd_tmp = rnd(50);
4050             mon->mcansee = 0;
4051             if ((mon->mblinded + rnd_tmp) > 127)
4052                 mon->mblinded = 127;
4053             else
4054                 mon->mblinded += rnd_tmp;
4055         }
4056         if (!rn2(3))
4057             (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
4058         /* not actually possible yet */
4059         if (!rn2(3))
4060             (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
4061         break;
4062     case ZT_POISON_GAS:
4063         if (resists_poison(mon)) {
4064             sho_shieldeff = TRUE;
4065             break;
4066         }
4067         tmp = d(nd, 6);
4068         break;
4069     case ZT_ACID:
4070         if (resists_acid(mon)) {
4071             sho_shieldeff = TRUE;
4072             break;
4073         }
4074         tmp = d(nd, 6);
4075         if (!rn2(6))
4076             acid_damage(MON_WEP(mon));
4077         if (!rn2(6))
4078             erode_armor(mon, ERODE_CORRODE);
4079         break;
4080     }
4081     if (sho_shieldeff)
4082         shieldeff(mon->mx, mon->my);
4083     if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
4084         tmp *= 2;
4085     if (tmp > 0 && type >= 0
4086         && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
4087         tmp /= 2;
4088     if (tmp < 0)
4089         tmp = 0; /* don't allow negative damage */
4090     debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
4091                 mon->mhp, tmp);
4092     mon->mhp -= tmp;
4093     return tmp;
4094 }
4095
4096 STATIC_OVL void
4097 zhitu(type, nd, fltxt, sx, sy)
4098 int type, nd;
4099 const char *fltxt;
4100 xchar sx, sy;
4101 {
4102     int dam = 0, abstyp = abs(type);
4103 #if 1 /*JP*/
4104     char buf[BUFSZ];
4105
4106     Sprintf(buf, "%s\82É\82æ\82Á\82Ä", fltxt);
4107     fltxt = buf;
4108 #endif
4109
4110     switch (abstyp % 10) {
4111     case ZT_MAGIC_MISSILE:
4112         if (Antimagic) {
4113             shieldeff(sx, sy);
4114 /*JP
4115             pline_The("missiles bounce off!");
4116 */
4117             pline("\96\82\96@\82Ì\96î\82Í\94½\8eË\82µ\82½\81I");
4118         } else {
4119             dam = d(nd, 6);
4120             exercise(A_STR, FALSE);
4121         }
4122         break;
4123     case ZT_FIRE:
4124         if (Fire_resistance) {
4125             shieldeff(sx, sy);
4126 /*JP
4127             You("don't feel hot!");
4128 */
4129             You("\94M\82³\82ð\8a´\82\82È\82¢\81I");
4130             ugolemeffects(AD_FIRE, d(nd, 6));
4131         } else {
4132             dam = d(nd, 6);
4133         }
4134         burn_away_slime();
4135         if (burnarmor(&youmonst)) { /* "body hit" */
4136             if (!rn2(3))
4137                 destroy_item(POTION_CLASS, AD_FIRE);
4138             if (!rn2(3))
4139                 destroy_item(SCROLL_CLASS, AD_FIRE);
4140             if (!rn2(5))
4141                 destroy_item(SPBOOK_CLASS, AD_FIRE);
4142             destroy_item(FOOD_CLASS, AD_FIRE);
4143         }
4144         break;
4145     case ZT_COLD:
4146         if (Cold_resistance) {
4147             shieldeff(sx, sy);
4148 /*JP
4149             You("don't feel cold.");
4150 */
4151             You("\97â\82½\82³\82ð\8a´\82\82È\82¢\81D");
4152             ugolemeffects(AD_COLD, d(nd, 6));
4153         } else {
4154             dam = d(nd, 6);
4155         }
4156         if (!rn2(3))
4157             destroy_item(POTION_CLASS, AD_COLD);
4158         break;
4159     case ZT_SLEEP:
4160         if (Sleep_resistance) {
4161             shieldeff(u.ux, u.uy);
4162 /*JP
4163             You("don't feel sleepy.");
4164 */
4165             You("\96°\82­\82È\82ç\82È\82¢\81D");
4166         } else {
4167             fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
4168         }
4169         break;
4170     case ZT_DEATH:
4171         if (abstyp == ZT_BREATH(ZT_DEATH)) {
4172             if (Disint_resistance) {
4173 /*JP
4174                 You("are not disintegrated.");
4175 */
4176                 You("\95ª\89ð\82³\82ê\82È\82¢\81D");
4177                 break;
4178             } else if (uarms) {
4179                 /* destroy shield; other possessions are safe */
4180                 (void) destroy_arm(uarms);
4181                 break;
4182             } else if (uarm) {
4183                 /* destroy suit; if present, cloak goes too */
4184                 if (uarmc)
4185                     (void) destroy_arm(uarmc);
4186                 (void) destroy_arm(uarm);
4187                 break;
4188             }
4189             /* no shield or suit, you're dead; wipe out cloak
4190                and/or shirt in case of life-saving or bones */
4191             if (uarmc)
4192                 (void) destroy_arm(uarmc);
4193             if (uarmu)
4194                 (void) destroy_arm(uarmu);
4195         } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4196             shieldeff(sx, sy);
4197 /*JP
4198             You("seem unaffected.");
4199 */
4200             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
4201             break;
4202         } else if (Antimagic) {
4203             shieldeff(sx, sy);
4204 /*JP
4205             You("aren't affected.");
4206 */
4207             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D");
4208             break;
4209         }
4210         killer.format = KILLED_BY_AN;
4211         Strcpy(killer.name, fltxt ? fltxt : "");
4212         /* when killed by disintegration breath, don't leave corpse */
4213         u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4214         done(DIED);
4215         return; /* lifesaved */
4216     case ZT_LIGHTNING:
4217         if (Shock_resistance) {
4218             shieldeff(sx, sy);
4219 /*JP
4220             You("aren't affected.");
4221 */
4222             You("\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D");
4223             ugolemeffects(AD_ELEC, d(nd, 6));
4224         } else {
4225             dam = d(nd, 6);
4226             exercise(A_CON, FALSE);
4227         }
4228         if (!rn2(3))
4229             destroy_item(WAND_CLASS, AD_ELEC);
4230         if (!rn2(3))
4231             destroy_item(RING_CLASS, AD_ELEC);
4232         break;
4233     case ZT_POISON_GAS:
4234 /*JP
4235         poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4236 */
4237         poisoned("\91§", A_DEX, "\93Å\82Ì\91§", 15, FALSE);
4238         break;
4239     case ZT_ACID:
4240         if (Acid_resistance) {
4241 /*JP
4242             pline_The("%s doesn't hurt.", hliquid("acid"));
4243 */
4244             pline_The("%s\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D", hliquid("\8e_"));
4245             dam = 0;
4246         } else {
4247 /*JP
4248             pline_The("%s burns!", hliquid("acid"));
4249 */
4250             pline_The("%s\82Å\8fÄ\82¯\82½\81I", hliquid("\8e_"));
4251             dam = d(nd, 6);
4252             exercise(A_STR, FALSE);
4253         }
4254         /* using two weapons at once makes both of them more vulnerable */
4255         if (!rn2(u.twoweap ? 3 : 6))
4256             acid_damage(uwep);
4257         if (u.twoweap && !rn2(3))
4258             acid_damage(uswapwep);
4259         if (!rn2(6))
4260             erode_armor(&youmonst, ERODE_CORRODE);
4261         break;
4262     }
4263
4264     /* Half_spell_damage protection yields half-damage for wands & spells,
4265        including hero's own ricochets; breath attacks do full damage */
4266     if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4267         dam = (dam + 1) / 2;
4268     losehp(dam, fltxt, KILLED_BY_AN);
4269     return;
4270 }
4271
4272 /*
4273  * burn objects (such as scrolls and spellbooks) on floor
4274  * at position x,y; return the number of objects burned
4275  */
4276 int
4277 burn_floor_objects(x, y, give_feedback, u_caused)
4278 int x, y;
4279 boolean give_feedback; /* caller needs to decide about visibility checks */
4280 boolean u_caused;
4281 {
4282     struct obj *obj, *obj2;
4283     long i, scrquan, delquan;
4284     char buf1[BUFSZ], buf2[BUFSZ];
4285     int cnt = 0;
4286
4287     for (obj = level.objects[x][y]; obj; obj = obj2) {
4288         obj2 = obj->nexthere;
4289         if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4290             || (obj->oclass == FOOD_CLASS
4291                 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4292             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4293                 || obj_resists(obj, 2, 100))
4294                 continue;
4295             scrquan = obj->quan; /* number present */
4296             delquan = 0L;        /* number to destroy */
4297             for (i = scrquan; i > 0L; i--)
4298                 if (!rn2(3))
4299                     delquan++;
4300             if (delquan) {
4301                 /* save name before potential delobj() */
4302                 if (give_feedback) {
4303                     obj->quan = 1L;
4304                     Strcpy(buf1, (x == u.ux && y == u.uy)
4305                                      ? xname(obj)
4306                                      : distant_name(obj, xname));
4307                     obj->quan = 2L;
4308                     Strcpy(buf2, (x == u.ux && y == u.uy)
4309                                      ? xname(obj)
4310                                      : distant_name(obj, xname));
4311                     obj->quan = scrquan;
4312                 }
4313                 /* useupf(), which charges, only if hero caused damage */
4314                 if (u_caused)
4315                     useupf(obj, delquan);
4316                 else if (delquan < scrquan)
4317                     obj->quan -= delquan;
4318                 else
4319                     delobj(obj);
4320                 cnt += delquan;
4321                 if (give_feedback) {
4322                     if (delquan > 1L)
4323 #if 0 /*JP*/
4324                         pline("%ld %s burn.", delquan, buf2);
4325 #else
4326                         pline("%ld%s\82Ì%s\82ª\94R\82¦\82½\81D", 
4327                               delquan, 
4328                               obj->oclass == SCROLL_CLASS ? "\96\87" : "\8dû",
4329                               buf2);
4330 #endif
4331                     else
4332 /*JP
4333                         pline("%s burns.", An(buf1));
4334 */
4335                         pline("%s\82Í\94R\82¦\82½\81D", buf1);
4336                 }
4337             }
4338         }
4339     }
4340     return cnt;
4341 }
4342
4343 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4344 STATIC_OVL int
4345 zap_hit(ac, type)
4346 int ac;
4347 int type; /* either hero cast spell type or 0 */
4348 {
4349     int chance = rn2(20);
4350     int spell_bonus = type ? spell_hit_bonus(type) : 0;
4351
4352     /* small chance for naked target to avoid being hit */
4353     if (!chance)
4354         return rnd(10) < ac + spell_bonus;
4355
4356     /* very high armor protection does not achieve invulnerability */
4357     ac = AC_VALUE(ac);
4358
4359     return (3 - chance < ac + spell_bonus);
4360 }
4361
4362 STATIC_OVL void
4363 disintegrate_mon(mon, type, fltxt)
4364 struct monst *mon;
4365 int type; /* hero vs other */
4366 const char *fltxt;
4367 {
4368     struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4369
4370     if (canseemon(mon)) {
4371         if (!m_amulet)
4372 /*JP
4373             pline("%s is disintegrated!", Monnam(mon));
4374 */
4375             pline("%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I", Monnam(mon));
4376         else
4377 /*JP
4378             hit(fltxt, mon, "!");
4379 */
4380             hit(fltxt, mon, "\81I");
4381     }
4382
4383 /* note: worn amulet of life saving must be preserved in order to operate */
4384 #define oresist_disintegration(obj)                                       \
4385     (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4386      || is_quest_artifact(obj) || obj == m_amulet)
4387
4388     for (otmp = mon->minvent; otmp; otmp = otmp2) {
4389         otmp2 = otmp->nobj;
4390         if (!oresist_disintegration(otmp)) {
4391             if (otmp->owornmask) {
4392                 /* in case monster's life gets saved */
4393                 mon->misc_worn_check &= ~otmp->owornmask;
4394                 if (otmp->owornmask & W_WEP)
4395                     setmnotwielded(mon, otmp);
4396                 /* also dismounts hero if this object is steed's saddle */
4397                 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4398                 otmp->owornmask = 0L;
4399             }
4400             obj_extract_self(otmp);
4401             obfree(otmp, (struct obj *) 0);
4402         }
4403     }
4404
4405 #undef oresist_disintegration
4406
4407     if (type < 0)
4408         monkilled(mon, (char *) 0, -AD_RBRE);
4409     else
4410         xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
4411 }
4412
4413 void
4414 buzz(type, nd, sx, sy, dx, dy)
4415 int type, nd;
4416 xchar sx, sy;
4417 int dx, dy;
4418 {
4419     dobuzz(type, nd, sx, sy, dx, dy, TRUE);
4420 }
4421
4422 /*
4423  * type ==   0 to   9 : you shooting a wand
4424  * type ==  10 to  19 : you casting a spell
4425  * type ==  20 to  29 : you breathing as a monster
4426  * type == -10 to -19 : monster casting spell
4427  * type == -20 to -29 : monster breathing at you
4428  * type == -30 to -39 : monster shooting a wand
4429  * called with dx = dy = 0 with vertical bolts
4430  */
4431 void
4432 dobuzz(type, nd, sx, sy, dx, dy, say)
4433 register int type, nd;
4434 register xchar sx, sy;
4435 register int dx, dy;
4436 boolean say; /* Announce out of sight hit/miss events if true */
4437 {
4438     int range, abstype = abs(type) % 10;
4439     register xchar lsx, lsy;
4440     struct monst *mon;
4441     coord save_bhitpos;
4442     boolean shopdamage = FALSE;
4443     const char *fltxt;
4444     struct obj *otmp;
4445     int spell_type;
4446
4447     /* if its a Hero Spell then get its SPE_TYPE */
4448     spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4449
4450     fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4451     if (u.uswallow) {
4452         register int tmp;
4453
4454         if (type < 0)
4455             return;
4456         tmp = zhitm(u.ustuck, type, nd, &otmp);
4457         if (!u.ustuck)
4458             u.uswallow = 0;
4459         else
4460 #if 0 /*JP*/
4461             pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4462                   exclam(tmp));
4463 #else
4464             pline("%s\82Í%s\82ð\82Ð\82«\82³\82¢\82½%s", fltxt, mon_nam(u.ustuck),
4465                   exclam(tmp));
4466 #endif
4467         /* Using disintegration from the inside only makes a hole... */
4468         if (tmp == MAGIC_COOKIE)
4469             u.ustuck->mhp = 0;
4470         if (u.ustuck->mhp < 1)
4471             killed(u.ustuck);
4472         return;
4473     }
4474     if (type < 0)
4475         newsym(u.ux, u.uy);
4476     range = rn1(7, 7);
4477     if (dx == 0 && dy == 0)
4478         range = 1;
4479     save_bhitpos = bhitpos;
4480
4481     tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4482     while (range-- > 0) {
4483         lsx = sx;
4484         sx += dx;
4485         lsy = sy;
4486         sy += dy;
4487         if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
4488             goto make_bounce;
4489
4490         mon = m_at(sx, sy);
4491         if (cansee(sx, sy)) {
4492             /* reveal/unreveal invisible monsters before tmp_at() */
4493             if (mon && !canspotmon(mon))
4494                 map_invisible(sx, sy);
4495             else if (!mon)
4496                 (void) unmap_invisible(sx, sy);
4497             if (ZAP_POS(levl[sx][sy].typ)
4498                 || (isok(lsx, lsy) && cansee(lsx, lsy)))
4499                 tmp_at(sx, sy);
4500             delay_output(); /* wait a little */
4501         }
4502
4503         /* hit() and miss() need bhitpos to match the target */
4504         bhitpos.x = sx, bhitpos.y = sy;
4505         /* Fireballs only damage when they explode */
4506         if (type != ZT_SPELL(ZT_FIRE))
4507             range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4508
4509         if (mon) {
4510             if (type == ZT_SPELL(ZT_FIRE))
4511                 break;
4512             if (type >= 0)
4513                 mon->mstrategy &= ~STRAT_WAITMASK;
4514         buzzmonst:
4515             notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
4516             if (zap_hit(find_mac(mon), spell_type)) {
4517                 if (mon_reflects(mon, (char *) 0)) {
4518                     if (cansee(mon->mx, mon->my)) {
4519                         hit(fltxt, mon, exclam(0));
4520                         shieldeff(mon->mx, mon->my);
4521 #if 0 /*JP*/
4522                         (void) mon_reflects(mon,
4523                                             "But it reflects from %s %s!");
4524 #else
4525                         (void) mon_reflects(mon,
4526                                             "\82µ\82©\82µ\82»\82ê\82Í%s\82Ì%s\82Å\94½\8eË\82µ\82½\81I");
4527 #endif
4528                     }
4529                     dx = -dx;
4530                     dy = -dy;
4531                 } else {
4532                     boolean mon_could_move = mon->mcanmove;
4533                     int tmp = zhitm(mon, type, nd, &otmp);
4534
4535                     if (is_rider(mon->data)
4536                         && abs(type) == ZT_BREATH(ZT_DEATH)) {
4537                         if (canseemon(mon)) {
4538 /*JP
4539                             hit(fltxt, mon, ".");
4540 */
4541                             hit(fltxt, mon, "\81D");
4542 /*JP
4543                             pline("%s disintegrates.", Monnam(mon));
4544 */
4545                             pline("%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D", Monnam(mon));
4546 #if 0 /*JP*/
4547                             pline("%s body reintegrates before your %s!",
4548                                   s_suffix(Monnam(mon)),
4549                                   (eyecount(youmonst.data) == 1)
4550                                       ? body_part(EYE)
4551                                       : makeplural(body_part(EYE)));
4552 #else
4553                             pline("%s\82Ì\91Ì\82Í\82 \82È\82½\82Ì\96Ú\82Ì\91O\82Å\8dÄ\8c\8b\8d\87\82µ\82½\81I",
4554                                   Monnam(mon));
4555 #endif
4556 /*JP
4557                             pline("%s resurrects!", Monnam(mon));
4558 */
4559                             pline("%s\82Í\91h\82Á\82½\81I", Monnam(mon));
4560                         }
4561                         mon->mhp = mon->mhpmax;
4562                         break; /* Out of while loop */
4563                     }
4564                     if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4565                         if (canseemon(mon)) {
4566 /*JP
4567                             hit(fltxt, mon, ".");
4568 */
4569                             hit(fltxt, mon, "\81D");
4570 #if 0 /*JP*/
4571                             pline("%s absorbs the deadly %s!", Monnam(mon),
4572                                   type == ZT_BREATH(ZT_DEATH) ? "blast"
4573                                                               : "ray");
4574 #else
4575                             pline("%s\82Í\8e\80\82Ì%s\82ð\8bz\8eû\82µ\82½\81I", Monnam(mon),
4576                                   type == ZT_BREATH(ZT_DEATH) ? "\91§"
4577                                                               : "\8cõ\90ü");
4578 #endif
4579 /*JP
4580                             pline("It seems even stronger than before.");
4581 */
4582                             pline("\82³\82ç\82É\8b­\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82³\82¦\82·\82é\81D");
4583                         }
4584                         break; /* Out of while loop */
4585                     }
4586
4587                     if (tmp == MAGIC_COOKIE) { /* disintegration */
4588                         disintegrate_mon(mon, type, fltxt);
4589                     } else if (mon->mhp < 1) {
4590                         if (type < 0) {
4591                             /* mon has just been killed by another monster */
4592                             monkilled(mon, fltxt, AD_RBRE);
4593                         } else {
4594                             int xkflags = XKILL_GIVEMSG; /* killed(mon); */
4595
4596                             /* killed by hero; we know 'type' isn't negative;
4597                                if it's fire, highly flammable monsters leave
4598                                no corpse; don't bother reporting that they
4599                                "burn completely" -- unnecessary verbosity */
4600                             if ((type % 10 == ZT_FIRE)
4601                                 /* paper golem or straw golem */
4602                                 && completelyburns(mon->data))
4603                                 xkflags |= XKILL_NOCORPSE;
4604                             xkilled(mon, xkflags);
4605                         }
4606                     } else {
4607                         if (!otmp) {
4608                             /* normal non-fatal hit */
4609                             if (say || canseemon(mon))
4610                                 hit(fltxt, mon, exclam(tmp));
4611                         } else {
4612                             /* some armor was destroyed; no damage done */
4613                             if (canseemon(mon))
4614 #if 0 /*JP*/
4615                                 pline("%s %s is disintegrated!",
4616                                       s_suffix(Monnam(mon)),
4617                                       distant_name(otmp, xname));
4618 #else
4619                                 pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
4620                                       Monnam(mon),
4621                                       distant_name(otmp, xname));
4622 #endif
4623                             m_useup(mon, otmp);
4624                         }
4625                         if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4626                             slept_monst(mon);
4627                     }
4628                 }
4629                 range -= 2;
4630             } else {
4631                 if (say || canseemon(mon))
4632                     miss(fltxt, mon);
4633             }
4634         } else if (sx == u.ux && sy == u.uy && range >= 0) {
4635             nomul(0);
4636             if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4637                 mon = u.usteed;
4638                 goto buzzmonst;
4639             } else if (zap_hit((int) u.uac, 0)) {
4640                 range -= 2;
4641 /*JP
4642                 pline("%s hits you!", The(fltxt));
4643 */
4644                 pline("%s\82Í\82 \82È\82½\82É\96½\92\86\82µ\82½\81I", fltxt);
4645                 if (Reflecting) {
4646                     if (!Blind) {
4647 #if 0 /*JP*/
4648                         (void) ureflects("But %s reflects from your %s!",
4649                                          "it");
4650 #else
4651                         (void) ureflects("\82µ\82©\82µ\81C%s\82Í\82 \82È\82½\82Ì%s\82É\82æ\82Á\82Ä\94½\8eË\82µ\82½\81D",
4652                                          "\82»\82ê");
4653 #endif
4654                     } else
4655 /*JP
4656                         pline("For some reason you are not affected.");
4657 */
4658                         pline("\82È\82º\82©\82 \82È\82½\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D");
4659                     dx = -dx;
4660                     dy = -dy;
4661                     shieldeff(sx, sy);
4662                 } else {
4663                     zhitu(type, nd, fltxt, sx, sy);
4664                 }
4665             } else if (!Blind) {
4666 /*JP
4667                 pline("%s whizzes by you!", The(fltxt));
4668 */
4669                 pline("%s\82Í\82 \82È\82½\82Ì\82»\82Î\82ð\82©\82·\82ß\82½\81I", fltxt);
4670             } else if (abstype == ZT_LIGHTNING) {
4671 /*JP
4672                 Your("%s tingles.", body_part(ARM));
4673 */
4674                 Your("%s\82Í\83q\83\8a\83q\83\8a\82µ\82½\81D", body_part(ARM));
4675             }
4676             if (abstype == ZT_LIGHTNING)
4677                 (void) flashburn((long) d(nd, 50));
4678             stop_occupation();
4679             nomul(0);
4680         }
4681
4682         if (!ZAP_POS(levl[sx][sy].typ)
4683             || (closed_door(sx, sy) && range >= 0)) {
4684             int bounce, bchance;
4685             uchar rmn;
4686             boolean fireball;
4687
4688         make_bounce:
4689             bchance = (levl[sx][sy].typ == STONE) ? 10
4690                 : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
4691                 : 75;
4692             bounce = 0;
4693             fireball = (type == ZT_SPELL(ZT_FIRE));
4694             if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
4695                 || fireball) {
4696                 if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
4697 /*JP
4698                     pline_The("%s vanishes into the aether!", fltxt);
4699 */
4700                     pline_The("%s\82Í\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½\81I", fltxt);
4701                     if (fireball)
4702                         type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
4703                     break;
4704                 } else if (fireball) {
4705                     sx = lsx;
4706                     sy = lsy;
4707                     break; /* fireballs explode before the obstacle */
4708                 } else
4709 /*JP
4710                     pline_The("%s bounces!", fltxt);
4711 */
4712                     pline_The("%s\82Í\94½\8eË\82µ\82½\81I", fltxt);
4713             }
4714             if (!dx || !dy || !rn2(bchance)) {
4715                 dx = -dx;
4716                 dy = -dy;
4717             } else {
4718                 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4719                     && !closed_door(sx, lsy)
4720                     && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4721                                          && ZAP_POS(levl[sx + dx][lsy].typ))))
4722                     bounce = 1;
4723                 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4724                     && !closed_door(lsx, sy)
4725                     && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4726                                          && ZAP_POS(levl[lsx][sy + dy].typ))))
4727                     if (!bounce || rn2(2))
4728                         bounce = 2;
4729
4730                 switch (bounce) {
4731                 case 0:
4732                     dx = -dx;
4733                     /*FALLTHRU*/
4734                 case 1:
4735                     dy = -dy;
4736                     break;
4737                 case 2:
4738                     dx = -dx;
4739                     break;
4740                 }
4741                 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4742             }
4743         }
4744     }
4745     tmp_at(DISP_END, 0);
4746     if (type == ZT_SPELL(ZT_FIRE))
4747         explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4748     if (shopdamage)
4749 #if 0 /*JP*/
4750         pay_for_damage(abstype == ZT_FIRE
4751                           ? "burn away"
4752                           : abstype == ZT_COLD
4753                              ? "shatter"
4754                              /* "damage" indicates wall rather than door */
4755                              : abstype == ZT_ACID
4756                                 ? "damage"
4757                                 : abstype == ZT_DEATH
4758                                    ? "disintegrate"
4759                                    : "destroy",
4760                        FALSE);
4761 #else
4762         pay_for_damage(abstype == ZT_FIRE
4763                        ? "\94R\82â\82·"
4764                        : abstype == ZT_COLD
4765                           ? "\95²\81X\82É\82·\82é"
4766                           : abstype == ZT_ACID
4767                           ? "\8f\9d\82Â\82¯\82é"
4768                              : abstype == ZT_DEATH
4769                                 ? "\95²\8dÓ\82·\82é"
4770                                 : "\94j\89ó\82·\82é",
4771                        FALSE);
4772 #endif
4773     bhitpos = save_bhitpos;
4774 }
4775
4776 void
4777 melt_ice(x, y, msg)
4778 xchar x, y;
4779 const char *msg;
4780 {
4781     struct rm *lev = &levl[x][y];
4782     struct obj *otmp;
4783
4784     if (!msg)
4785 /*JP
4786         msg = "The ice crackles and melts.";
4787 */
4788         msg = "\95X\82Í\83s\83L\83s\83L\96Â\82è\81C\97n\82¯\82½\81D";
4789     if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
4790         lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4791     } else { /* lev->typ == ICE */
4792 #ifdef STUPID
4793         if (lev->icedpool == ICED_POOL)
4794             lev->typ = POOL;
4795         else
4796             lev->typ = MOAT;
4797 #else
4798         lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4799 #endif
4800         lev->icedpool = 0;
4801     }
4802     spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4803     obj_ice_effects(x, y, FALSE);
4804     unearth_objs(x, y);
4805     if (Underwater)
4806         vision_recalc(1);
4807     newsym(x, y);
4808     if (cansee(x, y))
4809         Norep("%s", msg);
4810     if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4811         if (cansee(x, y))
4812 /*JP
4813             pline("%s settles...", An(xname(otmp)));
4814 */
4815             pline("%s\82Í\82Í\82Ü\82Á\82½\81D\81D\81D", xname(otmp));
4816         do {
4817             obj_extract_self(otmp); /* boulder isn't being pushed */
4818             if (!boulder_hits_pool(otmp, x, y, FALSE))
4819                 impossible("melt_ice: no pool?");
4820             /* try again if there's another boulder and pool didn't fill */
4821         } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4822         newsym(x, y);
4823     }
4824     if (x == u.ux && y == u.uy)
4825         spoteffects(TRUE); /* possibly drown, notice objects */
4826 }
4827
4828 #define MIN_ICE_TIME 50
4829 #define MAX_ICE_TIME 2000
4830 /*
4831  * Usually start a melt_ice timer; sometimes the ice will become
4832  * permanent instead.
4833  */
4834 void
4835 start_melt_ice_timeout(x, y, min_time)
4836 xchar x, y;
4837 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4838 {
4839     int when;
4840     long where;
4841
4842     when = (int) min_time;
4843     if (when < MIN_ICE_TIME - 1)
4844         when = MIN_ICE_TIME - 1;
4845
4846     /* random timeout; surrounding ice locations ought to be a factor... */
4847     while (++when <= MAX_ICE_TIME)
4848         if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4849             break;
4850
4851     /* if we're within MAX_ICE_TIME, install a melt timer;
4852        otherwise, omit it to leave this ice permanent */
4853     if (when <= MAX_ICE_TIME) {
4854         where = ((long) x << 16) | (long) y;
4855         (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4856                            long_to_any(where));
4857     }
4858 }
4859 #undef MIN_ICE_TIME
4860 #undef MAX_ICE_TIME
4861
4862 /*
4863  * Called when ice has melted completely away.
4864  */
4865 void
4866 melt_ice_away(arg, timeout)
4867 anything *arg;
4868 long timeout UNUSED;
4869 {
4870     xchar x, y;
4871     long where = arg->a_long;
4872
4873     y = (xchar) (where & 0xFFFF);
4874     x = (xchar) ((where >> 16) & 0xFFFF);
4875     /* melt_ice does newsym when appropriate */
4876 /*JP
4877     melt_ice(x, y, "Some ice melts away.");
4878 */
4879     melt_ice(x, y, "\95X\82ª\8f­\82µ\97n\82¯\82½\81D");
4880 }
4881
4882 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4883  * Used both for normal bolts of fire, cold, etc... and for fireballs.
4884  * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4885  * amount by which range is reduced (the latter is just ignored by fireballs)
4886  */
4887 int
4888 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4889 xchar x, y;
4890 int type;
4891 boolean *shopdamage;
4892 short exploding_wand_typ;
4893 {
4894     const char *zapverb;
4895     struct monst *mon;
4896     struct trap *t;
4897     struct rm *lev = &levl[x][y];
4898     boolean see_it = cansee(x, y), yourzap;
4899     int rangemod = 0, abstype = abs(type) % 10;
4900
4901     switch (abstype) {
4902     case ZT_FIRE:
4903         t = t_at(x, y);
4904         if (t && t->ttyp == WEB) {
4905             /* a burning web is too flimsy to notice if you can't see it */
4906             if (see_it)
4907 /*JP
4908                 Norep("A web bursts into flames!");
4909 */
4910                 Norep("\82­\82à\82Ì\91\83\82Í\89\8a\82É\95ï\82Ü\82ê\82½\81I");
4911             (void) delfloortrap(t);
4912             if (see_it)
4913                 newsym(x, y);
4914         }
4915         if (is_ice(x, y)) {
4916             melt_ice(x, y, (char *) 0);
4917         } else if (is_pool(x, y)) {
4918 /*JP
4919             const char *msgtxt = "You hear hissing gas.";
4920 */
4921             const char *msgtxt = "\82µ\82ã\81[\82Á\82Æ\82¢\82¤\83K\83X\82Ì\89¹\82ð\95·\82¢\82½\81D";
4922
4923             if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4924                 if (see_it)
4925 /*JP
4926                     msgtxt = "Some water evaporates.";
4927 */
4928                     msgtxt = "\82·\82±\82µ\90\85\82ª\8fö\94­\82µ\82½\81D";
4929             } else {
4930                 rangemod -= 3;
4931                 lev->typ = ROOM;
4932                 t = maketrap(x, y, PIT);
4933                 if (t)
4934                     t->tseen = 1;
4935                 if (see_it)
4936 /*JP
4937                     msgtxt = "The water evaporates.";
4938 */
4939                     msgtxt = "\90\85\82ª\8fö\94­\82µ\82½\81D";
4940             }
4941             Norep("%s", msgtxt);
4942             if (lev->typ == ROOM)
4943                 newsym(x, y);
4944         } else if (IS_FOUNTAIN(lev->typ)) {
4945             if (see_it)
4946 /*JP
4947                 pline("Steam billows from the fountain.");
4948 */
4949                 pline("\90ò\82©\82ç\8fö\8bC\82ª\97§\82¿\82Ì\82Ú\82Á\82½\81D");
4950             rangemod -= 1;
4951             dryup(x, y, type > 0);
4952         }
4953         break; /* ZT_FIRE */
4954
4955     case ZT_COLD:
4956         if (is_pool(x, y) || is_lava(x, y)) {
4957             boolean lava = is_lava(x, y),
4958                     moat = is_moat(x, y);
4959
4960             if (lev->typ == WATER) {
4961                 /* For now, don't let WATER freeze. */
4962                 if (see_it)
4963 /*JP
4964                     pline_The("%s freezes for a moment.", hliquid("water"));
4965 */
4966                     pline_The("%s\82Í\88ê\8fu\93\80\82Á\82½\81D", hliquid("\90\85"));
4967                 else
4968 /*JP
4969                     You_hear("a soft crackling.");
4970 */
4971                     You_hear("\83s\83L\81I\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
4972                 rangemod -= 1000; /* stop */
4973             } else {
4974                 char buf[BUFSZ];
4975
4976                 Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
4977                 rangemod -= 3;
4978                 if (lev->typ == DRAWBRIDGE_UP) {
4979                     lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4980                     lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4981                 } else {
4982                     if (!lava)
4983                         lev->icedpool = (lev->typ == POOL) ? ICED_POOL
4984                                                            : ICED_MOAT;
4985                     lev->typ = lava ? ROOM : ICE;
4986                 }
4987                 bury_objs(x, y);
4988                 if (see_it) {
4989                     if (lava)
4990 /*JP
4991                         Norep("The %s cools and solidifies.", hliquid("lava"));
4992 */
4993                         Norep("%s\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D", hliquid("lava"));
4994                     else if (moat)
4995 /*JP
4996                         Norep("The %s is bridged with ice!", buf);
4997 */
4998                         Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I", buf);
4999                     else
5000 /*JP
5001                         Norep("The %s freezes.", hliquid("water"));
5002 */
5003                         Norep("%s\82Í\93\80\82Á\82½\81D", hliquid("\95X"));
5004                     newsym(x, y);
5005                 } else if (!lava)
5006 /*JP
5007                     You_hear("a crackling sound.");
5008 */
5009                     You_hear("\83s\83L\83s\83L\83b\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
5010
5011                 if (x == u.ux && y == u.uy) {
5012                     if (u.uinwater) { /* not just `if (Underwater)' */
5013                         /* leave the no longer existent water */
5014                         u.uinwater = 0;
5015                         u.uundetected = 0;
5016                         docrt();
5017                         vision_full_recalc = 1;
5018                     } else if (u.utrap && u.utraptype == TT_LAVA) {
5019                         if (Passes_walls) {
5020                             u.utrap = 0;
5021 /*JP
5022                             You("pass through the now-solid rock.");
5023 */
5024                             You("\82¢\82Ü\8cÅ\82­\82È\82Á\82½\82Î\82©\82è\82Ì\90Î\82Ì\92\86\82ð\82·\82è\94²\82¯\82½\81D");
5025                         } else {
5026                             u.utrap = rn1(50, 20);
5027                             u.utraptype = TT_INFLOOR;
5028 /*JP
5029                             You("are firmly stuck in the cooling rock.");
5030 */
5031                             You("\97â\82¦\82½\8aâ\82Ì\82È\82©\82É\82µ\82Á\82©\82è\82Æ\96\84\82Ü\82Á\82½\81D");
5032                         }
5033                     }
5034                 } else if ((mon = m_at(x, y)) != 0) {
5035                     /* probably ought to do some hefty damage to any
5036                        non-ice creature caught in freezing water;
5037                        at a minimum, eels are forced out of hiding */
5038                     if (is_swimmer(mon->data) && mon->mundetected) {
5039                         mon->mundetected = 0;
5040                         newsym(x, y);
5041                     }
5042                 }
5043                 if (!lava) {
5044                     start_melt_ice_timeout(x, y, 0L);
5045                     obj_ice_effects(x, y, TRUE);
5046                 }
5047             } /* ?WATER */
5048
5049         } else if (is_ice(x, y)) {
5050             long melt_time;
5051
5052             /* Already ice here, so just firm it up. */
5053             /* Now ensure that only ice that is already timed is affected */
5054             if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
5055                 spot_stop_timers(x, y, MELT_ICE_AWAY);
5056                 start_melt_ice_timeout(x, y, melt_time);
5057             }
5058         }
5059         break; /* ZT_COLD */
5060
5061     case ZT_POISON_GAS:
5062         (void) create_gas_cloud(x, y, 1, 8);
5063         break;
5064
5065     case ZT_ACID:
5066         if (lev->typ == IRONBARS) {
5067             if ((lev->wall_info & W_NONDIGGABLE) != 0) {
5068                 if (see_it)
5069 /*JP
5070                     Norep("The %s corrode somewhat but remain intact.",
5071 */
5072                     Norep("%s\82Í\8f­\82µ\92É\82ñ\82¾\82ª\82Ü\82¾\82µ\82Á\82©\82è\82µ\82Ä\82¢\82é\81D",
5073                           defsyms[S_bars].explanation);
5074                 /* but nothing actually happens... */
5075             } else {
5076                 rangemod -= 3;
5077                 if (see_it)
5078 /*JP
5079                     Norep("The %s melt.", defsyms[S_bars].explanation);
5080 */
5081                     Norep("%s\82ª\97n\82¯\82½\81D", defsyms[S_bars].explanation);
5082                 if (*in_rooms(x, y, SHOPBASE)) {
5083                     /* in case we ever have a shop bounded by bars */
5084                     lev->typ = ROOM;
5085                     if (see_it)
5086                         newsym(x, y);
5087                     add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
5088                     if (type >= 0)
5089                         *shopdamage = TRUE;
5090                 } else {
5091                     lev->typ = DOOR;
5092                     lev->doormask = D_NODOOR;
5093                     if (see_it)
5094                         newsym(x, y);
5095                 }
5096             }
5097         }
5098         break; /* ZT_ACID */
5099
5100     default:
5101         break;
5102     }
5103
5104     /* set up zap text for possible door feedback; for exploding wand, we
5105        want "the blast" rather than "your blast" even if hero caused it */
5106     yourzap = (type >= 0 && !exploding_wand_typ);
5107 #if 0 /*JP*/
5108     zapverb = "blast"; /* breath attack or wand explosion */
5109 #else
5110     zapverb = "\8fÕ\8c\82"; /* breath attack or wand explosion */
5111 #endif
5112     if (!exploding_wand_typ) {
5113         if (abs(type) < ZT_SPELL(0))
5114 #if 0 /*JP*/
5115             zapverb = "bolt"; /* wand zap */
5116 #else
5117             zapverb = "\8cõ\90ü"; /* wand zap */
5118 #endif
5119         else if (abs(type) < ZT_BREATH(0))
5120 /*JP
5121             zapverb = "spell";
5122 */
5123             zapverb = "\8eô\95¶";
5124     }
5125
5126     /* secret door gets revealed, converted into regular door */
5127     if (levl[x][y].typ == SDOOR) {
5128         cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
5129         /* target spot will now pass closed_door() test below
5130            (except on rogue level) */
5131         newsym(x, y);
5132         if (see_it)
5133 #if 0 /*JP*/
5134             pline("%s %s reveals a secret door.",
5135                   yourzap ? "Your" : "The", zapverb);
5136 #else
5137             pline("%s\82Å\89B\82µ\94à\82ª\96¾\82ç\82©\82É\82È\82Á\82½\81D", zapverb);
5138 #endif
5139         else if (Is_rogue_level(&u.uz))
5140             draft_message(FALSE); /* "You feel a draft." (open doorway) */
5141     }
5142
5143     /* regular door absorbs remaining zap range, possibly gets destroyed */
5144     if (closed_door(x, y)) {
5145         int new_doormask = -1;
5146         const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
5147
5148         rangemod = -1000;
5149         switch (abstype) {
5150         case ZT_FIRE:
5151             new_doormask = D_NODOOR;
5152 /*JP
5153             see_txt = "The door is consumed in flames!";
5154 */
5155             see_txt = "\94à\82Í\89\8a\82Å\8fÄ\82«\82Â\82­\82³\82ê\82½\81I";
5156 /*JP
5157             sense_txt = "smell smoke.";
5158 */
5159             sense_txt = "\89\8c\82Ì\93õ\82¢\82ª\82µ\82½\81D";
5160             break;
5161         case ZT_COLD:
5162             new_doormask = D_NODOOR;
5163 /*JP
5164             see_txt = "The door freezes and shatters!";
5165 */
5166             see_txt = "\94à\82Í\93\80\82è\81C\82±\82È\82²\82È\82É\82È\82Á\82½\81I";
5167 /*JP
5168             sense_txt = "feel cold.";
5169 */
5170             sense_txt = "\97â\8bC\82ð\8a´\82\82½\81D";
5171             break;
5172         case ZT_DEATH:
5173             /* death spells/wands don't disintegrate */
5174             if (abs(type) != ZT_BREATH(ZT_DEATH))
5175                 goto def_case;
5176             new_doormask = D_NODOOR;
5177 /*JP
5178             see_txt = "The door disintegrates!";
5179 */
5180             see_txt = "\94à\82Í\95²\8dÓ\82³\82ê\82½\81I";
5181 /*JP
5182             hear_txt = "crashing wood.";
5183 */
5184             hear_txt = "\96Ø\82Ì\89ó\82ê\82é\89¹\82ð\95·\82¢\82½\81D";
5185             break;
5186         case ZT_LIGHTNING:
5187             new_doormask = D_BROKEN;
5188 /*JP
5189             see_txt = "The door splinters!";
5190 */
5191             see_txt = "\94à\82Í\82¸\82½\82¸\82½\82É\82È\82Á\82½\81I";
5192 /*JP
5193             hear_txt = "crackling.";
5194 */
5195             hear_txt = "\83s\83L\83s\83L\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D";
5196             break;
5197         default:
5198         def_case:
5199             if (exploding_wand_typ > 0) {
5200                 /* Magical explosion from misc exploding wand */
5201                 if (exploding_wand_typ == WAN_STRIKING) {
5202                     new_doormask = D_BROKEN;
5203 /*JP
5204                     see_txt = "The door crashes open!";
5205 */
5206                     see_txt = "\94à\82Í\89ó\82ê\82Ä\8aJ\82¢\82½\81I";
5207 /*JP
5208                     sense_txt = "feel a burst of cool air.";
5209 */
5210                     sense_txt = "\97â\8bC\82Ì\8f[\96\9e\82ð\8a´\82\82½\81D";
5211                     break;
5212                 }
5213             }
5214             if (see_it) {
5215                 /* "the door absorbs the blast" would be
5216                    inaccurate for an exploding wand since
5217                    other adjacent locations still get hit */
5218                 if (exploding_wand_typ)
5219 /*JP
5220                     pline_The("door remains intact.");
5221 */
5222                     pline_The("\94à\82Í\96³\8f\9d\82¾\81D");
5223                 else
5224 #if 0 /*JP*/
5225                     pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
5226                               zapverb);
5227 #else
5228                     pline_The("\94à\82Í%s%s\82ð\8bz\8eû\82µ\82½\81I", yourzap ? "\82 \82È\82½\82ª\95ú\82Á\82½" : "",
5229                               zapverb);
5230 #endif
5231             } else
5232 /*JP
5233                 You_feel("vibrations.");
5234 */
5235                 You("\90U\93®\82ð\8a´\82\82½\81D");
5236             break;
5237         }
5238         if (new_doormask >= 0) { /* door gets broken */
5239             if (*in_rooms(x, y, SHOPBASE)) {
5240                 if (type >= 0) {
5241                     add_damage(x, y, SHOP_DOOR_COST);
5242                     *shopdamage = TRUE;
5243                 } else /* caused by monster */
5244                     add_damage(x, y, 0L);
5245             }
5246             lev->doormask = new_doormask;
5247             unblock_point(x, y); /* vision */
5248             if (see_it) {
5249                 pline1(see_txt);
5250                 newsym(x, y);
5251             } else if (sense_txt) {
5252 #if 0 /*JP*//*\81u\82 \82È\82½\82Í\81v\82ª\95s\93K\90Ø\82È\95\82à\82 \82é*/
5253                 You1(sense_txt);
5254 #else
5255                 pline1(sense_txt);
5256 #endif
5257             } else if (hear_txt)
5258                 You_hear1(hear_txt);
5259             if (picking_at(x, y)) {
5260                 stop_occupation();
5261                 reset_pick();
5262             }
5263         }
5264     }
5265
5266     if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5267         if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5268             newsym(x, y);
5269 /*JP
5270             You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5271 */
5272             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½");
5273         }
5274     if ((mon = m_at(x, y)) != 0) {
5275         wakeup(mon, FALSE);
5276         if (type >= 0) {
5277             setmangry(mon, TRUE);
5278             if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5279                 ghod_hitsu(mon);
5280             if (mon->isshk && !*u.ushops)
5281                 hot_pursuit(mon);
5282         }
5283     }
5284     return rangemod;
5285 }
5286
5287 /* fractured by pick-axe or wand of striking */
5288 void
5289 fracture_rock(obj)
5290 register struct obj *obj; /* no texts here! */
5291 {
5292     xchar x, y;
5293     boolean by_you = !context.mon_moving;
5294
5295     if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5296         struct monst *shkp = 0;
5297         char objroom = *in_rooms(x, y, SHOPBASE);
5298
5299         if (billable(&shkp, obj, objroom, FALSE)) {
5300             /* shop message says "you owe <shk> <$> for it!" so we need
5301                to precede that with a message explaining what "it" is */
5302 /*JP
5303             You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5304 */
5305             You("%s\82Ì%s\82ð\89ó\82µ\82½\81D", shkname(shkp), xname(obj));
5306             breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5307         }
5308     }
5309     if (by_you && obj->otyp == BOULDER)
5310         sokoban_guilt();
5311
5312     obj->otyp = ROCK;
5313     obj->oclass = GEM_CLASS;
5314     obj->quan = (long) rn1(60, 7);
5315     obj->owt = weight(obj);
5316     obj->dknown = obj->bknown = obj->rknown = 0;
5317     obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5318     dealloc_oextra(obj);
5319
5320     if (obj->where == OBJ_FLOOR) {
5321         obj_extract_self(obj); /* move rocks back on top */
5322         place_object(obj, obj->ox, obj->oy);
5323         if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5324             unblock_point(obj->ox, obj->oy);
5325         if (cansee(obj->ox, obj->oy))
5326             newsym(obj->ox, obj->oy);
5327     }
5328 }
5329
5330 /* handle statue hit by striking/force bolt/pick-axe */
5331 boolean
5332 break_statue(obj)
5333 register struct obj *obj;
5334 {
5335     /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5336     struct trap *trap = t_at(obj->ox, obj->oy);
5337     struct obj *item;
5338     boolean by_you = !context.mon_moving;
5339
5340     if (trap && trap->ttyp == STATUE_TRAP
5341         && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5342         return FALSE;
5343     /* drop any objects contained inside the statue */
5344     while ((item = obj->cobj) != 0) {
5345         obj_extract_self(item);
5346         place_object(item, obj->ox, obj->oy);
5347     }
5348     if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5349 /*JP
5350         You_feel("guilty about damaging such a historic statue.");
5351 */
5352         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");
5353         adjalign(-1);
5354     }
5355     obj->spe = 0;
5356     fracture_rock(obj);
5357     return TRUE;
5358 }
5359
5360 /*
5361  * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5362  *      [0] freezing potion
5363  *      [1] boiling potion other than oil
5364  *      [2] boiling potion of oil
5365  *      [3] burning scroll
5366  *      [4] burning spellbook
5367  *      [5] shocked ring
5368  *      [6] shocked wand
5369  * (books, rings, and wands don't stack so don't need plural form;
5370  *  crumbling ring doesn't do damage so doesn't need killer reason)
5371  */
5372 const char *const destroy_strings[][3] = {
5373     /* also used in trap.c */
5374 /*JP
5375     { "freezes and shatters", "freeze and shatter", "shattered potion" },
5376 */
5377     { "\93\80\8c\8b\82µ\82Ä\8dÓ\82¯\82½", "\93\80\8c\8b\82µ\82Ä\8dÓ\82¯\82½", "\8dÓ\82¯\82½\96ò\95r\82Å" },
5378 /*JP
5379     { "boils and explodes", "boil and explode", "boiling potion" },
5380 */
5381     { "\95¦\93«\82µ\82Ä\94\9a\94­\82µ\82½", "\95¦\93«\82µ\82Ä\94\9a\94­\82µ\82½", "\95¦\93«\82µ\82½\96ò\82Å" },
5382 /*JP
5383     { "ignites and explodes", "ignite and explode", "exploding potion" },
5384 */
5385     { "\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Å" },
5386 /*JP
5387     { "catches fire and burns", "catch fire and burn", "burning scroll" },
5388 */
5389     { "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\89Î\82ª\82Â\82¢\82Ä\94R\82¦\82½", "\94R\82¦\82½\8aª\95¨\82Å" },
5390 /*JP
5391     { "catches fire and burns", "", "burning book" },
5392 */
5393     { "\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Å" },
5394 /*JP
5395     { "turns to dust and vanishes", "", "" },
5396 */
5397     { "\90o\82É\82È\82Á\82Ä\8fÁ\82¦\82½", "\90o\82É\82È\82Á\82Ä\8fÁ\82¦\82½", "" },
5398 /*JP
5399     { "breaks apart and explodes", "", "exploding wand" },
5400 */
5401     { "\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Å" },
5402 };
5403
5404 void
5405 destroy_item(osym, dmgtyp)
5406 register int osym, dmgtyp;
5407 {
5408     register struct obj *obj, *obj2;
5409     int dmg, xresist, skip;
5410     long i, cnt, quan;
5411     int dindx;
5412     const char *mult;
5413     boolean physical_damage;
5414
5415     for (obj = invent; obj; obj = obj2) {
5416         obj2 = obj->nobj;
5417         physical_damage = FALSE;
5418         if (obj->oclass != osym)
5419             continue; /* test only objs of type osym */
5420         if (obj->oartifact)
5421             continue; /* don't destroy artifacts */
5422         if (obj->in_use && obj->quan == 1L)
5423             continue; /* not available */
5424         xresist = skip = 0;
5425         /* lint suppression */
5426         dmg = dindx = 0;
5427         quan = 0L;
5428
5429         switch (dmgtyp) {
5430         case AD_COLD:
5431             if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5432                 quan = obj->quan;
5433                 dindx = 0;
5434                 dmg = rnd(4);
5435             } else
5436                 skip++;
5437             break;
5438         case AD_FIRE:
5439             xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5440                        && obj->otyp != GLOB_OF_GREEN_SLIME);
5441
5442             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5443                 skip++;
5444             if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5445                 skip++;
5446                 if (!Blind)
5447 #if 0 /*JP:T*/
5448                     pline("%s glows a strange %s, but remains intact.",
5449                           The(xname(obj)), hcolor("dark red"));
5450 #else
5451                     pline("%s\82Í\8aï\96­\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
5452                           xname(obj), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
5453 #endif
5454
5455             }
5456             quan = obj->quan;
5457             switch (osym) {
5458             case POTION_CLASS:
5459                 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5460                 dmg = rnd(6);
5461                 break;
5462             case SCROLL_CLASS:
5463                 dindx = 3;
5464                 dmg = 1;
5465                 break;
5466             case SPBOOK_CLASS:
5467                 dindx = 4;
5468                 dmg = 1;
5469                 break;
5470             case FOOD_CLASS:
5471                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5472                     dindx = 1; /* boil and explode */
5473                     dmg = (obj->owt + 19) / 20;
5474                 } else {
5475                     skip++;
5476                 }
5477                 break;
5478             default:
5479                 skip++;
5480                 break;
5481             }
5482             break;
5483         case AD_ELEC:
5484             xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5485             quan = obj->quan;
5486             switch (osym) {
5487             case RING_CLASS:
5488                 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5489                     skip++;
5490                     break;
5491                 }
5492                 dindx = 5;
5493                 dmg = 0;
5494                 break;
5495             case WAND_CLASS:
5496                 if (obj->otyp == WAN_LIGHTNING) {
5497                     skip++;
5498                     break;
5499                 }
5500 #if 0
5501                 if (obj == current_wand) {  skip++;  break;  }
5502 #endif
5503                 dindx = 6;
5504                 dmg = rnd(10);
5505                 break;
5506             default:
5507                 skip++;
5508                 break;
5509             }
5510             break;
5511         default:
5512             skip++;
5513             break;
5514         }
5515         if (!skip) {
5516             if (obj->in_use)
5517                 --quan; /* one will be used up elsewhere */
5518             for (i = cnt = 0L; i < quan; i++)
5519                 if (!rn2(3))
5520                     cnt++;
5521
5522             if (!cnt)
5523                 continue;
5524 #if 0 /*JP*/
5525             mult = (cnt == 1L)
5526                    ? (quan == 1L) ? "Your"                        /* 1 of 1 */
5527                                   : "One of your"                 /* 1 of N */
5528                    : (cnt < quan) ? "Some of your"                /* n of N */
5529                                   : (quan == 2L) ? "Both of your" /* 2 of 2 */
5530                                                  : "All of your"; /* N of N */
5531 #else
5532             mult = (cnt == quan)
5533                    ? ""
5534                    : (cnt == 1L) ? "\82Ì\82Ð\82Æ\82Â" : "\82Ì\82¢\82­\82Â\82©";
5535 #endif
5536 #if 0 /*JP*/
5537             pline("%s %s %s!", mult, xname(obj),
5538                   destroy_strings[dindx][(cnt > 1L)]);
5539 #else
5540             pline("\82 \82È\82½\82Ì%s%s\82Í%s\81I", xname(obj), mult, 
5541                   destroy_strings[dindx][(cnt > 1L)]);
5542 #endif
5543             if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5544                 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5545                     potionbreathe(obj);
5546             }
5547             if (obj->owornmask) {
5548                 if (obj->owornmask & W_RING) /* ring being worn */
5549                     Ring_gone(obj);
5550                 else
5551                     setnotworn(obj);
5552             }
5553             if (obj == current_wand)
5554                 current_wand = 0; /* destroyed */
5555             for (i = 0; i < cnt; i++)
5556                 useup(obj);
5557             if (dmg) {
5558                 if (xresist)
5559 /*JP
5560                     You("aren't hurt!");
5561 */
5562                     You("\8f\9d\82Â\82©\82È\82¢\81I");
5563                 else {
5564                     const char *how = destroy_strings[dindx][2];
5565                     boolean one = (cnt == 1L);
5566
5567                     if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
5568 /*JP
5569                         how = "exploding glob of slime";
5570 */
5571                         how = "\83X\83\89\83C\83\80\82Ì\82Ë\82Î\82Ë\82Î\82Ì\94\9a\94­\82Å";
5572                     if (physical_damage)
5573                         dmg = Maybe_Half_Phys(dmg);
5574                     losehp(dmg, one ? how : (const char *) makeplural(how),
5575                            one ? KILLED_BY_AN : KILLED_BY);
5576                     exercise(A_STR, FALSE);
5577                 }
5578             }
5579         }
5580     }
5581     return;
5582 }
5583
5584 int
5585 destroy_mitem(mtmp, osym, dmgtyp)
5586 struct monst *mtmp;
5587 int osym, dmgtyp;
5588 {
5589     struct obj *obj, *obj2;
5590     int skip, tmp = 0;
5591     long i, cnt, quan;
5592     int dindx;
5593     boolean vis;
5594
5595     if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5596         destroy_item(osym, dmgtyp);
5597         return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5598     }
5599
5600     vis = canseemon(mtmp);
5601     for (obj = mtmp->minvent; obj; obj = obj2) {
5602         obj2 = obj->nobj;
5603         if (obj->oclass != osym)
5604             continue; /* test only objs of type osym */
5605         skip = 0;
5606         quan = 0L;
5607         dindx = 0;
5608
5609         switch (dmgtyp) {
5610         case AD_COLD:
5611             if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5612                 quan = obj->quan;
5613                 dindx = 0;
5614                 tmp++;
5615             } else
5616                 skip++;
5617             break;
5618         case AD_FIRE:
5619             if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5620                 skip++;
5621             if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5622                 skip++;
5623                 if (vis)
5624 #if 0 /*JP*/
5625                     pline("%s glows a strange %s, but remains intact.",
5626                           The(distant_name(obj, xname)), hcolor("dark red"));
5627 #else
5628                     pline("%s\82Í\8aï\96­\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
5629                           The(distant_name(obj, xname)), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
5630 #endif
5631             }
5632             quan = obj->quan;
5633             switch (osym) {
5634             case POTION_CLASS:
5635                 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5636                 tmp++;
5637                 break;
5638             case SCROLL_CLASS:
5639                 dindx = 3;
5640                 tmp++;
5641                 break;
5642             case SPBOOK_CLASS:
5643                 dindx = 4;
5644                 tmp++;
5645                 break;
5646             case FOOD_CLASS:
5647                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5648                     dindx = 1; /* boil and explode */
5649                     tmp += (obj->owt + 19) / 20;
5650                 } else {
5651                     skip++;
5652                 }
5653                 break;
5654             default:
5655                 skip++;
5656                 break;
5657             }
5658             break;
5659         case AD_ELEC:
5660             quan = obj->quan;
5661             switch (osym) {
5662             case RING_CLASS:
5663                 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5664                     skip++;
5665                     break;
5666                 }
5667                 dindx = 5;
5668                 break;
5669             case WAND_CLASS:
5670                 if (obj->otyp == WAN_LIGHTNING) {
5671                     skip++;
5672                     break;
5673                 }
5674                 dindx = 6;
5675                 tmp++;
5676                 break;
5677             default:
5678                 skip++;
5679                 break;
5680             }
5681             break;
5682         default:
5683             skip++;
5684             break;
5685         }
5686         if (!skip) {
5687             for (i = cnt = 0L; i < quan; i++)
5688                 if (!rn2(3))
5689                     cnt++;
5690
5691             if (!cnt)
5692                 continue;
5693             if (vis)
5694 #if 0 /*JP*/
5695                 pline("%s%s %s!",
5696                       (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5697                                                            : "One of ",
5698                       (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5699                       destroy_strings[dindx][(cnt > 1L)]);
5700 #else
5701                 pline("%s%s\82Í%s\81I",
5702                       (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5703                       (cnt == obj->quan) ? "" : (cnt > 1L) ? "\82Ì\82¢\82­\82Â\82©"
5704                                                            : "\82Ì\82Ð\82Æ\82Â",
5705                       destroy_strings[dindx][(cnt > 1L)]);
5706 #endif
5707             for (i = 0; i < cnt; i++)
5708                 m_useup(mtmp, obj);
5709         }
5710     }
5711     return tmp;
5712 }
5713
5714 int
5715 resist(mtmp, oclass, damage, tell)
5716 struct monst *mtmp;
5717 char oclass;
5718 int damage, tell;
5719 {
5720     int resisted;
5721     int alev, dlev;
5722
5723     /* attack level */
5724     switch (oclass) {
5725     case WAND_CLASS:
5726         alev = 12;
5727         break;
5728     case TOOL_CLASS:
5729         alev = 10;
5730         break; /* instrument */
5731     case WEAPON_CLASS:
5732         alev = 10;
5733         break; /* artifact */
5734     case SCROLL_CLASS:
5735         alev = 9;
5736         break;
5737     case POTION_CLASS:
5738         alev = 6;
5739         break;
5740     case RING_CLASS:
5741         alev = 5;
5742         break;
5743     default:
5744         alev = u.ulevel;
5745         break; /* spell */
5746     }
5747     /* defense level */
5748     dlev = (int) mtmp->m_lev;
5749     if (dlev > 50)
5750         dlev = 50;
5751     else if (dlev < 1)
5752         dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5753
5754     resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5755     if (resisted) {
5756         if (tell) {
5757             shieldeff(mtmp->mx, mtmp->my);
5758 /*JP
5759             pline("%s resists!", Monnam(mtmp));
5760 */
5761             pline("%s\82Í\96h\82¢\82¾\81I", Monnam(mtmp));
5762         }
5763         damage = (damage + 1) / 2;
5764     }
5765
5766     if (damage) {
5767         mtmp->mhp -= damage;
5768         if (mtmp->mhp < 1) {
5769             if (m_using)
5770                 monkilled(mtmp, "", AD_RBRE);
5771             else
5772                 killed(mtmp);
5773         }
5774     }
5775     return resisted;
5776 }
5777
5778 #define MAXWISHTRY 5
5779
5780 STATIC_OVL void
5781 wishcmdassist(triesleft)
5782 int triesleft;
5783 {
5784     static NEARDATA const char *
5785         wishinfo[] = {
5786   "Wish details:",
5787   "",
5788   "Enter the name of an object, such as \"potion of monster detection\",",
5789   "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5790   "(without the quotes).",
5791   "",
5792   "For object types which come in stacks, you may specify a plural name",
5793   "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5794   "pieces\", although that aspect of your wish might not be granted.",
5795   "",
5796   "You may also specify various prefix values which might be used to",
5797   "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5798   "Most modifiers shown when viewing your inventory can be specified.",
5799   "",
5800   "You may specify 'nothing' to explicitly decline this wish.",
5801   0,
5802     },
5803         preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5804         retry_info[] =
5805                     "If you specify an unrecognized object name %s%s time%s,",
5806         retry_too[] = "a randomly chosen item will be granted.",
5807         suppress_cmdassist[] =
5808             "(Suppress this assistance with !cmdassist in your config file.)",
5809         *cardinals[] = { "zero",  "one",  "two", "three", "four", "five" },
5810         too_many[] = "too many";
5811     int i;
5812     winid win;
5813     char buf[BUFSZ];
5814
5815     win = create_nhwindow(NHW_TEXT);
5816     if (!win)
5817         return;
5818     for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5819         putstr(win, 0, wishinfo[i]);
5820     if (!u.uconduct.wishes)
5821         putstr(win, 0, preserve_wishless);
5822     putstr(win, 0, "");
5823     Sprintf(buf, retry_info,
5824             (triesleft >= 0 && triesleft < SIZE(cardinals))
5825                ? cardinals[triesleft]
5826                : too_many,
5827             (triesleft < MAXWISHTRY) ? " more" : "",
5828             plur(triesleft));
5829     putstr(win, 0, buf);
5830     putstr(win, 0, retry_too);
5831     putstr(win, 0, "");
5832     if (iflags.cmdassist)
5833         putstr(win, 0, suppress_cmdassist);
5834     display_nhwindow(win, FALSE);
5835     destroy_nhwindow(win);
5836 }
5837
5838 void
5839 makewish()
5840 {
5841     static char buf[BUFSZ] = DUMMY;
5842     char promptbuf[BUFSZ];
5843     struct obj *otmp, nothing;
5844     int tries = 0;
5845
5846     promptbuf[0] = '\0';
5847     nothing = zeroobj; /* lint suppression; only its address matters */
5848     if (flags.verbose)
5849 /*JP
5850         You("may wish for an object.");
5851 */
5852         You("\96]\82Ý\82Ì\82à\82Ì\82ð\8eè\82É\93ü\82ê\82ç\82ê\82é\81D");
5853 retry:
5854 /*JP
5855     Strcpy(promptbuf, "For what do you wish");
5856 */
5857     Strcpy(promptbuf, "(\93ú\96{\8cê\82Å)\89½\82ð\82¨\96]\82Ý");
5858     if (iflags.cmdassist && tries > 0)
5859 /*JP
5860         Strcat(promptbuf, " (enter 'help' for assistance)");
5861 */
5862         Strcat(promptbuf, " (\8f\95\82¯\82ª\95K\97v\82È\82ç 'help' \82Æ\93ü\97Í)");
5863 /*JP
5864     Strcat(promptbuf, "?");
5865 */
5866     Strcat(promptbuf, "\81H");
5867     getlin(promptbuf, buf);
5868     (void) mungspaces(buf);
5869     if (buf[0] == '\033') {
5870         buf[0] = '\0';
5871     } else if (!strcmpi(buf, "help")) {
5872         wishcmdassist(MAXWISHTRY - tries);
5873         goto retry;
5874     }
5875     /*
5876      *  Note: if they wished for and got a non-object successfully,
5877      *  otmp == &zeroobj.  That includes gold, or an artifact that
5878      *  has been denied.  Wishing for "nothing" requires a separate
5879      *  value to remain distinct.
5880      */
5881     otmp = readobjnam(buf, &nothing);
5882     if (!otmp) {
5883 /*JP
5884         pline("Nothing fitting that description exists in the game.");
5885 */
5886         pline("\82¤\81[\82ñ\81D\82»\82ñ\82È\82à\82Ì\82Í\91\8dÝ\82µ\82È\82¢\82æ\82¤\82¾\81D");
5887         if (++tries < MAXWISHTRY)
5888             goto retry;
5889         pline1(thats_enough_tries);
5890         otmp = readobjnam((char *) 0, (struct obj *) 0);
5891         if (!otmp)
5892             return; /* for safety; should never happen */
5893     } else if (otmp == &nothing) {
5894         /* explicitly wished for "nothing", presumably attempting
5895            to retain wishless conduct */
5896         return;
5897     }
5898
5899     /* KMH, conduct */
5900     u.uconduct.wishes++;
5901
5902     if (otmp != &zeroobj) {
5903         const char
5904 /*JP
5905             *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5906 */
5907             *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "\8a\8a\82è\97\8e\82¿\82½" : "\97\8e\82¿\82½"),
5908 #if 0 /*JP*/
5909             *oops_msg = (u.uswallow
5910                          ? "Oops!  %s out of your reach!"
5911                          : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5912                             || levl[u.ux][u.uy].typ < IRONBARS
5913                             || levl[u.ux][u.uy].typ >= ICE)
5914                             ? "Oops!  %s away from you!"
5915                             : "Oops!  %s to the floor!");
5916
5917         /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5918         (void) hold_another_object(otmp, oops_msg,
5919                                    The(aobjnam(otmp, verb)),
5920                                    (const char *) 0);
5921 #else
5922             *oops_msg = (u.uswallow
5923                          ? "\82¨\82Á\82Æ\81C%%s\82ª\93Í\82©\82È\82¢\82Æ\82±\82ë\82É%s\81I"
5924                          : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5925                             || levl[u.ux][u.uy].typ < IRONBARS
5926                             || levl[u.ux][u.uy].typ >= ICE)
5927                             ? "\82¨\82Á\82Æ\81C%%s\82ª\8eè\82©\82ç%s\81I"
5928                             : "\82¨\82Á\82Æ\81C%%s\82ª\8f°\82É%s\81I");
5929         char oopsbuf[BUFSZ];
5930         Sprintf(oopsbuf, oops_msg, verb);
5931
5932         (void) hold_another_object(otmp, oopsbuf,
5933                                    xname(otmp),
5934                                    (const char *) 0);
5935 #endif
5936         u.ublesscnt += rn1(100, 50); /* the gods take notice */
5937     }
5938 }
5939
5940 /*zap.c*/