OSDN Git Service

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