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-2016 */
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 Strcat(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"] */
2876 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2877 ordinary = FALSE; /* say blasted rather than zapped */
2878 how = (obj->oclass != SPBOOK_CLASS)
2879 ? (const char *) ansimpleoname(obj)
2883 : "
\8cõ
\82Ì
\96\82\96@";
2885 Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2888 Sprintf(buf, "
\8e©
\95ª
\82Å%s
\82ð
\97\81\82Ñ
\82Ä", how);
2890 /* might rehumanize(); could be fatal, but only for Unchanging */
2892 losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2894 losehp(Maybe_Half_Phys(dmg), buf, KILLED_BY);
2900 /* light[ning] causes blindness */
2905 if (!resists_blnd(&youmonst)) {
2906 You(are_blinded_by_the_flash);
2907 make_blinded(duration, FALSE);
2909 Your1(vision_clears);
2915 /* you've zapped a wand downwards while riding
2916 * Return TRUE if the steed was hit by the wand.
2917 * Return FALSE if the steed was not hit by the wand.
2921 struct obj *obj; /* wand or spell */
2923 int steedhit = FALSE;
2925 bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
2927 switch (obj->otyp) {
2929 * Wands that are allowed to hit the steed
2930 * Carefully test the results of any that are
2931 * moved here from the bottom section.
2934 probe_monster(u.usteed);
2938 case WAN_TELEPORTATION:
2939 case SPE_TELEPORT_AWAY:
2940 /* you go together */
2942 /* same criteria as when unmounted (zapyourself) */
2943 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2944 || distu(u.ux0, u.uy0) >= 16)
2949 /* Default processing via bhitm() for these */
2950 case SPE_CURE_SICKNESS:
2951 case WAN_MAKE_INVISIBLE:
2952 case WAN_CANCELLATION:
2953 case SPE_CANCELLATION:
2957 case SPE_FORCE_BOLT:
2958 case WAN_SLOW_MONSTER:
2959 case SPE_SLOW_MONSTER:
2960 case WAN_SPEED_MONSTER:
2962 case SPE_EXTRA_HEALING:
2963 case SPE_DRAIN_LIFE:
2966 (void) bhitm(u.usteed, obj);
2978 * cancel a monster (possibly the hero). inventory is cancelled only
2979 * if the monster is zapping itself directly, since otherwise the
2980 * effect is too strong. currently non-hero monsters do not zap
2981 * themselves with cancellation.
2984 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2985 register struct monst *mdef;
2986 register struct obj *obj;
2987 boolean youattack, allow_cancel_kill, self_cancel;
2989 boolean youdefend = (mdef == &youmonst);
2990 static const char writing_vanishes[] =
2992 "Some writing vanishes from %s head!";
2994 "
\89½
\82©
\82Ì
\95¶
\8e\9a\82ª%s
\82Ì
\93ª
\82©
\82ç
\8fÁ
\82¦
\82½
\81I";
2996 static const char your[] = "your"; /* should be extern */
2998 static const char your[] = "
\82 \82È
\82½"; /* should be extern */
3001 if (youdefend ? (!youattack && Antimagic)
3002 : resist(mdef, obj->oclass, 0, NOTELL))
3003 return FALSE; /* resisted cancellation */
3005 if (self_cancel) { /* 1st cancel inventory */
3008 for (otmp = (youdefend ? invent : mdef->minvent); otmp;
3012 context.botl = 1; /* potential AC change */
3017 /* now handle special cases */
3020 if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
3021 pline(writing_vanishes, your);
3025 Your("amulet grows hot for a moment, then cools.");
3027 Your("
\96\82\8f\9c\82¯
\82Í
\82µ
\82Î
\82ç
\82
\94M
\82
\82È
\82è
\81C
\82â
\82ª
\82Ä
\8c³
\82É
\96ß
\82Á
\82½
\81D");
3034 if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
3037 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
3038 if (canseemon(mdef))
3040 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
3042 pline(writing_vanishes, mon_nam(mdef));
3045 if (allow_cancel_kill) {
3049 monkilled(mdef, "", AD_SPEL);
3056 /* you've zapped an immediate type wand up or down */
3059 struct obj *obj; /* wand or spell */
3061 boolean striking = FALSE, disclose = FALSE;
3062 int x, y, xx, yy, ptmp;
3068 /* some wands have special effects other than normal bhitpile */
3069 /* drawbridge might change <u.ux,u.uy> */
3070 x = xx = u.ux; /* <x,y> is zap location */
3071 y = yy = u.uy; /* <xx,yy> is drawbridge (portcullis) position */
3072 ttmp = t_at(x, y); /* trap if there is one */
3074 switch (obj->otyp) {
3079 You("probe towards the %s.", ceiling(x, y));
3081 You("
\8fã
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", ceiling(x,y));
3083 ptmp += bhitpile(obj, bhito, x, y, u.dz);
3085 You("probe beneath the %s.", surface(x, y));
3087 You("
\89º
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", surface(x,y));
3088 ptmp += display_binventory(x, y, TRUE);
3092 Your("probe reveals nothing.");
3094 pline("
\92²
\8d¸
\82Ì
\8c\8b\89Ê
\89½
\82à
\82Å
\82Ä
\82±
\82È
\82©
\82Á
\82½
\81D");
3095 return TRUE; /* we've done our own bhitpile */
3098 /* up or down, but at closed portcullis only */
3099 if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
3100 open_drawbridge(xx, yy);
3102 } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
3103 /* can't use the stairs down to quest level 2 until
3104 leader "unlocks" them; give feedback if you try */
3105 && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
3107 pline_The("stairs seem to ripple momentarily.");
3109 pline("
\8aK
\92i
\82ª
\88ê
\8fu
\97h
\82ê
\82½
\82æ
\82¤
\82É
\8c©
\82¦
\82½
\81D");
3112 /* down will release you from bear trap or web */
3113 if (u.dz > 0 && u.utrap) {
3114 (void) openholdingtrap(&youmonst, &disclose);
3115 /* down will trigger trapdoor, hole, or [spiked-] pit */
3116 } else if (u.dz > 0 && !u.utrap) {
3117 (void) openfallingtrap(&youmonst, FALSE, &disclose);
3121 case SPE_FORCE_BOLT:
3125 case SPE_WIZARD_LOCK:
3126 /* down at open bridge or up or down at open portcullis */
3127 if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
3129 : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
3130 && find_drawbridge(&xx, &yy)) {
3132 close_drawbridge(xx, yy);
3134 destroy_drawbridge(xx, yy);
3136 } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
3137 && !Is_waterlevel(&u.uz) && !Underwater
3138 && !Is_qstart(&u.uz)) {
3140 /* similar to zap_dig() */
3142 pline("A rock is dislodged from the %s and falls on your %s.",
3143 ceiling(x, y), body_part(HEAD));
3145 pline("%s
\82©
\82ç
\8aâ
\82ª
\97\8e\82¿
\82Ä
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81D",
3146 ceiling(x, y), body_part(HEAD));
3148 dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
3150 losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
3152 losehp(Maybe_Half_Phys(dmg), "
\97\8e\8aâ
\82Å", KILLED_BY_AN);
3153 if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
3154 (void) xname(otmp); /* set dknown, maybe bknown */
3158 } else if (u.dz > 0 && ttmp) {
3159 if (!striking && closeholdingtrap(&youmonst, &disclose)) {
3160 ; /* now stuck in web or bear trap */
3161 } else if (striking && ttmp->ttyp == TRAPDOOR) {
3162 /* striking transforms trapdoor into hole */
3163 if (Blind && !ttmp->tseen) {
3165 pline("%s beneath you shatters.", Something);
3167 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\89½
\82©
\82ª
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3168 } else if (!ttmp->tseen) { /* => !Blind */
3170 pline("There's a trapdoor beneath you; it shatters.");
3172 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82Í
\97\8e\82µ
\94à
\82ª
\82 \82Á
\82½
\81G
\82»
\82ê
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3175 pline("The trapdoor beneath you shatters.");
3177 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\97\8e\82µ
\94à
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3183 /* might fall down hole */
3185 } else if (!striking && ttmp->ttyp == HOLE) {
3186 /* locking transforms hole into trapdoor */
3187 ttmp->ttyp = TRAPDOOR;
3188 if (Blind || !ttmp->tseen) {
3190 pline("Some %s swirls beneath you.",
3191 is_ice(x, y) ? "frost" : "dust");
3193 pline("
\82 \82È
\82½
\82Ì
\89º
\82Å%s
\82ª
\82¤
\82¸
\82ð
\8aª
\82
\82Ì
\82ª
\8c©
\82¦
\82½
\81D",
3194 is_ice(x,y) ? "
\91\9a" : "
\82Ù
\82±
\82è");
3200 pline("A trapdoor appears beneath you.");
3202 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\97\8e\82µ
\94à
\82ª
\82 \82ç
\82í
\82ê
\82½
\81D");
3205 /* hadn't fallen down hole; won't fall now */
3209 case SPE_STONE_TO_FLESH:
3210 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3211 || (Is_qstart(&u.uz) && u.dz < 0)) {
3212 pline1(nothing_happens);
3213 } else if (u.dz < 0) { /* we should do more... */
3215 pline("Blood drips on your %s.", body_part(FACE));
3217 pline("
\8c\8c\82ª
\82 \82È
\82½
\82Ì%s
\82Ö
\82µ
\82½
\82½
\82è
\97\8e\82¿
\82Ä
\82«
\82½
\81D", body_part(FACE));
3218 } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3220 Print this message only if there wasn't an engraving
3221 affected here. If water or ice, act like waterlevel case.
3223 e = engr_at(u.ux, u.uy);
3224 if (!(e && e->engr_type == ENGRAVE)) {
3225 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3226 pline1(nothing_happens);
3229 pline("Blood %ss %s your %s.",
3230 is_lava(u.ux, u.uy) ? "boil" : "pool",
3231 Levitation ? "beneath" : "at",
3232 makeplural(body_part(FOOT)));
3235 makeplural(body_part(FOOT)),
3236 Levitation ? "
\82Ì
\89º" : "
\8c³",
3237 is_lava(u.ux, u.uy) ?
3238 "
\82Å
\8c\8c\82ª
\95¦
\93«
\82µ
\82½" : "
\82É
\8c\8c\82¾
\82Ü
\82è
\82ª
\8fo
\97\88\82½");
3248 /* zapping downward */
3249 (void) bhitpile(obj, bhito, x, y, u.dz);
3251 /* subset of engraving effects; none sets `disclose' */
3252 if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3253 switch (obj->otyp) {
3257 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3259 case WAN_CANCELLATION:
3260 case SPE_CANCELLATION:
3261 case WAN_MAKE_INVISIBLE:
3264 case WAN_TELEPORTATION:
3265 case SPE_TELEPORT_AWAY:
3268 case SPE_STONE_TO_FLESH:
3269 if (e->engr_type == ENGRAVE) {
3270 /* only affects things in stone */
3272 pline_The(Hallucination
3273 ? "floor runs like butter!"
3274 : "edges on the floor get smoother.");
3277 ? "
\8f°
\82ª
\83o
\83^
\81[
\82Ì
\82æ
\82¤
\82É
\91\96\82Á
\82Ä
\82¢
\82Á
\82½
\81I"
3278 : "
\8f°
\82Ì
\89\8f\82ª
\82È
\82ß
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D");
3280 wipe_engr_at(x, y, d(2, 4), TRUE);
3284 case SPE_FORCE_BOLT:
3285 wipe_engr_at(x, y, d(2, 4), TRUE);
3291 } else if (u.dz < 0) {
3292 /* zapping upward */
3294 /* game flavor: if you're hiding under "something"
3295 * a zap upward should hit that "something".
3297 if (u.uundetected && hides_under(youmonst.data)) {
3299 otmp = level.objects[u.ux][u.uy];
3302 hitit = bhito(otmp, obj);
3304 (void) hideunder(&youmonst);
3313 /* used by do_break_wand() was well as by weffects() */
3323 /* if do_osshock() set obj_zapped while polying, give a message now */
3326 You_feel("shuddering vibrations.");
3328 You("
\82¼
\82Á
\82Æ
\82·
\82é
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
3332 /* called for various wand and spell effects - M. Stephenson */
3337 int otyp = obj->otyp;
3338 boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3340 exercise(A_WIS, TRUE);
3341 if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3342 && (u.dz > 0) && zap_steed(obj)) {
3344 } else if (objects[otyp].oc_dir == IMMEDIATE) {
3345 zapsetup(); /* reset obj_zapped */
3347 (void) bhitm(u.ustuck, obj);
3348 /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3350 disclose = zap_updown(obj);
3352 (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3355 zapwrapup(); /* give feedback for obj_zapped */
3357 } else if (objects[otyp].oc_dir == NODIR) {
3361 /* neither immediate nor directionless */
3363 if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3365 else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3366 buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3368 else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3369 buzz(otyp - WAN_MAGIC_MISSILE,
3370 (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3372 impossible("weffects: unexpected spell or wand");
3378 more_experienced(0, 10);
3383 /* augment damage for a spell dased on the hero's intelligence (and level) */
3385 spell_damage_bonus(dmg)
3386 int dmg; /* base amount to be adjusted by bonus or penalty */
3388 int intell = ACURR(A_INT);
3390 /* Punish low intelligence before low level else low intelligence
3391 gets punished only when high level */
3393 /* -3 penalty, but never reduce combined amount below 1
3394 (if dmg is 0 for some reason, we're careful to leave it there) */
3396 dmg = (dmg <= 3) ? 1 : dmg - 3;
3397 } else if (intell <= 13 || u.ulevel < 5)
3398 ; /* no bonus or penalty; dmg remains same */
3399 else if (intell <= 18)
3401 else if (intell <= 24 || u.ulevel < 14)
3404 dmg += 3; /* Int 25 */
3410 * Generate the to hit bonus for a spell. Based on the hero's skill in
3411 * spell class and dexterity.
3414 spell_hit_bonus(skill)
3418 int dex = ACURR(A_DEX);
3420 switch (P_SKILL(spell_skilltype(skill))) {
3421 case P_ISRESTRICTED:
3443 /* Will change when print stuff below removed */
3446 /* Even increment for dextrous heroes (see weapon.c abon) */
3447 hit_bon += dex - 14;
3456 /* force == 0 occurs e.g. with sleep ray */
3457 /* note that large force is usual with wands so that !! would
3458 require information about hand/weapon/wand */
3460 return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3462 return (const char *) ((force < 0) ? "
\81H" : (force <= 4) ? "
\81D" : "
\81I");
3466 hit(str, mtmp, force)
3469 const char *force; /* usually either "." or "!" */
3471 if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3472 && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3474 pline("%s %s it.", The(str), vtense(str, "hit"));
3476 pline("%s
\82Í
\89½
\82©
\82É
\96½
\92\86\82µ
\82½
\81D", str);
3479 pline("%s %s %s%s", The(str), vtense(str, "hit"),
3480 mon_nam(mtmp), force);
3482 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", str,
3483 mon_nam(mtmp), force);
3489 register const char *str;
3490 register struct monst *mtmp;
3494 "%s %s %s.", The(str), vtense(str, "miss"),
3495 ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3500 "%s
\82Ì%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\82Í
\82¸
\82ê
\82½
\81D", str,
3501 ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3508 skiprange(range, skipstart, skipend)
3509 int range, *skipstart, *skipend;
3511 int tr = (range / 4);
3512 int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3515 *skipend = tmp - ((tmp / 4) * rnd(3));
3516 if (*skipend >= tmp)
3521 * Called for the following distance effects:
3522 * when a weapon is thrown (weapon == THROWN_WEAPON)
3523 * when an object is kicked (KICKED_WEAPON)
3524 * when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3525 * when a light beam is flashed (FLASHED_LIGHT)
3526 * when a mirror is applied (INVIS_BEAM)
3527 * A thrown/kicked object falls down at end of its range or when a monster
3528 * is hit. The variable 'bhitpos' is set to the final position of the weapon
3529 * thrown/zapped. The ray of a wand may affect (by calling a provided
3530 * function) several objects and monsters on its path. The return value
3531 * is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3533 * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3534 * destroyed and *pobj set to NULL to indicate this.
3536 * Check !u.uswallow before calling bhit().
3537 * This function reveals the absence of a remembered invisible monster in
3538 * necessary cases (throwing or kicking weapons). The presence of a real
3539 * one is revealed for a weapon, but if not a weapon is left up to fhitm().
3542 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3543 register int ddx, ddy, range; /* direction and range */
3544 int weapon; /* see values in hack.h */
3545 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3546 FDECL((*fhito), (OBJ_P, OBJ_P));
3547 struct obj **pobj; /* object tossed/used, set to NULL
3548 * if object is destroyed */
3551 struct obj *obj = *pobj;
3553 boolean shopdoor = FALSE, point_blank = TRUE;
3554 boolean in_skip = FALSE, allow_skip = FALSE;
3555 int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3557 if (weapon == KICKED_WEAPON) {
3558 /* object starts one square in front of player */
3559 bhitpos.x = u.ux + ddx;
3560 bhitpos.y = u.uy + ddy;
3567 if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3568 skiprange(range, &skiprange_start, &skiprange_end);
3569 allow_skip = !rn2(3);
3572 if (weapon == FLASHED_LIGHT) {
3573 tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3574 } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3575 tmp_at(DISP_FLASH, obj_to_glyph(obj));
3577 while (range-- > 0) {
3591 if (is_pick(obj) && inside_shop(x, y)
3592 && (mtmp = shkcatch(obj, x, y)) != 0) {
3593 tmp_at(DISP_END, 0);
3597 typ = levl[bhitpos.x][bhitpos.y].typ;
3599 /* iron bars will block anything big enough */
3600 if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3602 && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
3603 point_blank ? 0 : !rn2(5), 1)) {
3604 /* caveat: obj might now be null... */
3611 if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3612 boolean learn_it = FALSE;
3614 switch (obj->otyp) {
3617 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3618 if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3620 open_drawbridge(x, y);
3624 case SPE_WIZARD_LOCK:
3625 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3626 && levl[x][y].typ == DRAWBRIDGE_DOWN)
3628 close_drawbridge(x, y);
3631 case SPE_FORCE_BOLT:
3632 if (typ != DRAWBRIDGE_UP)
3633 destroy_drawbridge(x, y);
3641 mtmp = m_at(bhitpos.x, bhitpos.y);
3646 * skiprange_start is only set if this is a thrown rock
3648 if (skiprange_start && (range == skiprange_start) && allow_skip) {
3649 if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3653 pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3654 skipcount ? " again" : "");
3656 pline("%s
\82Í%s
\92µ
\82Ë
\82½
\81D", Yname2(obj),
3657 skipcount ? "
\8dÄ
\82Ñ" : "");
3661 You_hear("%s skip.", yname(obj));
3663 You_hear("%s
\82ª
\92µ
\82Ë
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D", yname(obj));
3665 } else if (skiprange_start > skiprange_end + 1) {
3670 if (range <= skiprange_end) {
3672 if (range > 3) /* another bounce? */
3673 skiprange(range, &skiprange_start, &skiprange_end);
3674 } else if (mtmp && M_IN_WATER(mtmp->data)) {
3675 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3677 pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3680 pline("%s
\82Í%s
\82ð
\94ò
\82Ñ
\89z
\82¦
\82½
\81D", Yname2(obj),
3686 if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3687 notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3688 if (weapon == FLASHED_LIGHT) {
3689 /* FLASHED_LIGHT hitting invisible monster should
3690 pass through instead of stop so we call
3691 flash_hits_mon() directly rather than returning
3692 mtmp back to caller. That allows the flash to
3693 keep on going. Note that we use mtmp->minvis
3694 not canspotmon() because it makes no difference
3695 whether the hero can see the monster or not. */
3697 obj->ox = u.ux, obj->oy = u.uy;
3698 (void) flash_hits_mon(mtmp, obj);
3700 tmp_at(DISP_END, 0);
3701 return mtmp; /* caller will call flash_hits_mon */
3703 } else if (weapon == INVIS_BEAM) {
3704 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3705 through invisible targets; unlike it, we aren't
3706 prepared for multiple hits so just get first one
3707 that's either visible or could see its invisible
3708 self. [No tmp_at() cleanup is needed here.] */
3709 if (!mtmp->minvis || perceives(mtmp->data))
3711 } else if (weapon != ZAPPED_WAND) {
3712 /* THROWN_WEAPON, KICKED_WEAPON */
3713 tmp_at(DISP_END, 0);
3714 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3715 map_invisible(bhitpos.x, bhitpos.y);
3719 (*fhitm)(mtmp, obj);
3723 if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3724 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3725 unmap_object(bhitpos.x, bhitpos.y);
3730 if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3733 if (weapon == KICKED_WEAPON
3734 && ((obj->oclass == COIN_CLASS
3735 && OBJ_AT(bhitpos.x, bhitpos.y))
3736 || ship_object(obj, bhitpos.x, bhitpos.y,
3737 costly_spot(bhitpos.x, bhitpos.y)))) {
3738 tmp_at(DISP_END, 0);
3739 return (struct monst *) 0;
3742 if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3743 switch (obj->otyp) {
3748 case SPE_WIZARD_LOCK:
3749 case SPE_FORCE_BOLT:
3750 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3751 if (cansee(bhitpos.x, bhitpos.y)
3752 || (obj->otyp == WAN_STRIKING && !Deaf))
3754 if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3755 && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3757 add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
3763 if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3768 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3769 /* 'I' present but no monster: erase */
3770 /* do this before the tmp_at() */
3771 if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3773 unmap_object(bhitpos.x, bhitpos.y);
3776 tmp_at(bhitpos.x, bhitpos.y);
3778 /* kicked objects fall in pools */
3779 if ((weapon == KICKED_WEAPON)
3780 && (is_pool(bhitpos.x, bhitpos.y)
3781 || is_lava(bhitpos.x, bhitpos.y)))
3783 if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3784 break; /* physical objects fall onto sink */
3786 /* limit range of ball so hero won't make an invalid move */
3787 if (weapon == THROWN_WEAPON && range > 0
3788 && obj->otyp == HEAVY_IRON_BALL) {
3792 if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3795 pline("%s hits %s.", The(distant_name(obj, xname)),
3798 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", distant_name(obj, xname),
3802 } else if (obj == uball) {
3803 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3804 /* nb: it didn't hit anything directly */
3807 pline("%s jerks to an abrupt halt.",
3808 The(distant_name(obj, xname))); /* lame */
3810 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\83K
\83N
\83\93\82Æ
\8e~
\82Ü
\82Á
\82½
\81D",
3811 distant_name(obj, xname)); /* lame */
3814 } else if (Sokoban && (t = t_at(x, y)) != 0
3815 && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3816 || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3817 /* hero falls into the trap, so ball stops */
3823 /* thrown/kicked missile has moved away from its starting spot */
3824 point_blank = FALSE; /* affects passing through iron bars */
3827 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3828 tmp_at(DISP_END, 0);
3832 pay_for_damage("destroy", FALSE);
3834 pay_for_damage("
\94j
\89ó
\82·
\82é", FALSE);
3836 return (struct monst *) 0;
3839 /* process thrown boomerang, which travels a curving path...
3840 * A multi-shot volley ought to have all missiles in flight at once,
3841 * but we're called separately for each one. We terminate the volley
3842 * early on a failed catch since continuing to throw after being hit
3843 * is too obviously silly.
3846 boomhit(obj, dx, dy)
3851 int boom; /* showsym[] index */
3853 boolean counterclockwise = TRUE; /* right-handed throw */
3855 /* counterclockwise traversal patterns:
3856 * ..........................54.................................
3857 * ..................43.....6..3....765.........................
3858 * ..........32.....5..2...7...2...8...4....87..................
3859 * .........4..1....6..1...8..1....9...3...9..6.....98..........
3860 * ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3861 * .3...9....6..9....89.....................1..4...1..6....1..8.
3862 * .4...8.....78.............................23....2..5...2...7.
3863 * ..567............................................34....3..6..
3864 * ........................................................45...
3865 * (invert rows for corresponding clockwise patterns)
3870 boom = counterclockwise ? S_boomleft : S_boomright;
3871 for (i = 0; i < 8; i++)
3872 if (xdir[i] == dx && ydir[i] == dy)
3874 tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3875 for (ct = 0; ct < 10; ct++) {
3876 i = (i + 8) % 8; /* 0..7 (8 -> 0, -1 -> 7) */
3877 boom = (S_boomleft + S_boomright - boom); /* toggle */
3878 tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3883 if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3885 tmp_at(DISP_END, 0);
3888 if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3889 || closed_door(bhitpos.x, bhitpos.y)) {
3894 if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3895 if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3896 /* we hit ourselves */
3897 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
3901 "
\83u
\81[
\83\81\83\89\83\93");
3904 } else { /* we catch it */
3905 tmp_at(DISP_END, 0);
3907 You("skillfully catch the boomerang.");
3909 You("
\8fã
\8eè
\82É
\83u
\81[
\83\81\83\89\83\93\82ð
\92Í
\82Ü
\82¦
\82½
\81D");
3913 tmp_at(bhitpos.x, bhitpos.y);
3915 if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3920 pline("
\83J
\83\89\83\93\81I");
3921 break; /* boomerang falls on sink */
3923 /* ct==0, initial position, we want next delta to be same;
3924 ct==5, opposite position, repeat delta undoes first one */
3926 i += (counterclockwise ? -1 : 1);
3928 tmp_at(DISP_END, 0); /* do not leave last symbol */
3929 return (struct monst *) 0;
3932 /* used by buzz(); also used by munslime(muse.c); returns damage applied
3933 to mon; note: caller is responsible for killing mon if damage is fatal */
3935 zhitm(mon, type, nd, ootmp)
3936 register struct monst *mon;
3937 register int type, nd;
3938 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3940 register int tmp = 0;
3941 register int abstype = abs(type) % 10;
3942 boolean sho_shieldeff = FALSE;
3943 boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3945 *ootmp = (struct obj *) 0;
3947 case ZT_MAGIC_MISSILE:
3948 if (resists_magm(mon)) {
3949 sho_shieldeff = TRUE;
3954 tmp = spell_damage_bonus(tmp);
3957 if (resists_fire(mon)) {
3958 sho_shieldeff = TRUE;
3962 if (resists_cold(mon))
3965 tmp = spell_damage_bonus(tmp);
3966 if (burnarmor(mon)) {
3968 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3970 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3972 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3973 destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3977 if (resists_cold(mon)) {
3978 sho_shieldeff = TRUE;
3982 if (resists_fire(mon))
3985 tmp = spell_damage_bonus(tmp);
3987 (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3991 (void) sleep_monst(mon, d(nd, 25),
3992 type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3994 case ZT_DEATH: /* death/disintegration */
3995 if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3996 if (mon->data == &mons[PM_DEATH]) {
3997 mon->mhpmax += mon->mhpmax / 2;
3998 if (mon->mhpmax >= MAGIC_COOKIE)
3999 mon->mhpmax = MAGIC_COOKIE - 1;
4000 mon->mhp = mon->mhpmax;
4004 if (nonliving(mon->data) || is_demon(mon->data)
4005 || is_vampshifter(mon) || resists_magm(mon)) {
4006 /* similar to player */
4007 sho_shieldeff = TRUE;
4010 type = -1; /* so they don't get saving throws */
4014 if (resists_disint(mon)) {
4015 sho_shieldeff = TRUE;
4016 } else if (mon->misc_worn_check & W_ARMS) {
4017 /* destroy shield; victim survives */
4018 *ootmp = which_armor(mon, W_ARMS);
4019 } else if (mon->misc_worn_check & W_ARM) {
4020 /* destroy body armor, also cloak if present */
4021 *ootmp = which_armor(mon, W_ARM);
4022 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4023 m_useup(mon, otmp2);
4025 /* no body armor, victim dies; destroy cloak
4026 and shirt now in case target gets life-saved */
4028 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
4029 m_useup(mon, otmp2);
4030 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
4031 m_useup(mon, otmp2);
4033 type = -1; /* no saving throw wanted */
4034 break; /* not ordinary damage */
4039 if (resists_elec(mon)) {
4040 sho_shieldeff = TRUE;
4042 /* can still blind the monster */
4046 tmp = spell_damage_bonus(tmp);
4047 if (!resists_blnd(mon)
4048 && !(type > 0 && u.uswallow && mon == u.ustuck)) {
4049 register unsigned rnd_tmp = rnd(50);
4051 if ((mon->mblinded + rnd_tmp) > 127)
4052 mon->mblinded = 127;
4054 mon->mblinded += rnd_tmp;
4057 (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
4058 /* not actually possible yet */
4060 (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
4063 if (resists_poison(mon)) {
4064 sho_shieldeff = TRUE;
4070 if (resists_acid(mon)) {
4071 sho_shieldeff = TRUE;
4076 acid_damage(MON_WEP(mon));
4078 erode_armor(mon, ERODE_CORRODE);
4082 shieldeff(mon->mx, mon->my);
4083 if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
4085 if (tmp > 0 && type >= 0
4086 && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
4089 tmp = 0; /* don't allow negative damage */
4090 debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
4097 zhitu(type, nd, fltxt, sx, sy)
4102 int dam = 0, abstyp = abs(type);
4106 Sprintf(buf, "%s
\82É
\82æ
\82Á
\82Ä", fltxt);
4110 switch (abstyp % 10) {
4111 case ZT_MAGIC_MISSILE:
4115 pline_The("missiles bounce off!");
4117 pline("
\96\82\96@
\82Ì
\96î
\82Í
\94½
\8eË
\82µ
\82½
\81I");
4120 exercise(A_STR, FALSE);
4124 if (Fire_resistance) {
4127 You("don't feel hot!");
4129 You("
\94M
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81I");
4130 ugolemeffects(AD_FIRE, d(nd, 6));
4135 if (burnarmor(&youmonst)) { /* "body hit" */
4137 destroy_item(POTION_CLASS, AD_FIRE);
4139 destroy_item(SCROLL_CLASS, AD_FIRE);
4141 destroy_item(SPBOOK_CLASS, AD_FIRE);
4142 destroy_item(FOOD_CLASS, AD_FIRE);
4146 if (Cold_resistance) {
4149 You("don't feel cold.");
4151 You("
\97â
\82½
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81D");
4152 ugolemeffects(AD_COLD, d(nd, 6));
4157 destroy_item(POTION_CLASS, AD_COLD);
4160 if (Sleep_resistance) {
4161 shieldeff(u.ux, u.uy);
4163 You("don't feel sleepy.");
4165 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81D");
4167 fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
4171 if (abstyp == ZT_BREATH(ZT_DEATH)) {
4172 if (Disint_resistance) {
4174 You("are not disintegrated.");
4176 You("
\95ª
\89ð
\82³
\82ê
\82È
\82¢
\81D");
4179 /* destroy shield; other possessions are safe */
4180 (void) destroy_arm(uarms);
4183 /* destroy suit; if present, cloak goes too */
4185 (void) destroy_arm(uarmc);
4186 (void) destroy_arm(uarm);
4189 /* no shield or suit, you're dead; wipe out cloak
4190 and/or shirt in case of life-saving or bones */
4192 (void) destroy_arm(uarmc);
4194 (void) destroy_arm(uarmu);
4195 } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4198 You("seem unaffected.");
4200 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
4202 } else if (Antimagic) {
4205 You("aren't affected.");
4207 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4210 killer.format = KILLED_BY_AN;
4211 Strcpy(killer.name, fltxt ? fltxt : "");
4212 /* when killed by disintegration breath, don't leave corpse */
4213 u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4215 return; /* lifesaved */
4217 if (Shock_resistance) {
4220 You("aren't affected.");
4222 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4223 ugolemeffects(AD_ELEC, d(nd, 6));
4226 exercise(A_CON, FALSE);
4229 destroy_item(WAND_CLASS, AD_ELEC);
4231 destroy_item(RING_CLASS, AD_ELEC);
4235 poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4237 poisoned("
\91§", A_DEX, "
\93Å
\82Ì
\91§", 15, FALSE);
4240 if (Acid_resistance) {
4242 pline_The("%s doesn't hurt.", hliquid("acid"));
4244 pline_The("%s
\82Å
\82Í
\8f\9d\82Â
\82©
\82È
\82©
\82Á
\82½
\81D", hliquid("
\8e_"));
4248 pline_The("%s burns!", hliquid("acid"));
4250 pline_The("%s
\82Å
\8fÄ
\82¯
\82½
\81I", hliquid("
\8e_"));
4252 exercise(A_STR, FALSE);
4254 /* using two weapons at once makes both of them more vulnerable */
4255 if (!rn2(u.twoweap ? 3 : 6))
4257 if (u.twoweap && !rn2(3))
4258 acid_damage(uswapwep);
4260 erode_armor(&youmonst, ERODE_CORRODE);
4264 /* Half_spell_damage protection yields half-damage for wands & spells,
4265 including hero's own ricochets; breath attacks do full damage */
4266 if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4267 dam = (dam + 1) / 2;
4268 losehp(dam, fltxt, KILLED_BY_AN);
4273 * burn objects (such as scrolls and spellbooks) on floor
4274 * at position x,y; return the number of objects burned
4277 burn_floor_objects(x, y, give_feedback, u_caused)
4279 boolean give_feedback; /* caller needs to decide about visibility checks */
4282 struct obj *obj, *obj2;
4283 long i, scrquan, delquan;
4284 char buf1[BUFSZ], buf2[BUFSZ];
4287 for (obj = level.objects[x][y]; obj; obj = obj2) {
4288 obj2 = obj->nexthere;
4289 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4290 || (obj->oclass == FOOD_CLASS
4291 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4292 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4293 || obj_resists(obj, 2, 100))
4295 scrquan = obj->quan; /* number present */
4296 delquan = 0L; /* number to destroy */
4297 for (i = scrquan; i > 0L; i--)
4301 /* save name before potential delobj() */
4302 if (give_feedback) {
4304 Strcpy(buf1, (x == u.ux && y == u.uy)
4306 : distant_name(obj, xname));
4308 Strcpy(buf2, (x == u.ux && y == u.uy)
4310 : distant_name(obj, xname));
4311 obj->quan = scrquan;
4313 /* useupf(), which charges, only if hero caused damage */
4315 useupf(obj, delquan);
4316 else if (delquan < scrquan)
4317 obj->quan -= delquan;
4321 if (give_feedback) {
4324 pline("%ld %s burn.", delquan, buf2);
4326 pline("%ld%s
\82Ì%s
\82ª
\94R
\82¦
\82½
\81D",
4328 obj->oclass == SCROLL_CLASS ? "
\96\87" : "
\8dû",
4333 pline("%s burns.", An(buf1));
4335 pline("%s
\82Í
\94R
\82¦
\82½
\81D", buf1);
4343 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4347 int type; /* either hero cast spell type or 0 */
4349 int chance = rn2(20);
4350 int spell_bonus = type ? spell_hit_bonus(type) : 0;
4352 /* small chance for naked target to avoid being hit */
4354 return rnd(10) < ac + spell_bonus;
4356 /* very high armor protection does not achieve invulnerability */
4359 return (3 - chance < ac + spell_bonus);
4363 disintegrate_mon(mon, type, fltxt)
4365 int type; /* hero vs other */
4368 struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4370 if (canseemon(mon)) {
4373 pline("%s is disintegrated!", Monnam(mon));
4375 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I", Monnam(mon));
4378 hit(fltxt, mon, "!");
4380 hit(fltxt, mon, "
\81I");
4383 /* note: worn amulet of life saving must be preserved in order to operate */
4384 #define oresist_disintegration(obj) \
4385 (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4386 || is_quest_artifact(obj) || obj == m_amulet)
4388 for (otmp = mon->minvent; otmp; otmp = otmp2) {
4390 if (!oresist_disintegration(otmp)) {
4391 if (otmp->owornmask) {
4392 /* in case monster's life gets saved */
4393 mon->misc_worn_check &= ~otmp->owornmask;
4394 if (otmp->owornmask & W_WEP)
4395 setmnotwielded(mon, otmp);
4396 /* also dismounts hero if this object is steed's saddle */
4397 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4398 otmp->owornmask = 0L;
4400 obj_extract_self(otmp);
4401 obfree(otmp, (struct obj *) 0);
4405 #undef oresist_disintegration
4408 monkilled(mon, (char *) 0, -AD_RBRE);
4410 xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
4414 buzz(type, nd, sx, sy, dx, dy)
4419 dobuzz(type, nd, sx, sy, dx, dy, TRUE);
4423 * type == 0 to 9 : you shooting a wand
4424 * type == 10 to 19 : you casting a spell
4425 * type == 20 to 29 : you breathing as a monster
4426 * type == -10 to -19 : monster casting spell
4427 * type == -20 to -29 : monster breathing at you
4428 * type == -30 to -39 : monster shooting a wand
4429 * called with dx = dy = 0 with vertical bolts
4432 dobuzz(type, nd, sx, sy, dx, dy, say)
4433 register int type, nd;
4434 register xchar sx, sy;
4435 register int dx, dy;
4436 boolean say; /* Announce out of sight hit/miss events if true */
4438 int range, abstype = abs(type) % 10;
4439 register xchar lsx, lsy;
4442 boolean shopdamage = FALSE;
4447 /* if its a Hero Spell then get its SPE_TYPE */
4448 spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4450 fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4456 tmp = zhitm(u.ustuck, type, nd, &otmp);
4461 pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4464 pline("%s
\82Í%s
\82ð
\82Ð
\82«
\82³
\82¢
\82½%s", fltxt, mon_nam(u.ustuck),
4467 /* Using disintegration from the inside only makes a hole... */
4468 if (tmp == MAGIC_COOKIE)
4470 if (u.ustuck->mhp < 1)
4477 if (dx == 0 && dy == 0)
4479 save_bhitpos = bhitpos;
4481 tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4482 while (range-- > 0) {
4487 if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
4491 if (cansee(sx, sy)) {
4492 /* reveal/unreveal invisible monsters before tmp_at() */
4493 if (mon && !canspotmon(mon))
4494 map_invisible(sx, sy);
4496 (void) unmap_invisible(sx, sy);
4497 if (ZAP_POS(levl[sx][sy].typ)
4498 || (isok(lsx, lsy) && cansee(lsx, lsy)))
4500 delay_output(); /* wait a little */
4503 /* hit() and miss() need bhitpos to match the target */
4504 bhitpos.x = sx, bhitpos.y = sy;
4505 /* Fireballs only damage when they explode */
4506 if (type != ZT_SPELL(ZT_FIRE))
4507 range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4510 if (type == ZT_SPELL(ZT_FIRE))
4513 mon->mstrategy &= ~STRAT_WAITMASK;
4515 notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
4516 if (zap_hit(find_mac(mon), spell_type)) {
4517 if (mon_reflects(mon, (char *) 0)) {
4518 if (cansee(mon->mx, mon->my)) {
4519 hit(fltxt, mon, exclam(0));
4520 shieldeff(mon->mx, mon->my);
4522 (void) mon_reflects(mon,
4523 "But it reflects from %s %s!");
4525 (void) mon_reflects(mon,
4526 "
\82µ
\82©
\82µ
\82»
\82ê
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81I");
4532 boolean mon_could_move = mon->mcanmove;
4533 int tmp = zhitm(mon, type, nd, &otmp);
4535 if (is_rider(mon->data)
4536 && abs(type) == ZT_BREATH(ZT_DEATH)) {
4537 if (canseemon(mon)) {
4539 hit(fltxt, mon, ".");
4541 hit(fltxt, mon, "
\81D");
4543 pline("%s disintegrates.", Monnam(mon));
4545 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D", Monnam(mon));
4547 pline("%s body reintegrates before your %s!",
4548 s_suffix(Monnam(mon)),
4549 (eyecount(youmonst.data) == 1)
4551 : makeplural(body_part(EYE)));
4553 pline("%s
\82Ì
\91Ì
\82Í
\82 \82È
\82½
\82Ì
\96Ú
\82Ì
\91O
\82Å
\8dÄ
\8c\8b\8d\87\82µ
\82½
\81I",
4557 pline("%s resurrects!", Monnam(mon));
4559 pline("%s
\82Í
\91h
\82Á
\82½
\81I", Monnam(mon));
4561 mon->mhp = mon->mhpmax;
4562 break; /* Out of while loop */
4564 if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4565 if (canseemon(mon)) {
4567 hit(fltxt, mon, ".");
4569 hit(fltxt, mon, "
\81D");
4571 pline("%s absorbs the deadly %s!", Monnam(mon),
4572 type == ZT_BREATH(ZT_DEATH) ? "blast"
4575 pline("%s
\82Í
\8e\80\82Ì%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", Monnam(mon),
4576 type == ZT_BREATH(ZT_DEATH) ? "
\91§"
4580 pline("It seems even stronger than before.");
4582 pline("
\82³
\82ç
\82É
\8b
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82³
\82¦
\82·
\82é
\81D");
4584 break; /* Out of while loop */
4587 if (tmp == MAGIC_COOKIE) { /* disintegration */
4588 disintegrate_mon(mon, type, fltxt);
4589 } else if (mon->mhp < 1) {
4591 /* mon has just been killed by another monster */
4592 monkilled(mon, fltxt, AD_RBRE);
4594 int xkflags = XKILL_GIVEMSG; /* killed(mon); */
4596 /* killed by hero; we know 'type' isn't negative;
4597 if it's fire, highly flammable monsters leave
4598 no corpse; don't bother reporting that they
4599 "burn completely" -- unnecessary verbosity */
4600 if ((type % 10 == ZT_FIRE)
4601 /* paper golem or straw golem */
4602 && completelyburns(mon->data))
4603 xkflags |= XKILL_NOCORPSE;
4604 xkilled(mon, xkflags);
4608 /* normal non-fatal hit */
4609 if (say || canseemon(mon))
4610 hit(fltxt, mon, exclam(tmp));
4612 /* some armor was destroyed; no damage done */
4615 pline("%s %s is disintegrated!",
4616 s_suffix(Monnam(mon)),
4617 distant_name(otmp, xname));
4619 pline("%s
\82Ì%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I",
4621 distant_name(otmp, xname));
4625 if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4631 if (say || canseemon(mon))
4634 } else if (sx == u.ux && sy == u.uy && range >= 0) {
4636 if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4639 } else if (zap_hit((int) u.uac, 0)) {
4642 pline("%s hits you!", The(fltxt));
4644 pline("%s
\82Í
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I", fltxt);
4648 (void) ureflects("But %s reflects from your %s!",
4651 (void) ureflects("
\82µ
\82©
\82µ
\81C%s
\82Í
\82 \82È
\82½
\82Ì%s
\82É
\82æ
\82Á
\82Ä
\94½
\8eË
\82µ
\82½
\81D",
4656 pline("For some reason you are not affected.");
4658 pline("
\82È
\82º
\82©
\82 \82È
\82½
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82©
\82Á
\82½
\81D");
4663 zhitu(type, nd, fltxt, sx, sy);
4665 } else if (!Blind) {
4667 pline("%s whizzes by you!", The(fltxt));
4669 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82»
\82Î
\82ð
\82©
\82·
\82ß
\82½
\81I", fltxt);
4670 } else if (abstype == ZT_LIGHTNING) {
4672 Your("%s tingles.", body_part(ARM));
4674 Your("%s
\82Í
\83q
\83\8a\83q
\83\8a\82µ
\82½
\81D", body_part(ARM));
4676 if (abstype == ZT_LIGHTNING)
4677 (void) flashburn((long) d(nd, 50));
4682 if (!ZAP_POS(levl[sx][sy].typ)
4683 || (closed_door(sx, sy) && range >= 0)) {
4684 int bounce, bchance;
4689 bchance = (levl[sx][sy].typ == STONE) ? 10
4690 : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
4693 fireball = (type == ZT_SPELL(ZT_FIRE));
4694 if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
4696 if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
4698 pline_The("%s vanishes into the aether!", fltxt);
4700 pline_The("%s
\82Í
\83G
\81[
\83e
\83\8b\8bó
\8aÔ
\82É
\8fÁ
\82¦
\82½
\81I", fltxt);
4702 type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
4704 } else if (fireball) {
4707 break; /* fireballs explode before the obstacle */
4710 pline_The("%s bounces!", fltxt);
4712 pline_The("%s
\82Í
\94½
\8eË
\82µ
\82½
\81I", fltxt);
4714 if (!dx || !dy || !rn2(bchance)) {
4718 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4719 && !closed_door(sx, lsy)
4720 && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4721 && ZAP_POS(levl[sx + dx][lsy].typ))))
4723 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4724 && !closed_door(lsx, sy)
4725 && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4726 && ZAP_POS(levl[lsx][sy + dy].typ))))
4727 if (!bounce || rn2(2))
4741 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4745 tmp_at(DISP_END, 0);
4746 if (type == ZT_SPELL(ZT_FIRE))
4747 explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4750 pay_for_damage(abstype == ZT_FIRE
4752 : abstype == ZT_COLD
4754 /* "damage" indicates wall rather than door */
4755 : abstype == ZT_ACID
4757 : abstype == ZT_DEATH
4762 pay_for_damage(abstype == ZT_FIRE
4764 : abstype == ZT_COLD
4765 ? "
\95²
\81X
\82É
\82·
\82é"
4766 : abstype == ZT_ACID
4767 ? "
\8f\9d\82Â
\82¯
\82é"
4768 : abstype == ZT_DEATH
4769 ? "
\95²
\8dÓ
\82·
\82é"
4770 : "
\94j
\89ó
\82·
\82é",
4773 bhitpos = save_bhitpos;
4781 struct rm *lev = &levl[x][y];
4786 msg = "The ice crackles and melts.";
4788 msg = "
\95X
\82Í
\83s
\83L
\83s
\83L
\96Â
\82è
\81C
\97n
\82¯
\82½
\81D";
4789 if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
4790 lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4791 } else { /* lev->typ == ICE */
4793 if (lev->icedpool == ICED_POOL)
4798 lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4802 spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4803 obj_ice_effects(x, y, FALSE);
4810 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4813 pline("%s settles...", An(xname(otmp)));
4815 pline("%s
\82Í
\82Í
\82Ü
\82Á
\82½
\81D
\81D
\81D", xname(otmp));
4817 obj_extract_self(otmp); /* boulder isn't being pushed */
4818 if (!boulder_hits_pool(otmp, x, y, FALSE))
4819 impossible("melt_ice: no pool?");
4820 /* try again if there's another boulder and pool didn't fill */
4821 } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4824 if (x == u.ux && y == u.uy)
4825 spoteffects(TRUE); /* possibly drown, notice objects */
4828 #define MIN_ICE_TIME 50
4829 #define MAX_ICE_TIME 2000
4831 * Usually start a melt_ice timer; sometimes the ice will become
4832 * permanent instead.
4835 start_melt_ice_timeout(x, y, min_time)
4837 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4842 when = (int) min_time;
4843 if (when < MIN_ICE_TIME - 1)
4844 when = MIN_ICE_TIME - 1;
4846 /* random timeout; surrounding ice locations ought to be a factor... */
4847 while (++when <= MAX_ICE_TIME)
4848 if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4851 /* if we're within MAX_ICE_TIME, install a melt timer;
4852 otherwise, omit it to leave this ice permanent */
4853 if (when <= MAX_ICE_TIME) {
4854 where = ((long) x << 16) | (long) y;
4855 (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4856 long_to_any(where));
4863 * Called when ice has melted completely away.
4866 melt_ice_away(arg, timeout)
4868 long timeout UNUSED;
4871 long where = arg->a_long;
4873 y = (xchar) (where & 0xFFFF);
4874 x = (xchar) ((where >> 16) & 0xFFFF);
4875 /* melt_ice does newsym when appropriate */
4877 melt_ice(x, y, "Some ice melts away.");
4879 melt_ice(x, y, "
\95X
\82ª
\8f
\82µ
\97n
\82¯
\82½
\81D");
4882 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4883 * Used both for normal bolts of fire, cold, etc... and for fireballs.
4884 * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4885 * amount by which range is reduced (the latter is just ignored by fireballs)
4888 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4891 boolean *shopdamage;
4892 short exploding_wand_typ;
4894 const char *zapverb;
4897 struct rm *lev = &levl[x][y];
4898 boolean see_it = cansee(x, y), yourzap;
4899 int rangemod = 0, abstype = abs(type) % 10;
4904 if (t && t->ttyp == WEB) {
4905 /* a burning web is too flimsy to notice if you can't see it */
4908 Norep("A web bursts into flames!");
4910 Norep("
\82
\82à
\82Ì
\91\83\82Í
\89\8a\82É
\95ï
\82Ü
\82ê
\82½
\81I");
4911 (void) delfloortrap(t);
4916 melt_ice(x, y, (char *) 0);
4917 } else if (is_pool(x, y)) {
4919 const char *msgtxt = "You hear hissing gas.";
4921 const char *msgtxt = "
\82µ
\82ã
\81[
\82Á
\82Æ
\82¢
\82¤
\83K
\83X
\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4923 if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4926 msgtxt = "Some water evaporates.";
4928 msgtxt = "
\82·
\82±
\82µ
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4932 t = maketrap(x, y, PIT);
4937 msgtxt = "The water evaporates.";
4939 msgtxt = "
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4941 Norep("%s", msgtxt);
4942 if (lev->typ == ROOM)
4944 } else if (IS_FOUNTAIN(lev->typ)) {
4947 pline("Steam billows from the fountain.");
4949 pline("
\90ò
\82©
\82ç
\8fö
\8bC
\82ª
\97§
\82¿
\82Ì
\82Ú
\82Á
\82½
\81D");
4951 dryup(x, y, type > 0);
4953 break; /* ZT_FIRE */
4956 if (is_pool(x, y) || is_lava(x, y)) {
4957 boolean lava = is_lava(x, y),
4958 moat = is_moat(x, y);
4960 if (lev->typ == WATER) {
4961 /* For now, don't let WATER freeze. */
4964 pline_The("%s freezes for a moment.", hliquid("water"));
4966 pline_The("%s
\82Í
\88ê
\8fu
\93\80\82Á
\82½
\81D", hliquid("
\90\85"));
4969 You_hear("a soft crackling.");
4971 You_hear("
\83s
\83L
\81I
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4972 rangemod -= 1000; /* stop */
4976 Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
4978 if (lev->typ == DRAWBRIDGE_UP) {
4979 lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4980 lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4983 lev->icedpool = (lev->typ == POOL) ? ICED_POOL
4985 lev->typ = lava ? ROOM : ICE;
4991 Norep("The %s cools and solidifies.", hliquid("lava"));
4993 Norep("%s
\82Í
\97â
\82¦
\8cÅ
\82Ü
\82Á
\82½
\81D", hliquid("lava"));
4996 Norep("The %s is bridged with ice!", buf);
4998 Norep("%s
\82É
\95X
\82Ì
\8b´
\82ª
\82©
\82¯
\82ç
\82ê
\82½
\81I", buf);
5001 Norep("The %s freezes.", hliquid("water"));
5003 Norep("%s
\82Í
\93\80\82Á
\82½
\81D", hliquid("
\95X"));
5007 You_hear("a crackling sound.");
5009 You_hear("
\83s
\83L
\83s
\83L
\83b
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
5011 if (x == u.ux && y == u.uy) {
5012 if (u.uinwater) { /* not just `if (Underwater)' */
5013 /* leave the no longer existent water */
5017 vision_full_recalc = 1;
5018 } else if (u.utrap && u.utraptype == TT_LAVA) {
5022 You("pass through the now-solid rock.");
5024 You("
\82¢
\82Ü
\8cÅ
\82
\82È
\82Á
\82½
\82Î
\82©
\82è
\82Ì
\90Î
\82Ì
\92\86\82ð
\82·
\82è
\94²
\82¯
\82½
\81D");
5026 u.utrap = rn1(50, 20);
5027 u.utraptype = TT_INFLOOR;
5029 You("are firmly stuck in the cooling rock.");
5031 You("
\97â
\82¦
\82½
\8aâ
\82Ì
\82È
\82©
\82É
\82µ
\82Á
\82©
\82è
\82Æ
\96\84\82Ü
\82Á
\82½
\81D");
5034 } else if ((mon = m_at(x, y)) != 0) {
5035 /* probably ought to do some hefty damage to any
5036 non-ice creature caught in freezing water;
5037 at a minimum, eels are forced out of hiding */
5038 if (is_swimmer(mon->data) && mon->mundetected) {
5039 mon->mundetected = 0;
5044 start_melt_ice_timeout(x, y, 0L);
5045 obj_ice_effects(x, y, TRUE);
5049 } else if (is_ice(x, y)) {
5052 /* Already ice here, so just firm it up. */
5053 /* Now ensure that only ice that is already timed is affected */
5054 if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
5055 spot_stop_timers(x, y, MELT_ICE_AWAY);
5056 start_melt_ice_timeout(x, y, melt_time);
5059 break; /* ZT_COLD */
5062 (void) create_gas_cloud(x, y, 1, 8);
5066 if (lev->typ == IRONBARS) {
5067 if ((lev->wall_info & W_NONDIGGABLE) != 0) {
5070 Norep("The %s corrode somewhat but remain intact.",
5072 Norep("%s
\82Í
\8f
\82µ
\92É
\82ñ
\82¾
\82ª
\82Ü
\82¾
\82µ
\82Á
\82©
\82è
\82µ
\82Ä
\82¢
\82é
\81D",
5073 defsyms[S_bars].explanation);
5074 /* but nothing actually happens... */
5079 Norep("The %s melt.", defsyms[S_bars].explanation);
5081 Norep("%s
\82ª
\97n
\82¯
\82½
\81D", defsyms[S_bars].explanation);
5082 if (*in_rooms(x, y, SHOPBASE)) {
5083 /* in case we ever have a shop bounded by bars */
5087 add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
5092 lev->doormask = D_NODOOR;
5098 break; /* ZT_ACID */
5104 /* set up zap text for possible door feedback; for exploding wand, we
5105 want "the blast" rather than "your blast" even if hero caused it */
5106 yourzap = (type >= 0 && !exploding_wand_typ);
5108 zapverb = "blast"; /* breath attack or wand explosion */
5110 zapverb = "
\8fÕ
\8c\82"; /* breath attack or wand explosion */
5112 if (!exploding_wand_typ) {
5113 if (abs(type) < ZT_SPELL(0))
5115 zapverb = "bolt"; /* wand zap */
5117 zapverb = "
\8cõ
\90ü"; /* wand zap */
5119 else if (abs(type) < ZT_BREATH(0))
5123 zapverb = "
\8eô
\95¶";
5126 /* secret door gets revealed, converted into regular door */
5127 if (levl[x][y].typ == SDOOR) {
5128 cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
5129 /* target spot will now pass closed_door() test below
5130 (except on rogue level) */
5134 pline("%s %s reveals a secret door.",
5135 yourzap ? "Your" : "The", zapverb);
5137 pline("%s
\82Å
\89B
\82µ
\94à
\82ª
\96¾
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D", zapverb);
5139 else if (Is_rogue_level(&u.uz))
5140 draft_message(FALSE); /* "You feel a draft." (open doorway) */
5143 /* regular door absorbs remaining zap range, possibly gets destroyed */
5144 if (closed_door(x, y)) {
5145 int new_doormask = -1;
5146 const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
5151 new_doormask = D_NODOOR;
5153 see_txt = "The door is consumed in flames!";
5155 see_txt = "
\94à
\82Í
\89\8a\82Å
\8fÄ
\82«
\82Â
\82
\82³
\82ê
\82½
\81I";
5157 sense_txt = "smell smoke.";
5159 sense_txt = "
\89\8c\82Ì
\93õ
\82¢
\82ª
\82µ
\82½
\81D";
5162 new_doormask = D_NODOOR;
5164 see_txt = "The door freezes and shatters!";
5166 see_txt = "
\94à
\82Í
\93\80\82è
\81C
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I";
5168 sense_txt = "feel cold.";
5170 sense_txt = "
\97â
\8bC
\82ð
\8a´
\82¶
\82½
\81D";
5173 /* death spells/wands don't disintegrate */
5174 if (abs(type) != ZT_BREATH(ZT_DEATH))
5176 new_doormask = D_NODOOR;
5178 see_txt = "The door disintegrates!";
5180 see_txt = "
\94à
\82Í
\95²
\8dÓ
\82³
\82ê
\82½
\81I";
5182 hear_txt = "crashing wood.";
5184 hear_txt = "
\96Ø
\82Ì
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D";
5187 new_doormask = D_BROKEN;
5189 see_txt = "The door splinters!";
5191 see_txt = "
\94à
\82Í
\82¸
\82½
\82¸
\82½
\82É
\82È
\82Á
\82½
\81I";
5193 hear_txt = "crackling.";
5195 hear_txt = "
\83s
\83L
\83s
\83L
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D";
5199 if (exploding_wand_typ > 0) {
5200 /* Magical explosion from misc exploding wand */
5201 if (exploding_wand_typ == WAN_STRIKING) {
5202 new_doormask = D_BROKEN;
5204 see_txt = "The door crashes open!";
5206 see_txt = "
\94à
\82Í
\89ó
\82ê
\82Ä
\8aJ
\82¢
\82½
\81I";
5208 sense_txt = "feel a burst of cool air.";
5210 sense_txt = "
\97â
\8bC
\82Ì
\8f[
\96\9e\82ð
\8a´
\82¶
\82½
\81D";
5215 /* "the door absorbs the blast" would be
5216 inaccurate for an exploding wand since
5217 other adjacent locations still get hit */
5218 if (exploding_wand_typ)
5220 pline_The("door remains intact.");
5222 pline_The("
\94à
\82Í
\96³
\8f\9d\82¾
\81D");
5225 pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
5228 pline_The("
\94à
\82Í%s%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", yourzap ? "
\82 \82È
\82½
\82ª
\95ú
\82Á
\82½" : "",
5233 You_feel("vibrations.");
5235 You("
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
5238 if (new_doormask >= 0) { /* door gets broken */
5239 if (*in_rooms(x, y, SHOPBASE)) {
5241 add_damage(x, y, SHOP_DOOR_COST);
5243 } else /* caused by monster */
5244 add_damage(x, y, 0L);
5246 lev->doormask = new_doormask;
5247 unblock_point(x, y); /* vision */
5251 } else if (sense_txt) {
5252 #if 0 /*JP*//*
\81u
\82 \82È
\82½
\82Í
\81v
\82ª
\95s
\93K
\90Ø
\82È
\95¶
\82à
\82 \82é*/
5257 } else if (hear_txt)
5258 You_hear1(hear_txt);
5259 if (picking_at(x, y)) {
5266 if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5267 if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5270 You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5272 pline("%s
\81D", !Blind ? "
\82Û
\82í
\82Á
\82Æ
\89\8c\82ª
\82 \82ª
\82Á
\82½" : "
\89\8c\82Ì
\83v
\83\93\82Æ
\82¢
\82¤
\93õ
\82¢
\82ª
\82µ
\82½");
5274 if ((mon = m_at(x, y)) != 0) {
5277 setmangry(mon, TRUE);
5278 if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5280 if (mon->isshk && !*u.ushops)
5287 /* fractured by pick-axe or wand of striking */
5290 register struct obj *obj; /* no texts here! */
5293 boolean by_you = !context.mon_moving;
5295 if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5296 struct monst *shkp = 0;
5297 char objroom = *in_rooms(x, y, SHOPBASE);
5299 if (billable(&shkp, obj, objroom, FALSE)) {
5300 /* shop message says "you owe <shk> <$> for it!" so we need
5301 to precede that with a message explaining what "it" is */
5303 You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5305 You("%s
\82Ì%s
\82ð
\89ó
\82µ
\82½
\81D", shkname(shkp), xname(obj));
5306 breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5309 if (by_you && obj->otyp == BOULDER)
5313 obj->oclass = GEM_CLASS;
5314 obj->quan = (long) rn1(60, 7);
5315 obj->owt = weight(obj);
5316 obj->dknown = obj->bknown = obj->rknown = 0;
5317 obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5318 dealloc_oextra(obj);
5320 if (obj->where == OBJ_FLOOR) {
5321 obj_extract_self(obj); /* move rocks back on top */
5322 place_object(obj, obj->ox, obj->oy);
5323 if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5324 unblock_point(obj->ox, obj->oy);
5325 if (cansee(obj->ox, obj->oy))
5326 newsym(obj->ox, obj->oy);
5330 /* handle statue hit by striking/force bolt/pick-axe */
5333 register struct obj *obj;
5335 /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5336 struct trap *trap = t_at(obj->ox, obj->oy);
5338 boolean by_you = !context.mon_moving;
5340 if (trap && trap->ttyp == STATUE_TRAP
5341 && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5343 /* drop any objects contained inside the statue */
5344 while ((item = obj->cobj) != 0) {
5345 obj_extract_self(item);
5346 place_object(item, obj->ox, obj->oy);
5348 if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5350 You_feel("guilty about damaging such a historic statue.");
5352 You_feel("
\82±
\82Ì
\82æ
\82¤
\82È
\97ð
\8ej
\93I
\82È
\92¤
\91\9c\82É
\8f\9d\82ð
\82Â
\82¯
\82é
\82Ì
\82Í
\8dß
\90[
\82¢
\82±
\82Æ
\82¾
\82Æ
\8ev
\82Á
\82½
\81D");
5361 * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5362 * [0] freezing potion
5363 * [1] boiling potion other than oil
5364 * [2] boiling potion of oil
5365 * [3] burning scroll
5366 * [4] burning spellbook
5369 * (books, rings, and wands don't stack so don't need plural form;
5370 * crumbling ring doesn't do damage so doesn't need killer reason)
5372 const char *const destroy_strings[][3] = {
5373 /* also used in trap.c */
5375 { "freezes and shatters", "freeze and shatter", "shattered potion" },
5377 { "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\8dÓ
\82¯
\82½
\96ò
\95r
\82Å" },
5379 { "boils and explodes", "boil and explode", "boiling potion" },
5381 { "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82½
\96ò
\82Å" },
5383 { "ignites and explodes", "ignite and explode", "exploding potion" },
5385 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\94\9a\94
\82µ
\82½
\96ò
\82Å" },
5387 { "catches fire and burns", "catch fire and burn", "burning scroll" },
5389 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\8aª
\95¨
\82Å" },
5391 { "catches fire and burns", "", "burning book" },
5393 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\96\82\96@
\8f\91\82Å" },
5395 { "turns to dust and vanishes", "", "" },
5397 { "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "" },
5399 { "breaks apart and explodes", "", "exploding wand" },
5401 { "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\8fñ
\82Ì
\94\9a\94
\82Å" },
5405 destroy_item(osym, dmgtyp)
5406 register int osym, dmgtyp;
5408 register struct obj *obj, *obj2;
5409 int dmg, xresist, skip;
5413 boolean physical_damage;
5415 for (obj = invent; obj; obj = obj2) {
5417 physical_damage = FALSE;
5418 if (obj->oclass != osym)
5419 continue; /* test only objs of type osym */
5421 continue; /* don't destroy artifacts */
5422 if (obj->in_use && obj->quan == 1L)
5423 continue; /* not available */
5425 /* lint suppression */
5431 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5439 xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5440 && obj->otyp != GLOB_OF_GREEN_SLIME);
5442 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5444 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5448 pline("%s glows a strange %s, but remains intact.",
5449 The(xname(obj)), hcolor("dark red"));
5451 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5452 xname(obj), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5459 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5471 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5472 dindx = 1; /* boil and explode */
5473 dmg = (obj->owt + 19) / 20;
5484 xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5488 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5496 if (obj->otyp == WAN_LIGHTNING) {
5501 if (obj == current_wand) { skip++; break; }
5517 --quan; /* one will be used up elsewhere */
5518 for (i = cnt = 0L; i < quan; i++)
5526 ? (quan == 1L) ? "Your" /* 1 of 1 */
5527 : "One of your" /* 1 of N */
5528 : (cnt < quan) ? "Some of your" /* n of N */
5529 : (quan == 2L) ? "Both of your" /* 2 of 2 */
5530 : "All of your"; /* N of N */
5532 mult = (cnt == quan)
5534 : (cnt == 1L) ? "
\82Ì
\82Ð
\82Æ
\82Â" : "
\82Ì
\82¢
\82
\82Â
\82©";
5537 pline("%s %s %s!", mult, xname(obj),
5538 destroy_strings[dindx][(cnt > 1L)]);
5540 pline("
\82 \82È
\82½
\82Ì%s%s
\82Í%s
\81I", xname(obj), mult,
5541 destroy_strings[dindx][(cnt > 1L)]);
5543 if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5544 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5547 if (obj->owornmask) {
5548 if (obj->owornmask & W_RING) /* ring being worn */
5553 if (obj == current_wand)
5554 current_wand = 0; /* destroyed */
5555 for (i = 0; i < cnt; i++)
5560 You("aren't hurt!");
5562 You("
\8f\9d\82Â
\82©
\82È
\82¢
\81I");
5564 const char *how = destroy_strings[dindx][2];
5565 boolean one = (cnt == 1L);
5567 if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
5569 how = "exploding glob of slime";
5571 how = "
\83X
\83\89\83C
\83\80\82Ì
\82Ë
\82Î
\82Ë
\82Î
\82Ì
\94\9a\94
\82Å";
5572 if (physical_damage)
5573 dmg = Maybe_Half_Phys(dmg);
5574 losehp(dmg, one ? how : (const char *) makeplural(how),
5575 one ? KILLED_BY_AN : KILLED_BY);
5576 exercise(A_STR, FALSE);
5585 destroy_mitem(mtmp, osym, dmgtyp)
5589 struct obj *obj, *obj2;
5595 if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5596 destroy_item(osym, dmgtyp);
5597 return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5600 vis = canseemon(mtmp);
5601 for (obj = mtmp->minvent; obj; obj = obj2) {
5603 if (obj->oclass != osym)
5604 continue; /* test only objs of type osym */
5611 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5619 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5621 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5625 pline("%s glows a strange %s, but remains intact.",
5626 The(distant_name(obj, xname)), hcolor("dark red"));
5628 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5629 The(distant_name(obj, xname)), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5635 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5647 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5648 dindx = 1; /* boil and explode */
5649 tmp += (obj->owt + 19) / 20;
5663 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5670 if (obj->otyp == WAN_LIGHTNING) {
5687 for (i = cnt = 0L; i < quan; i++)
5696 (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5698 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5699 destroy_strings[dindx][(cnt > 1L)]);
5701 pline("%s%s
\82Í%s
\81I",
5702 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5703 (cnt == obj->quan) ? "" : (cnt > 1L) ? "
\82Ì
\82¢
\82
\82Â
\82©"
5704 : "
\82Ì
\82Ð
\82Æ
\82Â",
5705 destroy_strings[dindx][(cnt > 1L)]);
5707 for (i = 0; i < cnt; i++)
5715 resist(mtmp, oclass, damage, tell)
5730 break; /* instrument */
5733 break; /* artifact */
5748 dlev = (int) mtmp->m_lev;
5752 dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5754 resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5757 shieldeff(mtmp->mx, mtmp->my);
5759 pline("%s resists!", Monnam(mtmp));
5761 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", Monnam(mtmp));
5763 damage = (damage + 1) / 2;
5767 mtmp->mhp -= damage;
5768 if (mtmp->mhp < 1) {
5770 monkilled(mtmp, "", AD_RBRE);
5778 #define MAXWISHTRY 5
5781 wishcmdassist(triesleft)
5784 static NEARDATA const char *
5788 "Enter the name of an object, such as \"potion of monster detection\",",
5789 "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5790 "(without the quotes).",
5792 "For object types which come in stacks, you may specify a plural name",
5793 "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5794 "pieces\", although that aspect of your wish might not be granted.",
5796 "You may also specify various prefix values which might be used to",
5797 "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5798 "Most modifiers shown when viewing your inventory can be specified.",
5800 "You may specify 'nothing' to explicitly decline this wish.",
5803 preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5805 "If you specify an unrecognized object name %s%s time%s,",
5806 retry_too[] = "a randomly chosen item will be granted.",
5807 suppress_cmdassist[] =
5808 "(Suppress this assistance with !cmdassist in your config file.)",
5809 *cardinals[] = { "zero", "one", "two", "three", "four", "five" },
5810 too_many[] = "too many";
5815 win = create_nhwindow(NHW_TEXT);
5818 for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5819 putstr(win, 0, wishinfo[i]);
5820 if (!u.uconduct.wishes)
5821 putstr(win, 0, preserve_wishless);
5823 Sprintf(buf, retry_info,
5824 (triesleft >= 0 && triesleft < SIZE(cardinals))
5825 ? cardinals[triesleft]
5827 (triesleft < MAXWISHTRY) ? " more" : "",
5829 putstr(win, 0, buf);
5830 putstr(win, 0, retry_too);
5832 if (iflags.cmdassist)
5833 putstr(win, 0, suppress_cmdassist);
5834 display_nhwindow(win, FALSE);
5835 destroy_nhwindow(win);
5841 static char buf[BUFSZ] = DUMMY;
5842 char promptbuf[BUFSZ];
5843 struct obj *otmp, nothing;
5846 promptbuf[0] = '\0';
5847 nothing = zeroobj; /* lint suppression; only its address matters */
5850 You("may wish for an object.");
5852 You("
\96]
\82Ý
\82Ì
\82à
\82Ì
\82ð
\8eè
\82É
\93ü
\82ê
\82ç
\82ê
\82é
\81D");
5855 Strcpy(promptbuf, "For what do you wish");
5857 Strcpy(promptbuf, "(
\93ú
\96{
\8cê
\82Å)
\89½
\82ð
\82¨
\96]
\82Ý");
5858 if (iflags.cmdassist && tries > 0)
5860 Strcat(promptbuf, " (enter 'help' for assistance)");
5862 Strcat(promptbuf, " (
\8f\95\82¯
\82ª
\95K
\97v
\82È
\82ç 'help'
\82Æ
\93ü
\97Í)");
5864 Strcat(promptbuf, "?");
5866 Strcat(promptbuf, "
\81H");
5867 getlin(promptbuf, buf);
5868 (void) mungspaces(buf);
5869 if (buf[0] == '\033') {
5871 } else if (!strcmpi(buf, "help")) {
5872 wishcmdassist(MAXWISHTRY - tries);
5876 * Note: if they wished for and got a non-object successfully,
5877 * otmp == &zeroobj. That includes gold, or an artifact that
5878 * has been denied. Wishing for "nothing" requires a separate
5879 * value to remain distinct.
5881 otmp = readobjnam(buf, ¬hing);
5884 pline("Nothing fitting that description exists in the game.");
5886 pline("
\82¤
\81[
\82ñ
\81D
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\91¶
\8dÝ
\82µ
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
5887 if (++tries < MAXWISHTRY)
5889 pline1(thats_enough_tries);
5890 otmp = readobjnam((char *) 0, (struct obj *) 0);
5892 return; /* for safety; should never happen */
5893 } else if (otmp == ¬hing) {
5894 /* explicitly wished for "nothing", presumably attempting
5895 to retain wishless conduct */
5900 u.uconduct.wishes++;
5902 if (otmp != &zeroobj) {
5905 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5907 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "
\8a\8a\82è
\97\8e\82¿
\82½" : "
\97\8e\82¿
\82½"),
5909 *oops_msg = (u.uswallow
5910 ? "Oops! %s out of your reach!"
5911 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5912 || levl[u.ux][u.uy].typ < IRONBARS
5913 || levl[u.ux][u.uy].typ >= ICE)
5914 ? "Oops! %s away from you!"
5915 : "Oops! %s to the floor!");
5917 /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5918 (void) hold_another_object(otmp, oops_msg,
5919 The(aobjnam(otmp, verb)),
5922 *oops_msg = (u.uswallow
5923 ? "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\93Í
\82©
\82È
\82¢
\82Æ
\82±
\82ë
\82É%s
\81I"
5924 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5925 || levl[u.ux][u.uy].typ < IRONBARS
5926 || levl[u.ux][u.uy].typ >= ICE)
5927 ? "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\8eè
\82©
\82ç%s
\81I"
5928 : "
\82¨
\82Á
\82Æ
\81C%%s
\82ª
\8f°
\82É%s
\81I");
5929 char oopsbuf[BUFSZ];
5930 Sprintf(oopsbuf, oops_msg, verb);
5932 (void) hold_another_object(otmp, oopsbuf,
5936 u.ublesscnt += rn1(100, 50); /* the gods take notice */