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Ä", KILLED_BY);
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());
2557 killer.format = NO_KILLER_PREFIX;
2559 Strcpy(killer.name, "
\8e©
\95ª
\82ª
\8c\82\82Á
\82½
\8e\80\82Ì
\8cõ
\90ü
\82É
\82æ
\82Á
\82Ä");
2560 killer.format = KILLED_BY;
2563 You("irradiate yourself with pure energy!");
2565 You("
\83G
\83l
\83\8b\83M
\81[
\82ð
\8e©
\95ª
\8e©
\90g
\82É
\8fÆ
\8eË
\82µ
\82½
\81D");
2569 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D");
2570 /* They might survive with an amulet of life saving */
2573 case WAN_UNDEAD_TURNING:
2574 case SPE_TURN_UNDEAD:
2576 (void) unturn_dead(&youmonst);
2577 if (is_undead(youmonst.data)) {
2579 You_feel("frightened and %sstunned.",
2580 Stunned ? "even more " : "");
2582 You("
\8b°
\95|
\82µ%s
\82
\82ç
\82
\82ç
\82µ
\82½
\81D",
2583 Stunned ? "
\82³
\82ç
\82É" : "");
2585 make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
2588 You("shudder in dread.");
2590 You("
\8b°
\95|
\82Å
\90k
\82¦
\82½
\81D");
2593 case SPE_EXTRA_HEALING:
2594 learn_it = TRUE; /* (no effect for spells...) */
2595 healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE,
2596 (obj->otyp == SPE_EXTRA_HEALING));
2598 You_feel("%sbetter.", obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
2600 You("%s
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81D", obj->otyp == SPE_EXTRA_HEALING ? "
\82Æ
\82Ä
\82à" : "");
2602 case WAN_LIGHT: /* (broken wand) */
2603 /* assert( !ordinary ); */
2604 damage = d(obj->spe, 25);
2605 case EXPENSIVE_CAMERA:
2608 damage = lightdamage(obj, ordinary, damage);
2610 if (flashburn((long) damage))
2612 damage = 0; /* reset */
2620 if (u.utrap) { /* escape web or bear trap */
2621 (void) openholdingtrap(&youmonst, &learn_it);
2622 } else { /* trigger previously escaped trapdoor */
2623 (void) openfallingtrap(&youmonst, TRUE, &learn_it);
2627 case SPE_WIZARD_LOCK:
2629 (void) closeholdingtrap(&youmonst, &learn_it);
2634 case SPE_DETECT_UNSEEN:
2640 for (otmp = invent; otmp; otmp = otmp->nobj) {
2642 if (Is_container(otmp) || otmp->otyp == STATUE) {
2644 if (!SchroedingersBox(otmp))
2652 case SPE_STONE_TO_FLESH: {
2653 struct obj *otmp, *onxt;
2656 if (u.umonnum == PM_STONE_GOLEM) {
2658 (void) polymon(PM_FLESH_GOLEM);
2662 fix_petrification(); /* saved! */
2664 /* but at a cost.. */
2665 for (otmp = invent; otmp; otmp = onxt) {
2667 if (bhito(otmp, obj))
2671 * It is possible that we can now merge some inventory.
2672 * Do a highly paranoid merge. Restart from the beginning
2677 for (otmp = invent; !didmerge && otmp; otmp = otmp->nobj)
2678 for (onxt = otmp->nobj; onxt; onxt = onxt->nobj)
2679 if (merged(&otmp, &onxt)) {
2687 impossible("zapyourself: object %d used?", obj->otyp);
2690 /* if effect was observable then discover the wand type provided
2691 that the wand itself has been seen */
2697 /* called when poly'd hero uses breath attack against self */
2700 struct attack *mattk;
2702 int dtyp = 20 + mattk->adtyp - 1; /* breath by hero */
2703 const char *fltxt = flash_types[dtyp]; /* blast of <something> */
2705 zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
2708 /* light damages hero in gremlin form */
2710 lightdamage(obj, ordinary, amt)
2711 struct obj *obj; /* item making light (fake book if spell) */
2712 boolean ordinary; /* wand/camera zap vs wand destruction */
2713 int amt; /* pseudo-damage used to determine blindness duration */
2719 if (dmg && youmonst.data == &mons[PM_GREMLIN]) {
2720 /* reduce high values (from destruction of wand with many charges) */
2723 dmg = 10 + rnd(dmg - 10);
2726 pline("Ow, that light hurts%c", (dmg > 2 || u.mh <= 5) ? '!' : '.');
2727 /* [composing killer/reason is superfluous here; if fatal, cause
2728 of death will always be "killed while stuck in creature form"] */
2729 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
2730 ordinary = FALSE; /* say blasted rather than zapped */
2731 how = (obj->oclass != SPBOOK_CLASS)
2732 ? (const char *) ansimpleoname(obj)
2734 Sprintf(buf, "%s %sself with %s", ordinary ? "zapped" : "blasted",
2736 /* might rehumanize(); could be fatal, but only for Unchanging */
2738 losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
2740 losehp(Maybe_Half_Phys(dmg), buf, KILLED_BY);
2746 /* light[ning] causes blindness */
2751 if (!resists_blnd(&youmonst)) {
2752 You(are_blinded_by_the_flash);
2753 make_blinded(duration, FALSE);
2755 Your1(vision_clears);
2761 /* you've zapped a wand downwards while riding
2762 * Return TRUE if the steed was hit by the wand.
2763 * Return FALSE if the steed was not hit by the wand.
2767 struct obj *obj; /* wand or spell */
2769 int steedhit = FALSE;
2771 switch (obj->otyp) {
2773 * Wands that are allowed to hit the steed
2774 * Carefully test the results of any that are
2775 * moved here from the bottom section.
2778 probe_monster(u.usteed);
2782 case WAN_TELEPORTATION:
2783 case SPE_TELEPORT_AWAY:
2784 /* you go together */
2786 /* same criteria as when unmounted (zapyourself) */
2787 if ((Teleport_control && !Stunned) || !couldsee(u.ux0, u.uy0)
2788 || distu(u.ux0, u.uy0) >= 16)
2793 /* Default processing via bhitm() for these */
2794 case SPE_CURE_SICKNESS:
2795 case WAN_MAKE_INVISIBLE:
2796 case WAN_CANCELLATION:
2797 case SPE_CANCELLATION:
2801 case SPE_FORCE_BOLT:
2802 case WAN_SLOW_MONSTER:
2803 case SPE_SLOW_MONSTER:
2804 case WAN_SPEED_MONSTER:
2806 case SPE_EXTRA_HEALING:
2807 case SPE_DRAIN_LIFE:
2810 (void) bhitm(u.usteed, obj);
2822 * cancel a monster (possibly the hero). inventory is cancelled only
2823 * if the monster is zapping itself directly, since otherwise the
2824 * effect is too strong. currently non-hero monsters do not zap
2825 * themselves with cancellation.
2828 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2829 register struct monst *mdef;
2830 register struct obj *obj;
2831 boolean youattack, allow_cancel_kill, self_cancel;
2833 boolean youdefend = (mdef == &youmonst);
2834 static const char writing_vanishes[] =
2836 "Some writing vanishes from %s head!";
2838 "
\89½
\82©
\82Ì
\95¶
\8e\9a\82ª%s
\82Ì
\93ª
\82©
\82ç
\8fÁ
\82¦
\82½
\81I";
2840 static const char your[] = "your"; /* should be extern */
2842 static const char your[] = "
\82 \82È
\82½"; /* should be extern */
2845 if (youdefend ? (!youattack && Antimagic)
2846 : resist(mdef, obj->oclass, 0, NOTELL))
2847 return FALSE; /* resisted cancellation */
2849 if (self_cancel) { /* 1st cancel inventory */
2852 for (otmp = (youdefend ? invent : mdef->minvent); otmp;
2856 context.botl = 1; /* potential AC change */
2861 /* now handle special cases */
2864 if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
2865 pline(writing_vanishes, your);
2869 Your("amulet grows hot for a moment, then cools.");
2871 Your("
\96\82\8f\9c\82¯
\82Í
\82µ
\82Î
\82ç
\82
\94M
\82
\82È
\82è
\81C
\82â
\82ª
\82Ä
\8c³
\82É
\96ß
\82Á
\82½
\81D");
2878 if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
2881 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
2882 if (canseemon(mdef))
2883 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
2885 if (allow_cancel_kill) {
2889 monkilled(mdef, "", AD_SPEL);
2896 /* you've zapped an immediate type wand up or down */
2899 struct obj *obj; /* wand or spell */
2901 boolean striking = FALSE, disclose = FALSE;
2902 int x, y, xx, yy, ptmp;
2908 /* some wands have special effects other than normal bhitpile */
2909 /* drawbridge might change <u.ux,u.uy> */
2910 x = xx = u.ux; /* <x,y> is zap location */
2911 y = yy = u.uy; /* <xx,yy> is drawbridge (portcullis) position */
2912 ttmp = t_at(x, y); /* trap if there is one */
2914 switch (obj->otyp) {
2919 You("probe towards the %s.", ceiling(x, y));
2921 You("
\8fã
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", ceiling(x,y));
2923 ptmp += bhitpile(obj, bhito, x, y, u.dz);
2925 You("probe beneath the %s.", surface(x, y));
2927 You("
\89º
\95û
\82Ì%s
\82ð
\92²
\82×
\82½
\81D", surface(x,y));
2928 ptmp += display_binventory(x, y, TRUE);
2932 Your("probe reveals nothing.");
2934 pline("
\92²
\8d¸
\82Ì
\8c\8b\89Ê
\89½
\82à
\82Å
\82Ä
\82±
\82È
\82©
\82Á
\82½
\81D");
2935 return TRUE; /* we've done our own bhitpile */
2938 /* up or down, but at closed portcullis only */
2939 if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
2940 open_drawbridge(xx, yy);
2942 } else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
2943 /* can't use the stairs down to quest level 2 until
2944 leader "unlocks" them; give feedback if you try */
2945 on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
2947 pline_The("stairs seem to ripple momentarily.");
2949 pline("
\8aK
\92i
\82ª
\88ê
\8fu
\97h
\82ê
\82½
\82æ
\82¤
\82É
\8c©
\82¦
\82½
\81D");
2952 /* down will release you from bear trap or web */
2953 if (u.dz > 0 && u.utrap) {
2954 (void) openholdingtrap(&youmonst, &disclose);
2955 /* down will trigger trapdoor, hole, or [spiked-] pit */
2956 } else if (u.dz > 0 && !u.utrap) {
2957 (void) openfallingtrap(&youmonst, FALSE, &disclose);
2961 case SPE_FORCE_BOLT:
2965 case SPE_WIZARD_LOCK:
2966 /* down at open bridge or up or down at open portcullis */
2967 if (((levl[x][y].typ == DRAWBRIDGE_DOWN)
2969 : (is_drawbridge_wall(x, y) >= 0 && !is_db_wall(x, y)))
2970 && find_drawbridge(&xx, &yy)) {
2972 close_drawbridge(xx, yy);
2974 destroy_drawbridge(xx, yy);
2976 } else if (striking && u.dz < 0 && rn2(3) && !Is_airlevel(&u.uz)
2977 && !Is_waterlevel(&u.uz) && !Underwater
2978 && !Is_qstart(&u.uz)) {
2980 /* similar to zap_dig() */
2982 pline("A rock is dislodged from the %s and falls on your %s.",
2983 ceiling(x, y), body_part(HEAD));
2985 pline("%s
\82©
\82ç
\8aâ
\82ª
\97\8e\82¿
\82Ä
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81D",
2986 ceiling(x, y), body_part(HEAD));
2988 dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
2990 losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
2992 losehp(Maybe_Half_Phys(dmg), "
\97\8e\8aâ
\82Å", KILLED_BY_AN);
2993 if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
2994 (void) xname(otmp); /* set dknown, maybe bknown */
2998 } else if (u.dz > 0 && ttmp) {
2999 if (!striking && closeholdingtrap(&youmonst, &disclose)) {
3000 ; /* now stuck in web or bear trap */
3001 } else if (striking && ttmp->ttyp == TRAPDOOR) {
3002 /* striking transforms trapdoor into hole */
3003 if (Blind && !ttmp->tseen) {
3005 pline("%s beneath you shatters.", Something);
3007 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\89½
\82©
\82ª
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3008 } else if (!ttmp->tseen) { /* => !Blind */
3010 pline("There's a trapdoor beneath you; it shatters.");
3012 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82Í
\97\8e\82µ
\94à
\82ª
\82 \82Á
\82½
\81G
\82»
\82ê
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3015 pline("The trapdoor beneath you shatters.");
3017 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\82 \82é
\97\8e\82µ
\94à
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D");
3023 /* might fall down hole */
3025 } else if (!striking && ttmp->ttyp == HOLE) {
3026 /* locking transforms hole into trapdoor */
3027 ttmp->ttyp = TRAPDOOR;
3028 if (Blind || !ttmp->tseen) {
3030 pline("Some %s swirls beneath you.",
3031 is_ice(x, y) ? "frost" : "dust");
3033 pline("
\82 \82È
\82½
\82Ì
\89º
\82Å%s
\82ª
\82¤
\82¸
\82ð
\8aª
\82
\82Ì
\82ª
\8c©
\82¦
\82½
\81D",
3034 is_ice(x,y) ? "
\91\9a" : "
\82Ù
\82±
\82è");
3040 pline("A trapdoor appears beneath you.");
3042 pline("
\82 \82È
\82½
\82Ì
\89º
\82É
\97\8e\82µ
\94à
\82ª
\82 \82ç
\82í
\82ê
\82½
\81D");
3045 /* hadn't fallen down hole; won't fall now */
3049 case SPE_STONE_TO_FLESH:
3050 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || Underwater
3051 || (Is_qstart(&u.uz) && u.dz < 0)) {
3052 pline1(nothing_happens);
3053 } else if (u.dz < 0) { /* we should do more... */
3055 pline("Blood drips on your %s.", body_part(FACE));
3057 pline("
\8c\8c\82ª
\82 \82È
\82½
\82Ì%s
\82Ö
\82µ
\82½
\82½
\82è
\97\8e\82¿
\82Ä
\82«
\82½
\81D", body_part(FACE));
3058 } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
3060 Print this message only if there wasn't an engraving
3061 affected here. If water or ice, act like waterlevel case.
3063 e = engr_at(u.ux, u.uy);
3064 if (!(e && e->engr_type == ENGRAVE)) {
3065 if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
3066 pline1(nothing_happens);
3069 pline("Blood %ss %s your %s.",
3070 is_lava(u.ux, u.uy) ? "boil" : "pool",
3071 Levitation ? "beneath" : "at",
3072 makeplural(body_part(FOOT)));
3075 makeplural(body_part(FOOT)),
3076 Levitation ? "
\82Ì
\89º" : "
\8c³",
3077 is_lava(u.ux, u.uy) ?
3078 "
\82Å
\8c\8c\82ª
\95¦
\93«
\82µ
\82½" : "
\82É
\8c\8c\82¾
\82Ü
\82è
\82ª
\8fo
\97\88\82½");
3088 /* zapping downward */
3089 (void) bhitpile(obj, bhito, x, y, u.dz);
3091 /* subset of engraving effects; none sets `disclose' */
3092 if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
3093 switch (obj->otyp) {
3097 make_engr_at(x, y, random_engraving(buf), moves, (xchar) 0);
3099 case WAN_CANCELLATION:
3100 case SPE_CANCELLATION:
3101 case WAN_MAKE_INVISIBLE:
3104 case WAN_TELEPORTATION:
3105 case SPE_TELEPORT_AWAY:
3108 case SPE_STONE_TO_FLESH:
3109 if (e->engr_type == ENGRAVE) {
3110 /* only affects things in stone */
3112 pline_The(Hallucination
3113 ? "floor runs like butter!"
3114 : "edges on the floor get smoother.");
3117 ? "
\8f°
\82ª
\83o
\83^
\81[
\82Ì
\82æ
\82¤
\82É
\91\96\82Á
\82Ä
\82¢
\82Á
\82½
\81I"
3118 : "
\8f°
\82Ì
\89\8f\82ª
\82È
\82ß
\82ç
\82©
\82É
\82È
\82Á
\82½
\81D");
3120 wipe_engr_at(x, y, d(2, 4), TRUE);
3124 case SPE_FORCE_BOLT:
3125 wipe_engr_at(x, y, d(2, 4), TRUE);
3131 } else if (u.dz < 0) {
3132 /* zapping upward */
3134 /* game flavor: if you're hiding under "something"
3135 * a zap upward should hit that "something".
3137 if (u.uundetected && hides_under(youmonst.data)) {
3139 otmp = level.objects[u.ux][u.uy];
3142 hitit = bhito(otmp, obj);
3144 (void) hideunder(&youmonst);
3153 /* used by do_break_wand() was well as by weffects() */
3163 /* if do_osshock() set obj_zapped while polying, give a message now */
3166 You_feel("shuddering vibrations.");
3168 You("
\82¼
\82Á
\82Æ
\82·
\82é
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
3172 /* called for various wand and spell effects - M. Stephenson */
3177 int otyp = obj->otyp;
3178 boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
3180 exercise(A_WIS, TRUE);
3181 if (u.usteed && (objects[otyp].oc_dir != NODIR) && !u.dx && !u.dy
3182 && (u.dz > 0) && zap_steed(obj)) {
3184 } else if (objects[otyp].oc_dir == IMMEDIATE) {
3185 zapsetup(); /* reset obj_zapped */
3187 (void) bhitm(u.ustuck, obj);
3188 /* [how about `bhitpile(u.ustuck->minvent)' effect?] */
3190 disclose = zap_updown(obj);
3192 (void) bhit(u.dx, u.dy, rn1(8, 6), ZAPPED_WAND, bhitm, bhito,
3195 zapwrapup(); /* give feedback for obj_zapped */
3197 } else if (objects[otyp].oc_dir == NODIR) {
3201 /* neither immediate nor directionless */
3203 if (otyp == WAN_DIGGING || otyp == SPE_DIG)
3205 else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
3206 buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy,
3208 else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
3209 buzz(otyp - WAN_MAGIC_MISSILE,
3210 (otyp == WAN_MAGIC_MISSILE) ? 2 : 6, u.ux, u.uy, u.dx, u.dy);
3212 impossible("weffects: unexpected spell or wand");
3218 more_experienced(0, 10);
3223 /* augment damage for a spell dased on the hero's intelligence (and level) */
3225 spell_damage_bonus(dmg)
3226 int dmg; /* base amount to be adjusted by bonus or penalty */
3228 int intell = ACURR(A_INT);
3230 /* Punish low intelligence before low level else low intelligence
3231 gets punished only when high level */
3233 /* -3 penalty, but never reduce combined amount below 1
3234 (if dmg is 0 for some reason, we're careful to leave it there) */
3236 dmg = (dmg <= 3) ? 1 : dmg - 3;
3237 } else if (intell <= 13 || u.ulevel < 5)
3238 ; /* no bonus or penalty; dmg remains same */
3239 else if (intell <= 18)
3241 else if (intell <= 24 || u.ulevel < 14)
3244 dmg += 3; /* Int 25 */
3250 * Generate the to hit bonus for a spell. Based on the hero's skill in
3251 * spell class and dexterity.
3254 spell_hit_bonus(skill)
3258 int dex = ACURR(A_DEX);
3260 switch (P_SKILL(spell_skilltype(skill))) {
3261 case P_ISRESTRICTED:
3283 /* Will change when print stuff below removed */
3286 /* Even increment for dextrous heroes (see weapon.c abon) */
3287 hit_bon += dex - 14;
3296 /* force == 0 occurs e.g. with sleep ray */
3297 /* note that large force is usual with wands so that !! would
3298 require information about hand/weapon/wand */
3300 return (const char *) ((force < 0) ? "?" : (force <= 4) ? "." : "!");
3302 return (const char *) ((force < 0) ? "
\81H" : (force <= 4) ? "
\81D" : "
\81I");
3306 hit(str, mtmp, force)
3309 const char *force; /* usually either "." or "!" */
3311 if ((!cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp)
3312 && !(u.uswallow && mtmp == u.ustuck)) || !flags.verbose)
3314 pline("%s %s it.", The(str), vtense(str, "hit"));
3316 pline("%s
\82Í
\89½
\82©
\82É
\96½
\92\86\82µ
\82½
\81D", str);
3319 pline("%s %s %s%s", The(str), vtense(str, "hit"),
3320 mon_nam(mtmp), force);
3322 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½%s", str,
3323 mon_nam(mtmp), force);
3329 register const char *str;
3330 register struct monst *mtmp;
3334 "%s %s %s.", The(str), vtense(str, "miss"),
3335 ((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3340 "%s
\82Ì%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\82Í
\82¸
\82ê
\82½
\81D", str,
3341 ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
3348 skiprange(range, skipstart, skipend)
3349 int range, *skipstart, *skipend;
3351 int tr = (range / 4);
3352 int tmp = range - ((tr > 0) ? rnd(tr) : 0);
3354 *skipend = tmp - ((tmp / 4) * rnd(3));
3355 if (*skipend >= tmp)
3360 * Called for the following distance effects:
3361 * when a weapon is thrown (weapon == THROWN_WEAPON)
3362 * when an object is kicked (KICKED_WEAPON)
3363 * when an IMMEDIATE wand is zapped (ZAPPED_WAND)
3364 * when a light beam is flashed (FLASHED_LIGHT)
3365 * when a mirror is applied (INVIS_BEAM)
3366 * A thrown/kicked object falls down at end of its range or when a monster
3367 * is hit. The variable 'bhitpos' is set to the final position of the weapon
3368 * thrown/zapped. The ray of a wand may affect (by calling a provided
3369 * function) several objects and monsters on its path. The return value
3370 * is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
3372 * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
3373 * destroyed and *pobj set to NULL to indicate this.
3375 * Check !u.uswallow before calling bhit().
3376 * This function reveals the absence of a remembered invisible monster in
3377 * necessary cases (throwing or kicking weapons). The presence of a real
3378 * one is revealed for a weapon, but if not a weapon is left up to fhitm().
3381 bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
3382 register int ddx, ddy, range; /* direction and range */
3383 int weapon; /* see values in hack.h */
3384 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
3385 FDECL((*fhito), (OBJ_P, OBJ_P));
3386 struct obj **pobj; /* object tossed/used, set to NULL
3387 * if object is destroyed */
3390 struct obj *obj = *pobj;
3392 boolean shopdoor = FALSE, point_blank = TRUE;
3393 boolean in_skip = FALSE, allow_skip = FALSE;
3394 int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
3396 if (weapon == KICKED_WEAPON) {
3397 /* object starts one square in front of player */
3398 bhitpos.x = u.ux + ddx;
3399 bhitpos.y = u.uy + ddy;
3406 if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) {
3407 skiprange(range, &skiprange_start, &skiprange_end);
3408 allow_skip = !rn2(3);
3411 if (weapon == FLASHED_LIGHT) {
3412 tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
3413 } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3414 tmp_at(DISP_FLASH, obj_to_glyph(obj));
3416 while (range-- > 0) {
3430 if (is_pick(obj) && inside_shop(x, y)
3431 && (mtmp = shkcatch(obj, x, y))) {
3432 tmp_at(DISP_END, 0);
3436 typ = levl[bhitpos.x][bhitpos.y].typ;
3438 /* iron bars will block anything big enough */
3439 if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
3440 && typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
3441 point_blank ? 0 : !rn2(5), 1)) {
3442 /* caveat: obj might now be null... */
3449 if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
3450 boolean learn_it = FALSE;
3452 switch (obj->otyp) {
3455 if (is_db_wall(bhitpos.x, bhitpos.y)) {
3456 if (cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3458 open_drawbridge(x, y);
3462 case SPE_WIZARD_LOCK:
3463 if ((cansee(x, y) || cansee(bhitpos.x, bhitpos.y))
3464 && levl[x][y].typ == DRAWBRIDGE_DOWN)
3466 close_drawbridge(x, y);
3469 case SPE_FORCE_BOLT:
3470 if (typ != DRAWBRIDGE_UP)
3471 destroy_drawbridge(x, y);
3479 mtmp = m_at(bhitpos.x, bhitpos.y);
3484 * skiprange_start is only set if this is a thrown rock
3486 if (skiprange_start && (range == skiprange_start) && allow_skip) {
3487 if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
3490 pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
3491 skipcount ? " again" : "");
3493 You_hear("%s skip.", yname(obj));
3495 } else if (skiprange_start > skiprange_end + 1) {
3500 if (range <= skiprange_end) {
3502 if (range > 3) /* another bounce? */
3503 skiprange(range, &skiprange_start, &skiprange_end);
3504 } else if (mtmp && M_IN_WATER(mtmp->data)) {
3505 if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
3506 pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
3511 if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
3512 notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
3513 if (weapon == FLASHED_LIGHT) {
3514 /* FLASHED_LIGHT hitting invisible monster should
3515 pass through instead of stop so we call
3516 flash_hits_mon() directly rather than returning
3517 mtmp back to caller. That allows the flash to
3518 keep on going. Note that we use mtmp->minvis
3519 not canspotmon() because it makes no difference
3520 whether the hero can see the monster or not. */
3522 obj->ox = u.ux, obj->oy = u.uy;
3523 (void) flash_hits_mon(mtmp, obj);
3525 tmp_at(DISP_END, 0);
3526 return mtmp; /* caller will call flash_hits_mon */
3528 } else if (weapon == INVIS_BEAM) {
3529 /* Like FLASHED_LIGHT, INVIS_BEAM should continue
3530 through invisible targets; unlike it, we aren't
3531 prepared for multiple hits so just get first one
3532 that's either visible or could see its invisible
3533 self. [No tmp_at() cleanup is needed here.] */
3534 if (!mtmp->minvis || perceives(mtmp->data))
3536 } else if (weapon != ZAPPED_WAND) {
3537 /* THROWN_WEAPON, KICKED_WEAPON */
3538 tmp_at(DISP_END, 0);
3539 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
3540 map_invisible(bhitpos.x, bhitpos.y);
3544 (*fhitm)(mtmp, obj);
3548 if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING
3549 && glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
3550 unmap_object(bhitpos.x, bhitpos.y);
3555 if (bhitpile(obj, fhito, bhitpos.x, bhitpos.y, 0))
3558 if (weapon == KICKED_WEAPON
3559 && ((obj->oclass == COIN_CLASS
3560 && OBJ_AT(bhitpos.x, bhitpos.y))
3561 || ship_object(obj, bhitpos.x, bhitpos.y,
3562 costly_spot(bhitpos.x, bhitpos.y)))) {
3563 tmp_at(DISP_END, 0);
3564 return (struct monst *) 0;
3567 if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
3568 switch (obj->otyp) {
3573 case SPE_WIZARD_LOCK:
3574 case SPE_FORCE_BOLT:
3575 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
3576 if (cansee(bhitpos.x, bhitpos.y)
3577 || (obj->otyp == WAN_STRIKING && !Deaf))
3579 if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
3580 && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
3582 add_damage(bhitpos.x, bhitpos.y, 400L);
3588 if (!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
3593 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
3594 /* 'I' present but no monster: erase */
3595 /* do this before the tmp_at() */
3596 if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
3598 unmap_object(bhitpos.x, bhitpos.y);
3601 tmp_at(bhitpos.x, bhitpos.y);
3603 /* kicked objects fall in pools */
3604 if ((weapon == KICKED_WEAPON)
3605 && (is_pool(bhitpos.x, bhitpos.y)
3606 || is_lava(bhitpos.x, bhitpos.y)))
3608 if (IS_SINK(typ) && weapon != FLASHED_LIGHT)
3609 break; /* physical objects fall onto sink */
3611 /* limit range of ball so hero won't make an invalid move */
3612 if (weapon == THROWN_WEAPON && range > 0
3613 && obj->otyp == HEAVY_IRON_BALL) {
3616 if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
3619 pline("%s hits %s.", The(distant_name(obj, xname)),
3622 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", distant_name(obj, xname),
3626 } else if (obj == uball) {
3627 if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
3628 /* nb: it didn't hit anything directly */
3631 pline("%s jerks to an abrupt halt.",
3632 The(distant_name(obj, xname))); /* lame */
3634 pline("%s
\82Í
\82Æ
\82Â
\82º
\82ñ
\83K
\83N
\83\93\82Æ
\8e~
\82Ü
\82Á
\82½
\81D",
3635 distant_name(obj, xname)); /* lame */
3638 } else if (Sokoban && (t = t_at(x, y)) != 0
3639 && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
3640 || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
3641 /* hero falls into the trap, so ball stops */
3647 /* thrown/kicked missile has moved away from its starting spot */
3648 point_blank = FALSE; /* affects passing through iron bars */
3651 if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
3652 tmp_at(DISP_END, 0);
3656 pay_for_damage("destroy", FALSE);
3658 pay_for_damage("
\94j
\89ó
\82·
\82é", FALSE);
3660 return (struct monst *) 0;
3663 /* process thrown boomerang, which travels a curving path...
3664 * A multi-shot volley ought to have all missiles in flight at once,
3665 * but we're called separately for each one. We terminate the volley
3666 * early on a failed catch since continuing to throw after being hit
3667 * is too obviously silly.
3670 boomhit(obj, dx, dy)
3675 int boom; /* showsym[] index */
3677 boolean counterclockwise = TRUE; /* right-handed throw */
3679 /* counterclockwise traversal patterns:
3680 * ..........................54.................................
3681 * ..................43.....6..3....765.........................
3682 * ..........32.....5..2...7...2...8...4....87..................
3683 * .........4..1....6..1...8..1....9...3...9..6.....98..........
3684 * ..21@....5...@...7..@....9@......@12....@...5...@..7.....@9..
3685 * .3...9....6..9....89.....................1..4...1..6....1..8.
3686 * .4...8.....78.............................23....2..5...2...7.
3687 * ..567............................................34....3..6..
3688 * ........................................................45...
3689 * (invert rows for corresponding clockwise patterns)
3694 boom = counterclockwise ? S_boomleft : S_boomright;
3695 for (i = 0; i < 8; i++)
3696 if (xdir[i] == dx && ydir[i] == dy)
3698 tmp_at(DISP_FLASH, cmap_to_glyph(boom));
3699 for (ct = 0; ct < 10; ct++) {
3700 i = (i + 8) % 8; /* 0..7 (8 -> 0, -1 -> 7) */
3701 boom = (S_boomleft + S_boomright - boom); /* toggle */
3702 tmp_at(DISP_CHANGE, cmap_to_glyph(boom)); /* change glyph */
3707 if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
3709 tmp_at(DISP_END, 0);
3712 if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)
3713 || closed_door(bhitpos.x, bhitpos.y)) {
3718 if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
3719 if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
3720 /* we hit ourselves */
3721 (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), obj,
3725 "
\83u
\81[
\83\81\83\89\83\93");
3728 } else { /* we catch it */
3729 tmp_at(DISP_END, 0);
3731 You("skillfully catch the boomerang.");
3733 You("
\8fã
\8eè
\82É
\83u
\81[
\83\81\83\89\83\93\82ð
\92Í
\82Ü
\82¦
\82½
\81D");
3737 tmp_at(bhitpos.x, bhitpos.y);
3739 if (IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
3742 break; /* boomerang falls on sink */
3744 /* ct==0, initial position, we want next delta to be same;
3745 ct==5, opposite position, repeat delta undoes first one */
3747 i += (counterclockwise ? -1 : 1);
3749 tmp_at(DISP_END, 0); /* do not leave last symbol */
3750 return (struct monst *) 0;
3753 /* used by buzz(); also used by munslime(muse.c); returns damage to mon */
3755 zhitm(mon, type, nd, ootmp)
3756 register struct monst *mon;
3757 register int type, nd;
3758 struct obj **ootmp; /* to return worn armor for caller to disintegrate */
3760 register int tmp = 0;
3761 register int abstype = abs(type) % 10;
3762 boolean sho_shieldeff = FALSE;
3763 boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
3765 *ootmp = (struct obj *) 0;
3767 case ZT_MAGIC_MISSILE:
3768 if (resists_magm(mon)) {
3769 sho_shieldeff = TRUE;
3774 tmp = spell_damage_bonus(tmp);
3777 if (resists_fire(mon)) {
3778 sho_shieldeff = TRUE;
3782 if (resists_cold(mon))
3785 tmp = spell_damage_bonus(tmp);
3786 if (burnarmor(mon)) {
3788 (void) destroy_mitem(mon, POTION_CLASS, AD_FIRE);
3790 (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
3792 (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
3793 destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */
3797 if (resists_cold(mon)) {
3798 sho_shieldeff = TRUE;
3802 if (resists_fire(mon))
3805 tmp = spell_damage_bonus(tmp);
3807 (void) destroy_mitem(mon, POTION_CLASS, AD_COLD);
3811 (void) sleep_monst(mon, d(nd, 25),
3812 type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
3814 case ZT_DEATH: /* death/disintegration */
3815 if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
3816 if (mon->data == &mons[PM_DEATH]) {
3817 mon->mhpmax += mon->mhpmax / 2;
3818 if (mon->mhpmax >= MAGIC_COOKIE)
3819 mon->mhpmax = MAGIC_COOKIE - 1;
3820 mon->mhp = mon->mhpmax;
3824 if (nonliving(mon->data) || is_demon(mon->data)
3825 || is_vampshifter(mon) || resists_magm(mon)) {
3826 /* similar to player */
3827 sho_shieldeff = TRUE;
3830 type = -1; /* so they don't get saving throws */
3834 if (resists_disint(mon)) {
3835 sho_shieldeff = TRUE;
3836 } else if (mon->misc_worn_check & W_ARMS) {
3837 /* destroy shield; victim survives */
3838 *ootmp = which_armor(mon, W_ARMS);
3839 } else if (mon->misc_worn_check & W_ARM) {
3840 /* destroy body armor, also cloak if present */
3841 *ootmp = which_armor(mon, W_ARM);
3842 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
3843 m_useup(mon, otmp2);
3845 /* no body armor, victim dies; destroy cloak
3846 and shirt now in case target gets life-saved */
3848 if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
3849 m_useup(mon, otmp2);
3850 if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
3851 m_useup(mon, otmp2);
3853 type = -1; /* no saving throw wanted */
3854 break; /* not ordinary damage */
3859 if (resists_elec(mon)) {
3860 sho_shieldeff = TRUE;
3862 /* can still blind the monster */
3866 tmp = spell_damage_bonus(tmp);
3867 if (!resists_blnd(mon)
3868 && !(type > 0 && u.uswallow && mon == u.ustuck)) {
3869 register unsigned rnd_tmp = rnd(50);
3871 if ((mon->mblinded + rnd_tmp) > 127)
3872 mon->mblinded = 127;
3874 mon->mblinded += rnd_tmp;
3877 (void) destroy_mitem(mon, WAND_CLASS, AD_ELEC);
3878 /* not actually possible yet */
3880 (void) destroy_mitem(mon, RING_CLASS, AD_ELEC);
3883 if (resists_poison(mon)) {
3884 sho_shieldeff = TRUE;
3890 if (resists_acid(mon)) {
3891 sho_shieldeff = TRUE;
3896 acid_damage(MON_WEP(mon));
3898 erode_armor(mon, ERODE_CORRODE);
3902 shieldeff(mon->mx, mon->my);
3903 if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
3905 if (tmp > 0 && type >= 0
3906 && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
3909 tmp = 0; /* don't allow negative damage */
3910 debugpline3("zapped monster hp = %d (= %d - %d)", mon->mhp - tmp,
3917 zhitu(type, nd, fltxt, sx, sy)
3922 int dam = 0, abstyp = abs(type);
3926 Sprintf(buf, "%s
\82É
\82æ
\82Á
\82Ä", fltxt);
3930 switch (abstyp % 10) {
3931 case ZT_MAGIC_MISSILE:
3935 pline_The("missiles bounce off!");
3937 pline("
\96\82\96@
\82Ì
\96î
\82Í
\94½
\8eË
\82µ
\82½
\81I");
3940 exercise(A_STR, FALSE);
3944 if (Fire_resistance) {
3947 You("don't feel hot!");
3949 You("
\94M
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81I");
3950 ugolemeffects(AD_FIRE, d(nd, 6));
3955 if (burnarmor(&youmonst)) { /* "body hit" */
3957 destroy_item(POTION_CLASS, AD_FIRE);
3959 destroy_item(SCROLL_CLASS, AD_FIRE);
3961 destroy_item(SPBOOK_CLASS, AD_FIRE);
3962 destroy_item(FOOD_CLASS, AD_FIRE);
3966 if (Cold_resistance) {
3969 You("don't feel cold.");
3971 You("
\97â
\82½
\82³
\82ð
\8a´
\82¶
\82È
\82¢
\81D");
3972 ugolemeffects(AD_COLD, d(nd, 6));
3977 destroy_item(POTION_CLASS, AD_COLD);
3980 if (Sleep_resistance) {
3981 shieldeff(u.ux, u.uy);
3983 You("don't feel sleepy.");
3985 You("
\96°
\82
\82È
\82ç
\82È
\82¢
\81D");
3987 fall_asleep(-d(nd, 25), TRUE); /* sleep ray */
3991 if (abstyp == ZT_BREATH(ZT_DEATH)) {
3992 if (Disint_resistance) {
3994 You("are not disintegrated.");
3996 You("
\95ª
\89ð
\82³
\82ê
\82È
\82¢
\81D");
3999 /* destroy shield; other possessions are safe */
4000 (void) destroy_arm(uarms);
4003 /* destroy suit; if present, cloak goes too */
4005 (void) destroy_arm(uarmc);
4006 (void) destroy_arm(uarm);
4009 /* no shield or suit, you're dead; wipe out cloak
4010 and/or shirt in case of life-saving or bones */
4012 (void) destroy_arm(uarmc);
4014 (void) destroy_arm(uarmu);
4015 } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
4018 You("seem unaffected.");
4020 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
4022 } else if (Antimagic) {
4025 You("aren't affected.");
4027 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4030 killer.format = KILLED_BY_AN;
4031 Strcpy(killer.name, fltxt ? fltxt : "");
4032 /* when killed by disintegration breath, don't leave corpse */
4033 u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
4035 return; /* lifesaved */
4037 if (Shock_resistance) {
4040 You("aren't affected.");
4042 You("
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D");
4043 ugolemeffects(AD_ELEC, d(nd, 6));
4046 exercise(A_CON, FALSE);
4049 destroy_item(WAND_CLASS, AD_ELEC);
4051 destroy_item(RING_CLASS, AD_ELEC);
4055 poisoned("blast", A_DEX, "poisoned blast", 15, FALSE);
4057 poisoned("
\91§", A_DEX, "
\93Å
\82Ì
\91§", 15, FALSE);
4060 if (Acid_resistance) {
4062 pline_The("acid doesn't hurt.");
4064 pline("
\8e_
\82Å
\82Í
\8f\9d\82Â
\82©
\82È
\82©
\82Á
\82½
\81D");
4068 pline_The("acid burns!");
4070 pline("
\8e_
\82Å
\8fÄ
\82¯
\82½
\81I");
4072 exercise(A_STR, FALSE);
4074 /* using two weapons at once makes both of them more vulnerable */
4075 if (!rn2(u.twoweap ? 3 : 6))
4077 if (u.twoweap && !rn2(3))
4078 acid_damage(uswapwep);
4080 erode_armor(&youmonst, ERODE_CORRODE);
4084 /* Half_spell_damage protection yields half-damage for wands & spells,
4085 including hero's own ricochets; breath attacks do full damage */
4086 if (dam && Half_spell_damage && !(abstyp >= 20 && abstyp <= 29))
4087 dam = (dam + 1) / 2;
4088 losehp(dam, fltxt, KILLED_BY_AN);
4093 * burn objects (such as scrolls and spellbooks) on floor
4094 * at position x,y; return the number of objects burned
4097 burn_floor_objects(x, y, give_feedback, u_caused)
4099 boolean give_feedback; /* caller needs to decide about visibility checks */
4102 struct obj *obj, *obj2;
4103 long i, scrquan, delquan;
4104 char buf1[BUFSZ], buf2[BUFSZ];
4107 for (obj = level.objects[x][y]; obj; obj = obj2) {
4108 obj2 = obj->nexthere;
4109 if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
4110 || (obj->oclass == FOOD_CLASS
4111 && obj->otyp == GLOB_OF_GREEN_SLIME)) {
4112 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL
4113 || obj_resists(obj, 2, 100))
4115 scrquan = obj->quan; /* number present */
4116 delquan = 0L; /* number to destroy */
4117 for (i = scrquan; i > 0L; i--)
4121 /* save name before potential delobj() */
4122 if (give_feedback) {
4124 Strcpy(buf1, (x == u.ux && y == u.uy)
4126 : distant_name(obj, xname));
4128 Strcpy(buf2, (x == u.ux && y == u.uy)
4130 : distant_name(obj, xname));
4131 obj->quan = scrquan;
4133 /* useupf(), which charges, only if hero caused damage */
4135 useupf(obj, delquan);
4136 else if (delquan < scrquan)
4137 obj->quan -= delquan;
4141 if (give_feedback) {
4144 pline("%ld %s burn.", delquan, buf2);
4146 pline("%ld%s
\82Ì%s
\82ª
\94R
\82¦
\82½
\81D",
4148 obj->oclass == SCROLL_CLASS ? "
\96\87" : "
\8dû",
4153 pline("%s burns.", An(buf1));
4155 pline("%s
\82Í
\94R
\82¦
\82½
\81D", buf1);
4163 /* will zap/spell/breath attack score a hit against armor class `ac'? */
4167 int type; /* either hero cast spell type or 0 */
4169 int chance = rn2(20);
4170 int spell_bonus = type ? spell_hit_bonus(type) : 0;
4172 /* small chance for naked target to avoid being hit */
4174 return rnd(10) < ac + spell_bonus;
4176 /* very high armor protection does not achieve invulnerability */
4179 return (3 - chance < ac + spell_bonus);
4183 disintegrate_mon(mon, type, fltxt)
4185 int type; /* hero vs other */
4188 struct obj *otmp, *otmp2, *m_amulet = mlifesaver(mon);
4190 if (canseemon(mon)) {
4193 pline("%s is disintegrated!", Monnam(mon));
4195 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I", Monnam(mon));
4198 hit(fltxt, mon, "!");
4200 hit(fltxt, mon, "
\81I");
4203 /* note: worn amulet of life saving must be preserved in order to operate */
4204 #define oresist_disintegration(obj) \
4205 (objects[obj->otyp].oc_oprop == DISINT_RES || obj_resists(obj, 5, 50) \
4206 || is_quest_artifact(obj) || obj == m_amulet)
4208 for (otmp = mon->minvent; otmp; otmp = otmp2) {
4210 if (!oresist_disintegration(otmp)) {
4211 if (otmp->owornmask) {
4212 /* in case monster's life gets saved */
4213 mon->misc_worn_check &= ~otmp->owornmask;
4214 if (otmp->owornmask & W_WEP)
4215 setmnotwielded(mon, otmp);
4216 /* also dismounts hero if this object is steed's saddle */
4217 update_mon_intrinsics(mon, otmp, FALSE, TRUE);
4218 otmp->owornmask = 0L;
4220 obj_extract_self(otmp);
4221 obfree(otmp, (struct obj *) 0);
4225 #undef oresist_disintegration
4228 monkilled(mon, (char *) 0, -AD_RBRE);
4234 * type == 0 to 9 : you shooting a wand
4235 * type == 10 to 19 : you casting a spell
4236 * type == 20 to 29 : you breathing as a monster
4237 * type == -10 to -19 : monster casting spell
4238 * type == -20 to -29 : monster breathing at you
4239 * type == -30 to -39 : monster shooting a wand
4240 * called with dx = dy = 0 with vertical bolts
4243 buzz(type, nd, sx, sy, dx, dy)
4244 register int type, nd;
4245 register xchar sx, sy;
4246 register int dx, dy;
4248 int range, abstype = abs(type) % 10;
4250 register xchar lsx, lsy;
4253 boolean shopdamage = FALSE;
4258 /* if its a Hero Spell then get its SPE_TYPE */
4259 spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
4261 fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
4267 tmp = zhitm(u.ustuck, type, nd, &otmp);
4272 pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
4275 pline("%s
\82Í%s
\82ð
\82Ð
\82«
\82³
\82¢
\82½%s", fltxt, mon_nam(u.ustuck),
4278 /* Using disintegration from the inside only makes a hole... */
4279 if (tmp == MAGIC_COOKIE)
4281 if (u.ustuck->mhp < 1)
4288 if (dx == 0 && dy == 0)
4290 save_bhitpos = bhitpos;
4292 tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
4293 while (range-- > 0) {
4298 if (isok(sx, sy) && (lev = &levl[sx][sy])->typ) {
4300 if (cansee(sx, sy)) {
4301 /* reveal/unreveal invisible monsters before tmp_at() */
4302 if (mon && !canspotmon(mon))
4303 map_invisible(sx, sy);
4304 else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
4305 unmap_object(sx, sy);
4308 if (ZAP_POS(lev->typ) || (isok(lsx, lsy) && cansee(lsx, lsy)))
4310 delay_output(); /* wait a little */
4315 /* hit() and miss() need bhitpos to match the target */
4316 bhitpos.x = sx, bhitpos.y = sy;
4317 /* Fireballs only damage when they explode */
4318 if (type != ZT_SPELL(ZT_FIRE))
4319 range += zap_over_floor(sx, sy, type, &shopdamage, 0);
4322 if (type == ZT_SPELL(ZT_FIRE))
4325 mon->mstrategy &= ~STRAT_WAITMASK;
4327 if (zap_hit(find_mac(mon), spell_type)) {
4328 if (mon_reflects(mon, (char *) 0)) {
4329 if (cansee(mon->mx, mon->my)) {
4330 hit(fltxt, mon, exclam(0));
4331 shieldeff(mon->mx, mon->my);
4333 (void) mon_reflects(mon,
4334 "But it reflects from %s %s!");
4336 (void) mon_reflects(mon,
4337 "
\82µ
\82©
\82µ
\82»
\82ê
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81I");
4343 boolean mon_could_move = mon->mcanmove;
4344 int tmp = zhitm(mon, type, nd, &otmp);
4346 if (is_rider(mon->data)
4347 && abs(type) == ZT_BREATH(ZT_DEATH)) {
4348 if (canseemon(mon)) {
4349 hit(fltxt, mon, ".");
4351 pline("%s disintegrates.", Monnam(mon));
4353 pline("%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81D", Monnam(mon));
4355 pline("%s body reintegrates before your %s!",
4356 s_suffix(Monnam(mon)),
4357 (eyecount(youmonst.data) == 1)
4359 : makeplural(body_part(EYE)));
4361 pline("%s
\82Ì
\91Ì
\82Í
\82 \82È
\82½
\82Ì
\96Ú
\82Ì
\91O
\82Å
\8dÄ
\8c\8b\8d\87\82µ
\82½
\81I",
4365 pline("%s resurrects!", Monnam(mon));
4367 pline("%s
\82Í
\91h
\82Á
\82½
\81I", Monnam(mon));
4369 mon->mhp = mon->mhpmax;
4370 break; /* Out of while loop */
4372 if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
4373 if (canseemon(mon)) {
4375 hit(fltxt, mon, ".");
4377 hit(fltxt, mon, "
\81D");
4379 pline("%s absorbs the deadly %s!", Monnam(mon),
4380 type == ZT_BREATH(ZT_DEATH) ? "blast"
4383 pline("%s
\82Í
\8e\80\82Ì%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", Monnam(mon),
4384 type == ZT_BREATH(ZT_DEATH) ? "
\91§"
4388 pline("It seems even stronger than before.");
4390 pline("
\82³
\82ç
\82É
\8b
\82
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82³
\82¦
\82·
\82é
\81D");
4392 break; /* Out of while loop */
4395 if (tmp == MAGIC_COOKIE) { /* disintegration */
4396 disintegrate_mon(mon, type, fltxt);
4397 } else if (mon->mhp < 1) {
4399 monkilled(mon, fltxt, AD_RBRE);
4404 /* normal non-fatal hit */
4405 hit(fltxt, mon, exclam(tmp));
4407 /* some armor was destroyed; no damage done */
4410 pline("%s %s is disintegrated!",
4412 pline("%s
\82Ì%s
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I",
4413 s_suffix(Monnam(mon)),
4414 distant_name(otmp, xname));
4417 if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
4425 } else if (sx == u.ux && sy == u.uy && range >= 0) {
4427 if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *) 0)) {
4430 } else if (zap_hit((int) u.uac, 0)) {
4433 pline("%s hits you!", The(fltxt));
4435 pline("%s
\82Í
\82 \82È
\82½
\82É
\96½
\92\86\82µ
\82½
\81I", fltxt);
4439 (void) ureflects("But %s reflects from your %s!",
4442 (void) ureflects("
\82µ
\82©
\82µ
\81C%s
\82Í
\82 \82È
\82½
\82Ì%s
\82É
\82æ
\82Á
\82Ä
\94½
\8eË
\82µ
\82½
\81D",
4447 pline("For some reason you are not affected.");
4449 pline("
\82È
\82º
\82©
\82 \82È
\82½
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82©
\82Á
\82½
\81D");
4454 zhitu(type, nd, fltxt, sx, sy);
4456 } else if (!Blind) {
4458 pline("%s whizzes by you!", The(fltxt));
4460 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82»
\82Î
\82ð
\82©
\82·
\82ß
\82½
\81I", fltxt);
4461 } else if (abstype == ZT_LIGHTNING) {
4462 Your("%s tingles.", body_part(ARM));
4464 if (abstype == ZT_LIGHTNING)
4465 (void) flashburn((long) d(nd, 50));
4470 if (!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
4475 if (type == ZT_SPELL(ZT_FIRE)) {
4478 break; /* fireballs explode before the wall */
4482 if (range && isok(lsx, lsy) && cansee(lsx, lsy)) {
4483 pline("%s %s!", The(fltxt),
4485 ? "vanishes into the aether"
4487 if (Is_airlevel(&u.uz)) goto get_out_buzz;
4489 if (!dx || !dy || !rn2(20)) {
4493 if (isok(sx, lsy) && ZAP_POS(rmn = levl[sx][lsy].typ)
4494 && !closed_door(sx, lsy)
4495 && (IS_ROOM(rmn) || (isok(sx + dx, lsy)
4496 && ZAP_POS(levl[sx + dx][lsy].typ))))
4498 if (isok(lsx, sy) && ZAP_POS(rmn = levl[lsx][sy].typ)
4499 && !closed_door(lsx, sy)
4500 && (IS_ROOM(rmn) || (isok(lsx, sy + dy)
4501 && ZAP_POS(levl[lsx][sy + dy].typ))))
4502 if (!bounce || rn2(2))
4507 dx = -dx; /* fall into... */
4515 tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, abstype));
4519 tmp_at(DISP_END, 0);
4520 if (type == ZT_SPELL(ZT_FIRE))
4521 explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
4525 pay_for_damage(abstype == ZT_FIRE
4527 : abstype == ZT_COLD
4529 /* "damage" indicates wall rather than door */
4530 : abstype == ZT_ACID
4532 : abstype == ZT_DEATH
4537 pay_for_damage(abstype == ZT_FIRE
4539 : abstype == ZT_COLD
4540 ? "
\95²
\81X
\82É
\82·
\82é"
4541 : abstype == ZT_ACID
4542 ? "
\8f\9d\82Â
\82¯
\82é"
4543 : abstype == ZT_DEATH
4544 ? "
\95²
\8dÓ
\82·
\82é"
4545 : "
\94j
\89ó
\82·
\82é",
4548 bhitpos = save_bhitpos;
4556 struct rm *lev = &levl[x][y];
4561 msg = "The ice crackles and melts.";
4563 msg = "
\95X
\82Í
\83s
\83L
\83s
\83L
\96Â
\82è
\81C
\97n
\82¯
\82½
\81D";
4564 if (lev->typ == DRAWBRIDGE_UP) {
4565 lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
4566 } else { /* lev->typ == ICE */
4568 if (lev->icedpool == ICED_POOL)
4573 lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
4577 spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
4578 obj_ice_effects(x, y, FALSE);
4585 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
4588 pline("%s settles...", An(xname(otmp)));
4590 pline("%s
\82Í
\82Í
\82Ü
\82Á
\82½
\81D
\81D
\81D", xname(otmp));
4592 obj_extract_self(otmp); /* boulder isn't being pushed */
4593 if (!boulder_hits_pool(otmp, x, y, FALSE))
4594 impossible("melt_ice: no pool?");
4595 /* try again if there's another boulder and pool didn't fill */
4596 } while (is_pool(x, y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
4599 if (x == u.ux && y == u.uy)
4600 spoteffects(TRUE); /* possibly drown, notice objects */
4603 #define MIN_ICE_TIME 50
4604 #define MAX_ICE_TIME 2000
4606 * Usually start a melt_ice timer; sometimes the ice will become
4607 * permanent instead.
4610 start_melt_ice_timeout(x, y, min_time)
4612 long min_time; /* <x,y>'s old melt timeout (deleted by time we get here) */
4617 when = (int) min_time;
4618 if (when < MIN_ICE_TIME - 1)
4619 when = MIN_ICE_TIME - 1;
4621 /* random timeout; surrounding ice locations ought to be a factor... */
4622 while (++when <= MAX_ICE_TIME)
4623 if (!rn2((MAX_ICE_TIME - when) + MIN_ICE_TIME))
4626 /* if we're within MAX_ICE_TIME, install a melt timer;
4627 otherwise, omit it to leave this ice permanent */
4628 if (when <= MAX_ICE_TIME) {
4629 where = ((long) x << 16) | (long) y;
4630 (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
4631 long_to_any(where));
4638 * Called when ice has melted completely away.
4641 melt_ice_away(arg, timeout)
4643 long timeout UNUSED;
4646 long where = arg->a_long;
4648 y = (xchar) (where & 0xFFFF);
4649 x = (xchar) ((where >> 16) & 0xFFFF);
4650 /* melt_ice does newsym when appropriate */
4651 melt_ice(x, y, "Some ice melts away.");
4654 /* Burn floor scrolls, evaporate pools, etc... in a single square.
4655 * Used both for normal bolts of fire, cold, etc... and for fireballs.
4656 * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
4657 * amount by which range is reduced (the latter is just ignored by fireballs)
4660 zap_over_floor(x, y, type, shopdamage, exploding_wand_typ)
4663 boolean *shopdamage;
4664 short exploding_wand_typ;
4666 const char *zapverb;
4669 struct rm *lev = &levl[x][y];
4670 boolean see_it = cansee(x, y), yourzap;
4671 int rangemod = 0, abstype = abs(type) % 10;
4676 if (t && t->ttyp == WEB) {
4677 /* a burning web is too flimsy to notice if you can't see it */
4680 Norep("A web bursts into flames!");
4682 Norep("
\82
\82à
\82Ì
\91\83\82Í
\89\8a\82É
\95ï
\82Ü
\82ê
\82½
\81I");
4683 (void) delfloortrap(t);
4688 melt_ice(x, y, (char *) 0);
4689 } else if (is_pool(x, y)) {
4691 const char *msgtxt = "You hear hissing gas.";
4693 const char *msgtxt = "
\82µ
\82ã
\81[
\82Á
\82Æ
\82¢
\82¤
\83K
\83X
\82Ì
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4695 if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
4698 msgtxt = "Some water evaporates.";
4700 msgtxt = "
\82·
\82±
\82µ
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4704 t = maketrap(x, y, PIT);
4709 msgtxt = "The water evaporates.";
4711 msgtxt = "
\90\85\82ª
\8fö
\94
\82µ
\82½
\81D";
4713 Norep("%s", msgtxt);
4714 if (lev->typ == ROOM)
4716 } else if (IS_FOUNTAIN(lev->typ)) {
4719 pline("Steam billows from the fountain.");
4721 pline("
\90ò
\82©
\82ç
\8fö
\8bC
\82ª
\97§
\82¿
\82Ì
\82Ú
\82Á
\82½
\81D");
4723 dryup(x, y, type > 0);
4725 break; /* ZT_FIRE */
4728 if (is_pool(x, y) || is_lava(x, y)) {
4729 boolean lava = is_lava(x, y);
4730 boolean moat = is_moat(x, y);
4732 if (lev->typ == WATER) {
4733 /* For now, don't let WATER freeze. */
4736 pline_The("water freezes for a moment.");
4738 pline("
\90\85\82Í
\88ê
\8fu
\93\80\82Á
\82½
\81D");
4741 You_hear("a soft crackling.");
4743 You_hear("
\83s
\83L
\81I
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4744 rangemod -= 1000; /* stop */
4747 if (lev->typ == DRAWBRIDGE_UP) {
4748 lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
4749 lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
4753 (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
4754 lev->typ = (lava ? ROOM : ICE);
4760 Norep("The lava cools and solidifies.");
4762 Norep("
\97n
\8aâ
\82Í
\97â
\82¦
\8cÅ
\82Ü
\82Á
\82½
\81D");
4765 Norep("The %s is bridged with ice!",
4767 Norep("%s
\82É
\95X
\82Ì
\8b´
\82ª
\82©
\82¯
\82ç
\82ê
\82½
\81I",
4768 waterbody_name(x, y));
4771 Norep("The water freezes.");
4773 Norep("
\90\85\82Í
\93\80\82Á
\82½
\81D");
4777 You_hear("a crackling sound.");
4779 You_hear("
\83s
\83L
\83s
\83L
\83b
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
4781 if (x == u.ux && y == u.uy) {
4782 if (u.uinwater) { /* not just `if (Underwater)' */
4783 /* leave the no longer existent water */
4787 vision_full_recalc = 1;
4788 } else if (u.utrap && u.utraptype == TT_LAVA) {
4792 You("pass through the now-solid rock.");
4794 You("
\82¢
\82Ü
\8cÅ
\82
\82È
\82Á
\82½
\82Î
\82©
\82è
\82Ì
\90Î
\82Ì
\92\86\82ð
\82·
\82è
\94²
\82¯
\82½
\81D");
4796 u.utrap = rn1(50, 20);
4797 u.utraptype = TT_INFLOOR;
4799 You("are firmly stuck in the cooling rock.");
4801 You("
\97â
\82¦
\82½
\8aâ
\82Ì
\82È
\82©
\82É
\82µ
\82Á
\82©
\82è
\82Æ
\96\84\82Ü
\82Á
\82½
\81D");
4804 } else if ((mon = m_at(x, y)) != 0) {
4805 /* probably ought to do some hefty damage to any
4806 non-ice creature caught in freezing water;
4807 at a minimum, eels are forced out of hiding */
4808 if (is_swimmer(mon->data) && mon->mundetected) {
4809 mon->mundetected = 0;
4814 start_melt_ice_timeout(x, y, 0L);
4815 obj_ice_effects(x, y, TRUE);
4819 } else if (is_ice(x, y)) {
4822 /* Already ice here, so just firm it up. */
4823 /* Now ensure that only ice that is already timed is affected */
4824 if ((melt_time = spot_time_left(x, y, MELT_ICE_AWAY)) != 0L) {
4825 spot_stop_timers(x, y, MELT_ICE_AWAY);
4826 start_melt_ice_timeout(x, y, melt_time);
4829 break; /* ZT_COLD */
4832 if (lev->typ == IRONBARS) {
4833 if ((lev->wall_info & W_NONDIGGABLE) != 0) {
4835 Norep("The %s corrode somewhat but remain intact.",
4836 defsyms[S_bars].explanation);
4837 /* but nothing actually happens... */
4841 Norep("The %s melt.", defsyms[S_bars].explanation);
4842 if (*in_rooms(x, y, SHOPBASE)) {
4843 /* in case we ever have a shop bounded by bars */
4847 add_damage(x, y, (type >= 0) ? 300L : 0L);
4852 lev->doormask = D_NODOOR;
4858 break; /* ZT_ACID */
4864 /* set up zap text for possible door feedback; for exploding wand, we
4865 want "the blast" rather than "your blast" even if hero caused it */
4866 yourzap = (type >= 0 && !exploding_wand_typ);
4868 zapverb = "blast"; /* breath attack or wand explosion */
4870 zapverb = "
\8fÕ
\8c\82"; /* breath attack or wand explosion */
4872 if (!exploding_wand_typ) {
4873 if (abs(type) < ZT_SPELL(0))
4875 zapverb = "bolt"; /* wand zap */
4877 zapverb = "
\8cõ
\90ü"; /* wand zap */
4879 else if (abs(type) < ZT_BREATH(0))
4883 zapverb = "
\8eô
\95¶";
4886 /* secret door gets revealed, converted into regular door */
4887 if (levl[x][y].typ == SDOOR) {
4888 cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
4889 /* target spot will now pass closed_door() test below
4890 (except on rogue level) */
4893 pline("%s %s reveals a secret door.",
4894 yourzap ? "Your" : "The", zapverb);
4895 else if (Is_rogue_level(&u.uz))
4896 draft_message(FALSE); /* "You feel a draft." (open doorway) */
4899 /* regular door absorbs remaining zap range, possibly gets destroyed */
4900 if (closed_door(x, y)) {
4901 int new_doormask = -1;
4902 const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
4907 new_doormask = D_NODOOR;
4909 see_txt = "The door is consumed in flames!";
4911 see_txt = "
\94à
\82Í
\89\8a\82Å
\8fÄ
\82«
\82Â
\82
\82³
\82ê
\82½
\81I";
4913 sense_txt = "smell smoke.";
4915 sense_txt = "
\89\8c\82Ì
\93õ
\82¢
\82ª
\82µ
\82½
\81D";
4918 new_doormask = D_NODOOR;
4920 see_txt = "The door freezes and shatters!";
4922 see_txt = "
\94à
\82Í
\93\80\82è
\81C
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I";
4924 sense_txt = "feel cold.";
4926 sense_txt = "
\97â
\8bC
\82ð
\8a´
\82¶
\82½
\81D";
4929 /* death spells/wands don't disintegrate */
4930 if (abs(type) != ZT_BREATH(ZT_DEATH))
4932 new_doormask = D_NODOOR;
4934 see_txt = "The door disintegrates!";
4936 see_txt = "
\94à
\82Í
\95²
\8dÓ
\82³
\82ê
\82½
\81I";
4938 hear_txt = "crashing wood.";
4940 hear_txt = "
\96Ø
\82Ì
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4943 new_doormask = D_BROKEN;
4945 see_txt = "The door splinters!";
4947 see_txt = "
\94à
\82Í
\82¸
\82½
\82¸
\82½
\82É
\82È
\82Á
\82½
\81I";
4949 hear_txt = "crackling.";
4951 hear_txt = "
\83s
\83L
\83s
\83L
\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D";
4955 if (exploding_wand_typ > 0) {
4956 /* Magical explosion from misc exploding wand */
4957 if (exploding_wand_typ == WAN_STRIKING) {
4958 new_doormask = D_BROKEN;
4959 see_txt = "The door crashes open!";
4960 sense_txt = "feel a burst of cool air.";
4965 /* "the door absorbs the blast" would be
4966 inaccurate for an exploding wand since
4967 other adjacent locations still get hit */
4968 if (exploding_wand_typ)
4970 pline_The("door remains intact.");
4972 pline_The("
\94à
\82Í
\96³
\8f\9d\82¾
\81D");
4975 pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
4978 pline_The("
\94à
\82Í%s%s
\82ð
\8bz
\8eû
\82µ
\82½
\81I", yourzap ? "
\82 \82È
\82½
\82ª
\95ú
\82Á
\82½" : "",
4983 You_feel("vibrations.");
4985 You("
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D");
4988 if (new_doormask >= 0) { /* door gets broken */
4989 if (*in_rooms(x, y, SHOPBASE)) {
4991 add_damage(x, y, 400L);
4993 } else /* caused by monster */
4994 add_damage(x, y, 0L);
4996 lev->doormask = new_doormask;
4997 unblock_point(x, y); /* vision */
5001 } else if (sense_txt) {
5002 #if 0 /*JP*//*
\81u
\82 \82È
\82½
\82Í
\81v
\82ª
\95s
\93K
\90Ø
\82È
\95¶
\82à
\82 \82é*/
5007 } else if (hear_txt)
5008 You_hear1(hear_txt);
5009 if (picking_at(x, y)) {
5016 if (OBJ_AT(x, y) && abstype == ZT_FIRE)
5017 if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
5020 You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
5022 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½");
5024 if ((mon = m_at(x, y)) != 0) {
5025 /* Cannot use wakeup() which also angers the monster */
5031 if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
5033 if (mon->isshk && !*u.ushops)
5040 /* fractured by pick-axe or wand of striking */
5043 register struct obj *obj; /* no texts here! */
5046 boolean by_you = !context.mon_moving;
5048 if (by_you && get_obj_location(obj, &x, &y, 0) && costly_spot(x, y)) {
5049 struct monst *shkp = 0;
5050 char objroom = *in_rooms(x, y, SHOPBASE);
5052 if (billable(&shkp, obj, objroom, FALSE)) {
5053 /* shop message says "you owe <shk> <$> for it!" so we need
5054 to precede that with a message explaining what "it" is */
5055 You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
5056 breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
5059 if (by_you && obj->otyp == BOULDER)
5063 obj->oclass = GEM_CLASS;
5064 obj->quan = (long) rn1(60, 7);
5065 obj->owt = weight(obj);
5066 obj->dknown = obj->bknown = obj->rknown = 0;
5067 obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
5068 dealloc_oextra(obj);
5070 if (obj->where == OBJ_FLOOR) {
5071 obj_extract_self(obj); /* move rocks back on top */
5072 place_object(obj, obj->ox, obj->oy);
5073 if (!does_block(obj->ox, obj->oy, &levl[obj->ox][obj->oy]))
5074 unblock_point(obj->ox, obj->oy);
5075 if (cansee(obj->ox, obj->oy))
5076 newsym(obj->ox, obj->oy);
5080 /* handle statue hit by striking/force bolt/pick-axe */
5083 register struct obj *obj;
5085 /* [obj is assumed to be on floor, so no get_obj_location() needed] */
5086 struct trap *trap = t_at(obj->ox, obj->oy);
5088 boolean by_you = !context.mon_moving;
5090 if (trap && trap->ttyp == STATUE_TRAP
5091 && activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
5093 /* drop any objects contained inside the statue */
5094 while ((item = obj->cobj) != 0) {
5095 obj_extract_self(item);
5096 place_object(item, obj->ox, obj->oy);
5098 if (by_you && Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) {
5100 You_feel("guilty about damaging such a historic statue.");
5102 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");
5111 * destroy_strings[dindx][0:singular,1:plural,2:killer_reason]
5112 * [0] freezing potion
5113 * [1] boiling potion other than oil
5114 * [2] boiling potion of oil
5115 * [3] burning scroll
5116 * [4] burning spellbook
5119 * (books, rings, and wands don't stack so don't need plural form;
5120 * crumbling ring doesn't do damage so doesn't need killer reason)
5122 const char *const destroy_strings[][3] = {
5123 /* also used in trap.c */
5125 { "freezes and shatters", "freeze and shatter", "shattered potion" },
5127 { "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\93\80\8c\8b\82µ
\82Ä
\8dÓ
\82¯
\82½", "
\8dÓ
\82¯
\82½
\96ò
\95r
\82Å" },
5129 { "boils and explodes", "boil and explode", "boiling potion" },
5131 { "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82Ä
\94\9a\94
\82µ
\82½", "
\95¦
\93«
\82µ
\82½
\96ò
\82Å" },
5133 { "ignites and explodes", "ignite and explode", "exploding potion" },
5135 { "
\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Å" },
5137 { "catches fire and burns", "catch fire and burn", "burning scroll" },
5139 { "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\89Î
\82ª
\82Â
\82¢
\82Ä
\94R
\82¦
\82½", "
\94R
\82¦
\82½
\8aª
\95¨
\82Å" },
5141 { "catches fire and burns", "", "burning book" },
5143 { "
\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Å" },
5145 { "turns to dust and vanishes", "", "" },
5147 { "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "
\90o
\82É
\82È
\82Á
\82Ä
\8fÁ
\82¦
\82½", "" },
5149 { "breaks apart and explodes", "", "exploding wand" },
5151 { "
\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Å" },
5155 destroy_item(osym, dmgtyp)
5156 register int osym, dmgtyp;
5158 register struct obj *obj, *obj2;
5159 int dmg, xresist, skip;
5163 boolean physical_damage;
5165 for (obj = invent; obj; obj = obj2) {
5167 physical_damage = FALSE;
5168 if (obj->oclass != osym)
5169 continue; /* test only objs of type osym */
5171 continue; /* don't destroy artifacts */
5172 if (obj->in_use && obj->quan == 1L)
5173 continue; /* not available */
5175 /* lint suppression */
5181 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5189 xresist = (Fire_resistance && obj->oclass != POTION_CLASS
5190 && obj->otyp != GLOB_OF_GREEN_SLIME);
5192 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5194 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5198 pline("%s glows a strange %s, but remains intact.",
5199 The(xname(obj)), hcolor("dark red"));
5201 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5202 xname(obj), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5209 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5221 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5222 dindx = obj->owt / 20;
5234 xresist = (Shock_resistance && obj->oclass != RING_CLASS);
5238 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5246 if (obj->otyp == WAN_LIGHTNING) {
5251 if (obj == current_wand) { skip++; break; }
5267 --quan; /* one will be used up elsewhere */
5268 for (i = cnt = 0L; i < quan; i++)
5275 mult = (cnt == quan)
5276 ? (quan > 1) ? "All of your " : "Your"
5277 : (cnt == 1L) ? "One of your" : "Some of your";
5279 mult = (cnt == quan)
5281 : (cnt == 1L) ? "
\82Ì
\82Ð
\82Æ
\82Â" : "
\82Ì
\82¢
\82
\82Â
\82©";
5284 pline("%s %s %s!", mult, xname(obj),
5285 destroy_strings[dindx][(cnt > 1L)]);
5287 pline("
\82 \82È
\82½
\82Ì%s%s
\82Í%s
\81I", xname(obj), mult,
5288 destroy_strings[dindx][(cnt > 1L)]);
5290 if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
5291 if (!breathless(youmonst.data) || haseyes(youmonst.data))
5294 if (obj->owornmask) {
5295 if (obj->owornmask & W_RING) /* ring being worn */
5300 if (obj == current_wand)
5301 current_wand = 0; /* destroyed */
5302 for (i = 0; i < cnt; i++)
5307 You("aren't hurt!");
5309 You("
\8f\9d\82Â
\82©
\82È
\82¢
\81I");
5311 const char *how = destroy_strings[dindx][2];
5312 boolean one = (cnt == 1L);
5314 if (physical_damage)
5315 dmg = Maybe_Half_Phys(dmg);
5316 losehp(dmg, one ? how : (const char *) makeplural(how),
5317 one ? KILLED_BY_AN : KILLED_BY);
5318 exercise(A_STR, FALSE);
5327 destroy_mitem(mtmp, osym, dmgtyp)
5331 struct obj *obj, *obj2;
5337 if (mtmp == &youmonst) { /* this simplifies artifact_hit() */
5338 destroy_item(osym, dmgtyp);
5339 return 0; /* arbitrary; value doesn't matter to artifact_hit() */
5342 vis = canseemon(mtmp);
5343 for (obj = mtmp->minvent; obj; obj = obj2) {
5345 if (obj->oclass != osym)
5346 continue; /* test only objs of type osym */
5353 if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
5361 if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
5363 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
5367 pline("%s glows a strange %s, but remains intact.",
5368 The(distant_name(obj, xname)), hcolor("dark red"));
5370 pline("%s
\82Í
\8aï
\96
\82É%s
\8bP
\82¢
\82½
\82ª
\89½
\82à
\95Ï
\89»
\82µ
\82È
\82©
\82Á
\82½
\81D",
5371 The(distant_name(obj, xname)), jconj_adj(hcolor("
\88Ã
\8a\8c\90F
\82Ì")));
5377 dindx = (obj->otyp != POT_OIL) ? 1 : 2;
5389 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
5390 dindx = obj->owt / 20;
5405 if (obj->otyp == RIN_SHOCK_RESISTANCE) {
5412 if (obj->otyp == WAN_LIGHTNING) {
5429 for (i = cnt = 0L; i < quan; i++)
5438 (cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
5440 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5441 destroy_strings[dindx][(cnt > 1L)]);
5443 pline("%s%s
\82Í%s
\81I",
5444 (cnt == obj->quan) ? Yname2(obj) : yname(obj),
5445 (cnt == obj->quan) ? "" : (cnt > 1L) ? "
\82Ì
\82¢
\82
\82Â
\82©"
5446 : "
\82Ì
\82Ð
\82Æ
\82Â",
5447 destroy_strings[dindx][(cnt > 1L)]);
5449 for (i = 0; i < cnt; i++)
5457 resist(mtmp, oclass, damage, tell)
5472 break; /* instrument */
5475 break; /* artifact */
5490 dlev = (int) mtmp->m_lev;
5494 dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
5496 resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
5499 shieldeff(mtmp->mx, mtmp->my);
5501 pline("%s resists!", Monnam(mtmp));
5503 pline("%s
\82Í
\96h
\82¢
\82¾
\81I", Monnam(mtmp));
5505 damage = (damage + 1) / 2;
5509 mtmp->mhp -= damage;
5510 if (mtmp->mhp < 1) {
5512 monkilled(mtmp, "", AD_RBRE);
5520 #define MAXWISHTRY 5
5523 wishcmdassist(triesleft)
5526 static NEARDATA const char *
5530 "Enter the name of an object, such as \"potion of monster detection\",",
5531 "\"scroll labeled README\", \"elven mithril-coat\", or \"Grimtooth\"",
5532 "(without the quotes).",
5534 "For object types which come in stacks, you may specify a plural name",
5535 "such as \"potions of healing\", or specify a count, such as \"1000 gold",
5536 "pieces\", although that aspect of your wish might not be granted.",
5538 "You may also specify various prefix values which might be used to",
5539 "modify the item, such as \"uncursed\" or \"rustproof\" or \"+1\".",
5540 "Most modifiers shown when viewing your inventory can be specified.",
5542 "You may specify 'nothing' to explicitly decline this wish.",
5545 preserve_wishless[] = "Doing so will preserve 'wishless' conduct.",
5547 "If you specify an unrecognized object name %s%s time%s,",
5548 retry_too[] = "a randomly chosen item will be granted.",
5549 suppress_cmdassist[] =
5550 "(Suppress this assistance with !cmdassist in your config file.)",
5551 *cardinals[] = { "zero", "one", "two", "three", "four", "five" },
5552 too_many[] = "too many";
5557 win = create_nhwindow(NHW_TEXT);
5560 for (i = 0; i < SIZE(wishinfo) - 1; ++i)
5561 putstr(win, 0, wishinfo[i]);
5562 if (!u.uconduct.wishes)
5563 putstr(win, 0, preserve_wishless);
5565 Sprintf(buf, retry_info,
5566 (triesleft >= 0 && triesleft < SIZE(cardinals))
5567 ? cardinals[triesleft]
5569 (triesleft < MAXWISHTRY) ? " more" : "",
5571 putstr(win, 0, buf);
5572 putstr(win, 0, retry_too);
5574 if (iflags.cmdassist)
5575 putstr(win, 0, suppress_cmdassist);
5576 display_nhwindow(win, FALSE);
5577 destroy_nhwindow(win);
5583 char buf[BUFSZ], promptbuf[BUFSZ];
5584 struct obj *otmp, nothing;
5587 promptbuf[0] = '\0';
5588 nothing = zeroobj; /* lint suppression; only its address matters */
5591 You("may wish for an object.");
5593 You("
\96]
\82Ý
\82Ì
\82à
\82Ì
\82ð
\8eè
\82É
\93ü
\82ê
\82ç
\82ê
\82é
\81D");
5596 Strcpy(promptbuf, "For what do you wish");
5598 Strcpy(promptbuf, "
\89½
\82ð
\82¨
\96]
\82Ý");
5599 if (iflags.cmdassist && tries > 0)
5601 Strcat(promptbuf, " (enter 'help' for assistance)");
5603 Strcat(promptbuf, " (
\8f\95\82¯
\82ª
\95K
\97v
\82È
\82ç 'help'
\82Æ
\93ü
\97Í)");
5605 Strcat(promptbuf, "?");
5607 Strcat(promptbuf, "
\81H");
5608 getlin(promptbuf, buf);
5609 (void) mungspaces(buf);
5610 if (buf[0] == '\033') {
5612 } else if (!strcmpi(buf, "help")) {
5613 wishcmdassist(MAXWISHTRY - tries);
5617 * Note: if they wished for and got a non-object successfully,
5618 * otmp == &zeroobj. That includes gold, or an artifact that
5619 * has been denied. Wishing for "nothing" requires a separate
5620 * value to remain distinct.
5622 otmp = readobjnam(buf, ¬hing);
5625 pline("Nothing fitting that description exists in the game.");
5627 pline("
\82¤
\81[
\82ñ
\81D
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\91¶
\8dÝ
\82µ
\82È
\82¢
\82æ
\82¤
\82¾
\81D");
5628 if (++tries < MAXWISHTRY)
5630 pline1(thats_enough_tries);
5631 otmp = readobjnam((char *) 0, (struct obj *) 0);
5633 return; /* for safety; should never happen */
5634 } else if (otmp == ¬hing) {
5635 /* explicitly wished for "nothing", presumably attempting
5636 to retain wishless conduct */
5641 u.uconduct.wishes++;
5643 if (otmp != &zeroobj) {
5646 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"),
5648 *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "
\8a\8a\82è
\97\8e\82¿
\82½" : "
\97\8e\82¿
\82½"),
5650 *oops_msg = (u.uswallow
5651 ? "Oops! %s out of your reach!"
5652 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5653 || levl[u.ux][u.uy].typ < IRONBARS
5654 || levl[u.ux][u.uy].typ >= ICE)
5655 ? "Oops! %s away from you!"
5656 : "Oops! %s to the floor!");
5658 *oops_msg = (u.uswallow
5659 ? "
\82¨
\82Á
\82Æ
\81C
\93Í
\82©
\82È
\82¢
\82Æ
\82±
\82ë
\82É%s
\81I"
5660 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
5661 || levl[u.ux][u.uy].typ < IRONBARS
5662 || levl[u.ux][u.uy].typ >= ICE)
5663 ? "
\82¨
\82Á
\82Æ
\81C
\8eè
\82©
\82ç%s
\81I"
5664 : "
\82¨
\82Á
\82Æ
\81C
\8f°
\82É%s
\81I");
5667 /* The(aobjnam()) is safe since otmp is unidentified -dlc */
5668 (void) hold_another_object(otmp, oops_msg,
5669 The(aobjnam(otmp, verb)),
5671 u.ublesscnt += rn1(100, 50); /* the gods take notice */