1 /* NetHack 3.6 zap.c $NHDT-Date: 1447987787 2015/11/20 02:49:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.236 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
12 /* Disintegration rays have special treatment; corpses are never left.
13 * But the routine which calculates the damage is separate from the routine
14 * which kills the monster. The damage routine returns this cookie to
15 * indicate that the monster should be disintegrated.
17 #define MAGIC_COOKIE 1000
19 static NEARDATA boolean obj_zapped;
20 static NEARDATA int poly_zapped;
22 extern boolean notonhead; /* for long worms */
24 /* kludge to use mondied instead of killed */
25 extern boolean m_using;
27 STATIC_DCL void FDECL(polyuse, (struct obj *, int, int));
28 STATIC_DCL void FDECL(create_polymon, (struct obj *, int));
29 STATIC_DCL int FDECL(stone_to_flesh_obj, (struct obj *));
30 STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
31 STATIC_DCL void FDECL(zhitu, (int, int, const char *, XCHAR_P, XCHAR_P));
32 STATIC_DCL void FDECL(revive_egg, (struct obj *));
33 STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
34 STATIC_DCL void FDECL(skiprange, (int, int *, int *));
36 STATIC_DCL int FDECL(zap_hit, (int, int));
37 STATIC_OVL void FDECL(disintegrate_mon, (struct monst *, int, const char *));
38 STATIC_DCL void FDECL(backfire, (struct obj *));
39 STATIC_DCL int FDECL(spell_hit_bonus, (int));
41 #define ZT_MAGIC_MISSILE (AD_MAGM - 1)
42 #define ZT_FIRE (AD_FIRE - 1)
43 #define ZT_COLD (AD_COLD - 1)
44 #define ZT_SLEEP (AD_SLEE - 1)
45 #define ZT_DEATH (AD_DISN - 1) /* or disintegration */
46 #define ZT_LIGHTNING (AD_ELEC - 1)
47 #define ZT_POISON_GAS (AD_DRST - 1)
48 #define ZT_ACID (AD_ACID - 1)
49 /* 8 and 9 are currently unassigned */
51 #define ZT_WAND(x) (x)
52 #define ZT_SPELL(x) (10 + (x))
53 #define ZT_BREATH(x) (20 + (x))
55 #define is_hero_spell(type) ((type) >= 10 && (type) < 20)
57 #define M_IN_WATER(ptr) \
58 ((ptr)->mlet == S_EEL || amphibious(ptr) || is_swimmer(ptr))
60 STATIC_VAR const char are_blinded_by_the_flash[] =
62 "are blinded by the flash!";
64 "
\82Ü
\82Î
\82ä
\82¢
\8cõ
\82Å
\96Ú
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½
\81I";
66 const char *const flash_types[] =
67 { /* also used in buzzmu(mcastu.c) */
69 "magic missile", /* Wands must be 0-9 */
70 "bolt of fire", "bolt of cold", "sleep ray", "death ray",
71 "bolt of lightning", "", "", "", "",
73 "
\96\82\96@
\82Ì
\96î", /* Wands must be 0-9 */
78 "
\88î
\8dÈ
\82Ì
\91M
\8cõ",
86 "magic missile", /* Spell equivalents must be 10-19 */
87 "fireball", "cone of cold", "sleep ray", "finger of death",
88 "bolt of lightning", /* There is no spell, used for retribution */
91 "
\96\82\96@
\82Ì
\96î", /* Spell equivalents must be 10-19 */
96 "
\88î
\8dÈ
\82Ì
\91M
\8cõ", /* There is no spell, used for retribution */
104 "blast of missiles", /* Dragon breath equivalents 20-29*/
105 "blast of fire", "blast of frost", "blast of sleep gas",
106 "blast of disintegration", "blast of lightning", "blast of poison gas",
107 "blast of acid", "", ""
109 "
\96\82\96@
\82Ì
\96î
\82Ì
\91§", /* Dragon breath equivalents 20-29*/
112 "
\90\87\96°
\83K
\83X
\82Ì
\91§",
115 "
\93Å
\83K
\83X
\82Ì
\91§",
123 * Recognizing unseen wands by zapping: in 3.4.3 and earlier, zapping
124 * most wand types while blind would add that type to the discoveries
125 * list even if it had never been seen (ie, picked up while blinded
126 * and shown in inventory as simply "a wand"). This behavior has been
127 * changed; now such wands won't be discovered. But if the type is
128 * already discovered, then the individual wand whose effect was just
129 * observed will be flagged as if seen. [You already know wands of
130 * striking; you zap "a wand" and observe striking effect (presumably
131 * by sound or touch); it'll become shown in inventory as "a wand of
134 * Unfortunately, the new behavior isn't really correct either. There
135 * should be an `eknown' bit for "effect known" added for wands (and
136 * for potions since quaffing one of a stack is similar) so that the
137 * particular wand which has been zapped would have its type become
138 * known (it would change from "a wand" to "a wand of striking", for
139 * example) without the type becoming discovered or other unknown wands
140 * of that type showing additional information. When blindness ends,
141 * all objects in inventory with the eknown bit set would be discovered
142 * and other items of the same type would become known as such.
145 /* wand discovery gets special handling when hero is blinded */
150 /* For a wand (or wand-like tool) zapped by the player, if the
151 effect was observable (determined by caller; usually seen, but
152 possibly heard or felt if the hero is blinded) then discover the
153 object type provided that the object itself is known (as more
154 than just "a wand"). If object type is already discovered and
155 we observed the effect, mark the individual wand as having been
156 seen. Suppress spells (which use fake spellbook object for `obj')
157 so that casting a spell won't re-discover its forgotten book. */
158 if (obj->oclass != SPBOOK_CLASS) {
159 /* if type already discovered, treat this item has having been seen
160 even if hero is currently blinded (skips redundant makeknown) */
161 if (objects[obj->otyp].oc_name_known) {
162 obj->dknown = 1; /* will usually be set already */
164 /* otherwise discover it if item itself has been or can be seen */
166 /* in case it was picked up while blind and then zapped without
167 examining inventory after regaining sight (bypassing xname) */
170 /* make the discovery iff we know what we're manipulating */
172 makeknown(obj->otyp);
177 /* Routines for IMMEDIATE wands and spells. */
178 /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
184 boolean wake = TRUE; /* Most 'zaps' should wake monster */
185 boolean reveal_invis = FALSE, learn_it = FALSE;
186 boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
187 int dmg, otyp = otmp->otyp;
189 const char *zap_type_text = "spell";
191 const char *zap_type_text = "
\96\82\96@";
193 boolean disguised_mimic =
194 (mtmp->data->mlet == S_MIMIC && mtmp->m_ap_type != M_AP_NOTHING);
196 if (u.uswallow && mtmp == u.ustuck)
197 reveal_invis = FALSE;
202 zap_type_text = "wand";
204 zap_type_text = "
\8fñ";
208 if (resists_magm(mtmp)) { /* match effect on player */
209 shieldeff(mtmp->mx, mtmp->my);
213 pline("
\83{
\83C
\83\93\81I");
214 break; /* skip makeknown */
215 } else if (u.uswallow || rnd(20) < 10 + find_mac(mtmp)) {
219 if (otyp == SPE_FORCE_BOLT)
220 dmg = spell_damage_bonus(dmg);
221 hit(zap_type_text, mtmp, exclam(dmg));
222 (void) resist(mtmp, otmp->oclass, dmg, TELL);
224 miss(zap_type_text, mtmp);
227 case WAN_SLOW_MONSTER:
228 case SPE_SLOW_MONSTER:
229 if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
230 mon_adjust_speed(mtmp, -1, otmp);
231 m_dowear(mtmp, FALSE); /* might want speed boots */
232 if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) {
234 You("disrupt %s!", mon_nam(mtmp));
236 You("%s
\82ð
\83o
\83\89\83o
\83\89\82É
\82µ
\82½
\81I", mon_nam(mtmp));
238 pline("A huge hole opens up...");
240 pline("
\92E
\8fo
\82Å
\82«
\82»
\82¤
\82È
\8c\8a\82ª
\8aJ
\82¢
\82½
\81D
\81D
\81D");
241 expels(mtmp, mtmp->data, TRUE);
245 case WAN_SPEED_MONSTER:
246 if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
247 mon_adjust_speed(mtmp, 1, otmp);
248 m_dowear(mtmp, FALSE); /* might want speed boots */
251 case WAN_UNDEAD_TURNING:
252 case SPE_TURN_UNDEAD:
254 if (unturn_dead(mtmp))
256 if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
262 if (otyp == SPE_TURN_UNDEAD)
263 dmg = spell_damage_bonus(dmg);
264 context.bypasses = TRUE; /* for make_corpse() */
265 if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) {
267 monflee(mtmp, 0, FALSE, TRUE);
274 if (resists_magm(mtmp)) {
275 /* magic resistance protects from polymorph traps, so make
276 it guard against involuntary polymorph attacks too... */
277 shieldeff(mtmp->mx, mtmp->my);
278 } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
279 /* dropped inventory (due to death by system shock,
280 or loss of wielded weapon and/or worn armor due to
281 limitations of new shape) won't be hit by this zap */
282 for (obj = mtmp->minvent; obj; obj = obj->nobj)
284 /* natural shapechangers aren't affected by system shock
285 (unless protection from shapechangers is interfering
286 with their metabolism...) */
287 if (mtmp->cham == NON_PM && !rn2(25)) {
288 if (canseemon(mtmp)) {
290 pline("%s shudders!", Monnam(mtmp));
292 pline("%s
\82Í
\90g
\90k
\82¢
\82µ
\82½
\81I", Monnam(mtmp));
295 /* context.bypasses = TRUE; ## for make_corpse() */
296 /* no corpse after system shock */
298 } else if (newcham(mtmp, (struct permonst *) 0,
299 (otyp != POT_POLYMORPH), FALSE)) {
300 if (!Hallucination && canspotmon(mtmp))
305 case WAN_CANCELLATION:
306 case SPE_CANCELLATION:
307 (void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
309 case WAN_TELEPORTATION:
310 case SPE_TELEPORT_AWAY:
311 reveal_invis = !u_teleport_mon(mtmp, TRUE);
313 case WAN_MAKE_INVISIBLE: {
314 int oldinvis = mtmp->minvis;
317 /* format monster's name before altering its visibility */
318 Strcpy(nambuf, Monnam(mtmp));
319 mon_set_minvis(mtmp);
320 if (!oldinvis && knowninvisible(mtmp)) {
322 pline("%s turns transparent!", nambuf);
324 pline("%s
\82Í
\93§
\96¾
\82É
\82È
\82Á
\82½
\81I", nambuf);
330 case SPE_WIZARD_LOCK:
331 wake = closeholdingtrap(mtmp, &learn_it);
341 wake = FALSE; /* don't want immediate counterattack */
342 if (u.uswallow && mtmp == u.ustuck) {
343 if (is_animal(mtmp->data)) {
346 You_feel("a sudden rush of air!");
348 You("
\93Ë
\91R
\8c\83\82µ
\82¢
\8bó
\8bC
\82Ì
\97¬
\82ê
\82ð
\8a´
\82¶
\82½
\81I");
351 pline("%s opens its mouth!", Monnam(mtmp));
353 pline("%s
\82Í
\8cû
\82ð
\8aJ
\82¢
\82½
\81I", Monnam(mtmp));
355 expels(mtmp, mtmp->data, TRUE);
356 /* zap which hits steed will only release saddle if it
357 doesn't hit a holding or falling trap; playability
358 here overrides the more logical target ordering */
359 } else if (openholdingtrap(mtmp, &learn_it)) {
361 } else if (openfallingtrap(mtmp, TRUE, &learn_it)) {
362 /* mtmp might now be on the migrating monsters list */
364 } else if ((obj = which_armor(mtmp, W_SADDLE)) != 0) {
367 Sprintf(buf, "%s %s", s_suffix(Monnam(mtmp)),
368 distant_name(obj, xname));
369 if (cansee(mtmp->mx, mtmp->my)) {
370 if (!canspotmon(mtmp))
371 Strcpy(buf, An(distant_name(obj, xname)));
372 pline("%s falls to the %s.", buf,
373 surface(mtmp->mx, mtmp->my));
374 } else if (canspotmon(mtmp)) {
375 pline("%s falls off.", buf);
377 obj_extract_self(obj);
378 mdrop_obj(mtmp, obj, FALSE);
382 case SPE_EXTRA_HEALING:
384 if (mtmp->data != &mons[PM_PESTILENCE]) {
385 wake = FALSE; /* wakeup() makes the target angry */
386 mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4);
387 if (mtmp->mhp > mtmp->mhpmax)
388 mtmp->mhp = mtmp->mhpmax;
389 if (mtmp->mblinded) {
393 if (canseemon(mtmp)) {
394 if (disguised_mimic) {
395 if (is_obj_mappear(mtmp,STRANGE_OBJECT)) {
396 /* it can do better now */
398 newsym(mtmp->mx, mtmp->my);
400 mimic_hit_msg(mtmp, otyp);
403 pline("%s looks%s better.", Monnam(mtmp),
404 otyp == SPE_EXTRA_HEALING ? " much" : "");
406 pline("%s
\82Í%s
\8c³
\8bC
\82É
\82È
\82Á
\82½
\82æ
\82¤
\82¾
\81D", Monnam(mtmp),
407 otyp == SPE_EXTRA_HEALING ? "
\82Æ
\82Ä
\82à" : "" );
410 if (mtmp->mtame || mtmp->mpeaceful) {
411 adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
413 } else { /* Pestilence */
414 /* Pestilence will always resist; damage is half of 3d{4,8} */
415 (void) resist(mtmp, otmp->oclass,
416 d(3, otyp == SPE_EXTRA_HEALING ? 8 : 4), TELL);
419 case WAN_LIGHT: /* (broken wand) */
420 if (flash_hits_mon(mtmp, otmp)) {
425 case WAN_SLEEP: /* (broken wand) */
426 /* [wakeup() doesn't rouse victims of temporary sleep,
427 so it's okay to leave `wake' set to TRUE here] */
429 if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS))
434 case SPE_STONE_TO_FLESH:
435 if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
436 char *name = Monnam(mtmp);
438 /* turn into flesh golem */
439 if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE, FALSE)) {
442 pline("%s turns to flesh!", name);
444 pline("%s
\82Ì
\90Î
\89»
\82ª
\89ð
\82¯
\82½
\81I", name);
448 pline("%s looks rather fleshy for a moment.", name);
450 pline("%s
\82Í
\88ê
\8fu
\90Î
\89»
\82ª
\89ð
\82¯
\82½
\81D", name);
456 dmg = monhp_per_lvl(mtmp);
459 if (otyp == SPE_DRAIN_LIFE)
460 dmg = spell_damage_bonus(dmg);
461 if (resists_drli(mtmp))
462 shieldeff(mtmp->mx, mtmp->my);
463 else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
466 if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
472 pline("%s suddenly seems weaker!", Monnam(mtmp));
474 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\8eã
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I", Monnam(mtmp));
482 impossible("What an interesting effect (%d)", otyp);
489 if (mtmp->isshk && !*u.ushops)
491 } else if (mtmp->m_ap_type)
492 seemimic(mtmp); /* might unblock if mimicing a boulder/door */
494 /* note: bhitpos won't be set if swallowed, but that's okay since
495 * reveal_invis will be false. We can't use mtmp->mx, my since it
496 * might be an invisible worm hit on the tail.
499 if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y)
500 && !canspotmon(mtmp))
501 map_invisible(bhitpos.x, bhitpos.y);
503 /* if effect was observable then discover the wand type provided
504 that the wand itself has been seen */
518 return; /* don't show minvent for long worm tail */
521 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
522 otmp->dknown = 1; /* treat as "seen" */
523 if (Is_container(otmp) || otmp->otyp == STATUE) {
525 if (!SchroedingersBox(otmp))
529 (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET, (char *) 0);
532 pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
533 (u.uswallow && mtmp == u.ustuck) ? " besides you" : "");
535 pline("%s
\82Í%s
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", noit_Monnam(mtmp),
536 (u.uswallow && mtmp == u.ustuck) ? "
\82 \82È
\82½
\88È
\8aO
\82É" : "");
542 * Return the object's physical location. This only makes sense for
543 * objects that are currently on the level (i.e. migrating objects
544 * are nowhere). By default, only things that can be seen (in hero's
545 * inventory, monster's inventory, or on the ground) are reported.
546 * By adding BURIED_TOO and/or CONTAINED_TOO flags, you can also get
547 * the location of buried and contained objects. Note that if an
548 * object is carried by a monster, its reported position may change
549 * from turn to turn. This function returns FALSE if the position
550 * is not available or subject to the constraints above.
553 get_obj_location(obj, xp, yp, locflags)
558 switch (obj->where) {
568 if (obj->ocarry->mx) {
569 *xp = obj->ocarry->mx;
570 *yp = obj->ocarry->my;
573 break; /* !mx => migrating monster */
575 if (locflags & BURIED_TOO) {
582 if (locflags & CONTAINED_TOO)
583 return get_obj_location(obj->ocontainer, xp, yp, locflags);
591 get_mon_location(mon, xp, yp, locflags)
594 int locflags; /* non-zero means get location even if monster is buried */
596 if (mon == &youmonst) {
600 } else if (mon->mx > 0 && (!mon->mburied || locflags)) {
604 } else { /* migrating or buried */
610 /* used by revive() and animate_statue() */
616 struct monst *mtmp = (struct monst *) 0;
617 struct monst *mtmp2 = (struct monst *) 0;
620 mtmp2 = get_mtraits(obj, TRUE);
622 /* save_mtraits() validated mtmp2->mnum */
623 mtmp2->data = &mons[mtmp2->mnum];
624 if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
625 return (struct monst *) 0;
626 mtmp = makemon(mtmp2->data, cc->x, cc->y,
627 NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
631 /* heal the monster */
632 if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data))
633 mtmp2->mhpmax = mtmp->mhpmax;
634 mtmp2->mhp = mtmp2->mhpmax;
635 /* Get these ones from mtmp */
636 mtmp2->minvent = mtmp->minvent; /*redundant*/
637 /* monster ID is available if the monster died in the current
638 game, but will be zero if the corpse was in a bones level
639 (we cleared it when loading bones) */
641 mtmp2->m_id = mtmp->m_id;
642 /* might be bringing quest leader back to life */
643 if (quest_status.leader_is_dead &&
644 /* leader_is_dead implies leader_m_id is valid */
645 mtmp2->m_id == quest_status.leader_m_id)
646 quest_status.leader_is_dead = FALSE;
648 mtmp2->mx = mtmp->mx;
649 mtmp2->my = mtmp->my;
650 mtmp2->mux = mtmp->mux;
651 mtmp2->muy = mtmp->muy;
652 mtmp2->mw = mtmp->mw;
653 mtmp2->wormno = mtmp->wormno;
654 mtmp2->misc_worn_check = mtmp->misc_worn_check;
655 mtmp2->weapon_check = mtmp->weapon_check;
656 mtmp2->mtrapseen = mtmp->mtrapseen;
657 mtmp2->mflee = mtmp->mflee;
658 mtmp2->mburied = mtmp->mburied;
659 mtmp2->mundetected = mtmp->mundetected;
660 mtmp2->mfleetim = mtmp->mfleetim;
661 mtmp2->mlstmv = mtmp->mlstmv;
662 mtmp2->m_ap_type = mtmp->m_ap_type;
663 /* set these ones explicitly */
669 mtmp2->msleeping = 0;
672 /* most cancelled monsters return to normal,
673 but some need to stay cancelled */
674 if (!dmgtype(mtmp2->data, AD_SEDU)
675 && (!SYSOPT_SEDUCE || !dmgtype(mtmp2->data, AD_SSEX)))
677 mtmp2->mcansee = 1; /* set like in makemon */
681 replmon(mtmp, mtmp2);
682 newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
684 /* in case Protection_from_shape_changers is different
685 now than it was when the traits were stored */
692 * get_container_location() returns the following information
693 * about the outermost container:
694 * loc argument gets set to:
695 * OBJ_INVENT if in hero's inventory; return 0.
696 * OBJ_FLOOR if on the floor; return 0.
697 * OBJ_BURIED if buried; return 0.
698 * OBJ_MINVENT if in monster's inventory; return monster.
699 * container_nesting is updated with the nesting depth of the containers
703 get_container_location(obj, loc, container_nesting)
706 int *container_nesting;
711 if (container_nesting)
712 *container_nesting = 0;
713 while (obj && obj->where == OBJ_CONTAINED) {
714 if (container_nesting)
715 *container_nesting += 1;
716 obj = obj->ocontainer;
719 *loc = obj->where; /* outermost container's location */
720 if (obj->where == OBJ_MINVENT)
723 return (struct monst *) 0;
727 * Attempt to revive the given corpse, return the revived monster if
728 * successful. Note: this does NOT use up the corpse if it fails.
731 revive(corpse, by_hero)
735 struct monst *mtmp = 0;
736 struct permonst *mptr;
737 struct obj *container;
740 int montype, container_nesting = 0;
742 if (corpse->otyp != CORPSE) {
743 impossible("Attempting to revive %s?", xname(corpse));
744 return (struct monst *) 0;
748 if (corpse->where != OBJ_CONTAINED) {
749 /* only for invent, minvent, or floor */
751 (void) get_obj_location(corpse, &x, &y, 0);
753 /* deal with corpses in [possibly nested] containers */
754 struct monst *carrier;
755 int holder = OBJ_FREE;
757 container = corpse->ocontainer;
759 get_container_location(container, &holder, &container_nesting);
762 x = carrier->mx, y = carrier->my;
768 (void) get_obj_location(corpse, &x, &y, CONTAINED_TOO);
771 break; /* x,y are 0 */
775 /* Rules for revival from containers:
776 - the container cannot be locked
777 - the container cannot be heavily nested (>2 is arbitrary)
778 - the container cannot be a statue or bag of holding
779 (except in very rare cases for the latter)
781 (container && (container->olocked || container_nesting > 2
782 || container->otyp == STATUE
783 || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
784 return (struct monst *) 0;
786 /* record the object's location now that we're sure where it is */
787 corpse->ox = x, corpse->oy = y;
789 /* prepare for the monster */
790 montype = corpse->corpsenm;
791 mptr = &mons[montype];
792 /* [should probably handle recorporealization first; if corpse and
793 ghost are at same location, revived creature shouldn't be bumped
794 to an adjacent spot by ghost which joins with it] */
796 if (enexto(&xy, x, y, mptr))
800 if (mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ)) {
801 if (by_hero && cansee(x,y))
802 pline("%s twitches feebly.",
803 upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
804 return (struct monst *) 0;
807 if (cant_revive(&montype, TRUE, corpse)) {
808 /* make a zombie or doppelganger instead */
809 /* note: montype has changed; mptr keeps old value for newcham() */
810 mtmp = makemon(&mons[montype], x, y, NO_MINVENT | MM_NOWAIT);
812 /* skip ghost handling */
813 if (has_omid(corpse))
815 if (has_omonst(corpse))
817 if (mtmp->cham == PM_DOPPELGANGER) {
818 /* change shape to match the corpse */
819 (void) newcham(mtmp, mptr, FALSE, FALSE);
820 } else if (mtmp->data->mlet == S_ZOMBIE) {
821 mtmp->mhp = mtmp->mhpmax = 100;
822 mon_adjust_speed(mtmp, 2, (struct obj *) 0); /* MFAST */
825 } else if (has_omonst(corpse)) {
826 /* use saved traits */
828 mtmp = montraits(corpse, &xy);
829 if (mtmp && mtmp->mtame && !mtmp->isminion)
830 wary_dog(mtmp, TRUE);
832 /* make a new monster */
833 mtmp = makemon(mptr, x, y, NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
836 return (struct monst *) 0;
838 /* hiders shouldn't already be re-hidden when they revive */
839 if (mtmp->mundetected) {
840 mtmp->mundetected = 0;
841 newsym(mtmp->mx, mtmp->my);
846 /* if this is caused by the hero there might be a shop charge */
848 struct monst *shkp = 0;
850 x = corpse->ox, y = corpse->oy;
851 if (costly_spot(x, y))
852 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
856 "%s glows iridescently.",
857 upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
859 /* need some prior description of the corpse since
860 stolen_value() will refer to the object as "it" */
861 pline("A corpse is resuscitated.");
863 /* don't charge for shopkeeper's own corpse if we just revived him */
864 if (shkp && mtmp != shkp)
865 (void) stolen_value(corpse, x, y, (boolean) shkp->mpeaceful,
868 /* [we don't give any comparable message about the corpse for
869 the !by_hero case because caller might have already done so] */
872 /* handle recorporealization of an active ghost */
873 if (has_omid(corpse)) {
878 (void) memcpy((genericptr_t) &m_id, (genericptr_t) OMID(corpse),
880 ghost = find_mid(m_id, FM_FMON);
881 if (ghost && ghost->data == &mons[PM_GHOST]) {
882 if (canseemon(ghost))
884 pline("%s is suddenly drawn into its former body!",
886 pline("%s
\82Í
\93Ë
\91R
\82à
\82Æ
\82Ì
\91Ì
\82É
\88ø
\82«
\8d\9e\82Ü
\82ê
\82½
\81I",
889 /* transfer the ghost's inventory along with it */
890 while ((otmp = ghost->minvent) != 0) {
891 obj_extract_self(otmp);
892 add_to_minv(mtmp, otmp);
894 /* tame the revived monster if its ghost was tame */
895 if (ghost->mtame && !mtmp->mtame) {
896 if (tamedog(mtmp, (struct obj *) 0)) {
897 /* ghost's edog data is ignored */
898 mtmp->mtame = ghost->mtame;
901 /* was ghost, now alive, it's all very confusing */
903 /* separate ghost monster no longer exists */
909 /* monster retains its name */
910 if (has_oname(corpse))
911 mtmp = christen_monst(mtmp, ONAME(corpse));
912 /* partially eaten corpse yields wounded monster */
914 mtmp->mhp = eaten_stat(mtmp->mhp, corpse);
915 /* track that this monster was revived at least once */
918 /* finally, get rid of the corpse--it's gone now */
919 switch (corpse->where) {
924 /* in case MON_AT+enexto for invisible mon */
925 x = corpse->ox, y = corpse->oy;
926 /* not useupf(), which charges */
927 if (corpse->quan > 1L)
928 corpse = splitobj(corpse, 1L);
933 m_useup(corpse->ocarry, corpse);
936 obj_extract_self(corpse);
937 obfree(corpse, (struct obj *) 0);
951 * Note: generic eggs with corpsenm set to NON_PM will never hatch.
953 if (obj->otyp != EGG)
955 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
956 attach_egg_hatch_timeout(obj, 0L);
959 /* try to revive all corpses and eggs carried by `mon' */
964 struct obj *otmp, *otmp2;
966 char owner[BUFSZ], corpse[BUFSZ];
968 int once = 0, res = 0;
970 youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
971 otmp2 = (mon == &youmonst) ? invent : mon->minvent;
973 while ((otmp = otmp2) != 0) {
975 if (otmp->otyp == EGG)
977 if (otmp->otyp != CORPSE)
979 /* save the name; the object is liable to go away */
982 corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
984 /* for a merged group, only one is revived; should this be fixed? */
985 if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
990 Strcpy(owner, (mon == &youmonst) ? "Your"
992 Strcpy(owner, (mon == &youmonst) ? "
\82 \82È
\82½"
993 : s_suffix(Monnam(mon)));
995 pline("%s %s suddenly comes alive!", owner, corpse);
997 pline("%s
\82Ì%s
\82Í
\93Ë
\91R
\90¶
\96½
\82ð
\91Ñ
\82Ñ
\82½
\81I", owner, corpse);
998 } else if (canseemon(mtmp2))
1000 pline("%s suddenly appears!", Amonnam(mtmp2));
1002 pline("%s
\82ª
\93Ë
\91R
\8c»
\82í
\82ê
\82½
\81I", Amonnam(mtmp2));
1008 /* cancel obj, possibly carried by you or a monster */
1011 register struct obj *obj;
1013 boolean u_ring = (obj == uleft || obj == uright);
1014 int otyp = obj->otyp;
1017 case RIN_GAIN_STRENGTH:
1018 if ((obj->owornmask & W_RING) && u_ring) {
1019 ABON(A_STR) -= obj->spe;
1023 case RIN_GAIN_CONSTITUTION:
1024 if ((obj->owornmask & W_RING) && u_ring) {
1025 ABON(A_CON) -= obj->spe;
1030 if ((obj->owornmask & W_RING) && u_ring) {
1031 ABON(A_CHA) -= obj->spe;
1035 case RIN_INCREASE_ACCURACY:
1036 if ((obj->owornmask & W_RING) && u_ring)
1037 u.uhitinc -= obj->spe;
1039 case RIN_INCREASE_DAMAGE:
1040 if ((obj->owornmask & W_RING) && u_ring)
1041 u.udaminc -= obj->spe;
1043 case GAUNTLETS_OF_DEXTERITY:
1044 if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1045 ABON(A_DEX) -= obj->spe;
1049 case HELM_OF_BRILLIANCE:
1050 if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1051 ABON(A_INT) -= obj->spe;
1052 ABON(A_WIS) -= obj->spe;
1056 /* case RIN_PROTECTION: not needed */
1058 if (objects[otyp].oc_magic
1059 || (obj->spe && (obj->oclass == ARMOR_CLASS
1060 || obj->oclass == WEAPON_CLASS || is_weptool(obj)))
1062 || otyp == POT_SICKNESS
1063 || (otyp == POT_WATER && (obj->blessed || obj->cursed))) {
1064 if (obj->spe != ((obj->oclass == WAND_CLASS) ? -1 : 0)
1065 && otyp != WAN_CANCELLATION /* can't cancel cancellation */
1066 && otyp != MAGIC_LAMP /* cancelling doesn't remove djinni */
1067 && otyp != CANDELABRUM_OF_INVOCATION) {
1068 costly_alteration(obj, COST_CANCEL);
1069 obj->spe = (obj->oclass == WAND_CLASS) ? -1 : 0;
1071 switch (obj->oclass) {
1073 costly_alteration(obj, COST_CANCEL);
1074 obj->otyp = SCR_BLANK_PAPER;
1078 if (otyp != SPE_CANCELLATION && otyp != SPE_NOVEL
1079 && otyp != SPE_BOOK_OF_THE_DEAD) {
1080 costly_alteration(obj, COST_CANCEL);
1081 obj->otyp = SPE_BLANK_PAPER;
1085 costly_alteration(obj,
1088 : obj->cursed ? COST_UNCURS : COST_UNBLSS);
1089 if (otyp == POT_SICKNESS || otyp == POT_SEE_INVISIBLE) {
1090 /* sickness is "biologically contaminated" fruit juice;
1091 cancel it and it just becomes fruit juice...
1092 whereas see invisible tastes like "enchanted" fruit
1093 juice, it similarly cancels */
1094 obj->otyp = POT_FRUIT_JUICE;
1096 obj->otyp = POT_WATER;
1097 obj->odiluted = 0; /* same as any other water */
1107 /* Remove a positive enchantment or charge from obj,
1108 * possibly carried by you or a monster
1112 register struct obj *obj;
1116 /* Is this a charged/enchanted object? */
1118 || (!objects[obj->otyp].oc_charged && obj->oclass != WEAPON_CLASS
1119 && obj->oclass != ARMOR_CLASS && !is_weptool(obj))
1122 if (defends(AD_DRLI, obj) || defends_when_carried(AD_DRLI, obj)
1123 || obj_resists(obj, 10, 90))
1126 /* Charge for the cost of the object */
1127 costly_alteration(obj, COST_DRAIN);
1129 /* Drain the object and any implied effects */
1131 u_ring = (obj == uleft) || (obj == uright);
1132 switch (obj->otyp) {
1133 case RIN_GAIN_STRENGTH:
1134 if ((obj->owornmask & W_RING) && u_ring) {
1139 case RIN_GAIN_CONSTITUTION:
1140 if ((obj->owornmask & W_RING) && u_ring) {
1146 if ((obj->owornmask & W_RING) && u_ring) {
1151 case RIN_INCREASE_ACCURACY:
1152 if ((obj->owornmask & W_RING) && u_ring)
1155 case RIN_INCREASE_DAMAGE:
1156 if ((obj->owornmask & W_RING) && u_ring)
1159 case HELM_OF_BRILLIANCE:
1160 if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
1166 case GAUNTLETS_OF_DEXTERITY:
1167 if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
1172 case RIN_PROTECTION:
1182 obj_resists(obj, ochance, achance)
1184 int ochance, achance; /* percent chance for ordinary objects, artifacts */
1186 if (obj->otyp == AMULET_OF_YENDOR
1187 || obj->otyp == SPE_BOOK_OF_THE_DEAD
1188 || obj->otyp == CANDELABRUM_OF_INVOCATION
1189 || obj->otyp == BELL_OF_OPENING
1190 || (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm]))) {
1193 int chance = rn2(100);
1195 return (boolean) (chance < (obj->oartifact ? achance : ochance));
1205 if (context.bypasses && obj->bypass)
1208 if (obj->oclass == WAND_CLASS)
1209 zap_odds = 3; /* half-life = 2 zaps */
1210 else if (obj->cursed)
1211 zap_odds = 3; /* half-life = 2 zaps */
1212 else if (obj->blessed)
1213 zap_odds = 12; /* half-life = 8 zaps */
1215 zap_odds = 8; /* half-life = 6 zaps */
1217 /* adjust for "large" quantities of identical things */
1221 return (boolean) !rn2(zap_odds);
1224 /* Use up at least minwt number of things made of material mat.
1225 * There's also a chance that other stuff will be used up. Finally,
1226 * there's a random factor here to keep from always using the stuff
1227 * at the top of the pile.
1230 polyuse(objhdr, mat, minwt)
1234 register struct obj *otmp, *otmp2;
1236 for (otmp = objhdr; minwt > 0 && otmp; otmp = otmp2) {
1237 otmp2 = otmp->nexthere;
1238 if (context.bypasses && otmp->bypass)
1240 if (otmp == uball || otmp == uchain)
1242 if (obj_resists(otmp, 0, 0))
1243 continue; /* preserve unique objects */
1245 if (otmp->otyp == SCR_MAIL)
1249 if (((int) objects[otmp->otyp].oc_material == mat)
1250 == (rn2(minwt + 1) != 0)) {
1251 /* appropriately add damage to bill */
1252 if (costly_spot(otmp->ox, otmp->oy)) {
1254 addtobill(otmp, FALSE, FALSE, FALSE);
1256 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE,
1259 if (otmp->quan < LARGEST_INT)
1260 minwt -= (int) otmp->quan;
1269 * Polymorph some of the stuff in this pile into a monster, preferably
1270 * a golem of the kind okind.
1273 create_polymon(obj, okind)
1277 struct permonst *mdat = (struct permonst *) 0;
1279 const char *material;
1282 if (context.bypasses) {
1283 /* this is approximate because the "no golems" !obj->nexthere
1284 check below doesn't understand bypassed objects; but it
1285 should suffice since bypassed objects always end up as a
1286 consecutive group at the top of their pile */
1287 while (obj && obj->bypass)
1288 obj = obj->nexthere;
1291 /* no golems if you zap only one object -- not enough stuff */
1292 if (!obj || (!obj->nexthere && obj->quan == 1L))
1295 /* some of these choices are arbitrary */
1300 pm_index = PM_IRON_GOLEM;
1302 material = "metal ";
1304 material = "
\8bà
\91®";
1311 pm_index = rn2(2) ? PM_STONE_GOLEM : PM_CLAY_GOLEM;
1313 material = "lithic ";
1315 material = "
\8dz
\95¨";
1319 /* there is no flesh type, but all food is type 0, so we use it */
1320 pm_index = PM_FLESH_GOLEM;
1322 material = "organic ";
1324 material = "
\97L
\8b@
\95¨";
1327 pm_index = PM_WOOD_GOLEM;
1331 material = "
\96Ø
\8dÞ";
1334 pm_index = PM_LEATHER_GOLEM;
1336 material = "leather ";
1341 pm_index = PM_ROPE_GOLEM;
1343 material = "cloth ";
1348 pm_index = PM_SKELETON; /* nearest thing to "bone golem" */
1352 material = "
\8d\9c";
1355 pm_index = PM_GOLD_GOLEM;
1362 pm_index = PM_GLASS_GOLEM;
1364 material = "glassy ";
1366 material = "
\83K
\83\89\83X";
1369 pm_index = PM_PAPER_GOLEM;
1371 material = "paper ";
1373 material = "
\8e\86";
1376 /* if all else fails... */
1377 pm_index = PM_STRAW_GOLEM;
1381 material = "
\95¨
\91Ì";
1386 if (!(mvitals[pm_index].mvflags & G_GENOD))
1387 mdat = &mons[pm_index];
1389 mtmp = makemon(mdat, obj->ox, obj->oy, NO_MM_FLAGS);
1390 polyuse(obj, okind, (int) mons[pm_index].cwt);
1392 if (mtmp && cansee(mtmp->mx, mtmp->my)) {
1394 pline("Some %sobjects meld, and %s arises from the pile!", material,
1397 pline("
\82¢
\82
\82Â
\82©
\82Ì%s
\82ª
\97n
\82¯
\81C
\82»
\82Ì
\8eR
\82©
\82ç%s
\82ª
\8c»
\82í
\82ê
\82½
\81I", material,
1403 /* Assumes obj is on the floor. */
1411 if (obj->otyp == SCR_MAIL)
1416 if (poly_zapped < 0) {
1417 /* some may metamorphosize */
1418 for (i = obj->quan; i; i--)
1419 if (!rn2(Luck + 45)) {
1420 poly_zapped = objects[obj->otyp].oc_material;
1425 /* if quan > 1 then some will survive intact */
1426 if (obj->quan > 1L) {
1427 if (obj->quan > LARGEST_INT)
1428 obj = splitobj(obj, (long) rnd(30000));
1430 obj = splitobj(obj, (long) rnd((int) obj->quan - 1));
1433 /* appropriately add damage to bill */
1434 if (costly_spot(obj->ox, obj->oy)) {
1436 addtobill(obj, FALSE, FALSE, FALSE);
1438 (void) stolen_value(obj, obj->ox, obj->oy, FALSE, FALSE);
1441 /* zap the object */
1445 /* classes of items whose current charge count carries over across polymorph
1447 static const char charged_objs[] = { WAND_CLASS, WEAPON_CLASS, ARMOR_CLASS,
1451 * Polymorph the object to the given object ID. If the ID is STRANGE_OBJECT
1452 * then pick random object from the source's class (this is the standard
1453 * "polymorph" case). If ID is set to a specific object, inhibit fusing
1454 * n objects into 1. This could have been added as a flag, but currently
1455 * it is tied to not being the standard polymorph case. The new polymorphed
1456 * object replaces obj in its link chains. Return value is a pointer to
1459 * This should be safe to call for an object anywhere.
1468 boolean can_merge = (id == STRANGE_OBJECT);
1469 int obj_location = obj->where;
1471 if (obj->otyp == BOULDER)
1473 if (id == STRANGE_OBJECT) { /* preserve symbol */
1475 unsigned magic_obj = objects[obj->otyp].oc_magic;
1477 if (obj->otyp == UNICORN_HORN && obj->degraded_horn)
1479 /* Try up to 3 times to make the magic-or-not status of
1480 the new item be the same as it was for the old one. */
1481 otmp = (struct obj *) 0;
1485 otmp = mkobj(obj->oclass, FALSE);
1486 } while (--try_limit > 0
1487 && objects[otmp->otyp].oc_magic != magic_obj);
1489 /* literally replace obj with this new thing */
1490 otmp = mksobj(id, FALSE, FALSE);
1491 /* Actually more things use corpsenm but they polymorph differently */
1492 #define USES_CORPSENM(typ) \
1493 ((typ) == CORPSE || (typ) == STATUE || (typ) == FIGURINE)
1495 if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
1496 set_corpsenm(otmp, obj->corpsenm);
1497 #undef USES_CORPSENM
1500 /* preserve quantity */
1501 otmp->quan = obj->quan;
1502 /* preserve the shopkeepers (lack of) interest */
1503 otmp->no_charge = obj->no_charge;
1504 /* preserve inventory letter if in inventory */
1505 if (obj_location == OBJ_INVENT)
1506 otmp->invlet = obj->invlet;
1508 /* You can't send yourself 100 mail messages and then
1509 * polymorph them into useful scrolls
1511 if (obj->otyp == SCR_MAIL) {
1512 otmp->otyp = SCR_MAIL;
1517 /* avoid abusing eggs laid by you */
1518 if (obj->otyp == EGG && obj->spe) {
1519 int mnum, tryct = 100;
1521 /* first, turn into a generic egg */
1522 if (otmp->otyp == EGG)
1526 otmp->owt = weight(otmp);
1528 otmp->corpsenm = NON_PM;
1531 /* now change it into something laid by the hero */
1533 mnum = can_be_hatched(random_monster());
1534 if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
1535 otmp->spe = 1; /* laid by hero */
1536 set_corpsenm(otmp, mnum); /* also sets hatch timer */
1542 /* keep special fields (including charges on wands) */
1543 if (index(charged_objs, otmp->oclass))
1544 otmp->spe = obj->spe;
1545 otmp->recharged = obj->recharged;
1547 otmp->cursed = obj->cursed;
1548 otmp->blessed = obj->blessed;
1549 otmp->oeroded = obj->oeroded;
1550 otmp->oeroded2 = obj->oeroded2;
1551 if (!is_flammable(otmp) && !is_rustprone(otmp))
1553 if (!is_corrodeable(otmp) && !is_rottable(otmp))
1555 if (is_damageable(otmp))
1556 otmp->oerodeproof = obj->oerodeproof;
1558 /* Keep chest/box traps and poisoned ammo if we may */
1559 if (obj->otrapped && Is_box(otmp))
1560 otmp->otrapped = TRUE;
1562 if (obj->opoisoned && is_poisonable(otmp))
1563 otmp->opoisoned = TRUE;
1565 if (id == STRANGE_OBJECT && obj->otyp == CORPSE) {
1566 /* turn crocodile corpses into shoes */
1567 if (obj->corpsenm == PM_CROCODILE) {
1568 otmp->otyp = LOW_BOOTS;
1569 otmp->oclass = ARMOR_CLASS;
1572 otmp->oerodeproof = TRUE;
1574 otmp->cursed = FALSE;
1578 /* no box contents --KAA */
1579 if (Has_contents(otmp))
1580 delete_contents(otmp);
1582 /* 'n' merged objects may be fused into 1 object */
1583 if (otmp->quan > 1L && (!objects[otmp->otyp].oc_merge
1584 || (can_merge && otmp->quan > (long) rn2(1000))))
1587 switch (otmp->oclass) {
1589 if (otmp->otyp == MAGIC_LAMP) {
1590 otmp->otyp = OIL_LAMP;
1591 otmp->age = 1500L; /* "best" oil lamp possible */
1592 } else if (otmp->otyp == MAGIC_MARKER) {
1593 otmp->recharged = 1; /* degraded quality */
1595 /* don't care about the recharge count of other tools */
1599 while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
1600 otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
1601 /* altering the object tends to degrade its quality
1602 (analogous to spellbook `read count' handling) */
1603 if ((int) otmp->recharged < rn2(7)) /* recharge_limit */
1608 while (otmp->otyp == POT_POLYMORPH)
1609 otmp->otyp = rnd_class(POT_GAIN_ABILITY, POT_WATER);
1613 while (otmp->otyp == SPE_POLYMORPH)
1614 otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
1615 /* reduce spellbook abuse; non-blank books degrade */
1616 if (otmp->otyp != SPE_BLANK_PAPER) {
1617 otmp->spestudied = obj->spestudied + 1;
1618 if (otmp->spestudied > MAX_SPELL_STUDY) {
1619 otmp->otyp = SPE_BLANK_PAPER;
1620 /* writing a new book over it will yield an unstudied
1621 one; re-polymorphing this one as-is may or may not
1622 get something non-blank */
1623 otmp->spestudied = rn2(otmp->spestudied);
1629 if (otmp->quan > (long) rnd(4)
1630 && objects[obj->otyp].oc_material == MINERAL
1631 && objects[otmp->otyp].oc_material != MINERAL) {
1632 otmp->otyp = ROCK; /* transmutation backfired */
1633 otmp->quan /= 2L; /* some material has been lost */
1638 /* update the weight */
1639 otmp->owt = weight(otmp);
1641 /* handle polymorph of worn item: stone-to-flesh cast on self can
1642 affect multiple objects at once, but their new forms won't
1643 produce any side-effects; a single worn item dipped into potion
1644 of polymorph can produce side-effects but those won't yield out
1645 of sequence messages because current polymorph is finished */
1646 if (obj_location == OBJ_INVENT && obj->owornmask) {
1647 long old_wornmask = obj->owornmask & ~(W_ART | W_ARTI),
1648 new_wornmask = wearslot(otmp);
1649 boolean was_twohanded = bimanual(obj), was_twoweap = u.twoweap;
1651 remove_worn_item(obj, TRUE);
1652 /* if the new form can be worn in the same slot, make it so
1653 [possible extension: if it could be worn in some other
1654 slot which is currently unfilled, wear it there instead] */
1655 if ((old_wornmask & W_QUIVER) != 0L) {
1657 } else if ((old_wornmask & W_SWAPWEP) != 0L) {
1658 if (was_twohanded || !bimanual(otmp))
1660 if (was_twoweap && uswapwep)
1662 } else if ((old_wornmask & W_WEP) != 0L) {
1663 if (was_twohanded || !bimanual(otmp) || !uarms)
1665 if (was_twoweap && uwep && !bimanual(uwep))
1667 } else if ((old_wornmask & new_wornmask) != 0L) {
1668 new_wornmask &= old_wornmask;
1669 setworn(otmp, new_wornmask);
1670 set_wear(otmp); /* Armor_on() for side-effects */
1674 /* ** we are now done adjusting the object ** */
1676 /* swap otmp for obj */
1677 replace_object(obj, otmp);
1678 if (obj_location == OBJ_INVENT) {
1680 * We may need to do extra adjustments for the hero if we're
1681 * messing with the hero's inventory. The following calls are
1682 * equivalent to calling freeinv on obj and addinv on otmp,
1683 * while doing an in-place swap of the actual objects.
1688 } else if (obj_location == OBJ_FLOOR) {
1689 ox = otmp->ox, oy = otmp->oy; /* set by replace_object() */
1690 if (obj->otyp == BOULDER && otmp->otyp != BOULDER
1691 && !does_block(ox, oy, &levl[ox][oy]))
1692 unblock_point(ox, oy);
1693 else if (obj->otyp != BOULDER && otmp->otyp == BOULDER)
1694 /* (checking does_block() here would be redundant) */
1695 block_point(ox, oy);
1698 if ((!carried(otmp) || obj->unpaid)
1699 && get_obj_location(otmp, &ox, &oy, BURIED_TOO | CONTAINED_TOO)
1700 && costly_spot(ox, oy)) {
1701 register struct monst *shkp =
1702 shop_keeper(*in_rooms(ox, oy, SHOPBASE));
1704 if ((!obj->no_charge
1705 || (Has_contents(obj)
1706 && (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L)))
1707 && inhishop(shkp)) {
1708 if (shkp->mpeaceful) {
1710 && *in_rooms(u.ux, u.uy, 0)
1711 == *in_rooms(shkp->mx, shkp->my, 0)
1712 && !costly_spot(u.ux, u.uy))
1713 make_angry_shk(shkp, ox, oy);
1716 pline("%s gets angry!", Monnam(shkp));
1718 pline("%s
\82Í
\8c\83\93{
\82µ
\82½
\81I", Monnam(shkp));
1723 Norep("%s is furious!", Monnam(shkp));
1725 Norep("%s
\82Í
\93{
\82Á
\82½
\81I", Monnam(shkp));
1732 /* stone-to-flesh spell hits and maybe transforms or animates obj */
1734 stone_to_flesh_obj(obj)
1737 int res = 1; /* affected object by default */
1738 struct permonst *ptr;
1742 boolean smell = FALSE, golem_xform = FALSE;
1744 if (objects[obj->otyp].oc_material != MINERAL
1745 && objects[obj->otyp].oc_material != GEMSTONE)
1747 /* Heart of Ahriman usually resists; ordinary items rarely do */
1748 if (obj_resists(obj, 2, 98))
1751 (void) get_obj_location(obj, &oox, &ooy, 0);
1752 /* add more if stone objects are added.. */
1753 switch (objects[obj->otyp].oc_class) {
1754 case ROCK_CLASS: /* boulders and statues */
1755 case TOOL_CLASS: /* figurines */
1756 if (obj->otyp == BOULDER) {
1757 obj = poly_obj(obj, HUGE_CHUNK_OF_MEAT);
1759 } else if (obj->otyp == STATUE || obj->otyp == FIGURINE) {
1760 ptr = &mons[obj->corpsenm];
1761 if (is_golem(ptr)) {
1762 golem_xform = (ptr != &mons[PM_FLESH_GOLEM]);
1763 } else if (vegetarian(ptr)) {
1764 /* Don't animate monsters that aren't flesh */
1765 obj = poly_obj(obj, MEATBALL);
1769 if (obj->otyp == STATUE) {
1770 /* animate_statue() forces all golems to become flesh golems
1772 mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
1773 } else { /* (obj->otyp == FIGURINE) */
1775 ptr = &mons[PM_FLESH_GOLEM];
1776 mon = makemon(ptr, oox, ooy, NO_MINVENT);
1778 if (costly_spot(oox, ooy) && !obj->no_charge) {
1779 if (costly_spot(u.ux, u.uy))
1780 addtobill(obj, carried(obj), FALSE, FALSE);
1782 stolen_value(obj, oox, ooy, TRUE, FALSE);
1785 obj_stop_timers(obj);
1790 if (cansee(mon->mx, mon->my))
1792 pline_The("figurine %sanimates!",
1793 golem_xform ? "turns to flesh and " : "");
1795 pline_The("
\90l
\8c`
\82Í%s
\93®
\82«
\82¾
\82µ
\82½
\81I",
1796 golem_xform ? "
\90Î
\89»
\82ª
\89ð
\82¯
\82Ä" : "");
1802 /* this golem handling is redundant... */
1803 if (is_golem(ptr) && ptr != &mons[PM_FLESH_GOLEM])
1804 (void) newcham(mon, &mons[PM_FLESH_GOLEM], TRUE, FALSE);
1805 } else if ((ptr->geno & (G_NOCORPSE | G_UNIQ)) != 0) {
1806 /* didn't revive but can't leave corpse either */
1809 /* unlikely to get here since genociding monsters also
1810 sets the G_NOCORPSE flag; drop statue's contents */
1811 while ((item = obj->cobj) != 0) {
1812 bypass_obj(item); /* make stone-to-flesh miss it */
1813 obj_extract_self(item);
1814 place_object(item, oox, ooy);
1816 obj = poly_obj(obj, CORPSE);
1818 } else { /* miscellaneous tool or unexpected rock... */
1822 /* maybe add weird things to become? */
1823 case RING_CLASS: /* some of the rings are stone */
1824 obj = poly_obj(obj, MEAT_RING);
1827 case WAND_CLASS: /* marble wand */
1828 obj = poly_obj(obj, MEAT_STICK);
1831 case GEM_CLASS: /* stones & gems */
1832 obj = poly_obj(obj, MEATBALL);
1835 case WEAPON_CLASS: /* crysknife */
1843 /* non-meat eaters smell meat, meat eaters smell its flavor;
1844 monks are considered non-meat eaters regardless of behavior;
1845 other roles are non-meat eaters if they haven't broken
1846 vegetarian conduct yet (or if poly'd into non-carnivorous/
1847 non-omnivorous form, regardless of whether it's herbivorous,
1848 non-eating, or something stranger) */
1849 if (Role_if(PM_MONK) || !u.uconduct.unvegetarian
1850 || !carnivorous(youmonst.data))
1852 Norep("You smell the odor of meat.");
1854 Norep("
\93÷
\82Ì
\88«
\8fL
\82ª
\95Y
\82Á
\82½
\81D");
1857 Norep("You smell a delicious smell.");
1859 Norep("
\82·
\82Î
\82ç
\82µ
\82¢
\8d\81\82è
\82¾
\81I");
1866 * Object obj was hit by the effect of the wand/spell otmp. Return
1867 * non-zero if the wand/spell had any effect.
1871 struct obj *obj, *otmp;
1873 int res = 1; /* affected object by default */
1874 boolean learn_it = FALSE, maybelearnit;
1876 /* fundamental: a wand effect hitting itself doesn't do anything;
1877 otherwise we need to guard against accessing otmp after something
1878 strange has happened to it (along the lines of polymorph or
1879 stone-to-flesh [which aren't good examples since polymorph wands
1880 aren't affected by polymorph zaps and stone-to-flesh isn't
1881 available in wand form, but the concept still applies...]) */
1886 /* The bypass bit is currently only used as follows:
1888 * POLYMORPH - When a monster being polymorphed drops something
1889 * from its inventory as a result of the change.
1890 * If the items fall to the floor, they are not
1891 * subject to direct subsequent polymorphing
1892 * themselves on that same zap. This makes it
1893 * consistent with items that remain in the
1894 * monster's inventory. They are not polymorphed
1896 * UNDEAD_TURNING - When an undead creature gets killed via
1897 * undead turning, prevent its corpse from being
1898 * immediately revived by the same effect.
1899 * STONE_TO_FLESH - If a statue can't be revived, its
1900 * contents get dropped before turning it into
1901 * meat; prevent those contents from being hit.
1902 * retouch_equipment() - bypass flag is used to track which
1903 * items have been handled (bhito isn't involved).
1904 * menu_drop(), askchain() - inventory traversal where multiple
1905 * Drop can alter the invent chain while traversal
1906 * is in progress (bhito isn't involved).
1908 * The bypass bit on all objects is reset each turn, whenever
1909 * context.bypasses is set.
1911 * We check the obj->bypass bit above AND context.bypasses
1912 * as a safeguard against any stray occurrence left in an obj
1913 * struct someplace, although that should never happen.
1915 if (context.bypasses) {
1918 debugpline1("%s for a moment.", Tobjnam(obj, "pulsate"));
1924 * Some parts of this function expect the object to be on the floor
1925 * obj->{ox,oy} to be valid. The exception to this (so far) is
1926 * for the STONE_TO_FLESH spell.
1928 if (!(obj->where == OBJ_FLOOR || otmp->otyp == SPE_STONE_TO_FLESH))
1929 impossible("bhito: obj is not floor or Stone To Flesh spell");
1933 } else if (obj == uchain) {
1934 if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
1940 switch (otmp->otyp) {
1943 if (obj->otyp == WAN_POLYMORPH || obj->otyp == SPE_POLYMORPH
1944 || obj->otyp == POT_POLYMORPH || obj_resists(obj, 5, 95)) {
1949 u.uconduct.polypiles++;
1950 /* any saved lock context will be dangerously obsolete */
1952 (void) boxlock(obj, otmp);
1954 if (obj_shudders(obj)) {
1956 ((obj == level.objects[u.ux][u.uy]) && u.uundetected
1957 && hides_under(youmonst.data));
1959 if (cansee(obj->ox, obj->oy))
1962 /* eek - your cover might have been blown */
1964 (void) hideunder(&youmonst);
1967 obj = poly_obj(obj, STRANGE_OBJECT);
1968 newsym(obj->ox, obj->oy);
1972 /* target object has now been "seen (up close)" */
1974 if (Is_container(obj) || obj->otyp == STATUE) {
1975 obj->cknown = obj->lknown = 1;
1977 boolean catbox = SchroedingersBox(obj);
1979 /* we don't want to force alive vs dead
1980 determination for Schroedinger's Cat here,
1981 so just make probing be inconclusive for it */
1985 pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
1987 pline("%s
\82Í
\8bó
\82Á
\82Û%s
\82¾
\81D", xname(obj), catbox ? "
\82Ì
\82æ
\82¤" : "");
1990 /* view contents (not recursively) */
1991 for (o = obj->cobj; o; o = o->nobj)
1992 o->dknown = 1; /* "seen", even if blind */
1993 (void) display_cinventory(obj);
2001 case SPE_FORCE_BOLT:
2002 /* learn the type if you see or hear something break
2003 (the sound could be implicit) */
2004 maybelearnit = cansee(obj->ox, obj->oy) || !Deaf;
2005 if (obj->otyp == BOULDER) {
2006 if (cansee(obj->ox, obj->oy))
2007 pline_The("boulder falls apart.");
2009 You_hear("a crumbling sound.");
2011 } else if (obj->otyp == STATUE) {
2012 if (break_statue(obj)) {
2013 if (cansee(obj->ox, obj->oy)) {
2015 pline_The("%s shatters.", rndmonnam(NULL));
2017 pline_The("statue shatters.");
2019 You_hear("a crumbling sound.");
2022 if (context.mon_moving
2023 ? !breaks(obj, obj->ox, obj->oy)
2024 : !hero_breaks(obj, obj->ox, obj->oy, FALSE))
2025 maybelearnit = FALSE; /* nothing broke */
2031 case WAN_CANCELLATION:
2032 case SPE_CANCELLATION:
2035 newsym(obj->ox, obj->oy); /* might change color */
2038 case SPE_DRAIN_LIFE:
2039 (void) drain_item(obj);
2041 case WAN_TELEPORTATION:
2042 case SPE_TELEPORT_AWAY:
2045 case WAN_MAKE_INVISIBLE:
2047 case WAN_UNDEAD_TURNING:
2048 case SPE_TURN_UNDEAD:
2049 if (obj->otyp == EGG) {
2051 } else if (obj->otyp == CORPSE) {
2052 int corpsenm = corpse_revive_type(obj);
2054 res = !!revive(obj, TRUE);
2055 if (res && Role_if(PM_HEALER)) {
2056 if (Hallucination && !Deaf) {
2057 You_hear("the sound of a defibrillator.");
2059 } else if (!Blind) {
2060 You("observe %s %s change dramatically.",
2061 s_suffix(an(mons[corpsenm].mname)),
2062 nonliving(&mons[corpsenm]) ? "motility"
2067 exercise(A_WIS, TRUE);
2074 case SPE_WIZARD_LOCK:
2076 res = boxlock(obj, otmp);
2082 case WAN_SLOW_MONSTER: /* no effect on objects */
2083 case SPE_SLOW_MONSTER:
2084 case WAN_SPEED_MONSTER:
2087 case SPE_EXTRA_HEALING:
2090 case SPE_STONE_TO_FLESH:
2091 res = stone_to_flesh_obj(obj);
2094 impossible("What an interesting effect (%d)", otmp->otyp);
2097 /* if effect was observable then discover the wand type provided
2098 that the wand itself has been seen */
2104 /* returns nonzero if something was hit */
2106 bhitpile(obj, fhito, tx, ty, zz)
2108 int FDECL((*fhito), (OBJ_P, OBJ_P));
2112 int hitanything = 0;
2113 register struct obj *otmp, *next_obj;
2115 if (obj->otyp == SPE_FORCE_BOLT || obj->otyp == WAN_STRIKING) {
2116 struct trap *t = t_at(tx, ty);
2118 /* We can't settle for the default calling sequence of
2119 bhito(otmp) -> break_statue(otmp) -> activate_statue_trap(ox,oy)
2120 because that last call might end up operating on our `next_obj'
2121 (below), rather than on the current object, if it happens to
2122 encounter a statue which mustn't become animated. */
2123 if (t && t->ttyp == STATUE_TRAP
2124 && activate_statue_trap(t, tx, ty, TRUE))
2129 for (otmp = level.objects[tx][ty]; otmp; otmp = next_obj) {
2130 next_obj = otmp->nexthere;
2131 /* for zap downwards, don't hit object poly'd hero is hiding under */
2132 if (zz > 0 && u.uundetected && otmp == level.objects[u.ux][u.uy]
2133 && hides_under(youmonst.data))
2136 hitanything += (*fhito)(otmp, obj);
2138 if (poly_zapped >= 0)
2139 create_polymon(level.objects[tx][ty], poly_zapped);
2145 * zappable - returns 1 if zap is available, 0 otherwise.
2146 * it removes a charge from the wand if zappable.
2147 * added by GAN 11/03/86
2151 register struct obj *wand;
2153 if (wand->spe < 0 || (wand->spe == 0 && rn2(121)))
2157 You("wrest one last charge from the worn-out wand.");
2159 You("
\8eg
\82¢
\82«
\82Á
\82½
\8fñ
\82©
\82ç
\8dÅ
\8cã
\82Ì
\97Í
\82ð
\82µ
\82Ú
\82è
\82Æ
\82Á
\82½
\81D");
2165 * zapnodir - zaps a NODIR wand/spell.
2166 * added by GAN 11/03/86
2170 register struct obj *obj;
2172 boolean known = FALSE;
2174 switch (obj->otyp) {
2180 if (lightdamage(obj, TRUE, 5))
2183 case WAN_SECRET_DOOR_DETECTION:
2184 case SPE_DETECT_UNSEEN:
2190 case WAN_CREATE_MONSTER:
2191 known = create_critters(rn2(23) ? 1 : rn1(7, 2),
2192 (struct permonst *) 0, FALSE);
2196 if (Luck + rn2(5) < 0) {
2198 pline("Unfortunately, nothing happens.");
2200 pline("
\8ec
\94O
\82È
\82ª
\82ç
\81C
\89½
\82à
\8bN
\82«
\82È
\82©
\82Á
\82½
\81D");
2205 case WAN_ENLIGHTENMENT:
2208 You_feel("self-knowledgeable...");
2210 You("
\8e©
\95ª
\8e©
\90g
\82ª
\94»
\82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D
\81D
\81D");
2211 display_nhwindow(WIN_MESSAGE, FALSE);
2212 enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
2214 pline_The("feeling subsides.");
2216 pline("
\82»
\82Ì
\8a´
\82¶
\82Í
\82È
\82
\82È
\82Á
\82½
\81D");
2217 exercise(A_WIS, TRUE);
2221 if (!objects[obj->otyp].oc_name_known)
2222 more_experienced(0, 10);
2223 /* effect was observable; discover the wand type provided
2224 that the wand itself has been seen */
2234 otmp->in_use = TRUE; /* in case losehp() is fatal */
2236 pline("%s suddenly explodes!", The(xname(otmp)));
2238 pline("%s
\82Í
\93Ë
\91R
\94\9a\94
\82µ
\82½
\81I", xname(otmp));
2239 dmg = d(otmp->spe + 2, 6);
2241 losehp(Maybe_Half_Phys(dmg), "exploding wand", KILLED_BY_AN);
2243 losehp(Maybe_Half_Phys(dmg), "
\8fñ
\82Ì
\94\9a\94
\82Å", KILLED_BY_AN);
2247 static NEARDATA const char zap_syms[] = { WAND_CLASS, 0 };
2249 /* 'z' command (or 'y' if numbed_pad==-1) */
2253 register struct obj *obj;
2256 if (check_capacity((char *) 0))
2258 obj = getobj(zap_syms, "zap");
2264 /* zappable addition done by GAN 11/03/86 */
2266 pline1(nothing_happens);
2267 else if (obj->cursed && !rn2(WAND_BACKFIRE_CHANCE)) {
2268 backfire(obj); /* the wand blows up in your face! */
2269 exercise(A_STR, FALSE);
2271 } else if (!(objects[obj->otyp].oc_dir == NODIR) && !getdir((char *) 0)) {
2274 pline("%s glows and fades.", The(xname(obj)));
2276 pline("%s
\82Í
\88ê
\8fu
\8bP
\82¢
\82½
\81D", The(xname(obj)));
2277 /* make him pay for knowing !NODIR */
2278 } else if (!u.dx && !u.dy && !u.dz
2279 && !(objects[obj->otyp].oc_dir == NODIR)) {
2280 if ((damage = zapyourself(obj, TRUE)) != 0) {
2283 Sprintf(buf, "zapped %sself with a wand", uhim());
2284 losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
2286 losehp(Maybe_Half_Phys(damage), "
\8e©
\95ª
\8e©
\90g
\82Ì
\8fñ
\82Ì
\97Í
\82ð
\97\81\82Ñ
\82Ä", NO_KILLER_PREFIX);
2290 /* Are we having fun yet?
2291 * weffects -> buzz(obj->otyp) -> zhitm (temple priest) ->
2292 * attack -> hitum -> known_hitum -> ghod_hitsu ->
2293 * buzz(AD_ELEC) -> destroy_item(WAND_CLASS) ->
2294 * useup -> obfree -> dealloc_obj -> free(obj)
2301 if (obj && obj->spe < 0) {
2303 pline("%s to dust.", Tobjnam(obj, "turn"));
2305 pline("%s
\82Í
\82¿
\82è
\82Æ
\82È
\82Á
\82½
\81D", xname(obj));
2308 update_inventory(); /* maybe used a charge */
2313 zapyourself(obj, ordinary)
2317 boolean learn_it = FALSE;
2320 switch (obj->otyp) {
2322 case SPE_FORCE_BOLT:
2325 shieldeff(u.ux, u.uy);
2329 pline("
\83{
\83C
\83\93\81I");
2333 You("bash yourself!");
2335 You("
\8e©
\95ª
\8e©
\90g
\82ð
\91Å
\82¿
\82Â
\82¯
\82½
\81I");
2338 damage = d(1 + obj->spe, 6);
2339 exercise(A_STR, FALSE);
2345 if (!Shock_resistance) {
2347 You("shock yourself!");
2349 You("
\93d
\8c\82\82ð
\82¤
\82¯
\82½
\81I");
2351 exercise(A_CON, FALSE);
2353 shieldeff(u.ux, u.uy);
2355 You("zap yourself, but seem unharmed.");
2357 You("
\8e©
\95ª
\82É
\8fñ
\82ð
\82Ó
\82è
\82©
\82´
\82µ
\82½
\82ª
\81C
\89ö
\89ä
\82Í
\82µ
\82È
\82©
\82Á
\82½
\82æ
\82¤
\82¾
\81D");
2358 ugolemeffects(AD_ELEC, d(12, 6));
2360 destroy_item(WAND_CLASS, AD_ELEC);
2361 destroy_item(RING_CLASS, AD_ELEC);
2362 (void) flashburn((long) rnd(100));
2367 You("explode a fireball on top of yourself!");
2369 Your("
\93ª
\8fã
\82Å
\89Î
\82Ì
\8bÊ
\82ª
\94\9a\94
\82µ
\82½
\81I");
2370 explode(u.ux, u.uy, 11, d(6, 6), WAND_CLASS, EXPL_FIERY);
2375 if (Fire_resistance) {
2376 shieldeff(u.ux, u.uy);
2378 You_feel("rather warm.");
2380 You("
\82¿
\82å
\82Á
\82Æ
\92g
\82©
\82
\8a´
\82¶
\82½
\81D");
2381 ugolemeffects(AD_FIRE, d(12, 6));
2384 pline("You've set yourself afire!");
2386 You("
\89\8a\82É
\82Â
\82Â
\82Ü
\82ê
\82½
\81I");
2390 (void) burnarmor(&youmonst);
2391 destroy_item(SCROLL_CLASS, AD_FIRE);
2392 destroy_item(POTION_CLASS, AD_FIRE);
2393 destroy_item(SPBOOK_CLASS, AD_FIRE);
2394 destroy_item(FOOD_CLASS, AD_FIRE); /* only slime for now */
2398 case SPE_CONE_OF_COLD:
2401 if (Cold_resistance) {
2402 shieldeff(u.ux, u.uy);
2404 You_feel("a little chill.");
2406 You("
\82¿
\82å
\82Á
\82Æ
\97â
\82½
\82
\8a´
\82¶
\82½
\81D");
2407 ugolemeffects(AD_COLD, d(12, 6));
2410 You("imitate a popsicle!");
2412 You("
\83A
\83C
\83X
\83L
\83\83\83\93\83f
\81[
\82Ì
\82æ
\82¤
\82É
\82È
\82Á
\82½
\81I");
2415 destroy_item(POTION_CLASS, AD_COLD);
2418 case WAN_MAGIC_MISSILE:
2419 case SPE_MAGIC_MISSILE:
2422 shieldeff(u.ux, u.uy);
2424 pline_The("missiles bounce!");
2426 pline("
\96\82\96@
\82Ì
\96î
\82Í
\82Í
\82Ë
\82©
\82¦
\82Á
\82½
\81I");
2430 pline("Idiot! You've shot yourself!");
2432 pline("
\89½
\82â
\82Á
\82Ä
\82ñ
\82¾
\81I
\82 \82È
\82½
\82Í
\8e©
\95ª
\8e©
\90g
\82ð
\8c\82\82Á
\82½
\81I");
2444 case WAN_CANCELLATION:
2445 case SPE_CANCELLATION:
2446 (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
2449 case SPE_DRAIN_LIFE:
2450 if (!Drain_resistance) {
2451 learn_it = TRUE; /* (no effect for spells...) */
2453 losexp("life drainage");
2455 losexp("
\90¶
\96½
\97Í
\82ð
\8bz
\8eû
\82³
\82ê
\82Ä");
2457 damage = 0; /* No additional damage */
2460 case WAN_MAKE_INVISIBLE: {
2461 /* have to test before changing HInvis but must change
2462 * HInvis before doing newsym().
2464 int msg = !Invis && !Blind && !BInvis;
2466 if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
2467 /* A mummy wrapping absorbs it and protects you */
2469 You_feel("rather itchy under %s.", yname(uarmc));
2471 You("%s
\82Ì
\89º
\82ª
\83\80\83Y
\83\80\83Y
\82µ
\82½
\81D", xname(uarmc));
2474 if (ordinary || !rn2(10)) { /* permanent */
2475 HInvis |= FROMOUTSIDE;
2476 } else { /* temporary */
2477 incr_itimeout(&HInvis, d(obj->spe, 250));
2482 self_invis_message();
2487 case WAN_SPEED_MONSTER:
2488 if (!(HFast & INTRINSIC)) {
2494 You("
\93®
\82«
\82ª
\91¬
\82
\82È
\82Á
\82½
\81D");
2497 Your("quickness feels more natural.");
2499 You("
\91¬
\82³
\82É
\8aµ
\82ê
\82Ä
\82«
\82½
\81D");
2500 exercise(A_DEX, TRUE);
2502 HFast |= FROMOUTSIDE;
2508 if (Sleep_resistance) {
2509 shieldeff(u.ux, u.uy);
2511 You("don't feel sleepy!");
2513 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81I");
2516 pline_The("sleep ray hits you!");
2518 pline("
\96°
\82è
\8cõ
\90ü
\82ª
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I");
2519 fall_asleep(-rnd(50), TRUE);
2523 case WAN_SLOW_MONSTER:
2524 case SPE_SLOW_MONSTER:
2525 if (HFast & (TIMEOUT | INTRINSIC)) {
2531 case WAN_TELEPORTATION:
2532 case SPE_TELEPORT_AWAY:
2534 /* same criteria as when mounted (zap_steed) */
2535 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2536 || distu(u.ux0, u.uy0) >= 16)
2541 case SPE_FINGER_OF_DEATH:
2542 if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
2543 pline((obj->otyp == WAN_DEATH)
2545 ? "The wand shoots an apparently harmless beam at you."
2547 ? "
\8fñ
\82Ì
\8cõ
\90ü
\82Í
\82Ç
\82¤
\82â
\82ç
\82 \82È
\82½
\82É
\89e
\8b¿
\82ð
\97^
\82¦
\82È
\82¢
\82à
\82Ì
\82Ì
\82æ
\82¤
\82¾
\81D"
2549 : "You seem no deader than before.");
2551 : "
\82 \82È
\82½
\82Í
\82±
\82ê
\88È
\8fã
\8e\80\82Ë
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
2556 Sprintf(killer.name, "shot %sself with a death ray", uhim());
2558 Strcpy(killer.name, "
\8e©
\95ª
\82ª
\8c\82\82Á
\82½
\8e\80\82Ì
\8cõ
\90ü
\82É
\82æ
\82Á
\82Ä");
2559 killer.format = NO_KILLER_PREFIX;
2561 You("irradiate yourself with pure energy!");
2563 You("
\83G
\83l
\83\8b\83M
\81[
\82ð
\8e©
\95ª
\8e©
\90g
\82É
\8fÆ
\8eË
\82µ
\82½
\81D");
2567 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D");
2568 /* They might survive with an amulet of life saving */
2571 case WAN_UNDEAD_TURNING:
2572 case SPE_TURN_UNDEAD:
2574 (void) unturn_dead(&youmonst);
2575 if (is_undead(youmonst.data)) {
2577 You_feel("frightened and %sstunned.",
2578 Stunned ? "even more " : "");
2580 You("
\8b°
\95|
\82µ%s
\82
\82ç
\82
\82ç
\82µ
\82½
\81D",
2581 Stunned ? "
\82³
\82ç
\82É" : "");
2583 make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
2586 You("shudder in dread.");
2588 You("
\8b°
\95|
\82Å
\90k
\82¦
\82½
\81D");
2591 case SPE_EXTRA_HEALING:
2592 learn_it = TRUE; /* (no effect for spells...) */
2593 healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE,
2594 (obj->otyp == SPE_EXTRA_HEALING));
2596 You_feel("%sbetter.", obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
2598 You("%s
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81D", obj->otyp == SPE_EXTRA_HEALING ? "
\82Æ
\82Ä
\82à" : "");
2600 case WAN_LIGHT: /* (broken wand) */
2601 /* assert( !ordinary ); */
2602 damage = d(obj->spe, 25);
2603 case EXPENSIVE_CAMERA:
2606 damage = lightdamage(obj, ordinary, damage);
2608 if (flashburn((long) damage))
2610 damage = 0; /* reset */
2618 if (u.utrap) { /* escape web or bear trap */
2619 (void) openholdingtrap(&youmonst, &learn_it);
2620 } else { /* trigger previously escaped trapdoor */
2621 (void) openfallingtrap(&youmonst, TRUE, &learn_it);
2625 case SPE_WIZARD_LOCK:
2627 (void) closeholdingtrap(&youmonst, &learn_it);
2632 case SPE_DETECT_UNSEEN:
2638 for (otmp = invent; otmp; otmp = otmp->nobj) {
2640 if (Is_container(otmp) || otmp->otyp == STATUE) {
2642 if (!SchroedingersBox(otmp))
2650 case SPE_STONE_TO_FLESH: {
2651 struct obj *otmp, *onxt;
2654 if (u.umonnum == PM_STONE_GOLEM) {
2656 (void) polymon(PM_FLESH_GOLEM);
2660 fix_petrification(); /* saved! */
2662 /* but at a cost.. */
2663 for (otmp = invent; otmp; otmp = onxt) {
2665 if (bhito(otmp, obj))
2669 * It is possible that we can now merge some inventory.
2670 * Do a highly paranoid merge. Restart from the beginning
2675 for (otmp = invent; !didmerge && otmp; otmp = otmp->nobj)
2676 for (onxt = otmp->nobj; onxt; onxt = onxt->nobj)
2677 if (merged(&otmp, &onxt)) {
2685 impossible("zapyourself: object %d used?", obj->otyp);
2688 /* if effect was observable then discover the wand type provided
2689 that the wand itself has been seen */
2695 /* called when poly'd hero uses breath attack against self */
2698 struct attack *mattk;
2700 int dtyp = 20 + mattk->adtyp - 1; /* breath by hero */
2701 const char *fltxt = flash_types[dtyp]; /* blast of <something> */
2703 zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
2706 /* light damages hero in gremlin form */
2708 lightdamage(obj, ordinary, amt)
2709 struct obj *obj; /* item making light (fake book if spell) */
2710 boolean ordinary; /* wand/camera zap vs wand destruction */
2711 int amt; /* pseudo-damage used to determine blindness duration */
2717 if (dmg && youmonst.data == &mons[PM_GREMLIN]) {
2718 /* reduce high values (from destruction of wand with many charges) */
2721 dmg = 10 + rnd(dmg - 10);
2724 pline("Ow, that light hurts%c", (dmg > 2 || u.mh <= 5) ? '!' : '.');
2725 /* [composing killer/reason is superfluous here; if fatal, cause
2726 of death will always be "killed while stuck in creature form"] */
2727 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2728 ordinary = FALSE; /* say blasted rather than zapped */
2729 how = (obj->oclass != SPBOOK_CLASS)
2730 ? (const char *) ansimpleoname(obj)
2732 Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2734 /* might rehumanize(); could be fatal, but only for Unchanging */
2735 losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2740 /* light[ning] causes blindness */
2745 if (!resists_blnd(&youmonst)) {
2746 You(are_blinded_by_the_flash);
2747 make_blinded(duration, FALSE);
2749 Your1(vision_clears);
2755 /* you've zapped a wand downwards while riding
2756 * Return TRUE if the steed was hit by the wand.
2757 * Return FALSE if the steed was not hit by the wand.
2761 struct obj *obj; /* wand or spell */
2763 int steedhit = FALSE;
2765 switch (obj->otyp) {
2767 * Wands that are allowed to hit the steed
2768 * Carefully test the results of any that are
2769 * moved here from the bottom section.
2772 probe_monster(u.usteed);
2776 case WAN_TELEPORTATION:
2777 case SPE_TELEPORT_AWAY:
2778 /* you go together */
2780 /* same criteria as when unmounted (zapyourself) */
2781 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2782 || distu(u.ux0, u.uy0) >= 16)
2787 /* Default processing via bhitm() for these */
2788 case SPE_CURE_SICKNESS:
2789 case WAN_MAKE_INVISIBLE:
2790 case WAN_CANCELLATION:
2791 case SPE_CANCELLATION:
2795 case SPE_FORCE_BOLT:
2796 case WAN_SLOW_MONSTER:
2797 case SPE_SLOW_MONSTER:
2798 case WAN_SPEED_MONSTER:
2800 case SPE_EXTRA_HEALING:
2801 case SPE_DRAIN_LIFE:
2804 (void) bhitm(u.usteed, obj);
2816 * cancel a monster (possibly the hero). inventory is cancelled only
2817 * if the monster is zapping itself directly, since otherwise the
2818 * effect is too strong. currently non-hero monsters do not zap
2819 * themselves with cancellation.
2822 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2823 register struct monst *mdef;
2824 register struct obj *obj;
2825 boolean youattack, allow_cancel_kill, self_cancel;
2827 boolean youdefend = (mdef == &youmonst);
2828 static const char writing_vanishes[] =
2830 "Some writing vanishes from %s head!";
2832 "
\89½
\82©
\82Ì
\95¶
\8e\9a\82ª%s
\82Ì
\93ª
\82©
\82ç
\8fÁ
\82¦
\82½
\81I";
2834 static const char your[] = "your"; /* should be extern */
2836 static const char your[] = "
\82 \82È
\82½"; /* should be extern */
2839 if (youdefend ? (!youattack && Antimagic)
2840 : resist(mdef, obj->oclass, 0, NOTELL))
2841 return FALSE; /* resisted cancellation */
2843 if (self_cancel) { /* 1st cancel inventory */
2846 for (otmp = (youdefend ? invent : mdef->minvent); otmp;
2850 context.botl = 1; /* potential AC change */
2855 /* now handle special cases */
2858 if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
2859 pline(writing_vanishes, your);
2863 Your("amulet grows hot for a moment, then cools.");
2865 Your("
\96\82\8f\9c\82¯
\82Í
\82µ
\82Î
\82ç
\82
\94M
\82
\82È
\82è
\81C
\82â
\82ª
\82Ä
\8c³
\82É
\96ß
\82Á
\82½
\81D");
2872 if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
2875 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
2876 if (canseemon(mdef))
2877 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
2879 if (allow_cancel_kill) {
2883 monkilled(mdef, "", AD_SPEL);
2890 /* you've zapped an immediate type wand up or down */
2893 struct obj *obj; /* wand or spell */
2895 boolean striking = FALSE, disclose = FALSE;
2896 int x, y, xx, yy, ptmp;
2902 /* some wands have special effects other than normal bhitpile */
2903 /* drawbridge might change <u.ux,u.uy> */
2904 x = xx = u.ux; /* <x,y> is zap location */
2905 y = yy = u.uy; /* <xx,yy> is drawbridge (portcullis) position */
2906 ttmp = t_at(x, y); /* trap if there is one */
2908 switch (obj->otyp) {
2913 You("probe towards the %s.", ceiling(x, y));
2915 You("
\8fã
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", ceiling(x,y));
2917 ptmp += bhitpile(obj, bhito, x, y, u.dz);
2919 You("probe beneath the %s.", surface(x, y));
2921 You("
\89º
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", surface(x,y));
2922 ptmp += display_binventory(x, y, TRUE);
2926 Your("probe reveals nothing.");
2928 pline("
\92²
\8d¸
\82Ì
\8c\8b\89Ê
\89½
\82à
\82Å
\82Ä
\82±
\82È
\82©
\82Á
\82½
\81D");
2929 return TRUE; /* we've done our own bhitpile */
2932 /* up or down, but at closed portcullis only */
2933 if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
2934 open_drawbridge(xx, yy);
2936 } else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
2937 /* can't use the stairs down to quest level 2 until
2938 leader "unlocks" them; give feedback if you try */
2939 on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
2941 pline_The("stairs seem to ripple momentarily.");
2943 pline("
\8aK
\92i
\82ª
\88ê
\8fu
\97h
\82ê
\82½
\82æ
\82¤
\82É
\8c©
\82¦
\82½
\81D");
2946 /* down will release you from bear trap or web */
2947 if (u.dz > 0 && u.utrap) {
2948 (void) openholdingtrap(&youmonst, &disclose);
2949 /* down will trigger trapdoor, hole, or [spiked-] pit */
2950 } else if (u.dz > 0 && !u.utrap) {
2951 (void) openfallingtrap(&youmonst, FALSE, &disclose);
2955 case SPE_FORCE_BOLT:
2959 case SPE_WIZARD_LOCK:
2960 /* down at open bridge or up or down at open portcullis */
2961 if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
2963 : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
2964 && find_drawbridge(&xx, &yy)) {
2966 close_drawbridge(xx, yy);
2968 destroy_drawbridge(xx, yy);
2970 } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
2971 && !Is_waterlevel(&u.uz) && !Underwater
2972 && !Is_qstart(&u.uz)) {
2974 /* similar to zap_dig() */
2976 pline("A rock is dislodged from the %s and falls on your %s.",
2977 ceiling(x, y), body_part(HEAD));
2979 pline("%s
\82©
\82ç
\8aâ
\82ª
\97\8e\82¿
\82Ä
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81D",
2980 ceiling(x, y), body_part(HEAD));
2982 dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
2984 losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
2986 losehp(Maybe_Half_Phys(dmg), "
\97\8e\8aâ
\82Å", KILLED_BY_AN);
2987 if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
2988 (void) xname(otmp); /* set dknown, maybe bknown */
2992 } else if (u.dz > 0 && ttmp) {
2993 if (!striking && closeholdingtrap(&youmonst, &disclose)) {
2994 ; /* now stuck in web or bear trap */
2995 } else if (striking && ttmp->ttyp == TRAPDOOR) {
2996 /* striking transforms trapdoor into hole */
2997 if (Blind && !ttmp->tseen) {
2999 pline("%s beneath you shatters.", Something);
3001 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\89½
\82©
\82ª
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3002 } else if (!ttmp->tseen) { /* => !Blind */
3004 pline("There's a trapdoor beneath you; it shatters.");
3006 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82Í
\97\8e\82µ
\94à
\82ª
\82 \82Á
\82½
\81G
\82»
\82ê
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3009 pline("The trapdoor beneath you shatters.");
3011 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\97\8e\82µ
\94à
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3017 /* might fall down hole */
3019 } else if (!striking && ttmp->ttyp == HOLE) {
3020 /* locking transforms hole into trapdoor */
3021 ttmp->ttyp = TRAPDOOR;
3022 if (Blind || !ttmp->tseen) {
3024 pline("Some %s swirls beneath you.",
3025 is_ice(x, y) ? "frost" : "dust");
3027 pline("
\82 \82È
\82½
\82Ì
\89º
\82Å%s
\82ª
\82¤
\82¸
\82ð
\8aª
\82
\82Ì
\82ª
\8c©
\82¦
\82½
\81D",
3028 is_ice(x,y) ? "
\91\9a" : "
\82Ù
\82±
\82è");
3034 pline("A trapdoor appears beneath you.");
3036 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\97\8e\82µ
\94à
\82ª
\82 \82ç
\82í
\82ê
\82½
\81D");
3039 /* hadn't fallen down hole; won't fall now */
3043 case SPE_STONE_TO_FLESH:
3044 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3045 || (Is_qstart(&u.uz) && u.dz < 0)) {
3046 pline1(nothing_happens);
3047 } else if (u.dz < 0) { /* we should do more... */
3049 pline("Blood drips on your %s.", body_part(FACE));
3051 pline("
\8c\8c\82ª
\82 \82È
\82½
\82Ì%s
\82Ö
\82µ
\82½
\82½
\82è
\97\8e\82¿
\82Ä
\82«
\82½
\81D", body_part(FACE));
3052 } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3054 Print this message only if there wasn't an engraving
3055 affected here. If water or ice, act like waterlevel case.
3057 e = engr_at(u.ux, u.uy);
3058 if (!(e && e->engr_type == ENGRAVE)) {
3059 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3060 pline1(nothing_happens);
3063 pline("Blood %ss %s your %s.",
3064 is_lava(u.ux, u.uy) ? "boil" : "pool",
3065 Levitation ? "beneath" : "at",
3066 makeplural(body_part(FOOT)));
3069 makeplural(body_part(FOOT)),
3070 Levitation ? "
\82Ì
\89º" : "
\8c³",
3071 is_lava(u.ux, u.uy) ?
3072 "
\82Å
\8c\8c\82ª
\95¦
\93«
\82µ
\82½" : "
\82É
\8c\8c\82¾
\82Ü
\82è
\82ª
\8fo
\97\88\82½");
3082 /* zapping downward */
3083 (void) bhitpile(obj, bhito, x, y, u.dz);
3085 /* subset of engraving effects; none sets `disclose' */
3086 if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3087 switch (obj->otyp) {
3091 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3093 case WAN_CANCELLATION:
3094 case SPE_CANCELLATION:
3095 case WAN_MAKE_INVISIBLE:
3098 case WAN_TELEPORTATION:
3099 case SPE_TELEPORT_AWAY:
3102 case SPE_STONE_TO_FLESH:
3103 if (e->engr_type == ENGRAVE) {
3104 /* only affects things in stone */
3106 pline_The(Hallucination
3107 ? "floor runs like butter!"
3108 : "edges on the floor get smoother.");
3111 ? "
\8f°
\82ª
\83o
\83^
\81[
\82Ì
\82æ
\82¤
\82É
\91\96\82Á
\82Ä
\82¢
\82Á
\82½
\81I"
3112 : "
\8f°
\82Ì
\89\8f\82ª
\82È
\82ß
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D");
3114 wipe_engr_at(x, y, d(2, 4), TRUE);
3118 case SPE_FORCE_BOLT:
3119 wipe_engr_at(x, y, d(2, 4), TRUE);
3125 } else if (u.dz < 0) {
3126 /* zapping upward */
3128 /* game flavor: if you're hiding under "something"
3129 * a zap upward should hit that "something".
3131 if (u.uundetected && hides_under(youmonst.data)) {
3133 otmp = level.objects[u.ux][u.uy];
3136 hitit = bhito(otmp, obj);
3138 (void) hideunder(&youmonst);
3147 /* used by do_break_wand() was well as by weffects() */
3157 /* if do_osshock() set obj_zapped while polying, give a message now */
3160 You_feel("shuddering vibrations.");
3162 You("
\82¼
\82Á
\82Æ
\82·
\82é
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
3166 /* called for various wand and spell effects - M. Stephenson */
3171 int otyp = obj->otyp;
3172 boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3174 exercise(A_WIS, TRUE);
3175 if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3176 && (u.dz > 0) && zap_steed(obj)) {
3178 } else if (objects[otyp].oc_dir == IMMEDIATE) {
3179 zapsetup(); /* reset obj_zapped */
3181 (void) bhitm(u.ustuck, obj);
3182 /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3184 disclose = zap_updown(obj);
3186 (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3189 zapwrapup(); /* give feedback for obj_zapped */
3191 } else if (objects[otyp].oc_dir == NODIR) {
3195 /* neither immediate nor directionless */
3197 if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3199 else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3200 buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3202 else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3203 buzz(otyp - WAN_MAGIC_MISSILE,
3204 (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3206 impossible("weffects: unexpected spell or wand");
3212 more_experienced(0, 10);
3217 /* augment damage for a spell dased on the hero's intelligence (and level) */
3219 spell_damage_bonus(dmg)
3220 int dmg; /* base amount to be adjusted by bonus or penalty */
3222 int intell = ACURR(A_INT);
3224 /* Punish low intelligence before low level else low intelligence
3225 gets punished only when high level */
3227 /* -3 penalty, but never reduce combined amount below 1
3228 (if dmg is 0 for some reason, we're careful to leave it there) */
3230 dmg = (dmg <= 3) ? 1 : dmg - 3;
3231 } else if (intell <= 13 || u.ulevel < 5)
3232 ; /* no bonus or penalty; dmg remains same */
3233 else if (intell <= 18)
3235 else if (intell <= 24 || u.ulevel < 14)
3238 dmg += 3; /* Int 25 */
3244 * Generate the to hit bonus for a spell. Based on the hero's skill in
3245 * spell class and dexterity.
3248 spell_hit_bonus(skill)
3252 int dex = ACURR(A_DEX);
3254 switch (P_SKILL(spell_skilltype(skill))) {
3255 case P_ISRESTRICTED:
3277 /* Will change when print stuff below removed */
3280 /* Even increment for dextrous heroes (see weapon.c abon) */
3281 hit_bon += dex - 14;
3290 /* force == 0 occurs e.g. with sleep ray */
3291 /* note that large force is usual with wands so that !! would
3292 require information about hand/weapon/wand */
3294 return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3296 return (const char *) ((force < 0) ? "
\81H" : (force <= 4) ? "
\81D" : "
\81I");
3300 hit(str, mtmp, force)
3303 const char *force; /* usually either "." or "!" */
3305 if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3306 && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3308 pline("%s %s it.", The(str), vtense(str, "hit"));
3310 pline("%s
\82Í
\89½
\82©
\82É
\96½
\92\86\82µ
\82½
\81D", str);
3313 pline("%s %s %s%s", The(str), vtense(str, "hit"),
3314 mon_nam(mtmp), force);
3316 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", str,
3317 mon_nam(mtmp), force);
3323 register const char *str;
3324 register struct monst *mtmp;
3328 "%s %s %s.", The(str), vtense(str, "miss"),
3329 ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3334 "%s
\82Ì%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\82Í
\82¸
\82ê
\82½
\81D", str,
3335 ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3342 skiprange(range, skipstart, skipend)
3343 int range, *skipstart, *skipend;
3345 int tr = (range / 4);
3346 int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3348 *skipend = tmp - ((tmp / 4) * rnd(3));
3349 if (*skipend >= tmp)
3354 * Called for the following distance effects:
3355 * when a weapon is thrown (weapon == THROWN_WEAPON)
3356 * when an object is kicked (KICKED_WEAPON)
3357 * when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3358 * when a light beam is flashed (FLASHED_LIGHT)
3359 * when a mirror is applied (INVIS_BEAM)
3360 * A thrown/kicked object falls down at end of its range or when a monster
3361 * is hit. The variable 'bhitpos' is set to the final position of the weapon
3362 * thrown/zapped. The ray of a wand may affect (by calling a provided
3363 * function) several objects and monsters on its path. The return value
3364 * is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3366 * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3367 * destroyed and *pobj set to NULL to indicate this.
3369 * Check !u.uswallow before calling bhit().
3370 * This function reveals the absence of a remembered invisible monster in
3371 * necessary cases (throwing or kicking weapons). The presence of a real
3372 * one is revealed for a weapon, but if not a weapon is left up to fhitm().
3375 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3376 register int ddx, ddy, range; /* direction and range */
3377 int weapon; /* see values in hack.h */
3378 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3379 FDECL((*fhito), (OBJ_P, OBJ_P));
3380 struct obj **pobj; /* object tossed/used, set to NULL
3381 * if object is destroyed */
3384 struct obj *obj = *pobj;
3386 boolean shopdoor = FALSE, point_blank = TRUE;
3387 boolean in_skip = FALSE, allow_skip = FALSE;
3388 int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3390 if (weapon == KICKED_WEAPON) {
3391 /* object starts one square in front of player */
3392 bhitpos.x = u.ux + ddx;
3393 bhitpos.y = u.uy + ddy;
3400 if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3401 skiprange(range, &skiprange_start, &skiprange_end);
3402 allow_skip = !rn2(3);
3405 if (weapon == FLASHED_LIGHT) {
3406 tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3407 } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3408 tmp_at(DISP_FLASH, obj_to_glyph(obj));
3410 while (range-- > 0) {
3424 if (is_pick(obj) && inside_shop(x, y)
3425 && (mtmp = shkcatch(obj, x, y))) {
3426 tmp_at(DISP_END, 0);
3430 typ = levl[bhitpos.x][bhitpos.y].typ;
3432 /* iron bars will block anything big enough */
3433 if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3434 && typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
3435 point_blank ? 0 : !rn2(5), 1)) {
3436 /* caveat: obj might now be null... */
3443 if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3444 boolean learn_it = FALSE;
3446 switch (obj->otyp) {
3449 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3450 if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3452 open_drawbridge(x, y);
3456 case SPE_WIZARD_LOCK:
3457 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3458 && levl[x][y].typ == DRAWBRIDGE_DOWN)
3460 close_drawbridge(x, y);
3463 case SPE_FORCE_BOLT:
3464 if (typ != DRAWBRIDGE_UP)
3465 destroy_drawbridge(x, y);
3473 mtmp = m_at(bhitpos.x, bhitpos.y);
3478 * skiprange_start is only set if this is a thrown rock
3480 if (skiprange_start && (range == skiprange_start) && allow_skip) {
3481 if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3484 pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3485 skipcount ? " again" : "");
3487 You_hear("%s skip.", yname(obj));
3489 } else if (skiprange_start > skiprange_end + 1) {
3494 if (range <= skiprange_end) {
3496 if (range > 3) /* another bounce? */
3497 skiprange(range, &skiprange_start, &skiprange_end);
3498 } else if (mtmp && M_IN_WATER(mtmp->data)) {
3499 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3500 pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3505 if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3506 notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3507 if (weapon == FLASHED_LIGHT) {
3508 /* FLASHED_LIGHT hitting invisible monster should
3509 pass through instead of stop so we call
3510 flash_hits_mon() directly rather than returning
3511 mtmp back to caller. That allows the flash to
3512 keep on going. Note that we use mtmp->minvis
3513 not canspotmon() because it makes no difference
3514 whether the hero can see the monster or not. */
3516 obj->ox = u.ux, obj->oy = u.uy;
3517 (void) flash_hits_mon(mtmp, obj);
3519 tmp_at(DISP_END, 0);
3520 return mtmp; /* caller will call flash_hits_mon */
3522 } else if (weapon == INVIS_BEAM) {
3523 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3524 through invisible targets; unlike it, we aren't
3525 prepared for multiple hits so just get first one
3526 that's either visible or could see its invisible
3527 self. [No tmp_at() cleanup is needed here.] */
3528 if (!mtmp->minvis || perceives(mtmp->data))
3530 } else if (weapon != ZAPPED_WAND) {
3531 /* THROWN_WEAPON, KICKED_WEAPON */
3532 tmp_at(DISP_END, 0);
3533 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3534 map_invisible(bhitpos.x, bhitpos.y);
3538 (*fhitm)(mtmp, obj);
3542 if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3543 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3544 unmap_object(bhitpos.x, bhitpos.y);
3549 if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3552 if (weapon == KICKED_WEAPON
3553 && ((obj->oclass == COIN_CLASS
3554 && OBJ_AT(bhitpos.x, bhitpos.y))
3555 || ship_object(obj, bhitpos.x, bhitpos.y,
3556 costly_spot(bhitpos.x, bhitpos.y)))) {
3557 tmp_at(DISP_END, 0);
3558 return (struct monst *) 0;
3561 if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3562 switch (obj->otyp) {
3567 case SPE_WIZARD_LOCK:
3568 case SPE_FORCE_BOLT:
3569 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3570 if (cansee(bhitpos.x, bhitpos.y)
3571 || (obj->otyp == WAN_STRIKING && !Deaf))
3573 if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3574 && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3576 add_damage(bhitpos.x, bhitpos.y, 400L);
3582 if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3587 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3588 /* 'I' present but no monster: erase */
3589 /* do this before the tmp_at() */
3590 if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3592 unmap_object(bhitpos.x, bhitpos.y);
3595 tmp_at(bhitpos.x, bhitpos.y);
3597 /* kicked objects fall in pools */
3598 if ((weapon == KICKED_WEAPON)
3599 && (is_pool(bhitpos.x, bhitpos.y)
3600 || is_lava(bhitpos.x, bhitpos.y)))
3602 if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3603 break; /* physical objects fall onto sink */
3605 /* limit range of ball so hero won't make an invalid move */
3606 if (weapon == THROWN_WEAPON && range > 0
3607 && obj->otyp == HEAVY_IRON_BALL) {
3610 if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3613 pline("%s hits %s.", The(distant_name(obj, xname)),
3616 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", distant_name(obj, xname),
3620 } else if (obj == uball) {
3621 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3622 /* nb: it didn't hit anything directly */
3625 pline("%s jerks to an abrupt halt.",
3626 The(distant_name(obj, xname))); /* lame */
3628 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\83K
\83N
\83\93\82Æ
\8e~
\82Ü
\82Á
\82½
\81D",
3629 distant_name(obj, xname)); /* lame */
3632 } else if (Sokoban && (t = t_at(x, y)) != 0
3633 && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3634 || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3635 /* hero falls into the trap, so ball stops */
3641 /* thrown/kicked missile has moved away from its starting spot */
3642 point_blank = FALSE; /* affects passing through iron bars */
3645 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3646 tmp_at(DISP_END, 0);
3650 pay_for_damage("destroy", FALSE);
3652 pay_for_damage("
\94j
\89ó
\82·
\82é", FALSE);
3654 return (struct monst *) 0;
3657 /* process thrown boomerang, which travels a curving path...
3658 * A multi-shot volley ought to have all missiles in flight at once,
3659 * but we're called separately for each one. We terminate the volley
3660 * early on a failed catch since continuing to throw after being hit
3661 * is too obviously silly.
3664 boomhit(obj, dx, dy)
3669 int boom; /* showsym[] index */
3671 boolean counterclockwise = TRUE; /* right-handed throw */
3673 /* counterclockwise traversal patterns:
3674 * ..........................54.................................
3675 * ..................43.....6..3....765.........................
3676 * ..........32.....5..2...7...2...8...4....87..................
3677 * .........4..1....6..1...8..1....9...3...9..6.....98..........
3678 * ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3679 * .3...9....6..9....89.....................1..4...1..6....1..8.
3680 * .4...8.....78.............................23....2..5...2...7.
3681 * ..567............................................34....3..6..
3682 * ........................................................45...
3683 * (invert rows for corresponding clockwise patterns)
3688 boom = counterclockwise ? S_boomleft : S_boomright;
3689 for (i = 0; i < 8; i++)
3690 if (xdir[i] == dx && ydir[i] == dy)
3692 tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3693 for (ct = 0; ct < 10; ct++) {
3694 i = (i + 8) % 8; /* 0..7 (8 -> 0, -1 -> 7) */
3695 boom = (S_boomleft + S_boomright - boom); /* toggle */
3696 tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3701 if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3703 tmp_at(DISP_END, 0);
3706 if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3707 || closed_door(bhitpos.x, bhitpos.y)) {
3712 if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3713 if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3714 /* we hit ourselves */
3715 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), obj,
3719 "
\83u
\81[
\83\81\83\89\83\93");
3722 } else { /* we catch it */
3723 tmp_at(DISP_END, 0);
3725 You("skillfully catch the boomerang.");
3727 You("
\8fã
\8eè
\82É
\83u
\81[
\83\81\83\89\83\93\82ð
\92Í
\82Ü
\82¦
\82½
\81D");
3731 tmp_at(bhitpos.x, bhitpos.y);
3733 if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3736 break; /* boomerang falls on sink */
3738 /* ct==0, initial position, we want next delta to be same;
3739 ct==5, opposite position, repeat delta undoes first one */
3741 i += (counterclockwise ? -1 : 1);
3743 tmp_at(DISP_END, 0); /* do not leave last symbol */
3744 return (struct monst *) 0;
3747 /* used by buzz(); also used by munslime(muse.c); returns damage to mon */
3749 zhitm(mon, type, nd, ootmp)
3750 register struct monst *mon;
3751 register int type, nd;
3752 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3754 register int tmp = 0;
3755 register int abstype = abs(type) % 10;
3756 boolean sho_shieldeff = FALSE;
3757 boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3759 *ootmp = (struct obj *) 0;
3761 case ZT_MAGIC_MISSILE:
3762 if (resists_magm(mon)) {
3763 sho_shieldeff = TRUE;
3768 tmp = spell_damage_bonus(tmp);
3771 if (resists_fire(mon)) {
3772 sho_shieldeff = TRUE;
3776 if (resists_cold(mon))
3779 tmp = spell_damage_bonus(tmp);
3780 if (burnarmor(mon)) {
3782 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3784 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3786 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3787 destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3791 if (resists_cold(mon)) {
3792 sho_shieldeff = TRUE;
3796 if (resists_fire(mon))
3799 tmp = spell_damage_bonus(tmp);
3801 (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3805 (void) sleep_monst(mon, d(nd, 25),
3806 type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3808 case ZT_DEATH: /* death/disintegration */
3809 if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3810 if (mon->data == &mons[PM_DEATH]) {
3811 mon->mhpmax += mon->mhpmax / 2;
3812 if (mon->mhpmax >= MAGIC_COOKIE)
3813 mon->mhpmax = MAGIC_COOKIE - 1;
3814 mon->mhp = mon->mhpmax;
3818 if (nonliving(mon->data) || is_demon(mon->data)
3819 || is_vampshifter(mon) || resists_magm(mon)) {
3820 /* similar to player */
3821 sho_shieldeff = TRUE;
3824 type = -1; /* so they don't get saving throws */
3828 if (resists_disint(mon)) {
3829 sho_shieldeff = TRUE;
3830 } else if (mon->misc_worn_check & W_ARMS) {
3831 /* destroy shield; victim survives */
3832 *ootmp = which_armor(mon, W_ARMS);
3833 } else if (mon->misc_worn_check & W_ARM) {
3834 /* destroy body armor, also cloak if present */
3835 *ootmp = which_armor(mon, W_ARM);
3836 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
3837 m_useup(mon, otmp2);
3839 /* no body armor, victim dies; destroy cloak
3840 and shirt now in case target gets life-saved */
3842 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
3843 m_useup(mon, otmp2);
3844 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
3845 m_useup(mon, otmp2);
3847 type = -1; /* no saving throw wanted */
3848 break; /* not ordinary damage */
3853 if (resists_elec(mon)) {
3854 sho_shieldeff = TRUE;
3856 /* can still blind the monster */
3860 tmp = spell_damage_bonus(tmp);
3861 if (!resists_blnd(mon)
3862 && !(type > 0 && u.uswallow && mon == u.ustuck)) {
3863 register unsigned rnd_tmp = rnd(50);
3865 if ((mon->mblinded + rnd_tmp) > 127)
3866 mon->mblinded = 127;
3868 mon->mblinded += rnd_tmp;
3871 (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
3872 /* not actually possible yet */
3874 (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
3877 if (resists_poison(mon)) {
3878 sho_shieldeff = TRUE;
3884 if (resists_acid(mon)) {
3885 sho_shieldeff = TRUE;
3890 acid_damage(MON_WEP(mon));
3892 erode_armor(mon, ERODE_CORRODE);
3896 shieldeff(mon->mx, mon->my);
3897 if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
3899 if (tmp > 0 && type >= 0
3900 && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
3903 tmp = 0; /* don't allow negative damage */
3904 debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
3911 zhitu(type, nd, fltxt, sx, sy)
3916 int dam = 0, abstyp = abs(type);
3920 Sprintf(buf, "%s
\82É
\82æ
\82Á
\82Ä", fltxt);
3924 switch (abstyp % 10) {
3925 case ZT_MAGIC_MISSILE:
3929 pline_The("missiles bounce off!");
3931 pline("
\96\82\96@
\82Ì
\96î
\82Í
\94½
\8eË
\82µ
\82½
\81I");
3934 exercise(A_STR, FALSE);
3938 if (Fire_resistance) {
3941 You("don't feel hot!");
3943 You("
\94M
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81I");
3944 ugolemeffects(AD_FIRE, d(nd, 6));
3949 if (burnarmor(&youmonst)) { /* "body hit" */
3951 destroy_item(POTION_CLASS, AD_FIRE);
3953 destroy_item(SCROLL_CLASS, AD_FIRE);
3955 destroy_item(SPBOOK_CLASS, AD_FIRE);
3956 destroy_item(FOOD_CLASS, AD_FIRE);
3960 if (Cold_resistance) {
3963 You("don't feel cold.");
3965 You("
\97â
\82½
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81D");
3966 ugolemeffects(AD_COLD, d(nd, 6));
3971 destroy_item(POTION_CLASS, AD_COLD);
3974 if (Sleep_resistance) {
3975 shieldeff(u.ux, u.uy);
3977 You("don't feel sleepy.");
3979 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81D");
3981 fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
3985 if (abstyp == ZT_BREATH(ZT_DEATH)) {
3986 if (Disint_resistance) {
3988 You("are not disintegrated.");
3990 You("
\95ª
\89ð
\82³
\82ê
\82È
\82¢
\81D");
3993 /* destroy shield; other possessions are safe */
3994 (void) destroy_arm(uarms);
3997 /* destroy suit; if present, cloak goes too */
3999 (void) destroy_arm(uarmc);
4000 (void) destroy_arm(uarm);
4003 /* no shield or suit, you're dead; wipe out cloak
4004 and/or shirt in case of life-saving or bones */
4006 (void) destroy_arm(uarmc);
4008 (void) destroy_arm(uarmu);
4009 } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4012 You("seem unaffected.");
4014 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
4016 } else if (Antimagic) {
4019 You("aren't affected.");
4021 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4024 killer.format = KILLED_BY_AN;
4025 Strcpy(killer.name, fltxt ? fltxt : "");
4026 /* when killed by disintegration breath, don't leave corpse */
4027 u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4029 return; /* lifesaved */
4031 if (Shock_resistance) {
4034 You("aren't affected.");
4036 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4037 ugolemeffects(AD_ELEC, d(nd, 6));
4040 exercise(A_CON, FALSE);
4043 destroy_item(WAND_CLASS, AD_ELEC);
4045 destroy_item(RING_CLASS, AD_ELEC);
4049 poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4051 poisoned("
\91§", A_DEX, "
\93Å
\82Ì
\91§", 15, FALSE);
4054 if (Acid_resistance) {
4056 pline_The("acid doesn't hurt.");
4058 pline("
\8e_
\82Å
\82Í
\8f\9d\82Â
\82©
\82È
\82©
\82Á
\82½
\81D");
4062 pline_The("acid burns!");
4064 pline("
\8e_
\82Å
\8fÄ
\82¯
\82½
\81I");
4066 exercise(A_STR, FALSE);
4068 /* using two weapons at once makes both of them more vulnerable */
4069 if (!rn2(u.twoweap ? 3 : 6))
4071 if (u.twoweap && !rn2(3))
4072 acid_damage(uswapwep);
4074 erode_armor(&youmonst, ERODE_CORRODE);
4078 /* Half_spell_damage protection yields half-damage for wands & spells,
4079 including hero's own ricochets; breath attacks do full damage */
4080 if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4081 dam = (dam + 1) / 2;
4082 losehp(dam, fltxt, KILLED_BY_AN);
4087 * burn objects (such as scrolls and spellbooks) on floor
4088 * at position x,y; return the number of objects burned
4091 burn_floor_objects(x, y, give_feedback, u_caused)
4093 boolean give_feedback; /* caller needs to decide about visibility checks */
4096 struct obj *obj, *obj2;
4097 long i, scrquan, delquan;
4098 char buf1[BUFSZ], buf2[BUFSZ];
4101 for (obj = level.objects[x][y]; obj; obj = obj2) {
4102 obj2 = obj->nexthere;
4103 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4104 || (obj->oclass == FOOD_CLASS
4105 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4106 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4107 || obj_resists(obj, 2, 100))
4109 scrquan = obj->quan; /* number present */
4110 delquan = 0L; /* number to destroy */
4111 for (i = scrquan; i > 0L; i--)
4115 /* save name before potential delobj() */
4116 if (give_feedback) {
4118 Strcpy(buf1, (x == u.ux && y == u.uy)
4120 : distant_name(obj, xname));
4122 Strcpy(buf2, (x == u.ux && y == u.uy)
4124 : distant_name(obj, xname));
4125 obj->quan = scrquan;
4127 /* useupf(), which charges, only if hero caused damage */
4129 useupf(obj, delquan);
4130 else if (delquan < scrquan)
4131 obj->quan -= delquan;
4135 if (give_feedback) {
4138 pline("%ld %s burn.", delquan, buf2);
4140 pline("%ld%s
\82Ì%s
\82ª
\94R
\82¦
\82½
\81D",
4142 obj->oclass == SCROLL_CLASS ? "
\96\87" : "
\8dû",
4147 pline("%s burns.", An(buf1));
4149 pline("%s
\82Í
\94R
\82¦
\82½
\81D", buf1);
4157 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4161 int type; /* either hero cast spell type or 0 */
4163 int chance = rn2(20);
4164 int spell_bonus = type ? spell_hit_bonus(type) : 0;
4166 /* small chance for naked target to avoid being hit */
4168 return rnd(10) < ac + spell_bonus;
4170 /* very high armor protection does not achieve invulnerability */
4173 return (3 - chance < ac + spell_bonus);
4177 disintegrate_mon(mon, type, fltxt)
4179 int type; /* hero vs other */
4182 struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4184 if (canseemon(mon)) {
4187 pline("%s is disintegrated!", Monnam(mon));
4189 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I", Monnam(mon));
4192 hit(fltxt, mon, "!");
4194 hit(fltxt, mon, "
\81I");
4197 /* note: worn amulet of life saving must be preserved in order to operate */
4198 #define oresist_disintegration(obj) \
4199 (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4200 || is_quest_artifact(obj) || obj == m_amulet)
4202 for (otmp = mon->minvent; otmp; otmp = otmp2) {
4204 if (!oresist_disintegration(otmp)) {
4205 if (otmp->owornmask) {
4206 /* in case monster's life gets saved */
4207 mon->misc_worn_check &= ~otmp->owornmask;
4208 if (otmp->owornmask & W_WEP)
4209 setmnotwielded(mon, otmp);
4210 /* also dismounts hero if this object is steed's saddle */
4211 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4212 otmp->owornmask = 0L;
4214 obj_extract_self(otmp);
4215 obfree(otmp, (struct obj *) 0);
4219 #undef oresist_disintegration
4222 monkilled(mon, (char *) 0, -AD_RBRE);
4228 * type == 0 to 9 : you shooting a wand
4229 * type == 10 to 19 : you casting a spell
4230 * type == 20 to 29 : you breathing as a monster
4231 * type == -10 to -19 : monster casting spell
4232 * type == -20 to -29 : monster breathing at you
4233 * type == -30 to -39 : monster shooting a wand
4234 * called with dx = dy = 0 with vertical bolts
4237 buzz(type, nd, sx, sy, dx, dy)
4238 register int type, nd;
4239 register xchar sx, sy;
4240 register int dx, dy;
4242 int range, abstype = abs(type) % 10;
4244 register xchar lsx, lsy;
4247 boolean shopdamage = FALSE;
4252 /* if its a Hero Spell then get its SPE_TYPE */
4253 spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4255 fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4261 tmp = zhitm(u.ustuck, type, nd, &otmp);
4266 pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4269 pline("%s
\82Í%s
\82ð
\82Ð
\82«
\82³
\82¢
\82½%s", fltxt, mon_nam(u.ustuck),
4272 /* Using disintegration from the inside only makes a hole... */
4273 if (tmp == MAGIC_COOKIE)
4275 if (u.ustuck->mhp < 1)
4282 if (dx == 0 && dy == 0)
4284 save_bhitpos = bhitpos;
4286 tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4287 while (range-- > 0) {
4292 if (isok(sx, sy) && (lev = &levl[sx][sy])->typ) {
4294 if (cansee(sx, sy)) {
4295 /* reveal/unreveal invisible monsters before tmp_at() */
4296 if (mon && !canspotmon(mon))
4297 map_invisible(sx, sy);
4298 else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
4299 unmap_object(sx, sy);
4302 if (ZAP_POS(lev->typ) || (isok(lsx, lsy) && cansee(lsx, lsy)))
4304 delay_output(); /* wait a little */
4309 /* hit() and miss() need bhitpos to match the target */
4310 bhitpos.x = sx, bhitpos.y = sy;
4311 /* Fireballs only damage when they explode */
4312 if (type != ZT_SPELL(ZT_FIRE))
4313 range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4316 if (type == ZT_SPELL(ZT_FIRE))
4319 mon->mstrategy &= ~STRAT_WAITMASK;
4321 if (zap_hit(find_mac(mon), spell_type)) {
4322 if (mon_reflects(mon, (char *) 0)) {
4323 if (cansee(mon->mx, mon->my)) {
4324 hit(fltxt, mon, exclam(0));
4325 shieldeff(mon->mx, mon->my);
4327 (void) mon_reflects(mon,
4328 "But it reflects from %s %s!");
4330 (void) mon_reflects(mon,
4331 "
\82µ
\82©
\82µ
\82»
\82ê
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81I");
4337 boolean mon_could_move = mon->mcanmove;
4338 int tmp = zhitm(mon, type, nd, &otmp);
4340 if (is_rider(mon->data)
4341 && abs(type) == ZT_BREATH(ZT_DEATH)) {
4342 if (canseemon(mon)) {
4343 hit(fltxt, mon, ".");
4345 pline("%s disintegrates.", Monnam(mon));
4347 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D", Monnam(mon));
4349 pline("%s body reintegrates before your %s!",
4350 s_suffix(Monnam(mon)),
4351 (eyecount(youmonst.data) == 1)
4353 : makeplural(body_part(EYE)));
4355 pline("%s
\82Ì
\91Ì
\82Í
\82 \82È
\82½
\82Ì
\96Ú
\82Ì
\91O
\82Å
\8dÄ
\8c\8b\8d\87\82µ
\82½
\81I",
4359 pline("%s resurrects!", Monnam(mon));
4361 pline("%s
\82Í
\91h
\82Á
\82½
\81I", Monnam(mon));
4363 mon->mhp = mon->mhpmax;
4364 break; /* Out of while loop */
4366 if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4367 if (canseemon(mon)) {
4369 hit(fltxt, mon, ".");
4371 hit(fltxt, mon, "
\81D");
4373 pline("%s absorbs the deadly %s!", Monnam(mon),
4374 type == ZT_BREATH(ZT_DEATH) ? "blast"
4377 pline("%s
\82Í
\8e\80\82Ì%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", Monnam(mon),
4378 type == ZT_BREATH(ZT_DEATH) ? "
\91§"
4382 pline("It seems even stronger than before.");
4384 pline("
\82³
\82ç
\82É
\8b
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82³
\82¦
\82·
\82é
\81D");
4386 break; /* Out of while loop */
4389 if (tmp == MAGIC_COOKIE) { /* disintegration */
4390 disintegrate_mon(mon, type, fltxt);
4391 } else if (mon->mhp < 1) {
4393 monkilled(mon, fltxt, AD_RBRE);
4398 /* normal non-fatal hit */
4399 hit(fltxt, mon, exclam(tmp));
4401 /* some armor was destroyed; no damage done */
4404 pline("%s %s is disintegrated!",
4406 pline("%s
\82Ì%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I",
4407 s_suffix(Monnam(mon)),
4408 distant_name(otmp, xname));
4411 if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4419 } else if (sx == u.ux && sy == u.uy && range >= 0) {
4421 if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4424 } else if (zap_hit((int) u.uac, 0)) {
4427 pline("%s hits you!", The(fltxt));
4429 pline("%s
\82Í
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I", fltxt);
4433 (void) ureflects("But %s reflects from your %s!",
4436 (void) ureflects("
\82µ
\82©
\82µ
\81C%s
\82Í
\82 \82È
\82½
\82Ì%s
\82É
\82æ
\82Á
\82Ä
\94½
\8eË
\82µ
\82½
\81D",
4441 pline("For some reason you are not affected.");
4443 pline("
\82È
\82º
\82©
\82 \82È
\82½
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82©
\82Á
\82½
\81D");
4448 zhitu(type, nd, fltxt, sx, sy);
4450 } else if (!Blind) {
4452 pline("%s whizzes by you!", The(fltxt));
4454 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82»
\82Î
\82ð
\82©
\82·
\82ß
\82½
\81I", fltxt);
4455 } else if (abstype == ZT_LIGHTNING) {
4456 Your("%s tingles.", body_part(ARM));
4458 if (abstype == ZT_LIGHTNING)
4459 (void) flashburn((long) d(nd, 50));
4464 if (!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
4469 if (type == ZT_SPELL(ZT_FIRE)) {
4472 break; /* fireballs explode before the wall */
4476 if (range && isok(lsx, lsy) && cansee(lsx, lsy)) {
4477 pline("%s %s!", The(fltxt),
4479 ? "vanishes into the aether"
4481 if (Is_airlevel(&u.uz)) goto get_out_buzz;
4483 if (!dx || !dy || !rn2(20)) {
4487 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4488 && !closed_door(sx, lsy)
4489 && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4490 && ZAP_POS(levl[sx + dx][lsy].typ))))
4492 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4493 && !closed_door(lsx, sy)
4494 && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4495 && ZAP_POS(levl[lsx][sy + dy].typ))))
4496 if (!bounce || rn2(2))
4501 dx = -dx; /* fall into... */
4509 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4513 tmp_at(DISP_END, 0);
4514 if (type == ZT_SPELL(ZT_FIRE))
4515 explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4519 pay_for_damage(abstype == ZT_FIRE
4521 : abstype == ZT_COLD
4523 /* "damage" indicates wall rather than door */
4524 : abstype == ZT_ACID
4526 : abstype == ZT_DEATH
4531 pay_for_damage(abstype == ZT_FIRE
4533 : abstype == ZT_COLD
4534 ? "
\95²
\81X
\82É
\82·
\82é"
4535 : abstype == ZT_ACID
4536 ? "
\8f\9d\82Â
\82¯
\82é"
4537 : abstype == ZT_DEATH
4538 ? "
\95²
\8dÓ
\82·
\82é"
4539 : "
\94j
\89ó
\82·
\82é",
4542 bhitpos = save_bhitpos;
4550 struct rm *lev = &levl[x][y];
4555 msg = "The ice crackles and melts.";
4557 msg = "
\95X
\82Í
\83s
\83L
\83s
\83L
\96Â
\82è
\81C
\97n
\82¯
\82½
\81D";
4558 if (lev->typ == DRAWBRIDGE_UP) {
4559 lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4560 } else { /* lev->typ == ICE */
4562 if (lev->icedpool == ICED_POOL)
4567 lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4571 spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4572 obj_ice_effects(x, y, FALSE);
4579 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4582 pline("%s settles...", An(xname(otmp)));
4584 pline("%s
\82Í
\82Í
\82Ü
\82Á
\82½
\81D
\81D
\81D", xname(otmp));
4586 obj_extract_self(otmp); /* boulder isn't being pushed */
4587 if (!boulder_hits_pool(otmp, x, y, FALSE))
4588 impossible("melt_ice: no pool?");
4589 /* try again if there's another boulder and pool didn't fill */
4590 } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4593 if (x == u.ux && y == u.uy)
4594 spoteffects(TRUE); /* possibly drown, notice objects */
4597 #define MIN_ICE_TIME 50
4598 #define MAX_ICE_TIME 2000
4600 * Usually start a melt_ice timer; sometimes the ice will become
4601 * permanent instead.
4604 start_melt_ice_timeout(x, y, min_time)
4606 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4611 when = (int) min_time;
4612 if (when < MIN_ICE_TIME - 1)
4613 when = MIN_ICE_TIME - 1;
4615 /* random timeout; surrounding ice locations ought to be a factor... */
4616 while (++when <= MAX_ICE_TIME)
4617 if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4620 /* if we're within MAX_ICE_TIME, install a melt timer;
4621 otherwise, omit it to leave this ice permanent */
4622 if (when <= MAX_ICE_TIME) {
4623 where = ((long) x << 16) | (long) y;
4624 (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4625 long_to_any(where));
4632 * Called when ice has melted completely away.
4635 melt_ice_away(arg, timeout)
4637 long timeout UNUSED;
4640 long where = arg->a_long;
4642 y = (xchar) (where & 0xFFFF);
4643 x = (xchar) ((where >> 16) & 0xFFFF);
4644 /* melt_ice does newsym when appropriate */
4645 melt_ice(x, y, "Some ice melts away.");
4648 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4649 * Used both for normal bolts of fire, cold, etc... and for fireballs.
4650 * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4651 * amount by which range is reduced (the latter is just ignored by fireballs)
4654 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4657 boolean *shopdamage;
4658 short exploding_wand_typ;
4660 const char *zapverb;
4663 struct rm *lev = &levl[x][y];
4664 boolean see_it = cansee(x, y), yourzap;
4665 int rangemod = 0, abstype = abs(type) % 10;
4670 if (t && t->ttyp == WEB) {
4671 /* a burning web is too flimsy to notice if you can't see it */
4674 Norep("A web bursts into flames!");
4676 Norep("
\82
\82à
\82Ì
\91\83\82Í
\89\8a\82É
\95ï
\82Ü
\82ê
\82½
\81I");
4677 (void) delfloortrap(t);
4682 melt_ice(x, y, (char *) 0);
4683 } else if (is_pool(x, y)) {
4685 const char *msgtxt = "You hear hissing gas.";
4687 const char *msgtxt = "
\82µ
\82ã
\81[
\82Á
\82Æ
\82¢
\82¤
\83K
\83X
\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4689 if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4692 msgtxt = "Some water evaporates.";
4694 msgtxt = "
\82·
\82±
\82µ
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4698 t = maketrap(x, y, PIT);
4703 msgtxt = "The water evaporates.";
4705 msgtxt = "
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4707 Norep("%s", msgtxt);
4708 if (lev->typ == ROOM)
4710 } else if (IS_FOUNTAIN(lev->typ)) {
4713 pline("Steam billows from the fountain.");
4715 pline("
\90ò
\82©
\82ç
\8fö
\8bC
\82ª
\97§
\82¿
\82Ì
\82Ú
\82Á
\82½
\81D");
4717 dryup(x, y, type > 0);
4719 break; /* ZT_FIRE */
4722 if (is_pool(x, y) || is_lava(x, y)) {
4723 boolean lava = is_lava(x, y);
4724 boolean moat = is_moat(x, y);
4726 if (lev->typ == WATER) {
4727 /* For now, don't let WATER freeze. */
4730 pline_The("water freezes for a moment.");
4732 pline("
\90\85\82Í
\88ê
\8fu
\93\80\82Á
\82½
\81D");
4735 You_hear("a soft crackling.");
4737 You_hear("
\83s
\83L
\81I
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4738 rangemod -= 1000; /* stop */
4741 if (lev->typ == DRAWBRIDGE_UP) {
4742 lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4743 lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4747 (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
4748 lev->typ = (lava ? ROOM : ICE);
4754 Norep("The lava cools and solidifies.");
4756 Norep("
\97n
\8aâ
\82Í
\97â
\82¦
\8cÅ
\82Ü
\82Á
\82½
\81D");
4759 Norep("The %s is bridged with ice!",
4761 Norep("%s
\82É
\95X
\82Ì
\8b´
\82ª
\82©
\82¯
\82ç
\82ê
\82½
\81I",
4762 waterbody_name(x, y));
4765 Norep("The water freezes.");
4767 Norep("
\90\85\82Í
\93\80\82Á
\82½
\81D");
4771 You_hear("a crackling sound.");
4773 You_hear("
\83s
\83L
\83s
\83L
\83b
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4775 if (x == u.ux && y == u.uy) {
4776 if (u.uinwater) { /* not just `if (Underwater)' */
4777 /* leave the no longer existent water */
4781 vision_full_recalc = 1;
4782 } else if (u.utrap && u.utraptype == TT_LAVA) {
4786 You("pass through the now-solid rock.");
4788 You("
\82¢
\82Ü
\8cÅ
\82
\82È
\82Á
\82½
\82Î
\82©
\82è
\82Ì
\90Î
\82Ì
\92\86\82ð
\82·
\82è
\94²
\82¯
\82½
\81D");
4790 u.utrap = rn1(50, 20);
4791 u.utraptype = TT_INFLOOR;
4793 You("are firmly stuck in the cooling rock.");
4795 You("
\97â
\82¦
\82½
\8aâ
\82Ì
\82È
\82©
\82É
\82µ
\82Á
\82©
\82è
\82Æ
\96\84\82Ü
\82Á
\82½
\81D");
4798 } else if ((mon = m_at(x, y)) != 0) {
4799 /* probably ought to do some hefty damage to any
4800 non-ice creature caught in freezing water;
4801 at a minimum, eels are forced out of hiding */
4802 if (is_swimmer(mon->data) && mon->mundetected) {
4803 mon->mundetected = 0;
4808 start_melt_ice_timeout(x, y, 0L);
4809 obj_ice_effects(x, y, TRUE);
4813 } else if (is_ice(x, y)) {
4816 /* Already ice here, so just firm it up. */
4817 /* Now ensure that only ice that is already timed is affected */
4818 if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
4819 spot_stop_timers(x, y, MELT_ICE_AWAY);
4820 start_melt_ice_timeout(x, y, melt_time);
4823 break; /* ZT_COLD */
4826 if (lev->typ == IRONBARS) {
4827 if ((lev->wall_info & W_NONDIGGABLE) != 0) {
4829 Norep("The %s corrode somewhat but remain intact.",
4830 defsyms[S_bars].explanation);
4831 /* but nothing actually happens... */
4835 Norep("The %s melt.", defsyms[S_bars].explanation);
4836 if (*in_rooms(x, y, SHOPBASE)) {
4837 /* in case we ever have a shop bounded by bars */
4841 add_damage(x, y, (type >= 0) ? 300L : 0L);
4846 lev->doormask = D_NODOOR;
4852 break; /* ZT_ACID */
4858 /* set up zap text for possible door feedback; for exploding wand, we
4859 want "the blast" rather than "your blast" even if hero caused it */
4860 yourzap = (type >= 0 && !exploding_wand_typ);
4862 zapverb = "blast"; /* breath attack or wand explosion */
4864 zapverb = "
\8fÕ
\8c\82"; /* breath attack or wand explosion */
4866 if (!exploding_wand_typ) {
4867 if (abs(type) < ZT_SPELL(0))
4869 zapverb = "bolt"; /* wand zap */
4871 zapverb = "
\8cõ
\90ü"; /* wand zap */
4873 else if (abs(type) < ZT_BREATH(0))
4877 zapverb = "
\8eô
\95¶";
4880 /* secret door gets revealed, converted into regular door */
4881 if (levl[x][y].typ == SDOOR) {
4882 cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
4883 /* target spot will now pass closed_door() test below
4884 (except on rogue level) */
4887 pline("%s %s reveals a secret door.",
4888 yourzap ? "Your" : "The", zapverb);
4889 else if (Is_rogue_level(&u.uz))
4890 draft_message(FALSE); /* "You feel a draft." (open doorway) */
4893 /* regular door absorbs remaining zap range, possibly gets destroyed */
4894 if (closed_door(x, y)) {
4895 int new_doormask = -1;
4896 const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
4901 new_doormask = D_NODOOR;
4903 see_txt = "The door is consumed in flames!";
4905 see_txt = "
\94à
\82Í
\89\8a\82Å
\8fÄ
\82«
\82Â
\82
\82³
\82ê
\82½
\81I";
4907 sense_txt = "smell smoke.";
4909 sense_txt = "
\89\8c\82Ì
\93õ
\82¢
\82ª
\82µ
\82½
\81D";
4912 new_doormask = D_NODOOR;
4914 see_txt = "The door freezes and shatters!";
4916 see_txt = "
\94à
\82Í
\93\80\82è
\81C
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I";
4918 sense_txt = "feel cold.";
4920 sense_txt = "
\97â
\8bC
\82ð
\8a´
\82¶
\82½
\81D";
4923 /* death spells/wands don't disintegrate */
4924 if (abs(type) != ZT_BREATH(ZT_DEATH))
4926 new_doormask = D_NODOOR;
4928 see_txt = "The door disintegrates!";
4930 see_txt = "
\94à
\82Í
\95²
\8dÓ
\82³
\82ê
\82½
\81I";
4932 hear_txt = "crashing wood.";
4934 hear_txt = "
\96Ø
\82Ì
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4937 new_doormask = D_BROKEN;
4939 see_txt = "The door splinters!";
4941 see_txt = "
\94à
\82Í
\82¸
\82½
\82¸
\82½
\82É
\82È
\82Á
\82½
\81I";
4943 hear_txt = "crackling.";
4945 hear_txt = "
\83s
\83L
\83s
\83L
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4949 if (exploding_wand_typ > 0) {
4950 /* Magical explosion from misc exploding wand */
4951 if (exploding_wand_typ == WAN_STRIKING) {
4952 new_doormask = D_BROKEN;
4953 see_txt = "The door crashes open!";
4954 sense_txt = "feel a burst of cool air.";
4959 /* "the door absorbs the blast" would be
4960 inaccurate for an exploding wand since
4961 other adjacent locations still get hit */
4962 if (exploding_wand_typ)
4964 pline_The("door remains intact.");
4966 pline_The("
\94à
\82Í
\96³
\8f\9d\82¾
\81D");
4969 pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
4972 pline_The("
\94à
\82Í%s%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", yourzap ? "
\82 \82È
\82½
\82ª
\95ú
\82Á
\82½" : "",
4977 You_feel("vibrations.");
4979 You("
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
4982 if (new_doormask >= 0) { /* door gets broken */
4983 if (*in_rooms(x, y, SHOPBASE)) {
4985 add_damage(x, y, 400L);
4987 } else /* caused by monster */
4988 add_damage(x, y, 0L);
4990 lev->doormask = new_doormask;
4991 unblock_point(x, y); /* vision */
4995 } else if (sense_txt) {
4996 #if 0 /*JP*//*
\81u
\82 \82È
\82½
\82Í
\81v
\82ª
\95s
\93K
\90Ø
\82È
\95¶
\82à
\82 \82é*/
5001 } else if (hear_txt)
5002 You_hear1(hear_txt);
5003 if (picking_at(x, y)) {
5010 if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5011 if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5014 You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5016 pline("%s
\81D", !Blind ? "
\82Û
\82í
\82Á
\82Æ
\89\8c\82ª
\82 \82ª
\82Á
\82½" : "
\89\8c\82Ì
\83v
\83\93\82Æ
\82¢
\82¤
\93õ
\82¢
\82ª
\82µ
\82½");
5018 if ((mon = m_at(x, y)) != 0) {
5019 /* Cannot use wakeup() which also angers the monster */
5025 if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5027 if (mon->isshk && !*u.ushops)
5034 /* fractured by pick-axe or wand of striking */
5037 register struct obj *obj; /* no texts here! */
5040 boolean by_you = !context.mon_moving;
5042 if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5043 struct monst *shkp = 0;
5044 char objroom = *in_rooms(x, y, SHOPBASE);
5046 if (billable(&shkp, obj, objroom, FALSE)) {
5047 /* shop message says "you owe <shk> <$> for it!" so we need
5048 to precede that with a message explaining what "it" is */
5049 You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5050 breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5053 if (by_you && obj->otyp == BOULDER)
5057 obj->oclass = GEM_CLASS;
5058 obj->quan = (long) rn1(60, 7);
5059 obj->owt = weight(obj);
5060 obj->dknown = obj->bknown = obj->rknown = 0;
5061 obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5062 dealloc_oextra(obj);
5064 if (obj->where == OBJ_FLOOR) {
5065 obj_extract_self(obj); /* move rocks back on top */
5066 place_object(obj, obj->ox, obj->oy);
5067 if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5068 unblock_point(obj->ox, obj->oy);
5069 if (cansee(obj->ox, obj->oy))
5070 newsym(obj->ox, obj->oy);
5074 /* handle statue hit by striking/force bolt/pick-axe */
5077 register struct obj *obj;
5079 /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5080 struct trap *trap = t_at(obj->ox, obj->oy);
5082 boolean by_you = !context.mon_moving;
5084 if (trap && trap->ttyp == STATUE_TRAP
5085 && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5087 /* drop any objects contained inside the statue */
5088 while ((item = obj->cobj) != 0) {
5089 obj_extract_self(item);
5090 place_object(item, obj->ox, obj->oy);
5092 if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5094 You_feel("guilty about damaging such a historic statue.");
5096 You_feel("
\82±
\82Ì
\82æ
\82¤
\82È
\97ð
\8ej
\93I
\82È
\92¤
\91\9c\82É
\8f\9d\82ð
\82Â
\82¯
\82é
\82Ì
\82Í
\8dß
\90[
\82¢
\82±
\82Æ
\82¾
\82Æ
\8ev
\82Á
\82½
\81D");
5105 * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5106 * [0] freezing potion
5107 * [1] boiling potion other than oil
5108 * [2] boiling potion of oil
5109 * [3] burning scroll
5110 * [4] burning spellbook
5113 * (books, rings, and wands don't stack so don't need plural form;
5114 * crumbling ring doesn't do damage so doesn't need killer reason)
5116 const char *const destroy_strings[][3] = {
5117 /* also used in trap.c */
5119 { "freezes and shatters", "freeze and shatter", "shattered potion" },
5121 { "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\8dÓ
\82¯
\82½
\96ò
\95r
\82Å" },
5123 { "boils and explodes", "boil and explode", "boiling potion" },
5125 { "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82½
\96ò
\82Å" },
5127 { "ignites and explodes", "ignite and explode", "exploding potion" },
5129 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94\9a\94
\82µ
\82½", "
\94\9a\94
\82µ
\82½
\96ò
\82Å" },
5131 { "catches fire and burns", "catch fire and burn", "burning scroll" },
5133 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\8aª
\95¨
\82Å" },
5135 { "catches fire and burns", "", "burning book" },
5137 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\96\82\96@
\8f\91\82Å" },
5139 { "turns to dust and vanishes", "", "" },
5141 { "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "" },
5143 { "breaks apart and explodes", "", "exploding wand" },
5145 { "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\82Î
\82ç
\82Î
\82ç
\82É
\89ó
\82ê
\82Ä
\94\9a\94
\82µ
\82½", "
\8fñ
\82Ì
\94\9a\94
\82Å" },
5149 destroy_item(osym, dmgtyp)
5150 register int osym, dmgtyp;
5152 register struct obj *obj, *obj2;
5153 int dmg, xresist, skip;
5157 boolean physical_damage;
5159 for (obj = invent; obj; obj = obj2) {
5161 physical_damage = FALSE;
5162 if (obj->oclass != osym)
5163 continue; /* test only objs of type osym */
5165 continue; /* don't destroy artifacts */
5166 if (obj->in_use && obj->quan == 1L)
5167 continue; /* not available */
5169 /* lint suppression */
5175 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5183 xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5184 && obj->otyp != GLOB_OF_GREEN_SLIME);
5186 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5188 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5192 pline("%s glows a strange %s, but remains intact.",
5193 The(xname(obj)), hcolor("dark red"));
5195 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5196 xname(obj), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5203 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5215 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5216 dindx = obj->owt / 20;
5228 xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5232 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5240 if (obj->otyp == WAN_LIGHTNING) {
5245 if (obj == current_wand) { skip++; break; }
5261 --quan; /* one will be used up elsewhere */
5262 for (i = cnt = 0L; i < quan; i++)
5269 mult = (cnt == quan)
5270 ? (quan > 1) ? "All of your " : "Your"
5271 : (cnt == 1L) ? "One of your" : "Some of your";
5273 mult = (cnt == quan)
5275 : (cnt == 1L) ? "
\82Ì
\82Ð
\82Æ
\82Â" : "
\82Ì
\82¢
\82
\82Â
\82©";
5278 pline("%s %s %s!", mult, xname(obj),
5279 destroy_strings[dindx][(cnt > 1L)]);
5281 pline("
\82 \82È
\82½
\82Ì%s%s
\82Í%s
\81I", xname(obj), mult,
5282 destroy_strings[dindx][(cnt > 1L)]);
5284 if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5285 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5288 if (obj->owornmask) {
5289 if (obj->owornmask & W_RING) /* ring being worn */
5294 if (obj == current_wand)
5295 current_wand = 0; /* destroyed */
5296 for (i = 0; i < cnt; i++)
5301 You("aren't hurt!");
5303 You("
\8f\9d\82Â
\82©
\82È
\82¢
\81I");
5305 const char *how = destroy_strings[dindx][2];
5306 boolean one = (cnt == 1L);
5308 if (physical_damage)
5309 dmg = Maybe_Half_Phys(dmg);
5310 losehp(dmg, one ? how : (const char *) makeplural(how),
5311 one ? KILLED_BY_AN : KILLED_BY);
5312 exercise(A_STR, FALSE);
5321 destroy_mitem(mtmp, osym, dmgtyp)
5325 struct obj *obj, *obj2;
5331 if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5332 destroy_item(osym, dmgtyp);
5333 return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5336 vis = canseemon(mtmp);
5337 for (obj = mtmp->minvent; obj; obj = obj2) {
5339 if (obj->oclass != osym)
5340 continue; /* test only objs of type osym */
5347 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5355 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5357 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5361 pline("%s glows a strange %s, but remains intact.",
5362 The(distant_name(obj, xname)), hcolor("dark red"));
5364 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5365 The(distant_name(obj, xname)), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5371 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5383 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5384 dindx = obj->owt / 20;
5399 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5406 if (obj->otyp == WAN_LIGHTNING) {
5423 for (i = cnt = 0L; i < quan; i++)
5432 (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5434 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5435 destroy_strings[dindx][(cnt > 1L)]);
5437 pline("%s%s
\82Í%s
\81I",
5438 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5439 (cnt == obj->quan) ? "" : (cnt > 1L) ? "
\82Ì
\82¢
\82
\82Â
\82©"
5440 : "
\82Ì
\82Ð
\82Æ
\82Â",
5441 destroy_strings[dindx][(cnt > 1L)]);
5443 for (i = 0; i < cnt; i++)
5451 resist(mtmp, oclass, damage, tell)
5466 break; /* instrument */
5469 break; /* artifact */
5484 dlev = (int) mtmp->m_lev;
5488 dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5490 resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5493 shieldeff(mtmp->mx, mtmp->my);
5495 pline("%s resists!", Monnam(mtmp));
5497 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", Monnam(mtmp));
5499 damage = (damage + 1) / 2;
5503 mtmp->mhp -= damage;
5504 if (mtmp->mhp < 1) {
5506 monkilled(mtmp, "", AD_RBRE);
5514 #define MAXWISHTRY 5
5517 wishcmdassist(triesleft)
5520 static NEARDATA const char *
5524 "Enter the name of an object, such as \"potion of monster detection\",",
5525 "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5526 "(without the quotes).",
5528 "For object types which come in stacks, you may specify a plural name",
5529 "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5530 "pieces\", although that aspect of your wish might not be granted.",
5532 "You may also specify various prefix values which might be used to",
5533 "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5534 "Most modifiers shown when viewing your inventory can be specified.",
5536 "You may specify 'nothing' to explicitly decline this wish.",
5539 preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5541 "If you specify an unrecognized object name %s%s time%s,",
5542 retry_too[] = "a randomly chosen item will be granted.",
5543 suppress_cmdassist[] =
5544 "(Suppress this assistance with !cmdassist in your config file.)",
5545 *cardinals[] = { "zero", "one", "two", "three", "four", "five" },
5546 too_many[] = "too many";
5551 win = create_nhwindow(NHW_TEXT);
5554 for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5555 putstr(win, 0, wishinfo[i]);
5556 if (!u.uconduct.wishes)
5557 putstr(win, 0, preserve_wishless);
5559 Sprintf(buf, retry_info,
5560 (triesleft >= 0 && triesleft < SIZE(cardinals))
5561 ? cardinals[triesleft]
5563 (triesleft < MAXWISHTRY) ? " more" : "",
5565 putstr(win, 0, buf);
5566 putstr(win, 0, retry_too);
5568 if (iflags.cmdassist)
5569 putstr(win, 0, suppress_cmdassist);
5570 display_nhwindow(win, FALSE);
5571 destroy_nhwindow(win);
5577 char buf[BUFSZ], promptbuf[BUFSZ];
5578 struct obj *otmp, nothing;
5581 promptbuf[0] = '\0';
5582 nothing = zeroobj; /* lint suppression; only its address matters */
5585 You("may wish for an object.");
5587 You("
\96]
\82Ý
\82Ì
\82à
\82Ì
\82ð
\8eè
\82É
\93ü
\82ê
\82ç
\82ê
\82é
\81D");
5590 Strcpy(promptbuf, "For what do you wish");
5592 Strcpy(promptbuf, "
\89½
\82ð
\82¨
\96]
\82Ý");
5593 if (iflags.cmdassist && tries > 0)
5595 Strcat(promptbuf, " (enter 'help' for assistance)");
5597 Strcat(promptbuf, " (
\8f\95\82¯
\82ª
\95K
\97v
\82È
\82ç 'help'
\82Æ
\93ü
\97Í)");
5599 Strcat(promptbuf, "?");
5601 Strcat(promptbuf, "
\81H");
5602 getlin(promptbuf, buf);
5603 (void) mungspaces(buf);
5604 if (buf[0] == '\033') {
5606 } else if (!strcmpi(buf, "help")) {
5607 wishcmdassist(MAXWISHTRY - tries);
5611 * Note: if they wished for and got a non-object successfully,
5612 * otmp == &zeroobj. That includes gold, or an artifact that
5613 * has been denied. Wishing for "nothing" requires a separate
5614 * value to remain distinct.
5616 otmp = readobjnam(buf, ¬hing);
5619 pline("Nothing fitting that description exists in the game.");
5621 pline("
\82¤
\81[
\82ñ
\81D
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\91¶
\8dÝ
\82µ
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
5622 if (++tries < MAXWISHTRY)
5624 pline1(thats_enough_tries);
5625 otmp = readobjnam((char *) 0, (struct obj *) 0);
5627 return; /* for safety; should never happen */
5628 } else if (otmp == ¬hing) {
5629 /* explicitly wished for "nothing", presumably attempting
5630 to retain wishless conduct */
5635 u.uconduct.wishes++;
5637 if (otmp != &zeroobj) {
5640 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5642 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "
\8a\8a\82è
\97\8e\82¿
\82½" : "
\97\8e\82¿
\82½"),
5644 *oops_msg = (u.uswallow
5645 ? "Oops! %s out of your reach!"
5646 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5647 || levl[u.ux][u.uy].typ < IRONBARS
5648 || levl[u.ux][u.uy].typ >= ICE)
5649 ? "Oops! %s away from you!"
5650 : "Oops! %s to the floor!");
5652 *oops_msg = (u.uswallow
5653 ? "
\82¨
\82Á
\82Æ
\81C
\93Í
\82©
\82È
\82¢
\82Æ
\82±
\82ë
\82É%s
\81I"
5654 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5655 || levl[u.ux][u.uy].typ < IRONBARS
5656 || levl[u.ux][u.uy].typ >= ICE)
5657 ? "
\82¨
\82Á
\82Æ
\81C
\8eè
\82©
\82ç%s
\81I"
5658 : "
\82¨
\82Á
\82Æ
\81C
\8f°
\82É%s
\81I");
5661 /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5662 (void) hold_another_object(otmp, oops_msg,
5663 The(aobjnam(otmp, verb)),
5665 u.ublesscnt += rn1(100, 50); /* the gods take notice */