OSDN Git Service

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