1 /* NetHack 3.6 zap.c $NHDT-Date: 1524470244 2018/04/23 07:57:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.275 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2013. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* Disintegration rays have special treatment; corpses are never left.
14 * But the routine which calculates the damage is separate from the routine
15 * which kills the monster. The damage routine returns this cookie to
16 * indicate that the monster should be disintegrated.
18 #define MAGIC_COOKIE 1000
20 static NEARDATA boolean obj_zapped;
21 static NEARDATA int poly_zapped;
23 extern boolean notonhead; /* for long worms */
25 /* kludge to use mondied instead of killed */
26 extern boolean m_using;
28 STATIC_DCL void FDECL(polyuse, (struct obj *, int, int));
29 STATIC_DCL void FDECL(create_polymon, (struct obj *, int));
30 STATIC_DCL int FDECL(stone_to_flesh_obj, (struct obj *));
31 STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
32 STATIC_DCL void FDECL(zhitu, (int, int, const char *, XCHAR_P, XCHAR_P));
33 STATIC_DCL void FDECL(revive_egg, (struct obj *));
34 STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
35 STATIC_DCL void FDECL(skiprange, (int, int *, int *));
37 STATIC_DCL int FDECL(zap_hit, (int, int));
38 STATIC_OVL void FDECL(disintegrate_mon, (struct monst *, int, const char *));
39 STATIC_DCL void FDECL(backfire, (struct obj *));
40 STATIC_DCL int FDECL(spell_hit_bonus, (int));
42 #define ZT_MAGIC_MISSILE (AD_MAGM - 1)
43 #define ZT_FIRE (AD_FIRE - 1)
44 #define ZT_COLD (AD_COLD - 1)
45 #define ZT_SLEEP (AD_SLEE - 1)
46 #define ZT_DEATH (AD_DISN - 1) /* or disintegration */
47 #define ZT_LIGHTNING (AD_ELEC - 1)
48 #define ZT_POISON_GAS (AD_DRST - 1)
49 #define ZT_ACID (AD_ACID - 1)
50 /* 8 and 9 are currently unassigned */
52 #define ZT_WAND(x) (x)
53 #define ZT_SPELL(x) (10 + (x))
54 #define ZT_BREATH(x) (20 + (x))
56 #define is_hero_spell(type) ((type) >= 10 && (type) < 20)
58 #define M_IN_WATER(ptr) \
59 ((ptr)->mlet == S_EEL || amphibious(ptr) || is_swimmer(ptr))
61 STATIC_VAR const char are_blinded_by_the_flash[] =
63 "are blinded by the flash!";
65 "
\82Ü
\82Î
\82ä
\82¢
\8cõ
\82Å
\96Ú
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½
\81I";
67 const char *const flash_types[] = /* also used in buzzmu(mcastu.c) */
70 "magic missile", /* Wands must be 0-9 */
71 "bolt of fire", "bolt of cold", "sleep ray", "death ray",
72 "bolt of lightning", "", "", "", "",
74 "
\96\82\96@
\82Ì
\96î", /* Wands must be 0-9 */
79 "
\88î
\8dÈ
\82Ì
\91M
\8cõ",
87 "magic missile", /* Spell equivalents must be 10-19 */
88 "fireball", "cone of cold", "sleep ray", "finger of death",
89 "bolt of lightning", /* there is no spell, used for retribution */
92 "
\96\82\96@
\82Ì
\96î", /* Spell equivalents must be 10-19 */
97 "
\88î
\8dÈ
\82Ì
\91M
\8cõ", /* There is no spell, used for retribution */
105 "blast of missiles", /* Dragon breath equivalents 20-29*/
106 "blast of fire", "blast of frost", "blast of sleep gas",
107 "blast of disintegration", "blast of lightning",
108 "blast of poison gas", "blast of acid", "", ""
110 "
\96\82\96@
\82Ì
\96î
\82Ì
\91§", /* Dragon breath equivalents 20-29*/
113 "
\90\87\96°
\83K
\83X
\82Ì
\91§",
116 "
\93Å
\83K
\83X
\82Ì
\91§",
124 * Recognizing unseen wands by zapping: in 3.4.3 and earlier, zapping
125 * most wand types while blind would add that type to the discoveries
126 * list even if it had never been seen (ie, picked up while blinded
127 * and shown in inventory as simply "a wand"). This behavior has been
128 * changed; now such wands won't be discovered. But if the type is
129 * already discovered, then the individual wand whose effect was just
130 * observed will be flagged as if seen. [You already know wands of
131 * striking; you zap "a wand" and observe striking effect (presumably
132 * by sound or touch); it'll become shown in inventory as "a wand of
135 * Unfortunately, the new behavior isn't really correct either. There
136 * should be an `eknown' bit for "effect known" added for wands (and
137 * for potions since quaffing one of a stack is similar) so that the
138 * particular wand which has been zapped would have its type become
139 * known (it would change from "a wand" to "a wand of striking", for
140 * example) without the type becoming discovered or other unknown wands
141 * of that type showing additional information. When blindness ends,
142 * all objects in inventory with the eknown bit set would be discovered
143 * and other items of the same type would become known as such.
146 /* wand discovery gets special handling when hero is blinded */
151 /* For a wand (or wand-like tool) zapped by the player, if the
152 effect was observable (determined by caller; usually seen, but
153 possibly heard or felt if the hero is blinded) then discover the
154 object type provided that the object itself is known (as more
155 than just "a wand"). If object type is already discovered and
156 we observed the effect, mark the individual wand as having been
157 seen. Suppress spells (which use fake spellbook object for `obj')
158 so that casting a spell won't re-discover its forgotten book. */
159 if (obj->oclass != SPBOOK_CLASS) {
160 /* if type already discovered, treat this item has having been seen
161 even if hero is currently blinded (skips redundant makeknown) */
162 if (objects[obj->otyp].oc_name_known) {
163 obj->dknown = 1; /* will usually be set already */
165 /* otherwise discover it if item itself has been or can be seen */
167 /* in case it was picked up while blind and then zapped without
168 examining inventory after regaining sight (bypassing xname) */
171 /* make the discovery iff we know what we're manipulating */
173 makeknown(obj->otyp);
178 /* Routines for IMMEDIATE wands and spells. */
179 /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
185 boolean wake = TRUE; /* Most 'zaps' should wake monster */
186 boolean reveal_invis = FALSE, learn_it = FALSE;
187 boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
188 boolean helpful_gesture = FALSE;
189 int dmg, otyp = otmp->otyp;
191 const char *zap_type_text = "spell";
193 const char *zap_type_text = "
\96\82\96@";
195 boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC
196 && mtmp->m_ap_type != M_AP_NOTHING);
198 if (u.uswallow && mtmp == u.ustuck)
199 reveal_invis = FALSE;
201 notonhead = (mtmp->mx != bhitpos.x || mtmp->my != bhitpos.y);
205 zap_type_text = "wand";
207 zap_type_text = "
\8fñ";
213 if (resists_magm(mtmp)) { /* match effect on player */
214 shieldeff(mtmp->mx, mtmp->my);
218 pline("
\83{
\83C
\83\93\81I");
219 break; /* skip makeknown */
220 } else if (u.uswallow || rnd(20) < 10 + find_mac(mtmp)) {
224 if (otyp == SPE_FORCE_BOLT)
225 dmg = spell_damage_bonus(dmg);
226 hit(zap_type_text, mtmp, exclam(dmg));
227 (void) resist(mtmp, otmp->oclass, dmg, TELL);
229 miss(zap_type_text, mtmp);
232 case WAN_SLOW_MONSTER:
233 case SPE_SLOW_MONSTER:
234 if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
237 mon_adjust_speed(mtmp, -1, otmp);
238 m_dowear(mtmp, FALSE); /* might want speed boots */
239 if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) {
241 You("disrupt %s!", mon_nam(mtmp));
243 You("%s
\82ð
\83o
\83\89\83o
\83\89\82É
\82µ
\82½
\81I", mon_nam(mtmp));
245 pline("A huge hole opens up...");
247 pline("
\92E
\8fo
\82Å
\82«
\82»
\82¤
\82È
\8c\8a\82ª
\8aJ
\82¢
\82½
\81D
\81D
\81D");
248 expels(mtmp, mtmp->data, TRUE);
252 case WAN_SPEED_MONSTER:
253 if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
256 mon_adjust_speed(mtmp, 1, otmp);
257 m_dowear(mtmp, FALSE); /* might want speed boots */
260 helpful_gesture = TRUE;
262 case WAN_UNDEAD_TURNING:
263 case SPE_TURN_UNDEAD:
265 if (unturn_dead(mtmp))
267 if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
273 if (otyp == SPE_TURN_UNDEAD)
274 dmg = spell_damage_bonus(dmg);
275 context.bypasses = TRUE; /* for make_corpse() */
276 if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) {
278 monflee(mtmp, 0, FALSE, TRUE);
285 if (resists_magm(mtmp)) {
286 /* magic resistance protects from polymorph traps, so make
287 it guard against involuntary polymorph attacks too... */
288 shieldeff(mtmp->mx, mtmp->my);
289 } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
290 boolean polyspot = (otyp != POT_POLYMORPH),
291 give_msg = (!Hallucination
293 || (u.uswallow && mtmp == u.ustuck)));
295 /* dropped inventory (due to death by system shock,
296 or loss of wielded weapon and/or worn armor due to
297 limitations of new shape) won't be hit by this zap */
299 for (obj = mtmp->minvent; obj; obj = obj->nobj)
301 /* natural shapechangers aren't affected by system shock
302 (unless protection from shapechangers is interfering
303 with their metabolism...) */
304 if (mtmp->cham == NON_PM && !rn2(25)) {
305 if (canseemon(mtmp)) {
307 pline("%s shudders!", Monnam(mtmp));
309 pline("%s
\82Í
\90g
\90k
\82¢
\82µ
\82½
\81I", Monnam(mtmp));
312 /* context.bypasses = TRUE; ## for make_corpse() */
313 /* no corpse after system shock */
314 xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
315 } else if (newcham(mtmp, (struct permonst *) 0,
316 polyspot, give_msg) != 0
317 /* if shapechange failed because there aren't
318 enough eligible candidates (most likely for
319 vampshifter), try reverting to original form */
320 || (mtmp->cham >= LOW_PM
321 && newcham(mtmp, &mons[mtmp->cham],
322 polyspot, give_msg) != 0)) {
323 if (give_msg && (canspotmon(mtmp)
324 || (u.uswallow && mtmp == u.ustuck)))
329 case WAN_CANCELLATION:
330 case SPE_CANCELLATION:
333 (void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
335 case WAN_TELEPORTATION:
336 case SPE_TELEPORT_AWAY:
339 reveal_invis = !u_teleport_mon(mtmp, TRUE);
341 case WAN_MAKE_INVISIBLE: {
342 int oldinvis = mtmp->minvis;
347 /* format monster's name before altering its visibility */
348 Strcpy(nambuf, Monnam(mtmp));
349 mon_set_minvis(mtmp);
350 if (!oldinvis && knowninvisible(mtmp)) {
352 pline("%s turns transparent!", nambuf);
354 pline("%s
\82Í
\93§
\96¾
\82É
\82È
\82Á
\82½
\81I", nambuf);
361 case SPE_WIZARD_LOCK:
362 wake = closeholdingtrap(mtmp, &learn_it);
372 wake = FALSE; /* don't want immediate counterattack */
373 if (u.uswallow && mtmp == u.ustuck) {
374 if (is_animal(mtmp->data)) {
377 You_feel("a sudden rush of air!");
379 You("
\93Ë
\91R
\8c\83\82µ
\82¢
\8bó
\8bC
\82Ì
\97¬
\82ê
\82ð
\8a´
\82¶
\82½
\81I");
382 pline("%s opens its mouth!", Monnam(mtmp));
384 pline("%s
\82Í
\8cû
\82ð
\8aJ
\82¢
\82½
\81I", Monnam(mtmp));
386 expels(mtmp, mtmp->data, TRUE);
387 /* zap which hits steed will only release saddle if it
388 doesn't hit a holding or falling trap; playability
389 here overrides the more logical target ordering */
390 } else if (openholdingtrap(mtmp, &learn_it)) {
392 } else if (openfallingtrap(mtmp, TRUE, &learn_it)) {
393 /* mtmp might now be on the migrating monsters list */
395 } else if ((obj = which_armor(mtmp, W_SADDLE)) != 0) {
399 Sprintf(buf, "%s %s", s_suffix(Monnam(mtmp)),
400 distant_name(obj, xname));
402 Sprintf(buf, "%s
\82Ì%s", Monnam(mtmp),
403 distant_name(obj, xname));
405 if (cansee(mtmp->mx, mtmp->my)) {
406 if (!canspotmon(mtmp))
407 Strcpy(buf, An(distant_name(obj, xname)));
409 pline("%s falls to the %s.", buf,
410 surface(mtmp->mx, mtmp->my));
412 pline("%s
\82Í%s
\82É
\97\8e\82¿
\82½
\81D", buf,
413 surface(mtmp->mx, mtmp->my));
415 } else if (canspotmon(mtmp)) {
417 pline("%s falls off.", buf);
419 pline("%s
\82ª
\97\8e\82¿
\82½
\81D", buf);
421 obj_extract_self(obj);
422 mdrop_obj(mtmp, obj, FALSE);
426 case SPE_EXTRA_HEALING:
428 if (mtmp->data != &mons[PM_PESTILENCE]) {
429 wake = FALSE; /* wakeup() makes the target angry */
430 mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4);
431 if (mtmp->mhp > mtmp->mhpmax)
432 mtmp->mhp = mtmp->mhpmax;
433 if (mtmp->mblinded) {
437 if (canseemon(mtmp)) {
438 if (disguised_mimic) {
439 if (is_obj_mappear(mtmp,STRANGE_OBJECT)) {
440 /* it can do better now */
442 newsym(mtmp->mx, mtmp->my);
444 mimic_hit_msg(mtmp, otyp);
447 pline("%s looks%s better.", Monnam(mtmp),
448 otyp == SPE_EXTRA_HEALING ? " much" : "");
450 pline("%s
\82Í%s
\8c³
\8bC
\82É
\82È
\82Á
\82½
\82æ
\82¤
\82¾
\81D", Monnam(mtmp),
451 otyp == SPE_EXTRA_HEALING ? "
\82Æ
\82Ä
\82à" : "" );
454 if (mtmp->mtame || mtmp->mpeaceful) {
455 adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
457 } else { /* Pestilence */
458 /* Pestilence will always resist; damage is half of 3d{4,8} */
459 (void) resist(mtmp, otmp->oclass,
460 d(3, otyp == SPE_EXTRA_HEALING ? 8 : 4), TELL);
463 case WAN_LIGHT: /* (broken wand) */
464 if (flash_hits_mon(mtmp, otmp)) {
469 case WAN_SLEEP: /* (broken wand) */
470 /* [wakeup() doesn't rouse victims of temporary sleep,
471 so it's okay to leave `wake' set to TRUE here] */
473 if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS))
478 case SPE_STONE_TO_FLESH:
479 if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
480 char *name = Monnam(mtmp);
482 /* turn into flesh golem */
483 if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE, FALSE)) {
486 pline("%s turns to flesh!", name);
488 pline("%s
\82Ì
\90Î
\89»
\82ª
\89ð
\82¯
\82½
\81I", name);
492 pline("%s looks rather fleshy for a moment.", name);
494 pline("%s
\82Í
\88ê
\8fu
\90Î
\89»
\82ª
\89ð
\82¯
\82½
\81D", name);
502 dmg = monhp_per_lvl(mtmp);
505 if (otyp == SPE_DRAIN_LIFE)
506 dmg = spell_damage_bonus(dmg);
507 if (resists_drli(mtmp)) {
508 shieldeff(mtmp->mx, mtmp->my);
509 } else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
512 /* die if already level 0, regardless of hit points */
513 if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) {
519 pline("%s suddenly seems weaker!", Monnam(mtmp));
521 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\8eã
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I", Monnam(mtmp));
529 impossible("What an interesting effect (%d)", otyp);
534 wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
536 if (mtmp->isshk && !*u.ushops)
538 } else if (mtmp->m_ap_type)
539 seemimic(mtmp); /* might unblock if mimicing a boulder/door */
541 /* note: bhitpos won't be set if swallowed, but that's okay since
542 * reveal_invis will be false. We can't use mtmp->mx, my since it
543 * might be an invisible worm hit on the tail.
546 if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y)
547 && !canspotmon(mtmp))
548 map_invisible(bhitpos.x, bhitpos.y);
550 /* if effect was observable then discover the wand type provided
551 that the wand itself has been seen */
565 return; /* don't show minvent for long worm tail */
568 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
569 otmp->dknown = 1; /* treat as "seen" */
570 if (Is_container(otmp) || otmp->otyp == STATUE) {
572 if (!SchroedingersBox(otmp))
576 (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET | PICK_NONE,
580 pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
581 (u.uswallow && mtmp == u.ustuck) ? " besides you" : "");
583 pline("%s
\82Í%s
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", noit_Monnam(mtmp),
584 (u.uswallow && mtmp == u.ustuck) ? "
\82 \82È
\82½
\88È
\8aO
\82É" : "");
590 * Return the object's physical location. This only makes sense for
591 * objects that are currently on the level (i.e. migrating objects
592 * are nowhere). By default, only things that can be seen (in hero's
593 * inventory, monster's inventory, or on the ground) are reported.
594 * By adding BURIED_TOO and/or CONTAINED_TOO flags, you can also get
595 * the location of buried and contained objects. Note that if an
596 * object is carried by a monster, its reported position may change
597 * from turn to turn. This function returns FALSE if the position
598 * is not available or subject to the constraints above.
601 get_obj_location(obj, xp, yp, locflags)
606 switch (obj->where) {
616 if (obj->ocarry->mx) {
617 *xp = obj->ocarry->mx;
618 *yp = obj->ocarry->my;
621 break; /* !mx => migrating monster */
623 if (locflags & BURIED_TOO) {
630 if (locflags & CONTAINED_TOO)
631 return get_obj_location(obj->ocontainer, xp, yp, locflags);
639 get_mon_location(mon, xp, yp, locflags)
642 int locflags; /* non-zero means get location even if monster is buried */
644 if (mon == &youmonst) {
648 } else if (mon->mx > 0 && (!mon->mburied || locflags)) {
652 } else { /* migrating or buried */
658 /* used by revive() and animate_statue() */
664 struct monst *mtmp = (struct monst *) 0;
665 struct monst *mtmp2 = (struct monst *) 0;
668 mtmp2 = get_mtraits(obj, TRUE);
670 /* save_mtraits() validated mtmp2->mnum */
671 mtmp2->data = &mons[mtmp2->mnum];
672 if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
673 return (struct monst *) 0;
674 mtmp = makemon(mtmp2->data, cc->x, cc->y,
675 NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
679 /* heal the monster */
680 if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data))
681 mtmp2->mhpmax = mtmp->mhpmax;
682 mtmp2->mhp = mtmp2->mhpmax;
683 /* Get these ones from mtmp */
684 mtmp2->minvent = mtmp->minvent; /*redundant*/
685 /* monster ID is available if the monster died in the current
686 game, but will be zero if the corpse was in a bones level
687 (we cleared it when loading bones) */
689 mtmp2->m_id = mtmp->m_id;
690 /* might be bringing quest leader back to life */
691 if (quest_status.leader_is_dead
692 /* leader_is_dead implies leader_m_id is valid */
693 && mtmp2->m_id == quest_status.leader_m_id)
694 quest_status.leader_is_dead = FALSE;
696 mtmp2->mx = mtmp->mx;
697 mtmp2->my = mtmp->my;
698 mtmp2->mux = mtmp->mux;
699 mtmp2->muy = mtmp->muy;
700 mtmp2->mw = mtmp->mw;
701 mtmp2->wormno = mtmp->wormno;
702 mtmp2->misc_worn_check = mtmp->misc_worn_check;
703 mtmp2->weapon_check = mtmp->weapon_check;
704 mtmp2->mtrapseen = mtmp->mtrapseen;
705 mtmp2->mflee = mtmp->mflee;
706 mtmp2->mburied = mtmp->mburied;
707 mtmp2->mundetected = mtmp->mundetected;
708 mtmp2->mfleetim = mtmp->mfleetim;
709 mtmp2->mlstmv = mtmp->mlstmv;
710 mtmp2->m_ap_type = mtmp->m_ap_type;
711 /* set these ones explicitly */
717 mtmp2->msleeping = 0;
720 /* most cancelled monsters return to normal,
721 but some need to stay cancelled */
722 if (!dmgtype(mtmp2->data, AD_SEDU)
723 && (!SYSOPT_SEDUCE || !dmgtype(mtmp2->data, AD_SSEX)))
725 mtmp2->mcansee = 1; /* set like in makemon */
729 /* when traits are for a shopeekper, dummy monster 'mtmp' won't
730 have necessary eshk data for replmon() -> replshk() */
733 *ESHK(mtmp) = *ESHK(mtmp2);
734 if (ESHK(mtmp2)->bill_p != 0
735 && ESHK(mtmp2)->bill_p != (struct bill_x *) -1000)
736 ESHK(mtmp)->bill_p = &(ESHK(mtmp)->bill[0]);
739 replmon(mtmp, mtmp2);
740 newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
742 /* in case Protection_from_shape_changers is different
743 now than it was when the traits were stored */
750 * get_container_location() returns the following information
751 * about the outermost container:
752 * loc argument gets set to:
753 * OBJ_INVENT if in hero's inventory; return 0.
754 * OBJ_FLOOR if on the floor; return 0.
755 * OBJ_BURIED if buried; return 0.
756 * OBJ_MINVENT if in monster's inventory; return monster.
757 * container_nesting is updated with the nesting depth of the containers
761 get_container_location(obj, loc, container_nesting)
764 int *container_nesting;
769 if (container_nesting)
770 *container_nesting = 0;
771 while (obj && obj->where == OBJ_CONTAINED) {
772 if (container_nesting)
773 *container_nesting += 1;
774 obj = obj->ocontainer;
777 *loc = obj->where; /* outermost container's location */
778 if (obj->where == OBJ_MINVENT)
781 return (struct monst *) 0;
785 * Attempt to revive the given corpse, return the revived monster if
786 * successful. Note: this does NOT use up the corpse if it fails.
787 * If corpse->quan is more than 1, only one corpse will be affected
788 * and only one monster will be resurrected.
791 revive(corpse, by_hero)
795 struct monst *mtmp = 0;
796 struct permonst *mptr;
797 struct obj *container;
801 int montype, container_nesting = 0;
803 if (corpse->otyp != CORPSE) {
804 impossible("Attempting to revive %s?", xname(corpse));
805 return (struct monst *) 0;
809 if (corpse->where != OBJ_CONTAINED) {
810 /* only for invent, minvent, or floor */
812 (void) get_obj_location(corpse, &x, &y, 0);
814 /* deal with corpses in [possibly nested] containers */
815 struct monst *carrier;
816 int holder = OBJ_FREE;
818 container = corpse->ocontainer;
820 get_container_location(container, &holder, &container_nesting);
823 x = carrier->mx, y = carrier->my;
829 (void) get_obj_location(corpse, &x, &y, CONTAINED_TOO);
832 break; /* x,y are 0 */
836 /* Rules for revival from containers:
837 * - the container cannot be locked
838 * - the container cannot be heavily nested (>2 is arbitrary)
839 * - the container cannot be a statue or bag of holding
840 * (except in very rare cases for the latter)
842 || (container && (container->olocked || container_nesting > 2
843 || container->otyp == STATUE
844 || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
845 return (struct monst *) 0;
847 /* record the object's location now that we're sure where it is */
848 corpse->ox = x, corpse->oy = y;
850 /* prepare for the monster */
851 montype = corpse->corpsenm;
852 mptr = &mons[montype];
853 /* [should probably handle recorporealization first; if corpse and
854 ghost are at same location, revived creature shouldn't be bumped
855 to an adjacent spot by ghost which joins with it] */
857 if (enexto(&xy, x, y, mptr))
861 if ((mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ))
862 || (mons[montype].mlet == S_TROLL
863 && uwep && uwep->oartifact == ART_TROLLSBANE)) {
864 if (by_hero && cansee(x,y))
866 pline("%s twitches feebly.",
868 pline("%s
\82Í
\82í
\82¸
\82©
\82Éáz
\9d¹
\82µ
\82½
\81D",
869 upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
870 return (struct monst *) 0;
873 if (cant_revive(&montype, TRUE, corpse)) {
874 /* make a zombie or doppelganger instead */
875 /* note: montype has changed; mptr keeps old value for newcham() */
876 mtmp = makemon(&mons[montype], x, y, NO_MINVENT | MM_NOWAIT);
878 /* skip ghost handling */
879 if (has_omid(corpse))
881 if (has_omonst(corpse))
883 if (mtmp->cham == PM_DOPPELGANGER) {
884 /* change shape to match the corpse */
885 (void) newcham(mtmp, mptr, FALSE, FALSE);
886 } else if (mtmp->data->mlet == S_ZOMBIE) {
887 mtmp->mhp = mtmp->mhpmax = 100;
888 mon_adjust_speed(mtmp, 2, (struct obj *) 0); /* MFAST */
891 } else if (has_omonst(corpse)) {
892 /* use saved traits */
894 mtmp = montraits(corpse, &xy);
895 if (mtmp && mtmp->mtame && !mtmp->isminion)
896 wary_dog(mtmp, TRUE);
898 /* make a new monster */
899 mtmp = makemon(mptr, x, y, NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
902 return (struct monst *) 0;
904 /* hiders shouldn't already be re-hidden when they revive */
905 if (mtmp->mundetected) {
906 mtmp->mundetected = 0;
907 newsym(mtmp->mx, mtmp->my);
912 one_of = (corpse->quan > 1L);
914 corpse = splitobj(corpse, 1L);
916 /* if this is caused by the hero there might be a shop charge */
918 struct monst *shkp = 0;
920 x = corpse->ox, y = corpse->oy;
921 if (costly_spot(x, y)
922 && (carried(corpse) ? corpse->unpaid : !corpse->no_charge))
923 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
927 unsigned pfx = CXN_PFX_THE;
929 #if 1 /*JP*//*
\8e\80\91Ì
\96¼
\82Í
\90æ
\82É */
930 Strcpy(buf, corpse_xname(corpse, (const char *) 0, pfx));
933 Strcpy(buf, one_of ? "one of " : "");
934 #else /*
\8cê
\8f\87\82Í
\95Ï
\82í
\82Á
\82Ä
\82¢
\82é */
936 Strcat(buf, "
\82Ì
\88ê
\82Â");
939 #if 0 /*JP*//*
\82±
\82±
\82Å
\81u
\82 \82È
\82½
\82Ì
\81v
\82Í
\95s
\8e©
\91R */
940 if (carried(corpse) && !corpse->unpaid) {
941 Strcat(buf, "your ");
946 corpse->quan++; /* force plural */
947 #if 0 /*JP*//*
\8aù
\82É
\90Ý
\92è
\8dÏ
\82Ý */
948 Strcat(buf, corpse_xname(corpse, (const char *) 0, pfx));
950 if (one_of) /* could be simplified to ''corpse->quan = 1L;'' */
953 pline("%s glows iridescently.", upstart(buf));
955 pline("%s
\82Í
\93ø
\90F
\82É
\8bP
\82¢
\82½
\81D", upstart(buf));
957 /* need some prior description of the corpse since
958 stolen_value() will refer to the object as "it" */
960 pline("A corpse is resuscitated.");
962 pline("
\8e\80\91Ì
\82ª
\91h
\90¶
\82µ
\82½
\81D");
964 /* don't charge for shopkeeper's own corpse if we just revived him */
965 if (shkp && mtmp != shkp)
966 (void) stolen_value(corpse, x, y, (boolean) shkp->mpeaceful,
969 /* [we don't give any comparable message about the corpse for
970 the !by_hero case because caller might have already done so] */
973 /* handle recorporealization of an active ghost */
974 if (has_omid(corpse)) {
979 (void) memcpy((genericptr_t) &m_id, (genericptr_t) OMID(corpse),
981 ghost = find_mid(m_id, FM_FMON);
982 if (ghost && ghost->data == &mons[PM_GHOST]) {
983 if (canseemon(ghost))
985 pline("%s is suddenly drawn into its former body!",
987 pline("%s
\82Í
\93Ë
\91R
\82à
\82Æ
\82Ì
\91Ì
\82É
\88ø
\82«
\8d\9e\82Ü
\82ê
\82½
\81I",
990 /* transfer the ghost's inventory along with it */
991 while ((otmp = ghost->minvent) != 0) {
992 obj_extract_self(otmp);
993 add_to_minv(mtmp, otmp);
995 /* tame the revived monster if its ghost was tame */
996 if (ghost->mtame && !mtmp->mtame) {
997 if (tamedog(mtmp, (struct obj *) 0)) {
998 /* ghost's edog data is ignored */
999 mtmp->mtame = ghost->mtame;
1002 /* was ghost, now alive, it's all very confusing */
1004 /* separate ghost monster no longer exists */
1010 /* monster retains its name */
1011 if (has_oname(corpse) && !unique_corpstat(mtmp->data))
1012 mtmp = christen_monst(mtmp, ONAME(corpse));
1013 /* partially eaten corpse yields wounded monster */
1015 mtmp->mhp = eaten_stat(mtmp->mhp, corpse);
1016 /* track that this monster was revived at least once */
1019 /* finally, get rid of the corpse--it's gone now */
1020 switch (corpse->where) {
1025 /* in case MON_AT+enexto for invisible mon */
1026 x = corpse->ox, y = corpse->oy;
1027 /* not useupf(), which charges */
1028 if (corpse->quan > 1L)
1029 corpse = splitobj(corpse, 1L);
1034 m_useup(corpse->ocarry, corpse);
1037 obj_extract_self(corpse);
1038 obfree(corpse, (struct obj *) 0);
1052 * Note: generic eggs with corpsenm set to NON_PM will never hatch.
1054 if (obj->otyp != EGG)
1056 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1057 attach_egg_hatch_timeout(obj, 0L);
1060 /* try to revive all corpses and eggs carried by `mon' */
1065 struct obj *otmp, *otmp2;
1066 struct monst *mtmp2;
1067 char owner[BUFSZ], corpse[BUFSZ];
1071 youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
1072 otmp2 = (mon == &youmonst) ? invent : mon->minvent;
1073 owner[0] = corpse[0] = '\0'; /* lint suppression */
1075 while ((otmp = otmp2) != 0) {
1077 if (otmp->otyp == EGG)
1079 if (otmp->otyp != CORPSE)
1081 /* save the name; the object is liable to go away */
1084 corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
1085 Shk_Your(owner, otmp); /* includes a trailing space */
1088 /* for a stack, only one is revived */
1089 if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
1093 pline("%s%s suddenly comes alive!", owner, corpse);
1095 pline("%s%s
\82Í
\93Ë
\91R
\90¶
\96½
\82ð
\91Ñ
\82Ñ
\82½
\81I", owner, corpse);
1096 else if (canseemon(mtmp2))
1098 pline("%s suddenly appears!", Amonnam(mtmp2));
1100 pline("%s
\82ª
\93Ë
\91R
\8c»
\82í
\82ê
\82½
\81I", Amonnam(mtmp2));
1106 /* cancel obj, possibly carried by you or a monster */
1109 register struct obj *obj;
1111 boolean u_ring = (obj == uleft || obj == uright);
1112 int otyp = obj->otyp;
1115 case RIN_GAIN_STRENGTH:
1116 if ((obj->owornmask & W_RING) && u_ring) {
1117 ABON(A_STR) -= obj->spe;
1121 case RIN_GAIN_CONSTITUTION:
1122 if ((obj->owornmask & W_RING) && u_ring) {
1123 ABON(A_CON) -= obj->spe;
1128 if ((obj->owornmask & W_RING) && u_ring) {
1129 ABON(A_CHA) -= obj->spe;
1133 case RIN_INCREASE_ACCURACY:
1134 if ((obj->owornmask & W_RING) && u_ring)
1135 u.uhitinc -= obj->spe;
1137 case RIN_INCREASE_DAMAGE:
1138 if ((obj->owornmask & W_RING) && u_ring)
1139 u.udaminc -= obj->spe;
1141 case GAUNTLETS_OF_DEXTERITY:
1142 if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1143 ABON(A_DEX) -= obj->spe;
1147 case HELM_OF_BRILLIANCE:
1148 if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1149 ABON(A_INT) -= obj->spe;
1150 ABON(A_WIS) -= obj->spe;
1154 /* case RIN_PROTECTION: not needed */
1156 if (objects[otyp].oc_magic
1157 || (obj->spe && (obj->oclass == ARMOR_CLASS
1158 || obj->oclass == WEAPON_CLASS || is_weptool(obj)))
1160 || otyp == POT_SICKNESS
1161 || (otyp == POT_WATER && (obj->blessed || obj->cursed))) {
1162 if (obj->spe != ((obj->oclass == WAND_CLASS) ? -1 : 0)
1163 && otyp != WAN_CANCELLATION /* can't cancel cancellation */
1164 && otyp != MAGIC_LAMP /* cancelling doesn't remove djinni */
1165 && otyp != CANDELABRUM_OF_INVOCATION) {
1166 costly_alteration(obj, COST_CANCEL);
1167 obj->spe = (obj->oclass == WAND_CLASS) ? -1 : 0;
1169 switch (obj->oclass) {
1171 costly_alteration(obj, COST_CANCEL);
1172 obj->otyp = SCR_BLANK_PAPER;
1176 if (otyp != SPE_CANCELLATION && otyp != SPE_NOVEL
1177 && otyp != SPE_BOOK_OF_THE_DEAD) {
1178 costly_alteration(obj, COST_CANCEL);
1179 obj->otyp = SPE_BLANK_PAPER;
1183 costly_alteration(obj,
1186 : obj->cursed ? COST_UNCURS : COST_UNBLSS);
1187 if (otyp == POT_SICKNESS || otyp == POT_SEE_INVISIBLE) {
1188 /* sickness is "biologically contaminated" fruit juice;
1189 cancel it and it just becomes fruit juice...
1190 whereas see invisible tastes like "enchanted" fruit
1191 juice, it similarly cancels */
1192 obj->otyp = POT_FRUIT_JUICE;
1194 obj->otyp = POT_WATER;
1195 obj->odiluted = 0; /* same as any other water */
1205 /* Remove a positive enchantment or charge from obj,
1206 * possibly carried by you or a monster
1209 drain_item(obj, by_you)
1215 /* Is this a charged/enchanted object? */
1217 || (!objects[obj->otyp].oc_charged && obj->oclass != WEAPON_CLASS
1218 && obj->oclass != ARMOR_CLASS && !is_weptool(obj))
1221 if (defends(AD_DRLI, obj) || defends_when_carried(AD_DRLI, obj)
1222 || obj_resists(obj, 10, 90))
1225 /* Charge for the cost of the object */
1227 costly_alteration(obj, COST_DRAIN);
1229 /* Drain the object and any implied effects */
1231 u_ring = (obj == uleft) || (obj == uright);
1232 switch (obj->otyp) {
1233 case RIN_GAIN_STRENGTH:
1234 if ((obj->owornmask & W_RING) && u_ring) {
1239 case RIN_GAIN_CONSTITUTION:
1240 if ((obj->owornmask & W_RING) && u_ring) {
1246 if ((obj->owornmask & W_RING) && u_ring) {
1251 case RIN_INCREASE_ACCURACY:
1252 if ((obj->owornmask & W_RING) && u_ring)
1255 case RIN_INCREASE_DAMAGE:
1256 if ((obj->owornmask & W_RING) && u_ring)
1259 case RIN_PROTECTION:
1261 context.botl = 1; /* bot() will recalc u.uac */
1263 case HELM_OF_BRILLIANCE:
1264 if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1270 case GAUNTLETS_OF_DEXTERITY:
1271 if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1287 obj_resists(obj, ochance, achance)
1289 int ochance, achance; /* percent chance for ordinary objects, artifacts */
1291 if (obj->otyp == AMULET_OF_YENDOR
1292 || obj->otyp == SPE_BOOK_OF_THE_DEAD
1293 || obj->otyp == CANDELABRUM_OF_INVOCATION
1294 || obj->otyp == BELL_OF_OPENING
1295 || (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm]))) {
1298 int chance = rn2(100);
1300 return (boolean) (chance < (obj->oartifact ? achance : ochance));
1310 if (context.bypasses && obj->bypass)
1313 if (obj->oclass == WAND_CLASS)
1314 zap_odds = 3; /* half-life = 2 zaps */
1315 else if (obj->cursed)
1316 zap_odds = 3; /* half-life = 2 zaps */
1317 else if (obj->blessed)
1318 zap_odds = 12; /* half-life = 8 zaps */
1320 zap_odds = 8; /* half-life = 6 zaps */
1322 /* adjust for "large" quantities of identical things */
1326 return (boolean) !rn2(zap_odds);
1329 /* Use up at least minwt number of things made of material mat.
1330 * There's also a chance that other stuff will be used up. Finally,
1331 * there's a random factor here to keep from always using the stuff
1332 * at the top of the pile.
1335 polyuse(objhdr, mat, minwt)
1339 register struct obj *otmp, *otmp2;
1341 for (otmp = objhdr; minwt > 0 && otmp; otmp = otmp2) {
1342 otmp2 = otmp->nexthere;
1343 if (context.bypasses && otmp->bypass)
1345 if (otmp == uball || otmp == uchain)
1347 if (obj_resists(otmp, 0, 0))
1348 continue; /* preserve unique objects */
1350 if (otmp->otyp == SCR_MAIL)
1354 if (((int) objects[otmp->otyp].oc_material == mat)
1355 == (rn2(minwt + 1) != 0)) {
1356 /* appropriately add damage to bill */
1357 if (costly_spot(otmp->ox, otmp->oy)) {
1359 addtobill(otmp, FALSE, FALSE, FALSE);
1361 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE,
1364 if (otmp->quan < LARGEST_INT)
1365 minwt -= (int) otmp->quan;
1374 * Polymorph some of the stuff in this pile into a monster, preferably
1375 * a golem of the kind okind.
1378 create_polymon(obj, okind)
1382 struct permonst *mdat = (struct permonst *) 0;
1384 const char *material;
1387 if (context.bypasses) {
1388 /* this is approximate because the "no golems" !obj->nexthere
1389 check below doesn't understand bypassed objects; but it
1390 should suffice since bypassed objects always end up as a
1391 consecutive group at the top of their pile */
1392 while (obj && obj->bypass)
1393 obj = obj->nexthere;
1396 /* no golems if you zap only one object -- not enough stuff */
1397 if (!obj || (!obj->nexthere && obj->quan == 1L))
1400 /* some of these choices are arbitrary */
1405 pm_index = PM_IRON_GOLEM;
1407 material = "metal ";
1409 material = "
\8bà
\91®";
1416 pm_index = rn2(2) ? PM_STONE_GOLEM : PM_CLAY_GOLEM;
1418 material = "lithic ";
1420 material = "
\8dz
\95¨";
1424 /* there is no flesh type, but all food is type 0, so we use it */
1425 pm_index = PM_FLESH_GOLEM;
1427 material = "organic ";
1429 material = "
\97L
\8b@
\95¨";
1432 pm_index = PM_WOOD_GOLEM;
1436 material = "
\96Ø
\8dÞ";
1439 pm_index = PM_LEATHER_GOLEM;
1441 material = "leather ";
1446 pm_index = PM_ROPE_GOLEM;
1448 material = "cloth ";
1453 pm_index = PM_SKELETON; /* nearest thing to "bone golem" */
1457 material = "
\8d\9c";
1460 pm_index = PM_GOLD_GOLEM;
1467 pm_index = PM_GLASS_GOLEM;
1469 material = "glassy ";
1471 material = "
\83K
\83\89\83X";
1474 pm_index = PM_PAPER_GOLEM;
1476 material = "paper ";
1478 material = "
\8e\86";
1481 /* if all else fails... */
1482 pm_index = PM_STRAW_GOLEM;
1486 material = "
\95¨
\91Ì";
1491 if (!(mvitals[pm_index].mvflags & G_GENOD))
1492 mdat = &mons[pm_index];
1494 mtmp = makemon(mdat, obj->ox, obj->oy, NO_MM_FLAGS);
1495 polyuse(obj, okind, (int) mons[pm_index].cwt);
1497 if (mtmp && cansee(mtmp->mx, mtmp->my)) {
1499 pline("Some %sobjects meld, and %s arises from the pile!", material,
1502 pline("
\82¢
\82
\82Â
\82©
\82Ì%s
\82ª
\97n
\82¯
\81C
\82»
\82Ì
\8eR
\82©
\82ç%s
\82ª
\8c»
\82í
\82ê
\82½
\81I", material,
1508 /* Assumes obj is on the floor. */
1516 if (obj->otyp == SCR_MAIL)
1521 if (poly_zapped < 0) {
1522 /* some may metamorphosize */
1523 for (i = obj->quan; i; i--)
1524 if (!rn2(Luck + 45)) {
1525 poly_zapped = objects[obj->otyp].oc_material;
1530 /* if quan > 1 then some will survive intact */
1531 if (obj->quan > 1L) {
1532 if (obj->quan > LARGEST_INT)
1533 obj = splitobj(obj, (long) rnd(30000));
1535 obj = splitobj(obj, (long) rnd((int) obj->quan - 1));
1538 /* appropriately add damage to bill */
1539 if (costly_spot(obj->ox, obj->oy)) {
1541 addtobill(obj, FALSE, FALSE, FALSE);
1543 (void) stolen_value(obj, obj->ox, obj->oy, FALSE, FALSE);
1546 /* zap the object */
1550 /* classes of items whose current charge count carries over across polymorph
1552 static const char charged_objs[] = { WAND_CLASS, WEAPON_CLASS, ARMOR_CLASS,
1556 * Polymorph the object to the given object ID. If the ID is STRANGE_OBJECT
1557 * then pick random object from the source's class (this is the standard
1558 * "polymorph" case). If ID is set to a specific object, inhibit fusing
1559 * n objects into 1. This could have been added as a flag, but currently
1560 * it is tied to not being the standard polymorph case. The new polymorphed
1561 * object replaces obj in its link chains. Return value is a pointer to
1564 * This should be safe to call for an object anywhere.
1573 boolean can_merge = (id == STRANGE_OBJECT);
1574 int obj_location = obj->where;
1576 if (obj->otyp == BOULDER)
1578 if (id == STRANGE_OBJECT) { /* preserve symbol */
1580 unsigned magic_obj = objects[obj->otyp].oc_magic;
1582 if (obj->otyp == UNICORN_HORN && obj->degraded_horn)
1584 /* Try up to 3 times to make the magic-or-not status of
1585 the new item be the same as it was for the old one. */
1586 otmp = (struct obj *) 0;
1590 otmp = mkobj(obj->oclass, FALSE);
1591 } while (--try_limit > 0
1592 && objects[otmp->otyp].oc_magic != magic_obj);
1594 /* literally replace obj with this new thing */
1595 otmp = mksobj(id, FALSE, FALSE);
1596 /* Actually more things use corpsenm but they polymorph differently */
1597 #define USES_CORPSENM(typ) \
1598 ((typ) == CORPSE || (typ) == STATUE || (typ) == FIGURINE)
1600 if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
1601 set_corpsenm(otmp, obj->corpsenm);
1602 #undef USES_CORPSENM
1605 /* preserve quantity */
1606 otmp->quan = obj->quan;
1607 /* preserve the shopkeepers (lack of) interest */
1608 otmp->no_charge = obj->no_charge;
1609 /* preserve inventory letter if in inventory */
1610 if (obj_location == OBJ_INVENT)
1611 otmp->invlet = obj->invlet;
1613 /* You can't send yourself 100 mail messages and then
1614 * polymorph them into useful scrolls
1616 if (obj->otyp == SCR_MAIL) {
1617 otmp->otyp = SCR_MAIL;
1622 /* avoid abusing eggs laid by you */
1623 if (obj->otyp == EGG && obj->spe) {
1624 int mnum, tryct = 100;
1626 /* first, turn into a generic egg */
1627 if (otmp->otyp == EGG)
1631 otmp->owt = weight(otmp);
1633 otmp->corpsenm = NON_PM;
1636 /* now change it into something laid by the hero */
1638 mnum = can_be_hatched(random_monster());
1639 if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
1640 otmp->spe = 1; /* laid by hero */
1641 set_corpsenm(otmp, mnum); /* also sets hatch timer */
1647 /* keep special fields (including charges on wands) */
1648 if (index(charged_objs, otmp->oclass))
1649 otmp->spe = obj->spe;
1650 otmp->recharged = obj->recharged;
1652 otmp->cursed = obj->cursed;
1653 otmp->blessed = obj->blessed;
1655 if (erosion_matters(otmp)) {
1656 if (is_flammable(otmp) || is_rustprone(otmp))
1657 otmp->oeroded = obj->oeroded;
1658 if (is_corrodeable(otmp) || is_rottable(otmp))
1659 otmp->oeroded2 = obj->oeroded2;
1660 if (is_damageable(otmp))
1661 otmp->oerodeproof = obj->oerodeproof;
1664 /* Keep chest/box traps and poisoned ammo if we may */
1665 if (obj->otrapped && Is_box(otmp))
1666 otmp->otrapped = TRUE;
1668 if (obj->opoisoned && is_poisonable(otmp))
1669 otmp->opoisoned = TRUE;
1671 if (id == STRANGE_OBJECT && obj->otyp == CORPSE) {
1672 /* turn crocodile corpses into shoes */
1673 if (obj->corpsenm == PM_CROCODILE) {
1674 otmp->otyp = LOW_BOOTS;
1675 otmp->oclass = ARMOR_CLASS;
1678 otmp->oerodeproof = TRUE;
1680 otmp->cursed = FALSE;
1684 /* no box contents --KAA */
1685 if (Has_contents(otmp))
1686 delete_contents(otmp);
1688 /* 'n' merged objects may be fused into 1 object */
1689 if (otmp->quan > 1L && (!objects[otmp->otyp].oc_merge
1690 || (can_merge && otmp->quan > (long) rn2(1000))))
1693 switch (otmp->oclass) {
1695 if (otmp->otyp == MAGIC_LAMP) {
1696 otmp->otyp = OIL_LAMP;
1697 otmp->age = 1500L; /* "best" oil lamp possible */
1698 } else if (otmp->otyp == MAGIC_MARKER) {
1699 otmp->recharged = 1; /* degraded quality */
1701 /* don't care about the recharge count of other tools */
1705 while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
1706 otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
1707 /* altering the object tends to degrade its quality
1708 (analogous to spellbook `read count' handling) */
1709 if ((int) otmp->recharged < rn2(7)) /* recharge_limit */
1714 while (otmp->otyp == POT_POLYMORPH)
1715 otmp->otyp = rnd_class(POT_GAIN_ABILITY, POT_WATER);
1719 while (otmp->otyp == SPE_POLYMORPH)
1720 otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
1721 /* reduce spellbook abuse; non-blank books degrade */
1722 if (otmp->otyp != SPE_BLANK_PAPER) {
1723 otmp->spestudied = obj->spestudied + 1;
1724 if (otmp->spestudied > MAX_SPELL_STUDY) {
1725 otmp->otyp = SPE_BLANK_PAPER;
1726 /* writing a new book over it will yield an unstudied
1727 one; re-polymorphing this one as-is may or may not
1728 get something non-blank */
1729 otmp->spestudied = rn2(otmp->spestudied);
1735 if (otmp->quan > (long) rnd(4)
1736 && objects[obj->otyp].oc_material == MINERAL
1737 && objects[otmp->otyp].oc_material != MINERAL) {
1738 otmp->otyp = ROCK; /* transmutation backfired */
1739 otmp->quan /= 2L; /* some material has been lost */
1744 /* update the weight */
1745 otmp->owt = weight(otmp);
1747 /* handle polymorph of worn item: stone-to-flesh cast on self can
1748 affect multiple objects at once, but their new forms won't
1749 produce any side-effects; a single worn item dipped into potion
1750 of polymorph can produce side-effects but those won't yield out
1751 of sequence messages because current polymorph is finished */
1752 if (obj_location == OBJ_INVENT && obj->owornmask) {
1753 long old_wornmask = obj->owornmask & ~(W_ART | W_ARTI),
1754 new_wornmask = wearslot(otmp);
1755 boolean was_twohanded = bimanual(obj), was_twoweap = u.twoweap;
1757 remove_worn_item(obj, TRUE);
1758 /* if the new form can be worn in the same slot, make it so
1759 [possible extension: if it could be worn in some other
1760 slot which is currently unfilled, wear it there instead] */
1761 if ((old_wornmask & W_QUIVER) != 0L) {
1763 } else if ((old_wornmask & W_SWAPWEP) != 0L) {
1764 if (was_twohanded || !bimanual(otmp))
1766 if (was_twoweap && uswapwep)
1768 } else if ((old_wornmask & W_WEP) != 0L) {
1769 if (was_twohanded || !bimanual(otmp) || !uarms)
1771 if (was_twoweap && uwep && !bimanual(uwep))
1773 } else if ((old_wornmask & new_wornmask) != 0L) {
1774 new_wornmask &= old_wornmask;
1775 setworn(otmp, new_wornmask);
1776 set_wear(otmp); /* Armor_on() for side-effects */
1780 /* ** we are now done adjusting the object ** */
1782 /* swap otmp for obj */
1783 replace_object(obj, otmp);
1784 if (obj_location == OBJ_INVENT) {
1786 * We may need to do extra adjustments for the hero if we're
1787 * messing with the hero's inventory. The following calls are
1788 * equivalent to calling freeinv on obj and addinv on otmp,
1789 * while doing an in-place swap of the actual objects.
1794 } else if (obj_location == OBJ_FLOOR) {
1795 ox = otmp->ox, oy = otmp->oy; /* set by replace_object() */
1796 if (obj->otyp == BOULDER && otmp->otyp != BOULDER
1797 && !does_block(ox, oy, &levl[ox][oy]))
1798 unblock_point(ox, oy);
1799 else if (obj->otyp != BOULDER && otmp->otyp == BOULDER)
1800 /* (checking does_block() here would be redundant) */
1801 block_point(ox, oy);
1804 if ((!carried(otmp) || obj->unpaid)
1805 && get_obj_location(otmp, &ox, &oy, BURIED_TOO | CONTAINED_TOO)
1806 && costly_spot(ox, oy)) {
1807 register struct monst *shkp =
1808 shop_keeper(*in_rooms(ox, oy, SHOPBASE));
1810 if ((!obj->no_charge
1811 || (Has_contents(obj)
1812 && (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L)))
1813 && inhishop(shkp)) {
1814 if (shkp->mpeaceful) {
1816 && *in_rooms(u.ux, u.uy, 0)
1817 == *in_rooms(shkp->mx, shkp->my, 0)
1818 && !costly_spot(u.ux, u.uy)) {
1819 make_angry_shk(shkp, ox, oy);
1822 pline("%s gets angry!", Monnam(shkp));
1824 pline("%s
\82Í
\8c\83\93{
\82µ
\82½
\81I", Monnam(shkp));
1829 Norep("%s is furious!", Monnam(shkp));
1831 Norep("%s
\82Í
\93{
\82Á
\82½
\81I", Monnam(shkp));
1838 /* stone-to-flesh spell hits and maybe transforms or animates obj */
1840 stone_to_flesh_obj(obj)
1843 int res = 1; /* affected object by default */
1844 struct permonst *ptr;
1845 struct monst *mon, *shkp;
1848 boolean smell = FALSE, golem_xform = FALSE;
1850 if (objects[obj->otyp].oc_material != MINERAL
1851 && objects[obj->otyp].oc_material != GEMSTONE)
1853 /* Heart of Ahriman usually resists; ordinary items rarely do */
1854 if (obj_resists(obj, 2, 98))
1857 (void) get_obj_location(obj, &oox, &ooy, 0);
1858 /* add more if stone objects are added.. */
1859 switch (objects[obj->otyp].oc_class) {
1860 case ROCK_CLASS: /* boulders and statues */
1861 case TOOL_CLASS: /* figurines */
1862 if (obj->otyp == BOULDER) {
1863 obj = poly_obj(obj, HUGE_CHUNK_OF_MEAT);
1865 } else if (obj->otyp == STATUE || obj->otyp == FIGURINE) {
1866 ptr = &mons[obj->corpsenm];
1867 if (is_golem(ptr)) {
1868 golem_xform = (ptr != &mons[PM_FLESH_GOLEM]);
1869 } else if (vegetarian(ptr)) {
1870 /* Don't animate monsters that aren't flesh */
1871 obj = poly_obj(obj, MEATBALL);
1875 if (obj->otyp == STATUE) {
1876 /* animate_statue() forces all golems to become flesh golems */
1877 mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
1878 } else { /* (obj->otyp == FIGURINE) */
1880 ptr = &mons[PM_FLESH_GOLEM];
1881 mon = makemon(ptr, oox, ooy, NO_MINVENT);
1883 if (costly_spot(oox, ooy)
1884 && (carried(obj) ? obj->unpaid : !obj->no_charge)) {
1885 shkp = shop_keeper(*in_rooms(oox, ooy, SHOPBASE));
1886 stolen_value(obj, oox, ooy,
1887 (shkp && shkp->mpeaceful), FALSE);
1890 obj_stop_timers(obj);
1895 if (cansee(mon->mx, mon->my))
1897 pline_The("figurine %sanimates!",
1898 golem_xform ? "turns to flesh and " : "");
1900 pline_The("
\90l
\8c`
\82Í%s
\93®
\82«
\82¾
\82µ
\82½
\81I",
1901 golem_xform ? "
\90Î
\89»
\82ª
\89ð
\82¯
\82Ä" : "");
1907 /* this golem handling is redundant... */
1908 if (is_golem(ptr) && ptr != &mons[PM_FLESH_GOLEM])
1909 (void) newcham(mon, &mons[PM_FLESH_GOLEM], TRUE, FALSE);
1910 } else if ((ptr->geno & (G_NOCORPSE | G_UNIQ)) != 0) {
1911 /* didn't revive but can't leave corpse either */
1914 /* unlikely to get here since genociding monsters also
1915 sets the G_NOCORPSE flag; drop statue's contents */
1916 while ((item = obj->cobj) != 0) {
1917 bypass_obj(item); /* make stone-to-flesh miss it */
1918 obj_extract_self(item);
1919 place_object(item, oox, ooy);
1921 obj = poly_obj(obj, CORPSE);
1923 } else { /* miscellaneous tool or unexpected rock... */
1927 /* maybe add weird things to become? */
1928 case RING_CLASS: /* some of the rings are stone */
1929 obj = poly_obj(obj, MEAT_RING);
1932 case WAND_CLASS: /* marble wand */
1933 obj = poly_obj(obj, MEAT_STICK);
1936 case GEM_CLASS: /* stones & gems */
1937 obj = poly_obj(obj, MEATBALL);
1940 case WEAPON_CLASS: /* crysknife */
1948 /* non-meat eaters smell meat, meat eaters smell its flavor;
1949 monks are considered non-meat eaters regardless of behavior;
1950 other roles are non-meat eaters if they haven't broken
1951 vegetarian conduct yet (or if poly'd into non-carnivorous/
1952 non-omnivorous form, regardless of whether it's herbivorous,
1953 non-eating, or something stranger) */
1954 if (Role_if(PM_MONK) || !u.uconduct.unvegetarian
1955 || !carnivorous(youmonst.data))
1957 Norep("You smell the odor of meat.");
1959 Norep("
\93÷
\82Ì
\88«
\8fL
\82ª
\95Y
\82Á
\82½
\81D");
1962 Norep("You smell a delicious smell.");
1964 Norep("
\82·
\82Î
\82ç
\82µ
\82¢
\8d\81\82è
\82¾
\81I");
1971 * Object obj was hit by the effect of the wand/spell otmp. Return
1972 * non-zero if the wand/spell had any effect.
1976 struct obj *obj, *otmp;
1978 int res = 1; /* affected object by default */
1979 boolean learn_it = FALSE, maybelearnit;
1981 /* fundamental: a wand effect hitting itself doesn't do anything;
1982 otherwise we need to guard against accessing otmp after something
1983 strange has happened to it (along the lines of polymorph or
1984 stone-to-flesh [which aren't good examples since polymorph wands
1985 aren't affected by polymorph zaps and stone-to-flesh isn't
1986 available in wand form, but the concept still applies...]) */
1991 /* The bypass bit is currently only used as follows:
1993 * POLYMORPH - When a monster being polymorphed drops something
1994 * from its inventory as a result of the change.
1995 * If the items fall to the floor, they are not
1996 * subject to direct subsequent polymorphing
1997 * themselves on that same zap. This makes it
1998 * consistent with items that remain in the
1999 * monster's inventory. They are not polymorphed
2001 * UNDEAD_TURNING - When an undead creature gets killed via
2002 * undead turning, prevent its corpse from being
2003 * immediately revived by the same effect.
2004 * STONE_TO_FLESH - If a statue can't be revived, its
2005 * contents get dropped before turning it into
2006 * meat; prevent those contents from being hit.
2007 * retouch_equipment() - bypass flag is used to track which
2008 * items have been handled (bhito isn't involved).
2009 * menu_drop(), askchain() - inventory traversal where multiple
2010 * Drop can alter the invent chain while traversal
2011 * is in progress (bhito isn't involved).
2013 * The bypass bit on all objects is reset each turn, whenever
2014 * context.bypasses is set.
2016 * We check the obj->bypass bit above AND context.bypasses
2017 * as a safeguard against any stray occurrence left in an obj
2018 * struct someplace, although that should never happen.
2020 if (context.bypasses) {
2023 debugpline1("%s for a moment.", Tobjnam(obj, "pulsate"));
2029 * Some parts of this function expect the object to be on the floor
2030 * obj->{ox,oy} to be valid. The exception to this (so far) is
2031 * for the STONE_TO_FLESH spell.
2033 if (!(obj->where == OBJ_FLOOR || otmp->otyp == SPE_STONE_TO_FLESH))
2034 impossible("bhito: obj is not floor or Stone To Flesh spell");
2038 } else if (obj == uchain) {
2039 if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
2045 switch (otmp->otyp) {
2048 if (obj->otyp == WAN_POLYMORPH || obj->otyp == SPE_POLYMORPH
2049 || obj->otyp == POT_POLYMORPH || obj_resists(obj, 5, 95)) {
2054 u.uconduct.polypiles++;
2055 /* any saved lock context will be dangerously obsolete */
2057 (void) boxlock(obj, otmp);
2059 if (obj_shudders(obj)) {
2061 ((obj == level.objects[u.ux][u.uy]) && u.uundetected
2062 && hides_under(youmonst.data));
2064 if (cansee(obj->ox, obj->oy))
2067 /* eek - your cover might have been blown */
2069 (void) hideunder(&youmonst);
2072 obj = poly_obj(obj, STRANGE_OBJECT);
2073 newsym(obj->ox, obj->oy);
2077 /* target object has now been "seen (up close)" */
2079 if (Is_container(obj) || obj->otyp == STATUE) {
2080 obj->cknown = obj->lknown = 1;
2082 boolean catbox = SchroedingersBox(obj);
2084 /* we don't want to force alive vs dead
2085 determination for Schroedinger's Cat here,
2086 so just make probing be inconclusive for it */
2090 pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
2092 pline("%s
\82Í
\8bó
\82Á
\82Û%s
\82¾
\81D", xname(obj), catbox ? "
\82Ì
\82æ
\82¤" : "");
2095 /* view contents (not recursively) */
2096 for (o = obj->cobj; o; o = o->nobj)
2097 o->dknown = 1; /* "seen", even if blind */
2098 (void) display_cinventory(obj);
2106 case SPE_FORCE_BOLT:
2107 /* learn the type if you see or hear something break
2108 (the sound could be implicit) */
2109 maybelearnit = cansee(obj->ox, obj->oy) || !Deaf;
2110 if (obj->otyp == BOULDER) {
2111 if (cansee(obj->ox, obj->oy))
2113 pline_The("boulder falls apart.");
2115 pline_The("
\8aâ
\82Í
\82Î
\82ç
\82Î
\82ç
\82É
\82È
\82Á
\82½
\81D");
2118 You_hear("a crumbling sound.");
2120 You_hear("
\89½
\82©
\82ª
\8dÓ
\82¯
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D");
2122 } else if (obj->otyp == STATUE) {
2123 if (break_statue(obj)) {
2124 if (cansee(obj->ox, obj->oy)) {
2127 pline_The("%s shatters.", rndmonnam(NULL));
2129 pline_The("%s
\82Í
\95²
\81X
\82É
\82È
\82Á
\82½
\81D", rndmonnam(NULL));
2132 pline_The("statue shatters.");
2134 pline_The("
\90Î
\91\9c\82Í
\95²
\81X
\82É
\82È
\82Á
\82½
\81D");
2137 You_hear("a crumbling sound.");
2139 You_hear("
\89½
\82©
\82ª
\8dÓ
\82¯
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D");
2144 if (context.mon_moving
2145 ? !breaks(obj, obj->ox, obj->oy)
2146 : !hero_breaks(obj, obj->ox, obj->oy, FALSE))
2147 maybelearnit = FALSE; /* nothing broke */
2149 newsym_force(oox,ooy);
2155 case WAN_CANCELLATION:
2156 case SPE_CANCELLATION:
2159 newsym(obj->ox, obj->oy); /* might change color */
2162 case SPE_DRAIN_LIFE:
2163 (void) drain_item(obj, TRUE);
2165 case WAN_TELEPORTATION:
2166 case SPE_TELEPORT_AWAY:
2169 case WAN_MAKE_INVISIBLE:
2171 case WAN_UNDEAD_TURNING:
2172 case SPE_TURN_UNDEAD:
2173 if (obj->otyp == EGG) {
2175 } else if (obj->otyp == CORPSE) {
2176 int corpsenm = corpse_revive_type(obj);
2178 res = !!revive(obj, TRUE);
2179 if (res && Role_if(PM_HEALER)) {
2180 if (Hallucination && !Deaf) {
2182 You_hear("the sound of a defibrillator.");
2184 You_hear("
\8f\9c\8d×
\93®
\8aí
\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D");
2186 } else if (!Blind) {
2188 You("observe %s %s change dramatically.",
2189 s_suffix(an(mons[corpsenm].mname)),
2190 nonliving(&mons[corpsenm]) ? "motility"
2193 You("%s
\82Ì%s
\82ª
\8c\80\93I
\82É
\95Ï
\89»
\82·
\82é
\82Ì
\82ð
\8c©
\82½
\81D",
2194 mons[corpsenm].mname,
2195 nonliving(&mons[corpsenm]) ? "
\89^
\93®
\90«"
2201 exercise(A_WIS, TRUE);
2208 case SPE_WIZARD_LOCK:
2210 res = boxlock(obj, otmp);
2216 case WAN_SLOW_MONSTER: /* no effect on objects */
2217 case SPE_SLOW_MONSTER:
2218 case WAN_SPEED_MONSTER:
2221 case SPE_EXTRA_HEALING:
2224 case SPE_STONE_TO_FLESH:
2225 res = stone_to_flesh_obj(obj);
2228 impossible("What an interesting effect (%d)", otmp->otyp);
2231 /* if effect was observable then discover the wand type provided
2232 that the wand itself has been seen */
2238 /* returns nonzero if something was hit */
2240 bhitpile(obj, fhito, tx, ty, zz)
2242 int FDECL((*fhito), (OBJ_P, OBJ_P));
2246 int hitanything = 0;
2247 register struct obj *otmp, *next_obj;
2249 if (obj->otyp == SPE_FORCE_BOLT || obj->otyp == WAN_STRIKING) {
2250 struct trap *t = t_at(tx, ty);
2252 /* We can't settle for the default calling sequence of
2253 bhito(otmp) -> break_statue(otmp) -> activate_statue_trap(ox,oy)
2254 because that last call might end up operating on our `next_obj'
2255 (below), rather than on the current object, if it happens to
2256 encounter a statue which mustn't become animated. */
2257 if (t && t->ttyp == STATUE_TRAP
2258 && activate_statue_trap(t, tx, ty, TRUE))
2263 for (otmp = level.objects[tx][ty]; otmp; otmp = next_obj) {
2264 next_obj = otmp->nexthere;
2265 /* for zap downwards, don't hit object poly'd hero is hiding under */
2266 if (zz > 0 && u.uundetected && otmp == level.objects[u.ux][u.uy]
2267 && hides_under(youmonst.data))
2270 hitanything += (*fhito)(otmp, obj);
2272 if (poly_zapped >= 0)
2273 create_polymon(level.objects[tx][ty], poly_zapped);
2279 * zappable - returns 1 if zap is available, 0 otherwise.
2280 * it removes a charge from the wand if zappable.
2281 * added by GAN 11/03/86
2285 register struct obj *wand;
2287 if (wand->spe < 0 || (wand->spe == 0 && rn2(121)))
2291 You("wrest one last charge from the worn-out wand.");
2293 You("
\8eg
\82¢
\82«
\82Á
\82½
\8fñ
\82©
\82ç
\8dÅ
\8cã
\82Ì
\97Í
\82ð
\82µ
\82Ú
\82è
\82Æ
\82Á
\82½
\81D");
2299 * zapnodir - zaps a NODIR wand/spell.
2300 * added by GAN 11/03/86
2304 register struct obj *obj;
2306 boolean known = FALSE;
2308 switch (obj->otyp) {
2314 if (lightdamage(obj, TRUE, 5))
2317 case WAN_SECRET_DOOR_DETECTION:
2318 case SPE_DETECT_UNSEEN:
2324 case WAN_CREATE_MONSTER:
2325 known = create_critters(rn2(23) ? 1 : rn1(7, 2),
2326 (struct permonst *) 0, FALSE);
2330 if (Luck + rn2(5) < 0) {
2332 pline("Unfortunately, nothing happens.");
2334 pline("
\8ec
\94O
\82È
\82ª
\82ç
\81C
\89½
\82à
\8bN
\82«
\82È
\82©
\82Á
\82½
\81D");
2339 case WAN_ENLIGHTENMENT:
2342 You_feel("self-knowledgeable...");
2344 You("
\8e©
\95ª
\8e©
\90g
\82ª
\94»
\82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D
\81D
\81D");
2345 display_nhwindow(WIN_MESSAGE, FALSE);
2346 enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
2348 pline_The("feeling subsides.");
2350 pline("
\82»
\82Ì
\8a´
\82¶
\82Í
\82È
\82
\82È
\82Á
\82½
\81D");
2351 exercise(A_WIS, TRUE);
2355 if (!objects[obj->otyp].oc_name_known)
2356 more_experienced(0, 10);
2357 /* effect was observable; discover the wand type provided
2358 that the wand itself has been seen */
2369 otmp->in_use = TRUE; /* in case losehp() is fatal */
2371 pline("%s suddenly explodes!", The(xname(otmp)));
2373 pline("%s
\82Í
\93Ë
\91R
\94\9a\94
\82µ
\82½
\81I", xname(otmp));
2374 dmg = d(otmp->spe + 2, 6);
2376 losehp(Maybe_Half_Phys(dmg), "exploding wand", KILLED_BY_AN);
2378 losehp(Maybe_Half_Phys(dmg), "
\8fñ
\82Ì
\94\9a\94
\82Å", KILLED_BY_AN);
2382 static NEARDATA const char zap_syms[] = { WAND_CLASS, 0 };
2384 /* 'z' command (or 'y' if numbed_pad==-1) */
2388 register struct obj *obj;
2391 if (check_capacity((char *) 0))
2393 obj = getobj(zap_syms, "zap");
2399 /* zappable addition done by GAN 11/03/86 */
2401 pline1(nothing_happens);
2402 else if (obj->cursed && !rn2(WAND_BACKFIRE_CHANCE)) {
2403 backfire(obj); /* the wand blows up in your face! */
2404 exercise(A_STR, FALSE);
2406 } else if (!(objects[obj->otyp].oc_dir == NODIR) && !getdir((char *) 0)) {
2409 pline("%s glows and fades.", The(xname(obj)));
2411 pline("%s
\82Í
\88ê
\8fu
\8bP
\82¢
\82½
\81D", The(xname(obj)));
2412 /* make him pay for knowing !NODIR */
2413 } else if (!u.dx && !u.dy && !u.dz
2414 && !(objects[obj->otyp].oc_dir == NODIR)) {
2415 if ((damage = zapyourself(obj, TRUE)) != 0) {
2419 Sprintf(buf, "zapped %sself with a wand", uhim());
2420 losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
2422 losehp(Maybe_Half_Phys(damage),
2423 "
\8e©
\95ª
\8e©
\90g
\82Ì
\8fñ
\82Ì
\97Í
\82ð
\97\81\82Ñ
\82Ä", KILLED_BY);
2427 /* Are we having fun yet?
2428 * weffects -> buzz(obj->otyp) -> zhitm (temple priest) ->
2429 * attack -> hitum -> known_hitum -> ghod_hitsu ->
2430 * buzz(AD_ELEC) -> destroy_item(WAND_CLASS) ->
2431 * useup -> obfree -> dealloc_obj -> free(obj)
2438 if (obj && obj->spe < 0) {
2440 pline("%s to dust.", Tobjnam(obj, "turn"));
2442 pline("%s
\82Í
\82¿
\82è
\82Æ
\82È
\82Á
\82½
\81D", xname(obj));
2445 update_inventory(); /* maybe used a charge */
2450 zapyourself(obj, ordinary)
2454 boolean learn_it = FALSE;
2457 switch (obj->otyp) {
2459 case SPE_FORCE_BOLT:
2462 shieldeff(u.ux, u.uy);
2466 pline("
\83{
\83C
\83\93\81I");
2470 You("bash yourself!");
2472 You("
\8e©
\95ª
\8e©
\90g
\82ð
\91Å
\82¿
\82Â
\82¯
\82½
\81I");
2475 damage = d(1 + obj->spe, 6);
2476 exercise(A_STR, FALSE);
2482 if (!Shock_resistance) {
2484 You("shock yourself!");
2486 You("
\93d
\8c\82\82ð
\82¤
\82¯
\82½
\81I");
2488 exercise(A_CON, FALSE);
2490 shieldeff(u.ux, u.uy);
2492 You("zap yourself, but seem unharmed.");
2494 You("
\8e©
\95ª
\82É
\8fñ
\82ð
\82Ó
\82è
\82©
\82´
\82µ
\82½
\82ª
\81C
\89ö
\89ä
\82Í
\82µ
\82È
\82©
\82Á
\82½
\82æ
\82¤
\82¾
\81D");
2495 ugolemeffects(AD_ELEC, d(12, 6));
2497 destroy_item(WAND_CLASS, AD_ELEC);
2498 destroy_item(RING_CLASS, AD_ELEC);
2499 (void) flashburn((long) rnd(100));
2504 You("explode a fireball on top of yourself!");
2506 Your("
\93ª
\8fã
\82Å
\89Î
\82Ì
\8bÊ
\82ª
\94\9a\94
\82µ
\82½
\81I");
2507 explode(u.ux, u.uy, 11, d(6, 6), WAND_CLASS, EXPL_FIERY);
2512 if (Fire_resistance) {
2513 shieldeff(u.ux, u.uy);
2515 You_feel("rather warm.");
2517 You("
\82¿
\82å
\82Á
\82Æ
\92g
\82©
\82
\8a´
\82¶
\82½
\81D");
2518 ugolemeffects(AD_FIRE, d(12, 6));
2521 pline("You've set yourself afire!");
2523 You("
\89\8a\82É
\82Â
\82Â
\82Ü
\82ê
\82½
\81I");
2527 (void) burnarmor(&youmonst);
2528 destroy_item(SCROLL_CLASS, AD_FIRE);
2529 destroy_item(POTION_CLASS, AD_FIRE);
2530 destroy_item(SPBOOK_CLASS, AD_FIRE);
2531 destroy_item(FOOD_CLASS, AD_FIRE); /* only slime for now */
2535 case SPE_CONE_OF_COLD:
2538 if (Cold_resistance) {
2539 shieldeff(u.ux, u.uy);
2541 You_feel("a little chill.");
2543 You("
\82¿
\82å
\82Á
\82Æ
\97â
\82½
\82
\8a´
\82¶
\82½
\81D");
2544 ugolemeffects(AD_COLD, d(12, 6));
2547 You("imitate a popsicle!");
2549 You("
\83A
\83C
\83X
\83L
\83\83\83\93\83f
\81[
\82Ì
\82æ
\82¤
\82É
\82È
\82Á
\82½
\81I");
2552 destroy_item(POTION_CLASS, AD_COLD);
2555 case WAN_MAGIC_MISSILE:
2556 case SPE_MAGIC_MISSILE:
2559 shieldeff(u.ux, u.uy);
2561 pline_The("missiles bounce!");
2563 pline("
\96\82\96@
\82Ì
\96î
\82Í
\82Í
\82Ë
\82©
\82¦
\82Á
\82½
\81I");
2567 pline("Idiot! You've shot yourself!");
2569 pline("
\89½
\82â
\82Á
\82Ä
\82ñ
\82¾
\81I
\82 \82È
\82½
\82Í
\8e©
\95ª
\8e©
\90g
\82ð
\8c\82\82Á
\82½
\81I");
2581 case WAN_CANCELLATION:
2582 case SPE_CANCELLATION:
2583 (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
2586 case SPE_DRAIN_LIFE:
2587 if (!Drain_resistance) {
2588 learn_it = TRUE; /* (no effect for spells...) */
2590 losexp("life drainage");
2592 losexp("
\90¶
\96½
\97Í
\82ð
\8bz
\8eû
\82³
\82ê
\82Ä");
2594 damage = 0; /* No additional damage */
2597 case WAN_MAKE_INVISIBLE: {
2598 /* have to test before changing HInvis but must change
2599 * HInvis before doing newsym().
2601 int msg = !Invis && !Blind && !BInvis;
2603 if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
2604 /* A mummy wrapping absorbs it and protects you */
2606 You_feel("rather itchy under %s.", yname(uarmc));
2608 You("%s
\82Ì
\89º
\82ª
\83\80\83Y
\83\80\83Y
\82µ
\82½
\81D", xname(uarmc));
2611 if (ordinary || !rn2(10)) { /* permanent */
2612 HInvis |= FROMOUTSIDE;
2613 } else { /* temporary */
2614 incr_itimeout(&HInvis, d(obj->spe, 250));
2619 self_invis_message();
2624 case WAN_SPEED_MONSTER:
2625 if (!(HFast & INTRINSIC)) {
2631 You("
\93®
\82«
\82ª
\91¬
\82
\82È
\82Á
\82½
\81D");
2634 Your("quickness feels more natural.");
2636 You("
\91¬
\82³
\82É
\8aµ
\82ê
\82Ä
\82«
\82½
\81D");
2637 exercise(A_DEX, TRUE);
2639 HFast |= FROMOUTSIDE;
2645 if (Sleep_resistance) {
2646 shieldeff(u.ux, u.uy);
2648 You("don't feel sleepy!");
2650 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81I");
2653 pline_The("sleep ray hits you!");
2655 pline("
\96°
\82è
\8cõ
\90ü
\82ª
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I");
2656 fall_asleep(-rnd(50), TRUE);
2660 case WAN_SLOW_MONSTER:
2661 case SPE_SLOW_MONSTER:
2662 if (HFast & (TIMEOUT | INTRINSIC)) {
2668 case WAN_TELEPORTATION:
2669 case SPE_TELEPORT_AWAY:
2671 /* same criteria as when mounted (zap_steed) */
2672 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2673 || distu(u.ux0, u.uy0) >= 16)
2678 case SPE_FINGER_OF_DEATH:
2679 if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
2680 pline((obj->otyp == WAN_DEATH)
2682 ? "The wand shoots an apparently harmless beam at you."
2684 ? "
\8fñ
\82Ì
\8cõ
\90ü
\82Í
\82Ç
\82¤
\82â
\82ç
\82 \82È
\82½
\82É
\89e
\8b¿
\82ð
\97^
\82¦
\82È
\82¢
\82à
\82Ì
\82Ì
\82æ
\82¤
\82¾
\81D"
2686 : "You seem no deader than before.");
2688 : "
\82 \82È
\82½
\82Í
\82±
\82ê
\88È
\8fã
\8e\80\82Ë
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
2693 Sprintf(killer.name, "shot %sself with a death ray", uhim());
2694 killer.format = NO_KILLER_PREFIX;
2696 Strcpy(killer.name, "
\8e©
\95ª
\82ª
\8c\82\82Á
\82½
\8e\80\82Ì
\8cõ
\90ü
\82É
\82æ
\82Á
\82Ä");
2697 killer.format = KILLED_BY;
2700 You("irradiate yourself with pure energy!");
2702 You("
\83G
\83l
\83\8b\83M
\81[
\82ð
\8e©
\95ª
\8e©
\90g
\82É
\8fÆ
\8eË
\82µ
\82½
\81D");
2706 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D");
2707 /* They might survive with an amulet of life saving */
2710 case WAN_UNDEAD_TURNING:
2711 case SPE_TURN_UNDEAD:
2713 (void) unturn_dead(&youmonst);
2714 if (is_undead(youmonst.data)) {
2716 You_feel("frightened and %sstunned.",
2717 Stunned ? "even more " : "");
2719 You("
\8b°
\95|
\82µ%s
\82
\82ç
\82
\82ç
\82µ
\82½
\81D",
2720 Stunned ? "
\82³
\82ç
\82É" : "");
2722 make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
2725 You("shudder in dread.");
2727 You("
\8b°
\95|
\82Å
\90k
\82¦
\82½
\81D");
2730 case SPE_EXTRA_HEALING:
2731 learn_it = TRUE; /* (no effect for spells...) */
2732 healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE,
2733 (obj->otyp == SPE_EXTRA_HEALING));
2735 You_feel("%sbetter.", obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
2737 You("%s
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81D", obj->otyp == SPE_EXTRA_HEALING ? "
\82Æ
\82Ä
\82à" : "");
2739 case WAN_LIGHT: /* (broken wand) */
2740 /* assert( !ordinary ); */
2741 damage = d(obj->spe, 25);
2743 case EXPENSIVE_CAMERA:
2746 damage = lightdamage(obj, ordinary, damage);
2748 if (flashburn((long) damage))
2750 damage = 0; /* reset */
2758 if (u.utrap) { /* escape web or bear trap */
2759 (void) openholdingtrap(&youmonst, &learn_it);
2762 /* unlock carried boxes */
2763 for (otmp = invent; otmp; otmp = otmp->nobj)
2765 (void) boxlock(otmp, obj);
2766 /* trigger previously escaped trapdoor */
2767 (void) openfallingtrap(&youmonst, TRUE, &learn_it);
2771 case SPE_WIZARD_LOCK:
2773 (void) closeholdingtrap(&youmonst, &learn_it);
2778 case SPE_DETECT_UNSEEN:
2784 for (otmp = invent; otmp; otmp = otmp->nobj) {
2786 if (Is_container(otmp) || otmp->otyp == STATUE) {
2788 if (!SchroedingersBox(otmp))
2796 case SPE_STONE_TO_FLESH: {
2797 struct obj *otmp, *onxt;
2800 if (u.umonnum == PM_STONE_GOLEM) {
2802 (void) polymon(PM_FLESH_GOLEM);
2806 fix_petrification(); /* saved! */
2808 /* but at a cost.. */
2809 for (otmp = invent; otmp; otmp = onxt) {
2811 if (bhito(otmp, obj))
2815 * It is possible that we can now merge some inventory.
2816 * Do a highly paranoid merge. Restart from the beginning
2821 for (otmp = invent; !didmerge && otmp; otmp = otmp->nobj)
2822 for (onxt = otmp->nobj; onxt; onxt = onxt->nobj)
2823 if (merged(&otmp, &onxt)) {
2831 impossible("zapyourself: object %d used?", obj->otyp);
2834 /* if effect was observable then discover the wand type provided
2835 that the wand itself has been seen */
2841 /* called when poly'd hero uses breath attack against self */
2844 struct attack *mattk;
2846 int dtyp = 20 + mattk->adtyp - 1; /* breath by hero */
2847 const char *fltxt = flash_types[dtyp]; /* blast of <something> */
2849 zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
2852 /* light damages hero in gremlin form */
2854 lightdamage(obj, ordinary, amt)
2855 struct obj *obj; /* item making light (fake book if spell) */
2856 boolean ordinary; /* wand/camera zap vs wand destruction */
2857 int amt; /* pseudo-damage used to determine blindness duration */
2863 if (dmg && youmonst.data == &mons[PM_GREMLIN]) {
2864 /* reduce high values (from destruction of wand with many charges) */
2867 dmg = 10 + rnd(dmg - 10);
2871 pline("Ow, that light hurts%c", (dmg > 2 || u.mh <= 5) ? '!' : '.');
2873 pline("
\82¨
\82í
\81C
\8cõ
\82ª
\92É
\82¢%s", (dmg > 2 || u.mh <= 5) ? "
\81I" : "
\81D");
2874 /* [composing killer/reason is superfluous here; if fatal, cause
2875 of death will always be "killed while stuck in creature form"] */
2877 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2878 ordinary = FALSE; /* say blasted rather than zapped */
2880 how = (obj->oclass != SPBOOK_CLASS)
2881 ? (const char *) ansimpleoname(obj)
2885 : "
\8cõ
\82Ì
\96\82\96@";
2887 Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2890 Sprintf(buf, "
\8e©
\95ª
\82Å%s
\82ð
\97\81\82Ñ
\82Ä", how);
2892 /* might rehumanize(); could be fatal, but only for Unchanging */
2894 losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2896 losehp(Maybe_Half_Phys(dmg), buf, KILLED_BY);
2902 /* light[ning] causes blindness */
2907 if (!resists_blnd(&youmonst)) {
2908 You(are_blinded_by_the_flash);
2909 make_blinded(duration, FALSE);
2911 Your1(vision_clears);
2917 /* you've zapped a wand downwards while riding
2918 * Return TRUE if the steed was hit by the wand.
2919 * Return FALSE if the steed was not hit by the wand.
2923 struct obj *obj; /* wand or spell */
2925 int steedhit = FALSE;
2927 bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
2929 switch (obj->otyp) {
2931 * Wands that are allowed to hit the steed
2932 * Carefully test the results of any that are
2933 * moved here from the bottom section.
2936 probe_monster(u.usteed);
2940 case WAN_TELEPORTATION:
2941 case SPE_TELEPORT_AWAY:
2942 /* you go together */
2944 /* same criteria as when unmounted (zapyourself) */
2945 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2946 || distu(u.ux0, u.uy0) >= 16)
2951 /* Default processing via bhitm() for these */
2952 case SPE_CURE_SICKNESS:
2953 case WAN_MAKE_INVISIBLE:
2954 case WAN_CANCELLATION:
2955 case SPE_CANCELLATION:
2959 case SPE_FORCE_BOLT:
2960 case WAN_SLOW_MONSTER:
2961 case SPE_SLOW_MONSTER:
2962 case WAN_SPEED_MONSTER:
2964 case SPE_EXTRA_HEALING:
2965 case SPE_DRAIN_LIFE:
2968 (void) bhitm(u.usteed, obj);
2980 * cancel a monster (possibly the hero). inventory is cancelled only
2981 * if the monster is zapping itself directly, since otherwise the
2982 * effect is too strong. currently non-hero monsters do not zap
2983 * themselves with cancellation.
2986 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2987 register struct monst *mdef;
2988 register struct obj *obj;
2989 boolean youattack, allow_cancel_kill, self_cancel;
2991 boolean youdefend = (mdef == &youmonst);
2992 static const char writing_vanishes[] =
2994 "Some writing vanishes from %s head!";
2996 "
\89½
\82©
\82Ì
\95¶
\8e\9a\82ª%s
\82Ì
\93ª
\82©
\82ç
\8fÁ
\82¦
\82½
\81I";
2998 static const char your[] = "your"; /* should be extern */
3000 static const char your[] = "
\82 \82È
\82½"; /* should be extern */
3003 if (youdefend ? (!youattack && Antimagic)
3004 : resist(mdef, obj->oclass, 0, NOTELL))
3005 return FALSE; /* resisted cancellation */
3007 if (self_cancel) { /* 1st cancel inventory */
3010 for (otmp = (youdefend ? invent : mdef->minvent); otmp;
3014 context.botl = 1; /* potential AC change */
3019 /* now handle special cases */
3022 if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
3023 pline(writing_vanishes, your);
3027 Your("amulet grows hot for a moment, then cools.");
3029 Your("
\96\82\8f\9c\82¯
\82Í
\82µ
\82Î
\82ç
\82
\94M
\82
\82È
\82è
\81C
\82â
\82ª
\82Ä
\8c³
\82É
\96ß
\82Á
\82½
\81D");
3036 if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
3039 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
3040 if (canseemon(mdef))
3042 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
3044 pline(writing_vanishes, mon_nam(mdef));
3047 if (allow_cancel_kill) {
3051 monkilled(mdef, "", AD_SPEL);
3058 /* you've zapped an immediate type wand up or down */
3061 struct obj *obj; /* wand or spell */
3063 boolean striking = FALSE, disclose = FALSE;
3064 int x, y, xx, yy, ptmp;
3070 /* some wands have special effects other than normal bhitpile */
3071 /* drawbridge might change <u.ux,u.uy> */
3072 x = xx = u.ux; /* <x,y> is zap location */
3073 y = yy = u.uy; /* <xx,yy> is drawbridge (portcullis) position */
3074 ttmp = t_at(x, y); /* trap if there is one */
3076 switch (obj->otyp) {
3081 You("probe towards the %s.", ceiling(x, y));
3083 You("
\8fã
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", ceiling(x,y));
3085 ptmp += bhitpile(obj, bhito, x, y, u.dz);
3087 You("probe beneath the %s.", surface(x, y));
3089 You("
\89º
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", surface(x,y));
3090 ptmp += display_binventory(x, y, TRUE);
3094 Your("probe reveals nothing.");
3096 pline("
\92²
\8d¸
\82Ì
\8c\8b\89Ê
\89½
\82à
\82Å
\82Ä
\82±
\82È
\82©
\82Á
\82½
\81D");
3097 return TRUE; /* we've done our own bhitpile */
3100 /* up or down, but at closed portcullis only */
3101 if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
3102 open_drawbridge(xx, yy);
3104 } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
3105 /* can't use the stairs down to quest level 2 until
3106 leader "unlocks" them; give feedback if you try */
3107 && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
3109 pline_The("stairs seem to ripple momentarily.");
3111 pline("
\8aK
\92i
\82ª
\88ê
\8fu
\97h
\82ê
\82½
\82æ
\82¤
\82É
\8c©
\82¦
\82½
\81D");
3114 /* down will release you from bear trap or web */
3115 if (u.dz > 0 && u.utrap) {
3116 (void) openholdingtrap(&youmonst, &disclose);
3117 /* down will trigger trapdoor, hole, or [spiked-] pit */
3118 } else if (u.dz > 0 && !u.utrap) {
3119 (void) openfallingtrap(&youmonst, FALSE, &disclose);
3123 case SPE_FORCE_BOLT:
3127 case SPE_WIZARD_LOCK:
3128 /* down at open bridge or up or down at open portcullis */
3129 if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
3131 : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
3132 && find_drawbridge(&xx, &yy)) {
3134 close_drawbridge(xx, yy);
3136 destroy_drawbridge(xx, yy);
3138 } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
3139 && !Is_waterlevel(&u.uz) && !Underwater
3140 && !Is_qstart(&u.uz)) {
3142 /* similar to zap_dig() */
3144 pline("A rock is dislodged from the %s and falls on your %s.",
3145 ceiling(x, y), body_part(HEAD));
3147 pline("%s
\82©
\82ç
\8aâ
\82ª
\97\8e\82¿
\82Ä
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81D",
3148 ceiling(x, y), body_part(HEAD));
3150 dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
3152 losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
3154 losehp(Maybe_Half_Phys(dmg), "
\97\8e\8aâ
\82Å", KILLED_BY_AN);
3155 if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
3156 (void) xname(otmp); /* set dknown, maybe bknown */
3160 } else if (u.dz > 0 && ttmp) {
3161 if (!striking && closeholdingtrap(&youmonst, &disclose)) {
3162 ; /* now stuck in web or bear trap */
3163 } else if (striking && ttmp->ttyp == TRAPDOOR) {
3164 /* striking transforms trapdoor into hole */
3165 if (Blind && !ttmp->tseen) {
3167 pline("%s beneath you shatters.", Something);
3169 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\89½
\82©
\82ª
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3170 } else if (!ttmp->tseen) { /* => !Blind */
3172 pline("There's a trapdoor beneath you; it shatters.");
3174 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82Í
\97\8e\82µ
\94à
\82ª
\82 \82Á
\82½
\81G
\82»
\82ê
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3177 pline("The trapdoor beneath you shatters.");
3179 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\97\8e\82µ
\94à
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3185 /* might fall down hole */
3187 } else if (!striking && ttmp->ttyp == HOLE) {
3188 /* locking transforms hole into trapdoor */
3189 ttmp->ttyp = TRAPDOOR;
3190 if (Blind || !ttmp->tseen) {
3192 pline("Some %s swirls beneath you.",
3193 is_ice(x, y) ? "frost" : "dust");
3195 pline("
\82 \82È
\82½
\82Ì
\89º
\82Å%s
\82ª
\82¤
\82¸
\82ð
\8aª
\82
\82Ì
\82ª
\8c©
\82¦
\82½
\81D",
3196 is_ice(x,y) ? "
\91\9a" : "
\82Ù
\82±
\82è");
3202 pline("A trapdoor appears beneath you.");
3204 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\97\8e\82µ
\94à
\82ª
\82 \82ç
\82í
\82ê
\82½
\81D");
3207 /* hadn't fallen down hole; won't fall now */
3211 case SPE_STONE_TO_FLESH:
3212 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3213 || (Is_qstart(&u.uz) && u.dz < 0)) {
3214 pline1(nothing_happens);
3215 } else if (u.dz < 0) { /* we should do more... */
3217 pline("Blood drips on your %s.", body_part(FACE));
3219 pline("
\8c\8c\82ª
\82 \82È
\82½
\82Ì%s
\82Ö
\82µ
\82½
\82½
\82è
\97\8e\82¿
\82Ä
\82«
\82½
\81D", body_part(FACE));
3220 } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3222 Print this message only if there wasn't an engraving
3223 affected here. If water or ice, act like waterlevel case.
3225 e = engr_at(u.ux, u.uy);
3226 if (!(e && e->engr_type == ENGRAVE)) {
3227 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3228 pline1(nothing_happens);
3231 pline("Blood %ss %s your %s.",
3232 is_lava(u.ux, u.uy) ? "boil" : "pool",
3233 Levitation ? "beneath" : "at",
3234 makeplural(body_part(FOOT)));
3237 makeplural(body_part(FOOT)),
3238 Levitation ? "
\82Ì
\89º" : "
\8c³",
3239 is_lava(u.ux, u.uy) ?
3240 "
\82Å
\8c\8c\82ª
\95¦
\93«
\82µ
\82½" : "
\82É
\8c\8c\82¾
\82Ü
\82è
\82ª
\8fo
\97\88\82½");
3250 /* zapping downward */
3251 (void) bhitpile(obj, bhito, x, y, u.dz);
3253 /* subset of engraving effects; none sets `disclose' */
3254 if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3255 switch (obj->otyp) {
3259 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3261 case WAN_CANCELLATION:
3262 case SPE_CANCELLATION:
3263 case WAN_MAKE_INVISIBLE:
3266 case WAN_TELEPORTATION:
3267 case SPE_TELEPORT_AWAY:
3270 case SPE_STONE_TO_FLESH:
3271 if (e->engr_type == ENGRAVE) {
3272 /* only affects things in stone */
3274 pline_The(Hallucination
3275 ? "floor runs like butter!"
3276 : "edges on the floor get smoother.");
3279 ? "
\8f°
\82ª
\83o
\83^
\81[
\82Ì
\82æ
\82¤
\82É
\91\96\82Á
\82Ä
\82¢
\82Á
\82½
\81I"
3280 : "
\8f°
\82Ì
\89\8f\82ª
\82È
\82ß
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D");
3282 wipe_engr_at(x, y, d(2, 4), TRUE);
3286 case SPE_FORCE_BOLT:
3287 wipe_engr_at(x, y, d(2, 4), TRUE);
3293 } else if (u.dz < 0) {
3294 /* zapping upward */
3296 /* game flavor: if you're hiding under "something"
3297 * a zap upward should hit that "something".
3299 if (u.uundetected && hides_under(youmonst.data)) {
3301 otmp = level.objects[u.ux][u.uy];
3304 hitit = bhito(otmp, obj);
3306 (void) hideunder(&youmonst);
3315 /* used by do_break_wand() was well as by weffects() */
3325 /* if do_osshock() set obj_zapped while polying, give a message now */
3328 You_feel("shuddering vibrations.");
3330 You("
\82¼
\82Á
\82Æ
\82·
\82é
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
3334 /* called for various wand and spell effects - M. Stephenson */
3339 int otyp = obj->otyp;
3340 boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3342 exercise(A_WIS, TRUE);
3343 if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3344 && (u.dz > 0) && zap_steed(obj)) {
3346 } else if (objects[otyp].oc_dir == IMMEDIATE) {
3347 zapsetup(); /* reset obj_zapped */
3349 (void) bhitm(u.ustuck, obj);
3350 /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3352 disclose = zap_updown(obj);
3354 (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3357 zapwrapup(); /* give feedback for obj_zapped */
3359 } else if (objects[otyp].oc_dir == NODIR) {
3363 /* neither immediate nor directionless */
3365 if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3367 else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3368 buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3370 else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3371 buzz(otyp - WAN_MAGIC_MISSILE,
3372 (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3374 impossible("weffects: unexpected spell or wand");
3380 more_experienced(0, 10);
3385 /* augment damage for a spell dased on the hero's intelligence (and level) */
3387 spell_damage_bonus(dmg)
3388 int dmg; /* base amount to be adjusted by bonus or penalty */
3390 int intell = ACURR(A_INT);
3392 /* Punish low intelligence before low level else low intelligence
3393 gets punished only when high level */
3395 /* -3 penalty, but never reduce combined amount below 1
3396 (if dmg is 0 for some reason, we're careful to leave it there) */
3398 dmg = (dmg <= 3) ? 1 : dmg - 3;
3399 } else if (intell <= 13 || u.ulevel < 5)
3400 ; /* no bonus or penalty; dmg remains same */
3401 else if (intell <= 18)
3403 else if (intell <= 24 || u.ulevel < 14)
3406 dmg += 3; /* Int 25 */
3412 * Generate the to hit bonus for a spell. Based on the hero's skill in
3413 * spell class and dexterity.
3416 spell_hit_bonus(skill)
3420 int dex = ACURR(A_DEX);
3422 switch (P_SKILL(spell_skilltype(skill))) {
3423 case P_ISRESTRICTED:
3445 /* Will change when print stuff below removed */
3448 /* Even increment for dextrous heroes (see weapon.c abon) */
3449 hit_bon += dex - 14;
3458 /* force == 0 occurs e.g. with sleep ray */
3459 /* note that large force is usual with wands so that !! would
3460 require information about hand/weapon/wand */
3462 return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3464 return (const char *) ((force < 0) ? "
\81H" : (force <= 4) ? "
\81D" : "
\81I");
3468 hit(str, mtmp, force)
3471 const char *force; /* usually either "." or "!" */
3473 if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3474 && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3476 pline("%s %s it.", The(str), vtense(str, "hit"));
3478 pline("%s
\82Í
\89½
\82©
\82É
\96½
\92\86\82µ
\82½
\81D", str);
3481 pline("%s %s %s%s", The(str), vtense(str, "hit"),
3482 mon_nam(mtmp), force);
3484 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", str,
3485 mon_nam(mtmp), force);
3491 register const char *str;
3492 register struct monst *mtmp;
3496 "%s %s %s.", The(str), vtense(str, "miss"),
3497 ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3502 "%s
\82Ì%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\82Í
\82¸
\82ê
\82½
\81D", str,
3503 ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3510 skiprange(range, skipstart, skipend)
3511 int range, *skipstart, *skipend;
3513 int tr = (range / 4);
3514 int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3517 *skipend = tmp - ((tmp / 4) * rnd(3));
3518 if (*skipend >= tmp)
3523 * Called for the following distance effects:
3524 * when a weapon is thrown (weapon == THROWN_WEAPON)
3525 * when an object is kicked (KICKED_WEAPON)
3526 * when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3527 * when a light beam is flashed (FLASHED_LIGHT)
3528 * when a mirror is applied (INVIS_BEAM)
3529 * A thrown/kicked object falls down at end of its range or when a monster
3530 * is hit. The variable 'bhitpos' is set to the final position of the weapon
3531 * thrown/zapped. The ray of a wand may affect (by calling a provided
3532 * function) several objects and monsters on its path. The return value
3533 * is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3535 * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3536 * destroyed and *pobj set to NULL to indicate this.
3538 * Check !u.uswallow before calling bhit().
3539 * This function reveals the absence of a remembered invisible monster in
3540 * necessary cases (throwing or kicking weapons). The presence of a real
3541 * one is revealed for a weapon, but if not a weapon is left up to fhitm().
3544 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3545 register int ddx, ddy, range; /* direction and range */
3546 int weapon; /* see values in hack.h */
3547 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3548 FDECL((*fhito), (OBJ_P, OBJ_P));
3549 struct obj **pobj; /* object tossed/used, set to NULL
3550 * if object is destroyed */
3553 struct obj *obj = *pobj;
3555 boolean shopdoor = FALSE, point_blank = TRUE;
3556 boolean in_skip = FALSE, allow_skip = FALSE;
3557 int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3559 if (weapon == KICKED_WEAPON) {
3560 /* object starts one square in front of player */
3561 bhitpos.x = u.ux + ddx;
3562 bhitpos.y = u.uy + ddy;
3569 if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3570 skiprange(range, &skiprange_start, &skiprange_end);
3571 allow_skip = !rn2(3);
3574 if (weapon == FLASHED_LIGHT) {
3575 tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3576 } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3577 tmp_at(DISP_FLASH, obj_to_glyph(obj));
3579 while (range-- > 0) {
3593 if (is_pick(obj) && inside_shop(x, y)
3594 && (mtmp = shkcatch(obj, x, y)) != 0) {
3595 tmp_at(DISP_END, 0);
3599 typ = levl[bhitpos.x][bhitpos.y].typ;
3601 /* iron bars will block anything big enough */
3602 if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3604 && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
3605 point_blank ? 0 : !rn2(5), 1)) {
3606 /* caveat: obj might now be null... */
3613 if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3614 boolean learn_it = FALSE;
3616 switch (obj->otyp) {
3619 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3620 if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3622 open_drawbridge(x, y);
3626 case SPE_WIZARD_LOCK:
3627 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3628 && levl[x][y].typ == DRAWBRIDGE_DOWN)
3630 close_drawbridge(x, y);
3633 case SPE_FORCE_BOLT:
3634 if (typ != DRAWBRIDGE_UP)
3635 destroy_drawbridge(x, y);
3643 mtmp = m_at(bhitpos.x, bhitpos.y);
3648 * skiprange_start is only set if this is a thrown rock
3650 if (skiprange_start && (range == skiprange_start) && allow_skip) {
3651 if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3655 pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3656 skipcount ? " again" : "");
3658 pline("%s
\82Í%s
\92µ
\82Ë
\82½
\81D", Yname2(obj),
3659 skipcount ? "
\8dÄ
\82Ñ" : "");
3663 You_hear("%s skip.", yname(obj));
3665 You_hear("%s
\82ª
\92µ
\82Ë
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D", yname(obj));
3667 } else if (skiprange_start > skiprange_end + 1) {
3672 if (range <= skiprange_end) {
3674 if (range > 3) /* another bounce? */
3675 skiprange(range, &skiprange_start, &skiprange_end);
3676 } else if (mtmp && M_IN_WATER(mtmp->data)) {
3677 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3679 pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3682 pline("%s
\82Í%s
\82ð
\94ò
\82Ñ
\89z
\82¦
\82½
\81D", Yname2(obj),
3688 if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3689 notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3690 if (weapon == FLASHED_LIGHT) {
3691 /* FLASHED_LIGHT hitting invisible monster should
3692 pass through instead of stop so we call
3693 flash_hits_mon() directly rather than returning
3694 mtmp back to caller. That allows the flash to
3695 keep on going. Note that we use mtmp->minvis
3696 not canspotmon() because it makes no difference
3697 whether the hero can see the monster or not. */
3699 obj->ox = u.ux, obj->oy = u.uy;
3700 (void) flash_hits_mon(mtmp, obj);
3702 tmp_at(DISP_END, 0);
3703 return mtmp; /* caller will call flash_hits_mon */
3705 } else if (weapon == INVIS_BEAM) {
3706 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3707 through invisible targets; unlike it, we aren't
3708 prepared for multiple hits so just get first one
3709 that's either visible or could see its invisible
3710 self. [No tmp_at() cleanup is needed here.] */
3711 if (!mtmp->minvis || perceives(mtmp->data))
3713 } else if (weapon != ZAPPED_WAND) {
3714 /* THROWN_WEAPON, KICKED_WEAPON */
3715 tmp_at(DISP_END, 0);
3716 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3717 map_invisible(bhitpos.x, bhitpos.y);
3721 (*fhitm)(mtmp, obj);
3725 if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3726 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3727 unmap_object(bhitpos.x, bhitpos.y);
3732 if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3735 if (weapon == KICKED_WEAPON
3736 && ((obj->oclass == COIN_CLASS
3737 && OBJ_AT(bhitpos.x, bhitpos.y))
3738 || ship_object(obj, bhitpos.x, bhitpos.y,
3739 costly_spot(bhitpos.x, bhitpos.y)))) {
3740 tmp_at(DISP_END, 0);
3741 return (struct monst *) 0;
3744 if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3745 switch (obj->otyp) {
3750 case SPE_WIZARD_LOCK:
3751 case SPE_FORCE_BOLT:
3752 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3753 if (cansee(bhitpos.x, bhitpos.y)
3754 || (obj->otyp == WAN_STRIKING && !Deaf))
3756 if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3757 && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3759 add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
3765 if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3770 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3771 /* 'I' present but no monster: erase */
3772 /* do this before the tmp_at() */
3773 if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3775 unmap_object(bhitpos.x, bhitpos.y);
3778 tmp_at(bhitpos.x, bhitpos.y);
3780 /* kicked objects fall in pools */
3781 if ((weapon == KICKED_WEAPON)
3782 && (is_pool(bhitpos.x, bhitpos.y)
3783 || is_lava(bhitpos.x, bhitpos.y)))
3785 if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3786 break; /* physical objects fall onto sink */
3788 /* limit range of ball so hero won't make an invalid move */
3789 if (weapon == THROWN_WEAPON && range > 0
3790 && obj->otyp == HEAVY_IRON_BALL) {
3794 if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3797 pline("%s hits %s.", The(distant_name(obj, xname)),
3800 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", distant_name(obj, xname),
3804 } else if (obj == uball) {
3805 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3806 /* nb: it didn't hit anything directly */
3809 pline("%s jerks to an abrupt halt.",
3810 The(distant_name(obj, xname))); /* lame */
3812 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\83K
\83N
\83\93\82Æ
\8e~
\82Ü
\82Á
\82½
\81D",
3813 distant_name(obj, xname)); /* lame */
3816 } else if (Sokoban && (t = t_at(x, y)) != 0
3817 && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3818 || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3819 /* hero falls into the trap, so ball stops */
3825 /* thrown/kicked missile has moved away from its starting spot */
3826 point_blank = FALSE; /* affects passing through iron bars */
3829 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3830 tmp_at(DISP_END, 0);
3834 pay_for_damage("destroy", FALSE);
3836 pay_for_damage("
\94j
\89ó
\82·
\82é", FALSE);
3838 return (struct monst *) 0;
3841 /* process thrown boomerang, which travels a curving path...
3842 * A multi-shot volley ought to have all missiles in flight at once,
3843 * but we're called separately for each one. We terminate the volley
3844 * early on a failed catch since continuing to throw after being hit
3845 * is too obviously silly.
3848 boomhit(obj, dx, dy)
3853 int boom; /* showsym[] index */
3855 boolean counterclockwise = TRUE; /* right-handed throw */
3857 /* counterclockwise traversal patterns:
3858 * ..........................54.................................
3859 * ..................43.....6..3....765.........................
3860 * ..........32.....5..2...7...2...8...4....87..................
3861 * .........4..1....6..1...8..1....9...3...9..6.....98..........
3862 * ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3863 * .3...9....6..9....89.....................1..4...1..6....1..8.
3864 * .4...8.....78.............................23....2..5...2...7.
3865 * ..567............................................34....3..6..
3866 * ........................................................45...
3867 * (invert rows for corresponding clockwise patterns)
3872 boom = counterclockwise ? S_boomleft : S_boomright;
3873 for (i = 0; i < 8; i++)
3874 if (xdir[i] == dx && ydir[i] == dy)
3876 tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3877 for (ct = 0; ct < 10; ct++) {
3878 i = (i + 8) % 8; /* 0..7 (8 -> 0, -1 -> 7) */
3879 boom = (S_boomleft + S_boomright - boom); /* toggle */
3880 tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3885 if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3887 tmp_at(DISP_END, 0);
3890 if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3891 || closed_door(bhitpos.x, bhitpos.y)) {
3896 if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3897 if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3898 /* we hit ourselves */
3899 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
3903 "
\83u
\81[
\83\81\83\89\83\93");
3906 } else { /* we catch it */
3907 tmp_at(DISP_END, 0);
3909 You("skillfully catch the boomerang.");
3911 You("
\8fã
\8eè
\82É
\83u
\81[
\83\81\83\89\83\93\82ð
\92Í
\82Ü
\82¦
\82½
\81D");
3915 tmp_at(bhitpos.x, bhitpos.y);
3917 if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3922 pline("
\83J
\83\89\83\93\81I");
3923 break; /* boomerang falls on sink */
3925 /* ct==0, initial position, we want next delta to be same;
3926 ct==5, opposite position, repeat delta undoes first one */
3928 i += (counterclockwise ? -1 : 1);
3930 tmp_at(DISP_END, 0); /* do not leave last symbol */
3931 return (struct monst *) 0;
3934 /* used by buzz(); also used by munslime(muse.c); returns damage applied
3935 to mon; note: caller is responsible for killing mon if damage is fatal */
3937 zhitm(mon, type, nd, ootmp)
3938 register struct monst *mon;
3939 register int type, nd;
3940 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3942 register int tmp = 0;
3943 register int abstype = abs(type) % 10;
3944 boolean sho_shieldeff = FALSE;
3945 boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3947 *ootmp = (struct obj *) 0;
3949 case ZT_MAGIC_MISSILE:
3950 if (resists_magm(mon)) {
3951 sho_shieldeff = TRUE;
3956 tmp = spell_damage_bonus(tmp);
3959 if (resists_fire(mon)) {
3960 sho_shieldeff = TRUE;
3964 if (resists_cold(mon))
3967 tmp = spell_damage_bonus(tmp);
3968 if (burnarmor(mon)) {
3970 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3972 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3974 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3975 destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3979 if (resists_cold(mon)) {
3980 sho_shieldeff = TRUE;
3984 if (resists_fire(mon))
3987 tmp = spell_damage_bonus(tmp);
3989 (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3993 (void) sleep_monst(mon, d(nd, 25),
3994 type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3996 case ZT_DEATH: /* death/disintegration */
3997 if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3998 if (mon->data == &mons[PM_DEATH]) {
3999 mon->mhpmax += mon->mhpmax / 2;
4000 if (mon->mhpmax >= MAGIC_COOKIE)
4001 mon->mhpmax = MAGIC_COOKIE - 1;
4002 mon->mhp = mon->mhpmax;
4006 if (nonliving(mon->data) || is_demon(mon->data)
4007 || is_vampshifter(mon) || resists_magm(mon)) {
4008 /* similar to player */
4009 sho_shieldeff = TRUE;
4012 type = -1; /* so they don't get saving throws */
4016 if (resists_disint(mon)) {
4017 sho_shieldeff = TRUE;
4018 } else if (mon->misc_worn_check & W_ARMS) {
4019 /* destroy shield; victim survives */
4020 *ootmp = which_armor(mon, W_ARMS);
4021 } else if (mon->misc_worn_check & W_ARM) {
4022 /* destroy body armor, also cloak if present */
4023 *ootmp = which_armor(mon, W_ARM);
4024 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4025 m_useup(mon, otmp2);
4027 /* no body armor, victim dies; destroy cloak
4028 and shirt now in case target gets life-saved */
4030 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4031 m_useup(mon, otmp2);
4032 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
4033 m_useup(mon, otmp2);
4035 type = -1; /* no saving throw wanted */
4036 break; /* not ordinary damage */
4041 if (resists_elec(mon)) {
4042 sho_shieldeff = TRUE;
4044 /* can still blind the monster */
4048 tmp = spell_damage_bonus(tmp);
4049 if (!resists_blnd(mon)
4050 && !(type > 0 && u.uswallow && mon == u.ustuck)) {
4051 register unsigned rnd_tmp = rnd(50);
4053 if ((mon->mblinded + rnd_tmp) > 127)
4054 mon->mblinded = 127;
4056 mon->mblinded += rnd_tmp;
4059 (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
4060 /* not actually possible yet */
4062 (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
4065 if (resists_poison(mon)) {
4066 sho_shieldeff = TRUE;
4072 if (resists_acid(mon)) {
4073 sho_shieldeff = TRUE;
4078 acid_damage(MON_WEP(mon));
4080 erode_armor(mon, ERODE_CORRODE);
4084 shieldeff(mon->mx, mon->my);
4085 if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
4087 if (tmp > 0 && type >= 0
4088 && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
4091 tmp = 0; /* don't allow negative damage */
4092 debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
4099 zhitu(type, nd, fltxt, sx, sy)
4104 int dam = 0, abstyp = abs(type);
4108 Sprintf(buf, "%s
\82É
\82æ
\82Á
\82Ä", fltxt);
4112 switch (abstyp % 10) {
4113 case ZT_MAGIC_MISSILE:
4117 pline_The("missiles bounce off!");
4119 pline("
\96\82\96@
\82Ì
\96î
\82Í
\94½
\8eË
\82µ
\82½
\81I");
4122 exercise(A_STR, FALSE);
4126 if (Fire_resistance) {
4129 You("don't feel hot!");
4131 You("
\94M
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81I");
4132 ugolemeffects(AD_FIRE, d(nd, 6));
4137 if (burnarmor(&youmonst)) { /* "body hit" */
4139 destroy_item(POTION_CLASS, AD_FIRE);
4141 destroy_item(SCROLL_CLASS, AD_FIRE);
4143 destroy_item(SPBOOK_CLASS, AD_FIRE);
4144 destroy_item(FOOD_CLASS, AD_FIRE);
4148 if (Cold_resistance) {
4151 You("don't feel cold.");
4153 You("
\97â
\82½
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81D");
4154 ugolemeffects(AD_COLD, d(nd, 6));
4159 destroy_item(POTION_CLASS, AD_COLD);
4162 if (Sleep_resistance) {
4163 shieldeff(u.ux, u.uy);
4165 You("don't feel sleepy.");
4167 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81D");
4169 fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
4173 if (abstyp == ZT_BREATH(ZT_DEATH)) {
4174 if (Disint_resistance) {
4176 You("are not disintegrated.");
4178 You("
\95ª
\89ð
\82³
\82ê
\82È
\82¢
\81D");
4181 /* destroy shield; other possessions are safe */
4182 (void) destroy_arm(uarms);
4185 /* destroy suit; if present, cloak goes too */
4187 (void) destroy_arm(uarmc);
4188 (void) destroy_arm(uarm);
4191 /* no shield or suit, you're dead; wipe out cloak
4192 and/or shirt in case of life-saving or bones */
4194 (void) destroy_arm(uarmc);
4196 (void) destroy_arm(uarmu);
4197 } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4200 You("seem unaffected.");
4202 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
4204 } else if (Antimagic) {
4207 You("aren't affected.");
4209 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4212 killer.format = KILLED_BY_AN;
4213 Strcpy(killer.name, fltxt ? fltxt : "");
4214 /* when killed by disintegration breath, don't leave corpse */
4215 u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4217 return; /* lifesaved */
4219 if (Shock_resistance) {
4222 You("aren't affected.");
4224 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4225 ugolemeffects(AD_ELEC, d(nd, 6));
4228 exercise(A_CON, FALSE);
4231 destroy_item(WAND_CLASS, AD_ELEC);
4233 destroy_item(RING_CLASS, AD_ELEC);
4237 poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4239 poisoned("
\91§", A_DEX, "
\93Å
\82Ì
\91§", 15, FALSE);
4242 if (Acid_resistance) {
4244 pline_The("%s doesn't hurt.", hliquid("acid"));
4246 pline_The("%s
\82Å
\82Í
\8f\9d\82Â
\82©
\82È
\82©
\82Á
\82½
\81D", hliquid("
\8e_"));
4250 pline_The("%s burns!", hliquid("acid"));
4252 pline_The("%s
\82Å
\8fÄ
\82¯
\82½
\81I", hliquid("
\8e_"));
4254 exercise(A_STR, FALSE);
4256 /* using two weapons at once makes both of them more vulnerable */
4257 if (!rn2(u.twoweap ? 3 : 6))
4259 if (u.twoweap && !rn2(3))
4260 acid_damage(uswapwep);
4262 erode_armor(&youmonst, ERODE_CORRODE);
4266 /* Half_spell_damage protection yields half-damage for wands & spells,
4267 including hero's own ricochets; breath attacks do full damage */
4268 if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4269 dam = (dam + 1) / 2;
4270 losehp(dam, fltxt, KILLED_BY_AN);
4275 * burn objects (such as scrolls and spellbooks) on floor
4276 * at position x,y; return the number of objects burned
4279 burn_floor_objects(x, y, give_feedback, u_caused)
4281 boolean give_feedback; /* caller needs to decide about visibility checks */
4284 struct obj *obj, *obj2;
4285 long i, scrquan, delquan;
4286 char buf1[BUFSZ], buf2[BUFSZ];
4289 for (obj = level.objects[x][y]; obj; obj = obj2) {
4290 obj2 = obj->nexthere;
4291 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4292 || (obj->oclass == FOOD_CLASS
4293 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4294 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4295 || obj_resists(obj, 2, 100))
4297 scrquan = obj->quan; /* number present */
4298 delquan = 0L; /* number to destroy */
4299 for (i = scrquan; i > 0L; i--)
4303 /* save name before potential delobj() */
4304 if (give_feedback) {
4306 Strcpy(buf1, (x == u.ux && y == u.uy)
4308 : distant_name(obj, xname));
4310 Strcpy(buf2, (x == u.ux && y == u.uy)
4312 : distant_name(obj, xname));
4313 obj->quan = scrquan;
4315 /* useupf(), which charges, only if hero caused damage */
4317 useupf(obj, delquan);
4318 else if (delquan < scrquan)
4319 obj->quan -= delquan;
4323 if (give_feedback) {
4326 pline("%ld %s burn.", delquan, buf2);
4328 pline("%ld%s
\82Ì%s
\82ª
\94R
\82¦
\82½
\81D",
4330 obj->oclass == SCROLL_CLASS ? "
\96\87" : "
\8dû",
4335 pline("%s burns.", An(buf1));
4337 pline("%s
\82Í
\94R
\82¦
\82½
\81D", buf1);
4345 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4349 int type; /* either hero cast spell type or 0 */
4351 int chance = rn2(20);
4352 int spell_bonus = type ? spell_hit_bonus(type) : 0;
4354 /* small chance for naked target to avoid being hit */
4356 return rnd(10) < ac + spell_bonus;
4358 /* very high armor protection does not achieve invulnerability */
4361 return (3 - chance < ac + spell_bonus);
4365 disintegrate_mon(mon, type, fltxt)
4367 int type; /* hero vs other */
4370 struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4372 if (canseemon(mon)) {
4375 pline("%s is disintegrated!", Monnam(mon));
4377 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I", Monnam(mon));
4380 hit(fltxt, mon, "!");
4382 hit(fltxt, mon, "
\81I");
4385 /* note: worn amulet of life saving must be preserved in order to operate */
4386 #define oresist_disintegration(obj) \
4387 (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4388 || is_quest_artifact(obj) || obj == m_amulet)
4390 for (otmp = mon->minvent; otmp; otmp = otmp2) {
4392 if (!oresist_disintegration(otmp)) {
4393 if (otmp->owornmask) {
4394 /* in case monster's life gets saved */
4395 mon->misc_worn_check &= ~otmp->owornmask;
4396 if (otmp->owornmask & W_WEP)
4397 setmnotwielded(mon, otmp);
4398 /* also dismounts hero if this object is steed's saddle */
4399 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4400 otmp->owornmask = 0L;
4402 obj_extract_self(otmp);
4403 obfree(otmp, (struct obj *) 0);
4407 #undef oresist_disintegration
4410 monkilled(mon, (char *) 0, -AD_RBRE);
4412 xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
4416 buzz(type, nd, sx, sy, dx, dy)
4421 dobuzz(type, nd, sx, sy, dx, dy, TRUE);
4425 * type == 0 to 9 : you shooting a wand
4426 * type == 10 to 19 : you casting a spell
4427 * type == 20 to 29 : you breathing as a monster
4428 * type == -10 to -19 : monster casting spell
4429 * type == -20 to -29 : monster breathing at you
4430 * type == -30 to -39 : monster shooting a wand
4431 * called with dx = dy = 0 with vertical bolts
4434 dobuzz(type, nd, sx, sy, dx, dy, say)
4435 register int type, nd;
4436 register xchar sx, sy;
4437 register int dx, dy;
4438 boolean say; /* Announce out of sight hit/miss events if true */
4440 int range, abstype = abs(type) % 10;
4441 register xchar lsx, lsy;
4444 boolean shopdamage = FALSE;
4449 /* if its a Hero Spell then get its SPE_TYPE */
4450 spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4452 fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4458 tmp = zhitm(u.ustuck, type, nd, &otmp);
4463 pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4466 pline("%s
\82Í%s
\82ð
\82Ð
\82«
\82³
\82¢
\82½%s", fltxt, mon_nam(u.ustuck),
4469 /* Using disintegration from the inside only makes a hole... */
4470 if (tmp == MAGIC_COOKIE)
4472 if (u.ustuck->mhp < 1)
4479 if (dx == 0 && dy == 0)
4481 save_bhitpos = bhitpos;
4483 tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4484 while (range-- > 0) {
4489 if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
4493 if (cansee(sx, sy)) {
4494 /* reveal/unreveal invisible monsters before tmp_at() */
4495 if (mon && !canspotmon(mon))
4496 map_invisible(sx, sy);
4498 (void) unmap_invisible(sx, sy);
4499 if (ZAP_POS(levl[sx][sy].typ)
4500 || (isok(lsx, lsy) && cansee(lsx, lsy)))
4502 delay_output(); /* wait a little */
4505 /* hit() and miss() need bhitpos to match the target */
4506 bhitpos.x = sx, bhitpos.y = sy;
4507 /* Fireballs only damage when they explode */
4508 if (type != ZT_SPELL(ZT_FIRE))
4509 range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4512 if (type == ZT_SPELL(ZT_FIRE))
4515 mon->mstrategy &= ~STRAT_WAITMASK;
4517 notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
4518 if (zap_hit(find_mac(mon), spell_type)) {
4519 if (mon_reflects(mon, (char *) 0)) {
4520 if (cansee(mon->mx, mon->my)) {
4521 hit(fltxt, mon, exclam(0));
4522 shieldeff(mon->mx, mon->my);
4524 (void) mon_reflects(mon,
4525 "But it reflects from %s %s!");
4527 (void) mon_reflects(mon,
4528 "
\82µ
\82©
\82µ
\82»
\82ê
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81I");
4534 boolean mon_could_move = mon->mcanmove;
4535 int tmp = zhitm(mon, type, nd, &otmp);
4537 if (is_rider(mon->data)
4538 && abs(type) == ZT_BREATH(ZT_DEATH)) {
4539 if (canseemon(mon)) {
4541 hit(fltxt, mon, ".");
4543 hit(fltxt, mon, "
\81D");
4545 pline("%s disintegrates.", Monnam(mon));
4547 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D", Monnam(mon));
4549 pline("%s body reintegrates before your %s!",
4550 s_suffix(Monnam(mon)),
4551 (eyecount(youmonst.data) == 1)
4553 : makeplural(body_part(EYE)));
4555 pline("%s
\82Ì
\91Ì
\82Í
\82 \82È
\82½
\82Ì
\96Ú
\82Ì
\91O
\82Å
\8dÄ
\8c\8b\8d\87\82µ
\82½
\81I",
4559 pline("%s resurrects!", Monnam(mon));
4561 pline("%s
\82Í
\91h
\82Á
\82½
\81I", Monnam(mon));
4563 mon->mhp = mon->mhpmax;
4564 break; /* Out of while loop */
4566 if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4567 if (canseemon(mon)) {
4569 hit(fltxt, mon, ".");
4571 hit(fltxt, mon, "
\81D");
4573 pline("%s absorbs the deadly %s!", Monnam(mon),
4574 type == ZT_BREATH(ZT_DEATH) ? "blast"
4577 pline("%s
\82Í
\8e\80\82Ì%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", Monnam(mon),
4578 type == ZT_BREATH(ZT_DEATH) ? "
\91§"
4582 pline("It seems even stronger than before.");
4584 pline("
\82³
\82ç
\82É
\8b
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82³
\82¦
\82·
\82é
\81D");
4586 break; /* Out of while loop */
4589 if (tmp == MAGIC_COOKIE) { /* disintegration */
4590 disintegrate_mon(mon, type, fltxt);
4591 } else if (mon->mhp < 1) {
4593 /* mon has just been killed by another monster */
4594 monkilled(mon, fltxt, AD_RBRE);
4596 int xkflags = XKILL_GIVEMSG; /* killed(mon); */
4598 /* killed by hero; we know 'type' isn't negative;
4599 if it's fire, highly flammable monsters leave
4600 no corpse; don't bother reporting that they
4601 "burn completely" -- unnecessary verbosity */
4602 if ((type % 10 == ZT_FIRE)
4603 /* paper golem or straw golem */
4604 && completelyburns(mon->data))
4605 xkflags |= XKILL_NOCORPSE;
4606 xkilled(mon, xkflags);
4610 /* normal non-fatal hit */
4611 if (say || canseemon(mon))
4612 hit(fltxt, mon, exclam(tmp));
4614 /* some armor was destroyed; no damage done */
4617 pline("%s %s is disintegrated!",
4618 s_suffix(Monnam(mon)),
4619 distant_name(otmp, xname));
4621 pline("%s
\82Ì%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I",
4623 distant_name(otmp, xname));
4627 if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4633 if (say || canseemon(mon))
4636 } else if (sx == u.ux && sy == u.uy && range >= 0) {
4638 if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4641 } else if (zap_hit((int) u.uac, 0)) {
4644 pline("%s hits you!", The(fltxt));
4646 pline("%s
\82Í
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I", fltxt);
4650 (void) ureflects("But %s reflects from your %s!",
4653 (void) ureflects("
\82µ
\82©
\82µ
\81C%s
\82Í
\82 \82È
\82½
\82Ì%s
\82É
\82æ
\82Á
\82Ä
\94½
\8eË
\82µ
\82½
\81D",
4658 pline("For some reason you are not affected.");
4660 pline("
\82È
\82º
\82©
\82 \82È
\82½
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82©
\82Á
\82½
\81D");
4665 zhitu(type, nd, fltxt, sx, sy);
4667 } else if (!Blind) {
4669 pline("%s whizzes by you!", The(fltxt));
4671 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82»
\82Î
\82ð
\82©
\82·
\82ß
\82½
\81I", fltxt);
4672 } else if (abstype == ZT_LIGHTNING) {
4674 Your("%s tingles.", body_part(ARM));
4676 Your("%s
\82Í
\83q
\83\8a\83q
\83\8a\82µ
\82½
\81D", body_part(ARM));
4678 if (abstype == ZT_LIGHTNING)
4679 (void) flashburn((long) d(nd, 50));
4684 if (!ZAP_POS(levl[sx][sy].typ)
4685 || (closed_door(sx, sy) && range >= 0)) {
4686 int bounce, bchance;
4691 bchance = (levl[sx][sy].typ == STONE) ? 10
4692 : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
4695 fireball = (type == ZT_SPELL(ZT_FIRE));
4696 if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
4698 if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
4700 pline_The("%s vanishes into the aether!", fltxt);
4702 pline_The("%s
\82Í
\83G
\81[
\83e
\83\8b\8bó
\8aÔ
\82É
\8fÁ
\82¦
\82½
\81I", fltxt);
4704 type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
4706 } else if (fireball) {
4709 break; /* fireballs explode before the obstacle */
4712 pline_The("%s bounces!", fltxt);
4714 pline_The("%s
\82Í
\94½
\8eË
\82µ
\82½
\81I", fltxt);
4716 if (!dx || !dy || !rn2(bchance)) {
4720 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4721 && !closed_door(sx, lsy)
4722 && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4723 && ZAP_POS(levl[sx + dx][lsy].typ))))
4725 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4726 && !closed_door(lsx, sy)
4727 && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4728 && ZAP_POS(levl[lsx][sy + dy].typ))))
4729 if (!bounce || rn2(2))
4743 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4747 tmp_at(DISP_END, 0);
4748 if (type == ZT_SPELL(ZT_FIRE))
4749 explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4752 pay_for_damage(abstype == ZT_FIRE
4754 : abstype == ZT_COLD
4756 /* "damage" indicates wall rather than door */
4757 : abstype == ZT_ACID
4759 : abstype == ZT_DEATH
4764 pay_for_damage(abstype == ZT_FIRE
4766 : abstype == ZT_COLD
4767 ? "
\95²
\81X
\82É
\82·
\82é"
4768 : abstype == ZT_ACID
4769 ? "
\8f\9d\82Â
\82¯
\82é"
4770 : abstype == ZT_DEATH
4771 ? "
\95²
\8dÓ
\82·
\82é"
4772 : "
\94j
\89ó
\82·
\82é",
4775 bhitpos = save_bhitpos;
4783 struct rm *lev = &levl[x][y];
4788 msg = "The ice crackles and melts.";
4790 msg = "
\95X
\82Í
\83s
\83L
\83s
\83L
\96Â
\82è
\81C
\97n
\82¯
\82½
\81D";
4791 if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
4792 lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4793 } else { /* lev->typ == ICE */
4795 if (lev->icedpool == ICED_POOL)
4800 lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4804 spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4805 obj_ice_effects(x, y, FALSE);
4812 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4815 pline("%s settles...", An(xname(otmp)));
4817 pline("%s
\82Í
\82Í
\82Ü
\82Á
\82½
\81D
\81D
\81D", xname(otmp));
4819 obj_extract_self(otmp); /* boulder isn't being pushed */
4820 if (!boulder_hits_pool(otmp, x, y, FALSE))
4821 impossible("melt_ice: no pool?");
4822 /* try again if there's another boulder and pool didn't fill */
4823 } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4826 if (x == u.ux && y == u.uy)
4827 spoteffects(TRUE); /* possibly drown, notice objects */
4830 #define MIN_ICE_TIME 50
4831 #define MAX_ICE_TIME 2000
4833 * Usually start a melt_ice timer; sometimes the ice will become
4834 * permanent instead.
4837 start_melt_ice_timeout(x, y, min_time)
4839 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4844 when = (int) min_time;
4845 if (when < MIN_ICE_TIME - 1)
4846 when = MIN_ICE_TIME - 1;
4848 /* random timeout; surrounding ice locations ought to be a factor... */
4849 while (++when <= MAX_ICE_TIME)
4850 if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4853 /* if we're within MAX_ICE_TIME, install a melt timer;
4854 otherwise, omit it to leave this ice permanent */
4855 if (when <= MAX_ICE_TIME) {
4856 where = ((long) x << 16) | (long) y;
4857 (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4858 long_to_any(where));
4865 * Called when ice has melted completely away.
4868 melt_ice_away(arg, timeout)
4870 long timeout UNUSED;
4873 long where = arg->a_long;
4875 y = (xchar) (where & 0xFFFF);
4876 x = (xchar) ((where >> 16) & 0xFFFF);
4877 /* melt_ice does newsym when appropriate */
4879 melt_ice(x, y, "Some ice melts away.");
4881 melt_ice(x, y, "
\95X
\82ª
\8f
\82µ
\97n
\82¯
\82½
\81D");
4884 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4885 * Used both for normal bolts of fire, cold, etc... and for fireballs.
4886 * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4887 * amount by which range is reduced (the latter is just ignored by fireballs)
4890 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4893 boolean *shopdamage;
4894 short exploding_wand_typ;
4896 const char *zapverb;
4899 struct rm *lev = &levl[x][y];
4900 boolean see_it = cansee(x, y), yourzap;
4901 int rangemod = 0, abstype = abs(type) % 10;
4906 if (t && t->ttyp == WEB) {
4907 /* a burning web is too flimsy to notice if you can't see it */
4910 Norep("A web bursts into flames!");
4912 Norep("
\82
\82à
\82Ì
\91\83\82Í
\89\8a\82É
\95ï
\82Ü
\82ê
\82½
\81I");
4913 (void) delfloortrap(t);
4918 melt_ice(x, y, (char *) 0);
4919 } else if (is_pool(x, y)) {
4921 const char *msgtxt = "You hear hissing gas.";
4923 const char *msgtxt = "
\82µ
\82ã
\81[
\82Á
\82Æ
\82¢
\82¤
\83K
\83X
\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4925 if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4928 msgtxt = "Some water evaporates.";
4930 msgtxt = "
\82·
\82±
\82µ
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4934 t = maketrap(x, y, PIT);
4939 msgtxt = "The water evaporates.";
4941 msgtxt = "
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4943 Norep("%s", msgtxt);
4944 if (lev->typ == ROOM)
4946 } else if (IS_FOUNTAIN(lev->typ)) {
4949 pline("Steam billows from the fountain.");
4951 pline("
\90ò
\82©
\82ç
\8fö
\8bC
\82ª
\97§
\82¿
\82Ì
\82Ú
\82Á
\82½
\81D");
4953 dryup(x, y, type > 0);
4955 break; /* ZT_FIRE */
4958 if (is_pool(x, y) || is_lava(x, y)) {
4959 boolean lava = is_lava(x, y),
4960 moat = is_moat(x, y);
4962 if (lev->typ == WATER) {
4963 /* For now, don't let WATER freeze. */
4966 pline_The("%s freezes for a moment.", hliquid("water"));
4968 pline_The("%s
\82Í
\88ê
\8fu
\93\80\82Á
\82½
\81D", hliquid("
\90\85"));
4971 You_hear("a soft crackling.");
4973 You_hear("
\83s
\83L
\81I
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4974 rangemod -= 1000; /* stop */
4978 Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
4980 if (lev->typ == DRAWBRIDGE_UP) {
4981 lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4982 lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4985 lev->icedpool = (lev->typ == POOL) ? ICED_POOL
4987 lev->typ = lava ? ROOM : ICE;
4993 Norep("The %s cools and solidifies.", hliquid("lava"));
4995 Norep("%s
\82Í
\97â
\82¦
\8cÅ
\82Ü
\82Á
\82½
\81D", hliquid("lava"));
4998 Norep("The %s is bridged with ice!", buf);
5000 Norep("%s
\82É
\95X
\82Ì
\8b´
\82ª
\82©
\82¯
\82ç
\82ê
\82½
\81I", buf);
5003 Norep("The %s freezes.", hliquid("water"));
5005 Norep("%s
\82Í
\93\80\82Á
\82½
\81D", hliquid("
\95X"));
5009 You_hear("a crackling sound.");
5011 You_hear("
\83s
\83L
\83s
\83L
\83b
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
5013 if (x == u.ux && y == u.uy) {
5014 if (u.uinwater) { /* not just `if (Underwater)' */
5015 /* leave the no longer existent water */
5019 vision_full_recalc = 1;
5020 } else if (u.utrap && u.utraptype == TT_LAVA) {
5024 You("pass through the now-solid rock.");
5026 You("
\82¢
\82Ü
\8cÅ
\82
\82È
\82Á
\82½
\82Î
\82©
\82è
\82Ì
\90Î
\82Ì
\92\86\82ð
\82·
\82è
\94²
\82¯
\82½
\81D");
5028 u.utrap = rn1(50, 20);
5029 u.utraptype = TT_INFLOOR;
5031 You("are firmly stuck in the cooling rock.");
5033 You("
\97â
\82¦
\82½
\8aâ
\82Ì
\82È
\82©
\82É
\82µ
\82Á
\82©
\82è
\82Æ
\96\84\82Ü
\82Á
\82½
\81D");
5036 } else if ((mon = m_at(x, y)) != 0) {
5037 /* probably ought to do some hefty damage to any
5038 non-ice creature caught in freezing water;
5039 at a minimum, eels are forced out of hiding */
5040 if (is_swimmer(mon->data) && mon->mundetected) {
5041 mon->mundetected = 0;
5046 start_melt_ice_timeout(x, y, 0L);
5047 obj_ice_effects(x, y, TRUE);
5051 } else if (is_ice(x, y)) {
5054 /* Already ice here, so just firm it up. */
5055 /* Now ensure that only ice that is already timed is affected */
5056 if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
5057 spot_stop_timers(x, y, MELT_ICE_AWAY);
5058 start_melt_ice_timeout(x, y, melt_time);
5061 break; /* ZT_COLD */
5064 (void) create_gas_cloud(x, y, 1, 8);
5068 if (lev->typ == IRONBARS) {
5069 if ((lev->wall_info & W_NONDIGGABLE) != 0) {
5072 Norep("The %s corrode somewhat but remain intact.",
5074 Norep("%s
\82Í
\8f
\82µ
\92É
\82ñ
\82¾
\82ª
\82Ü
\82¾
\82µ
\82Á
\82©
\82è
\82µ
\82Ä
\82¢
\82é
\81D",
5075 defsyms[S_bars].explanation);
5076 /* but nothing actually happens... */
5081 Norep("The %s melt.", defsyms[S_bars].explanation);
5083 Norep("%s
\82ª
\97n
\82¯
\82½
\81D", defsyms[S_bars].explanation);
5084 if (*in_rooms(x, y, SHOPBASE)) {
5085 /* in case we ever have a shop bounded by bars */
5089 add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
5094 lev->doormask = D_NODOOR;
5100 break; /* ZT_ACID */
5106 /* set up zap text for possible door feedback; for exploding wand, we
5107 want "the blast" rather than "your blast" even if hero caused it */
5108 yourzap = (type >= 0 && !exploding_wand_typ);
5110 zapverb = "blast"; /* breath attack or wand explosion */
5112 zapverb = "
\8fÕ
\8c\82"; /* breath attack or wand explosion */
5114 if (!exploding_wand_typ) {
5115 if (abs(type) < ZT_SPELL(0))
5117 zapverb = "bolt"; /* wand zap */
5119 zapverb = "
\8cõ
\90ü"; /* wand zap */
5121 else if (abs(type) < ZT_BREATH(0))
5125 zapverb = "
\8eô
\95¶";
5128 /* secret door gets revealed, converted into regular door */
5129 if (levl[x][y].typ == SDOOR) {
5130 cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
5131 /* target spot will now pass closed_door() test below
5132 (except on rogue level) */
5136 pline("%s %s reveals a secret door.",
5137 yourzap ? "Your" : "The", zapverb);
5139 pline("%s
\82Å
\89B
\82µ
\94à
\82ª
\96¾
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D", zapverb);
5141 else if (Is_rogue_level(&u.uz))
5142 draft_message(FALSE); /* "You feel a draft." (open doorway) */
5145 /* regular door absorbs remaining zap range, possibly gets destroyed */
5146 if (closed_door(x, y)) {
5147 int new_doormask = -1;
5148 const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
5153 new_doormask = D_NODOOR;
5155 see_txt = "The door is consumed in flames!";
5157 see_txt = "
\94à
\82Í
\89\8a\82Å
\8fÄ
\82«
\82Â
\82
\82³
\82ê
\82½
\81I";
5159 sense_txt = "smell smoke.";
5161 sense_txt = "
\89\8c\82Ì
\93õ
\82¢
\82ª
\82µ
\82½
\81D";
5164 new_doormask = D_NODOOR;
5166 see_txt = "The door freezes and shatters!";
5168 see_txt = "
\94à
\82Í
\93\80\82è
\81C
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I";
5170 sense_txt = "feel cold.";
5172 sense_txt = "
\97â
\8bC
\82ð
\8a´
\82¶
\82½
\81D";
5175 /* death spells/wands don't disintegrate */
5176 if (abs(type) != ZT_BREATH(ZT_DEATH))
5178 new_doormask = D_NODOOR;
5180 see_txt = "The door disintegrates!";
5182 see_txt = "
\94à
\82Í
\95²
\8dÓ
\82³
\82ê
\82½
\81I";
5184 hear_txt = "crashing wood.";
5186 hear_txt = "
\96Ø
\82Ì
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D";
5189 new_doormask = D_BROKEN;
5191 see_txt = "The door splinters!";
5193 see_txt = "
\94à
\82Í
\82¸
\82½
\82¸
\82½
\82É
\82È
\82Á
\82½
\81I";
5195 hear_txt = "crackling.";
5197 hear_txt = "
\83s
\83L
\83s
\83L
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D";
5201 if (exploding_wand_typ > 0) {
5202 /* Magical explosion from misc exploding wand */
5203 if (exploding_wand_typ == WAN_STRIKING) {
5204 new_doormask = D_BROKEN;
5206 see_txt = "The door crashes open!";
5208 see_txt = "
\94à
\82Í
\89ó
\82ê
\82Ä
\8aJ
\82¢
\82½
\81I";
5210 sense_txt = "feel a burst of cool air.";
5212 sense_txt = "
\97â
\8bC
\82Ì
\8f[
\96\9e\82ð
\8a´
\82¶
\82½
\81D";
5217 /* "the door absorbs the blast" would be
5218 inaccurate for an exploding wand since
5219 other adjacent locations still get hit */
5220 if (exploding_wand_typ)
5222 pline_The("door remains intact.");
5224 pline_The("
\94à
\82Í
\96³
\8f\9d\82¾
\81D");
5227 pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
5230 pline_The("
\94à
\82Í%s%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", yourzap ? "
\82 \82È
\82½
\82ª
\95ú
\82Á
\82½" : "",
5235 You_feel("vibrations.");
5237 You("
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
5240 if (new_doormask >= 0) { /* door gets broken */
5241 if (*in_rooms(x, y, SHOPBASE)) {
5243 add_damage(x, y, SHOP_DOOR_COST);
5245 } else /* caused by monster */
5246 add_damage(x, y, 0L);
5248 lev->doormask = new_doormask;
5249 unblock_point(x, y); /* vision */
5253 } else if (sense_txt) {
5254 #if 0 /*JP*//*
\81u
\82 \82È
\82½
\82Í
\81v
\82ª
\95s
\93K
\90Ø
\82È
\95¶
\82à
\82 \82é*/
5259 } else if (hear_txt)
5260 You_hear1(hear_txt);
5261 if (picking_at(x, y)) {
5268 if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5269 if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5272 You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5274 pline("%s
\81D", !Blind ? "
\82Û
\82í
\82Á
\82Æ
\89\8c\82ª
\82 \82ª
\82Á
\82½" : "
\89\8c\82Ì
\83v
\83\93\82Æ
\82¢
\82¤
\93õ
\82¢
\82ª
\82µ
\82½");
5276 if ((mon = m_at(x, y)) != 0) {
5279 setmangry(mon, TRUE);
5280 if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5282 if (mon->isshk && !*u.ushops)
5289 /* fractured by pick-axe or wand of striking */
5292 register struct obj *obj; /* no texts here! */
5295 boolean by_you = !context.mon_moving;
5297 if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5298 struct monst *shkp = 0;
5299 char objroom = *in_rooms(x, y, SHOPBASE);
5301 if (billable(&shkp, obj, objroom, FALSE)) {
5302 /* shop message says "you owe <shk> <$> for it!" so we need
5303 to precede that with a message explaining what "it" is */
5305 You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5307 You("%s
\82Ì%s
\82ð
\89ó
\82µ
\82½
\81D", shkname(shkp), xname(obj));
5308 breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5311 if (by_you && obj->otyp == BOULDER)
5315 obj->oclass = GEM_CLASS;
5316 obj->quan = (long) rn1(60, 7);
5317 obj->owt = weight(obj);
5318 obj->dknown = obj->bknown = obj->rknown = 0;
5319 obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5320 dealloc_oextra(obj);
5322 if (obj->where == OBJ_FLOOR) {
5323 obj_extract_self(obj); /* move rocks back on top */
5324 place_object(obj, obj->ox, obj->oy);
5325 if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5326 unblock_point(obj->ox, obj->oy);
5327 if (cansee(obj->ox, obj->oy))
5328 newsym(obj->ox, obj->oy);
5332 /* handle statue hit by striking/force bolt/pick-axe */
5335 register struct obj *obj;
5337 /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5338 struct trap *trap = t_at(obj->ox, obj->oy);
5340 boolean by_you = !context.mon_moving;
5342 if (trap && trap->ttyp == STATUE_TRAP
5343 && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5345 /* drop any objects contained inside the statue */
5346 while ((item = obj->cobj) != 0) {
5347 obj_extract_self(item);
5348 place_object(item, obj->ox, obj->oy);
5350 if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5352 You_feel("guilty about damaging such a historic statue.");
5354 You_feel("
\82±
\82Ì
\82æ
\82¤
\82È
\97ð
\8ej
\93I
\82È
\92¤
\91\9c\82É
\8f\9d\82ð
\82Â
\82¯
\82é
\82Ì
\82Í
\8dß
\90[
\82¢
\82±
\82Æ
\82¾
\82Æ
\8ev
\82Á
\82½
\81D");
5363 * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5364 * [0] freezing potion
5365 * [1] boiling potion other than oil
5366 * [2] boiling potion of oil
5367 * [3] burning scroll
5368 * [4] burning spellbook
5371 * (books, rings, and wands don't stack so don't need plural form;
5372 * crumbling ring doesn't do damage so doesn't need killer reason)
5374 const char *const destroy_strings[][3] = {
5375 /* also used in trap.c */
5377 { "freezes and shatters", "freeze and shatter", "shattered potion" },
5379 { "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\8dÓ
\82¯
\82½
\96ò
\95r
\82Å" },
5381 { "boils and explodes", "boil and explode", "boiling potion" },
5383 { "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82½
\96ò
\82Å" },
5385 { "ignites and explodes", "ignite and explode", "exploding potion" },
5387 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\94\9a\94
\82µ
\82½
\96ò
\82Å" },
5389 { "catches fire and burns", "catch fire and burn", "burning scroll" },
5391 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\8aª
\95¨
\82Å" },
5393 { "catches fire and burns", "", "burning book" },
5395 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\96\82\96@
\8f\91\82Å" },
5397 { "turns to dust and vanishes", "", "" },
5399 { "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "" },
5401 { "breaks apart and explodes", "", "exploding wand" },
5403 { "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\8fñ
\82Ì
\94\9a\94
\82Å" },
5407 destroy_item(osym, dmgtyp)
5408 register int osym, dmgtyp;
5410 register struct obj *obj, *obj2;
5411 int dmg, xresist, skip;
5415 boolean physical_damage;
5417 for (obj = invent; obj; obj = obj2) {
5419 physical_damage = FALSE;
5420 if (obj->oclass != osym)
5421 continue; /* test only objs of type osym */
5423 continue; /* don't destroy artifacts */
5424 if (obj->in_use && obj->quan == 1L)
5425 continue; /* not available */
5427 /* lint suppression */
5433 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5441 xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5442 && obj->otyp != GLOB_OF_GREEN_SLIME);
5444 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5446 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5450 pline("%s glows a strange %s, but remains intact.",
5451 The(xname(obj)), hcolor("dark red"));
5453 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5454 xname(obj), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5461 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5473 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5474 dindx = 1; /* boil and explode */
5475 dmg = (obj->owt + 19) / 20;
5486 xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5490 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5498 if (obj->otyp == WAN_LIGHTNING) {
5503 if (obj == current_wand) { skip++; break; }
5519 --quan; /* one will be used up elsewhere */
5520 for (i = cnt = 0L; i < quan; i++)
5528 ? (quan == 1L) ? "Your" /* 1 of 1 */
5529 : "One of your" /* 1 of N */
5530 : (cnt < quan) ? "Some of your" /* n of N */
5531 : (quan == 2L) ? "Both of your" /* 2 of 2 */
5532 : "All of your"; /* N of N */
5534 mult = (cnt == quan)
5536 : (cnt == 1L) ? "
\82Ì
\82Ð
\82Æ
\82Â" : "
\82Ì
\82¢
\82
\82Â
\82©";
5539 pline("%s %s %s!", mult, xname(obj),
5540 destroy_strings[dindx][(cnt > 1L)]);
5542 pline("
\82 \82È
\82½
\82Ì%s%s
\82Í%s
\81I", xname(obj), mult,
5543 destroy_strings[dindx][(cnt > 1L)]);
5545 if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5546 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5549 if (obj->owornmask) {
5550 if (obj->owornmask & W_RING) /* ring being worn */
5555 if (obj == current_wand)
5556 current_wand = 0; /* destroyed */
5557 for (i = 0; i < cnt; i++)
5562 You("aren't hurt!");
5564 You("
\8f\9d\82Â
\82©
\82È
\82¢
\81I");
5566 const char *how = destroy_strings[dindx][2];
5567 boolean one = (cnt == 1L);
5569 if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
5571 how = "exploding glob of slime";
5573 how = "
\83X
\83\89\83C
\83\80\82Ì
\82Ë
\82Î
\82Ë
\82Î
\82Ì
\94\9a\94
\82Å";
5574 if (physical_damage)
5575 dmg = Maybe_Half_Phys(dmg);
5576 losehp(dmg, one ? how : (const char *) makeplural(how),
5577 one ? KILLED_BY_AN : KILLED_BY);
5578 exercise(A_STR, FALSE);
5587 destroy_mitem(mtmp, osym, dmgtyp)
5591 struct obj *obj, *obj2;
5597 if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5598 destroy_item(osym, dmgtyp);
5599 return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5602 vis = canseemon(mtmp);
5603 for (obj = mtmp->minvent; obj; obj = obj2) {
5605 if (obj->oclass != osym)
5606 continue; /* test only objs of type osym */
5613 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5621 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5623 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5627 pline("%s glows a strange %s, but remains intact.",
5628 The(distant_name(obj, xname)), hcolor("dark red"));
5630 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5631 The(distant_name(obj, xname)), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5637 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5649 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5650 dindx = 1; /* boil and explode */
5651 tmp += (obj->owt + 19) / 20;
5665 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5672 if (obj->otyp == WAN_LIGHTNING) {
5689 for (i = cnt = 0L; i < quan; i++)
5698 (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5700 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5701 destroy_strings[dindx][(cnt > 1L)]);
5703 pline("%s%s
\82Í%s
\81I",
5704 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5705 (cnt == obj->quan) ? "" : (cnt > 1L) ? "
\82Ì
\82¢
\82
\82Â
\82©"
5706 : "
\82Ì
\82Ð
\82Æ
\82Â",
5707 destroy_strings[dindx][(cnt > 1L)]);
5709 for (i = 0; i < cnt; i++)
5717 resist(mtmp, oclass, damage, tell)
5732 break; /* instrument */
5735 break; /* artifact */
5750 dlev = (int) mtmp->m_lev;
5754 dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5756 resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5759 shieldeff(mtmp->mx, mtmp->my);
5761 pline("%s resists!", Monnam(mtmp));
5763 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", Monnam(mtmp));
5765 damage = (damage + 1) / 2;
5769 mtmp->mhp -= damage;
5770 if (mtmp->mhp < 1) {
5772 monkilled(mtmp, "", AD_RBRE);
5780 #define MAXWISHTRY 5
5783 wishcmdassist(triesleft)
5786 static NEARDATA const char *
5790 "Enter the name of an object, such as \"potion of monster detection\",",
5791 "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5792 "(without the quotes).",
5794 "For object types which come in stacks, you may specify a plural name",
5795 "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5796 "pieces\", although that aspect of your wish might not be granted.",
5798 "You may also specify various prefix values which might be used to",
5799 "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5800 "Most modifiers shown when viewing your inventory can be specified.",
5802 "You may specify 'nothing' to explicitly decline this wish.",
5805 preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5807 "If you specify an unrecognized object name %s%s time%s,",
5808 retry_too[] = "a randomly chosen item will be granted.",
5809 suppress_cmdassist[] =
5810 "(Suppress this assistance with !cmdassist in your config file.)",
5811 *cardinals[] = { "zero", "one", "two", "three", "four", "five" },
5812 too_many[] = "too many";
5817 win = create_nhwindow(NHW_TEXT);
5820 for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5821 putstr(win, 0, wishinfo[i]);
5822 if (!u.uconduct.wishes)
5823 putstr(win, 0, preserve_wishless);
5825 Sprintf(buf, retry_info,
5826 (triesleft >= 0 && triesleft < SIZE(cardinals))
5827 ? cardinals[triesleft]
5829 (triesleft < MAXWISHTRY) ? " more" : "",
5831 putstr(win, 0, buf);
5832 putstr(win, 0, retry_too);
5834 if (iflags.cmdassist)
5835 putstr(win, 0, suppress_cmdassist);
5836 display_nhwindow(win, FALSE);
5837 destroy_nhwindow(win);
5843 static char buf[BUFSZ] = DUMMY;
5844 char promptbuf[BUFSZ];
5845 struct obj *otmp, nothing;
5848 promptbuf[0] = '\0';
5849 nothing = zeroobj; /* lint suppression; only its address matters */
5852 You("may wish for an object.");
5854 You("
\96]
\82Ý
\82Ì
\82à
\82Ì
\82ð
\8eè
\82É
\93ü
\82ê
\82ç
\82ê
\82é
\81D");
5857 Strcpy(promptbuf, "For what do you wish");
5859 Strcpy(promptbuf, "(
\93ú
\96{
\8cê
\82Å)
\89½
\82ð
\82¨
\96]
\82Ý");
5860 if (iflags.cmdassist && tries > 0)
5862 Strcat(promptbuf, " (enter 'help' for assistance)");
5864 Strcat(promptbuf, " (
\8f\95\82¯
\82ª
\95K
\97v
\82È
\82ç 'help'
\82Æ
\93ü
\97Í)");
5866 Strcat(promptbuf, "?");
5868 Strcat(promptbuf, "
\81H");
5869 getlin(promptbuf, buf);
5870 (void) mungspaces(buf);
5871 if (buf[0] == '\033') {
5873 } else if (!strcmpi(buf, "help")) {
5874 wishcmdassist(MAXWISHTRY - tries);
5878 * Note: if they wished for and got a non-object successfully,
5879 * otmp == &zeroobj. That includes gold, or an artifact that
5880 * has been denied. Wishing for "nothing" requires a separate
5881 * value to remain distinct.
5883 otmp = readobjnam(buf, ¬hing);
5886 pline("Nothing fitting that description exists in the game.");
5888 pline("
\82¤
\81[
\82ñ
\81D
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\91¶
\8dÝ
\82µ
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
5889 if (++tries < MAXWISHTRY)
5891 pline1(thats_enough_tries);
5892 otmp = readobjnam((char *) 0, (struct obj *) 0);
5894 return; /* for safety; should never happen */
5895 } else if (otmp == ¬hing) {
5896 /* explicitly wished for "nothing", presumably attempting
5897 to retain wishless conduct */
5902 u.uconduct.wishes++;
5904 if (otmp != &zeroobj) {
5907 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5909 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "
\8a\8a\82è
\97\8e\82¿
\82½" : "
\97\8e\82¿
\82½"),
5911 *oops_msg = (u.uswallow
5912 ? "Oops! %s out of your reach!"
5913 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5914 || levl[u.ux][u.uy].typ < IRONBARS
5915 || levl[u.ux][u.uy].typ >= ICE)
5916 ? "Oops! %s away from you!"
5917 : "Oops! %s to the floor!");
5919 /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5920 (void) hold_another_object(otmp, oops_msg,
5921 The(aobjnam(otmp, verb)),
5924 *oops_msg = (u.uswallow
5925 ? "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\93Í
\82©
\82È
\82¢
\82Æ
\82±
\82ë
\82É%s
\81I"
5926 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5927 || levl[u.ux][u.uy].typ < IRONBARS
5928 || levl[u.ux][u.uy].typ >= ICE)
5929 ? "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\8eè
\82©
\82ç%s
\81I"
5930 : "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\8f°
\82É%s
\81I");
5931 char oopsbuf[BUFSZ];
5932 Sprintf(oopsbuf, oops_msg, verb);
5934 (void) hold_another_object(otmp, oopsbuf,
5938 u.ublesscnt += rn1(100, 50); /* the gods take notice */