OSDN Git Service

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