From 49084e6debc87f4e1007f38bf35c44b2d1990ca8 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 2 Feb 2006 06:15:13 +0000 Subject: [PATCH] zapping unseen wands (trunk only) Noticed recently when a user reported that an unseen monster zapping an unseen wand caused wand of striking to become discovered. [That was because the zap also hit a door and the code for the latter didn't check whether the wand had been seen, and it got fixed a couple of weeks ago.] When the player zaps wands while the hero is blinded, it was discovering (for the cases where the effect can be observed without sight) the wand even though the wand's description was unknown (showed in inventory as "a wand"). This replaces the calls to makeknown() in zap.c with calls to new learnwand(), which checks whether the wand description is known; you no longer discover something you've never seen. Reverse effect has also been added: if the type of wand has been discovered earlier, zapping an unseen wand (another of the same type, picked up when blind and zapped while still blind) will now mark it as seen (to show up in inventory as "a wand of " instead of just a "a wand"). The latter aspect really ought to be independent of prior discovery, but we currently have no way to record "we know what this particular item does even though we don't know what type of item it is yet". [If we add that, it would be applicable to potions (when operating on stacks) and rings too.] Minor change: zapping yourself with wand of opening or spell of knock will remove attached ball&chain rather than give a "chain quivers" message. Explicitly zapping the chain already did that; if the unlocking magic works on the chain connected to your leg then it really should also work on your leg connected to the chain. Zapping unlocking at yourself probably should also scan inventory to check for carrying locked chests, but I didn't add that. (If added, then locking magic will need to be augmented likewise.) This also fixes 's recent complaint: zapping an unknown wand of teleportation at yourself didn't make it become discovered. Now it will be, under the same circumstances as when you're riding: if teleport control causes you to be prompted for destination, or if random destination moves you more than jumping distance away from your original position. (The Stunned exception to teleport control, which was missing in zap_steed, perhaps ought to be moved into the macro definition of Teleport_control itself so that all code always handles it consistently.) --- doc/fixes35.0 | 3 + src/zap.c | 297 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 198 insertions(+), 102 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 5d8433ce4..f838aedd9 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -109,6 +109,9 @@ fix monsndx panic which happened after currently moving monster expelled swallowed hero onto magic trap and was made tame by its effect; taming no longer replaces monster reduced message verbosity when re-entering a temple +zapping a never seen wand while blinded won't make the wand a discovery +zapping an unID'd wand of teleportation at self will discover it (usually) +zapping unlocking magic at self while punished will remove attached chain Platform- and/or Interface-Specific Fixes diff --git a/src/zap.c b/src/zap.c index 65d2e2d7d..f76c606bc 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)zap.c 3.5 2005/11/02 */ +/* SCCS Id: @(#)zap.c 3.5 2006/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -19,8 +19,9 @@ extern boolean notonhead; /* for long worms */ /* kludge to use mondied instead of killed */ extern boolean m_using; -STATIC_DCL void FDECL(polyuse, (struct obj*, int, int)); -STATIC_DCL void FDECL(create_polymon, (struct obj *, int)); +STATIC_DCL void FDECL(learnwand, (struct obj *)); +STATIC_DCL void FDECL(polyuse, (struct obj *,int,int)); +STATIC_DCL void FDECL(create_polymon, (struct obj *,int)); STATIC_DCL boolean FDECL(zap_updown, (struct obj *)); STATIC_DCL int FDECL(zhitm, (struct monst *,int,int,struct obj **)); STATIC_DCL void FDECL(zhitu, (int,int,const char *,XCHAR_P,XCHAR_P)); @@ -91,6 +92,58 @@ const char * const flash_types[] = { /* also used in buzzmu(mcastu.c) */ "" }; +/* + * Recognizing unseen wands by zapping: in 3.4.3 and earlier, zapping + * most wand types while blind would add that type to the discoveries + * list even if it had never been seen (ie, picked up while blinded + * and shown in inventory as simply "a wand"). This behavior has been + * changed; now such wands won't be discovered. But if the type is + * already discovered, then the individual wand whose effect was just + * observed will be flagged as if seen. [You already know wands of + * striking; you zap "a wand" and observe striking effect (presumeably + * by sound or touch); it'll become shown in inventory as "a wand of + * striking".] + * + * Unfortunately, the new behavior isn't really correct either. There + * should be an `eknown' bit for "effect known" added for wands (and + * for potions since quaffing one of a stack is similar) so that the + * particular wand which has been zapped would have its type become + * known (it would change from "a wand" to "a wand of striking", for + * example) without the type becoming discovered or other unknown wands + * of that type showing additional information. When blindness ends, + * all objects in inventory with the eknown bit set would be discovered + * and other items of the same type would become known as such. + */ + +/* wand discovery gets special handling when hero is blinded */ +STATIC_OVL void +learnwand(obj) +struct obj *obj; +{ + /* For a wand (or wand-like tool) zapped by the player, if the + effect was observable (determined by caller; usually seen, but + possibly heard or felt if the hero is blinded) then discover the + object type provided that the object itself is known (as more + than just "a wand"). If object type is already discovered and + we observed the effect, mark the individual wand as having been + seen. Suppress spells (which use fake spellbook object for `obj') + so that casting a spell won't re-discover its forgotten book. */ + if (obj->oclass != SPBOOK_CLASS) { + /* if type already discovered, treat this item has having been seen + even if the hero is currently blinded (skips redundant makeknown) */ + if (objects[obj->otyp].oc_name_known) { + obj->dknown = 1; /* will usually be set already */ + /* otherwise discover it if this item itself has been or can be seen */ + } else { + /* in case it was picked up while blind and then zapped without + examining inventory after regaining sight (bypassing xname()) */ + if (!Blind) obj->dknown = 1; + /* make the discovery iff we know what we're manipulating */ + if (obj->dknown) makeknown(obj->otyp); + } + } +} + /* Routines for IMMEDIATE wands and spells. */ /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */ int @@ -99,7 +152,7 @@ struct monst *mtmp; struct obj *otmp; { boolean wake = TRUE; /* Most 'zaps' should wake monster */ - boolean reveal_invis = FALSE; + boolean reveal_invis = FALSE, learn_it = FALSE; boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart; int dmg, otyp = otmp->otyp; const char *zap_type_text = "spell"; @@ -127,7 +180,7 @@ struct obj *otmp; hit(zap_type_text, mtmp, exclam(dmg)); (void) resist(mtmp, otmp->oclass, dmg, TELL); } else miss(zap_type_text, mtmp); - makeknown(otyp); + learn_it = TRUE; break; case WAN_SLOW_MONSTER: case SPE_SLOW_MONSTER: @@ -179,7 +232,7 @@ struct obj *otmp; if (mtmp->cham == CHAM_ORDINARY && !rn2(25)) { if (canseemon(mtmp)) { pline("%s shudders!", Monnam(mtmp)); - makeknown(otyp); + learn_it = TRUE; } /* dropped inventory shouldn't be hit by this zap */ for (obj = mtmp->minvent; obj; obj = obj->nobj) @@ -190,7 +243,7 @@ struct obj *otmp; } else if (newcham(mtmp, (struct permonst *)0, (otyp != POT_POLYMORPH), FALSE)) { if (!Hallucination && canspotmon(mtmp)) - makeknown(otyp); + learn_it = TRUE; } } break; @@ -212,7 +265,7 @@ struct obj *otmp; mon_set_minvis(mtmp); if (!oldinvis && knowninvisible(mtmp)) { pline("%s turns transparent!", nambuf); - makeknown(otyp); + learn_it = TRUE; } break; } @@ -225,7 +278,7 @@ struct obj *otmp; wake = FALSE; reveal_invis = TRUE; probe_monster(mtmp); - makeknown(otyp); + learn_it = TRUE; break; case WAN_OPENING: case SPE_KNOCK: @@ -283,7 +336,7 @@ struct obj *otmp; break; case WAN_LIGHT: /* (broken wand) */ if (flash_hits_mon(mtmp, otmp)) { - makeknown(WAN_LIGHT); + learn_it = TRUE; reveal_invis = TRUE; } break; @@ -293,7 +346,7 @@ struct obj *otmp; reveal_invis = TRUE; if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS)) slept_monst(mtmp); - if (!Blind) makeknown(WAN_SLEEP); + if (!Blind) learn_it = TRUE; break; case SPE_STONE_TO_FLESH: if (monsndx(mtmp->data) == PM_STONE_GOLEM) { @@ -351,6 +404,9 @@ struct obj *otmp; !canspotmon(mtmp)) map_invisible(bhitpos.x, bhitpos.y); } + /* if effect was observable then discover the wand type provided + that the wand itself has been seen */ + if (learn_it) learnwand(otmp); return 0; } @@ -1447,8 +1503,17 @@ bhito(obj, otmp) struct obj *obj, *otmp; { int res = 1; /* affected object by default */ + boolean learn_it = FALSE, maybelearnit; xchar refresh_x, refresh_y; + /* fundamental: a wand effect hitting itself doesn't do anything; + otherwise we need to guard against accessing otmp after something + strange has happened to it (along the lines of polymorph or + stone-to-flesh [which aren't good examples since polymorph wands + aren't affected by polymorph zaps and stone-to-flesh isn't + available in wand form, but the concept still applies...]) */ + if (obj == otmp) return 0; + if (obj->bypass) { /* The bypass bit is currently only used as follows: * @@ -1493,8 +1558,8 @@ struct obj *obj, *otmp; res = 0; } else if (obj == uchain) { if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) { + learn_it = TRUE; unpunish(); - makeknown(otmp->otyp); } else res = 0; } else @@ -1514,8 +1579,7 @@ struct obj *obj, *otmp; if (Is_box(obj)) (void) boxlock(obj, otmp); if (obj_shudders(obj)) { - if (cansee(obj->ox, obj->oy)) - makeknown(otmp->otyp); + if (cansee(obj->ox, obj->oy)) learn_it = TRUE; do_osshock(obj); break; } @@ -1539,23 +1603,25 @@ struct obj *obj, *otmp; } res = 1; } - if (res) makeknown(WAN_PROBING); + if (res) learn_it = TRUE; break; case WAN_STRIKING: case SPE_FORCE_BOLT: - if (obj->otyp == BOULDER) - fracture_rock(obj); - else if (obj->otyp == STATUE) - (void) break_statue(obj); - else { - if (!context.mon_moving) - (void)hero_breaks(obj, obj->ox, obj->oy, FALSE); - else - (void)breaks(obj, obj->ox, obj->oy); - res = 0; + /* learn the type if you see or hear something break + (the sound could be implicit) */ + maybelearnit = cansee(obj->ox, obj->oy) || !Deaf; + if (obj->otyp == BOULDER) { + fracture_rock(obj); + } else if (obj->otyp == STATUE) { + (void) break_statue(obj); + } else { + if (context.mon_moving ? + !breaks(obj, obj->ox, obj->oy) : + !hero_breaks(obj, obj->ox, obj->oy, FALSE)) + maybelearnit = FALSE; /* nothing broke */ + res = 0; } - /* BUG[?]: shouldn't this depend upon you seeing it happen? */ - makeknown(otmp->otyp); + if (maybelearnit) learn_it = TRUE; break; case WAN_CANCELLATION: case SPE_CANCELLATION: @@ -1586,22 +1652,17 @@ struct obj *obj, *otmp; res = !!revive(obj, TRUE); if (res && Role_if(PM_HEALER)) { - boolean u_noticed = FALSE; - if (Hallucination && !Deaf) { You_hear("the sound of a defibrillator."); - u_noticed = TRUE; + learn_it = TRUE; } else if (!Blind) { You("observe %s %s change dramatically.", s_suffix(an(mons[corpsenm].mname)), nonliving(&mons[corpsenm]) ? "motility" : "health"); - u_noticed = TRUE; - } - if (u_noticed) { - makeknown(otmp->otyp); - exercise(A_WIS, TRUE); + learn_it = TRUE; } + if (learn_it) exercise(A_WIS, TRUE); } } break; @@ -1613,8 +1674,7 @@ struct obj *obj, *otmp; res = boxlock(obj, otmp); else res = 0; - if (res /* && otmp->oclass == WAND_CLASS */) - makeknown(otmp->otyp); + if (res) learn_it = TRUE; break; case WAN_SLOW_MONSTER: /* no effect on objects */ case SPE_SLOW_MONSTER: @@ -1726,6 +1786,9 @@ smell: impossible("What an interesting effect (%d)", otmp->otyp); break; } + /* if effect was observable then discover the wand type provided + that the wand itself has been seen */ + if (learn_it) learnwand(otmp); return res; } @@ -1748,8 +1811,8 @@ bhitpile(obj,fhito,tx,ty) (below), rather than on the current object, if it happens to encounter a statue which mustn't become animated. */ if (t && t->ttyp == STATUE_TRAP && - activate_statue_trap(t, tx, ty, TRUE) && obj->otyp == WAN_STRIKING) - makeknown(obj->otyp); + activate_statue_trap(t, tx, ty, TRUE)) + learnwand(obj); } poly_zapped = -1; @@ -1823,9 +1886,12 @@ register struct obj *obj; exercise(A_WIS, TRUE); break; } - if (known && !objects[obj->otyp].oc_name_known) { - makeknown(obj->otyp); + if (known) { + if (!objects[obj->otyp].oc_name_known) more_experienced(0,10); + /* effect was observable; discover the wand type provided + that the wand itself has been seen */ + learnwand(obj); } } @@ -1897,12 +1963,13 @@ zapyourself(obj, ordinary) struct obj *obj; boolean ordinary; { + boolean learn_it = FALSE; int damage = 0; switch(obj->otyp) { case WAN_STRIKING: - makeknown(WAN_STRIKING); case SPE_FORCE_BOLT: + learn_it = TRUE; if(Antimagic) { shieldeff(u.ux, u.uy); pline("Boing!"); @@ -1917,7 +1984,7 @@ boolean ordinary; break; case WAN_LIGHTNING: - makeknown(WAN_LIGHTNING); + learn_it = TRUE; if (!Shock_resistance) { You("shock yourself!"); damage = d(12,6); @@ -1937,8 +2004,8 @@ boolean ordinary; explode(u.ux, u.uy, 11, d(6,6), WAND_CLASS, EXPL_FIERY); break; case WAN_FIRE: - makeknown(WAN_FIRE); case FIRE_HORN: + learn_it = TRUE; if (Fire_resistance) { shieldeff(u.ux, u.uy); You_feel("rather warm."); @@ -1955,9 +2022,9 @@ boolean ordinary; break; case WAN_COLD: - makeknown(WAN_COLD); case SPE_CONE_OF_COLD: case FROST_HORN: + learn_it = TRUE; if (Cold_resistance) { shieldeff(u.ux, u.uy); You_feel("a little chill."); @@ -1970,8 +2037,8 @@ boolean ordinary; break; case WAN_MAGIC_MISSILE: - makeknown(WAN_MAGIC_MISSILE); case SPE_MAGIC_MISSILE: + learn_it = TRUE; if(Antimagic) { shieldeff(u.ux, u.uy); pline_The("missiles bounce!"); @@ -1982,11 +2049,11 @@ boolean ordinary; break; case WAN_POLYMORPH: - if (!Unchanging) - makeknown(WAN_POLYMORPH); case SPE_POLYMORPH: - if (!Unchanging) - polyself(0); + if (!Unchanging) { + learn_it = TRUE; + polyself(0); + } break; case WAN_CANCELLATION: @@ -1995,12 +2062,12 @@ boolean ordinary; break; case SPE_DRAIN_LIFE: - if (!Drain_resistance) { - losexp("life drainage"); - makeknown(obj->otyp); - } - damage = 0; /* No additional damage */ - break; + if (!Drain_resistance) { + learn_it = TRUE; /* (no effect for spells...) */ + losexp("life drainage"); + } + damage = 0; /* No additional damage */ + break; case WAN_MAKE_INVISIBLE: { /* have to test before changing HInvis but must change @@ -2019,7 +2086,7 @@ boolean ordinary; incr_itimeout(&HInvis, d(obj->spe, 250)); } if (msg) { - makeknown(WAN_MAKE_INVISIBLE); + learn_it = TRUE; newsym(u.ux, u.uy); self_invis_message(); } @@ -2028,19 +2095,19 @@ boolean ordinary; case WAN_SPEED_MONSTER: if (!(HFast & INTRINSIC)) { + learn_it = TRUE; if (!Fast) You("speed up."); else Your("quickness feels more natural."); - makeknown(WAN_SPEED_MONSTER); exercise(A_DEX, TRUE); } HFast |= FROMOUTSIDE; break; case WAN_SLEEP: - makeknown(WAN_SLEEP); case SPE_SLEEP: + learn_it = TRUE; if(Sleep_resistance) { shieldeff(u.ux, u.uy); You("don't feel sleepy!"); @@ -2053,14 +2120,19 @@ boolean ordinary; case WAN_SLOW_MONSTER: case SPE_SLOW_MONSTER: if(HFast & (TIMEOUT | INTRINSIC)) { + learn_it = TRUE; u_slow_down(); - makeknown(obj->otyp); } break; case WAN_TELEPORTATION: case SPE_TELEPORT_AWAY: tele(); + /* same criteria as when mounted (zap_steed) */ + if ((Teleport_control && !Stunned) || + !couldsee(u.ux0, u.uy0) || + distu(u.ux0, u.uy0) >= 16) + learn_it = TRUE; break; case WAN_DEATH: @@ -2071,17 +2143,17 @@ boolean ordinary; : "You seem no deader than before."); break; } + learn_it = TRUE; Sprintf(killer.name,"shot %sself with a death ray",uhim()); killer.format = NO_KILLER_PREFIX; You("irradiate yourself with pure energy!"); You("die."); - makeknown(obj->otyp); /* They might survive with an amulet of life saving */ done(DIED); break; case WAN_UNDEAD_TURNING: - makeknown(WAN_UNDEAD_TURNING); case SPE_TURN_UNDEAD: + learn_it = TRUE; (void) unturn_dead(&youmonst); if (is_undead(youmonst.data)) { You_feel("frightened and %sstunned.", @@ -2092,6 +2164,7 @@ boolean ordinary; break; case SPE_HEALING: case SPE_EXTRA_HEALING: + learn_it = TRUE; /* (no effect for spells...) */ healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE, (obj->otyp == SPE_EXTRA_HEALING)); You_feel("%sbetter.", @@ -2104,13 +2177,15 @@ boolean ordinary; case EXPENSIVE_CAMERA: #endif damage += rnd(25); - if (flashburn((long)damage)) makeknown(obj->otyp); + if (flashburn((long)damage)) learn_it = TRUE; damage = 0; /* reset */ break; case WAN_OPENING: - if (Punished) makeknown(WAN_OPENING); case SPE_KNOCK: - if (Punished) Your("chain quivers for a moment."); + if (Punished) { + learn_it = TRUE; + unpunish(); + } break; case WAN_DIGGING: case SPE_DIG: @@ -2120,25 +2195,33 @@ boolean ordinary; case SPE_WIZARD_LOCK: break; case WAN_PROBING: - for (obj = invent; obj; obj = obj->nobj) - obj->dknown = 1; - /* note: `obj' reused; doesn't point at wand anymore */ - makeknown(WAN_PROBING); + { + struct obj *otmp; + + for (otmp = invent; otmp; otmp = otmp->nobj) + otmp->dknown = 1; + learn_it = TRUE; ustatusline(); break; + } case SPE_STONE_TO_FLESH: - { - struct obj *otemp, *onext; + { + struct obj *otmp, *onxt; boolean didmerge; - if (u.umonnum == PM_STONE_GOLEM) + if (u.umonnum == PM_STONE_GOLEM) { + learn_it = TRUE; (void) polymon(PM_FLESH_GOLEM); - if (Stoned) fix_petrification(); /* saved! */ + } + if (Stoned) { + learn_it = TRUE; + fix_petrification(); /* saved! */ + } /* but at a cost.. */ - for (otemp = invent; otemp; otemp = onext) { - onext = otemp->nobj; - (void) bhito(otemp, obj); - } + for (otmp = invent; otmp; otmp = onxt) { + onxt = otmp->nobj; + if (bhito(otmp, obj)) learn_it = TRUE; + } /* * It is possible that we can now merge some inventory. * Do a higly paranoid merge. Restart from the beginning @@ -2146,18 +2229,22 @@ boolean ordinary; */ do { didmerge = FALSE; - for (otemp = invent; !didmerge && otemp; otemp = otemp->nobj) - for (onext = otemp->nobj; onext; onext = onext->nobj) - if (merged(&otemp, &onext)) { - didmerge = TRUE; - break; - } + for (otmp = invent; !didmerge && otmp; otmp = otmp->nobj) + for (onxt = otmp->nobj; onxt; onxt = onxt->nobj) + if (merged(&otmp, &onxt)) { + didmerge = TRUE; + break; + } } while (didmerge); - } break; - default: impossible("object %d used?",obj->otyp); + } + default: + impossible("zapyourself: object %d used?", obj->otyp); break; } + /* if effect was observable then discover the wand type provided + that the wand itself has been seen */ + if (learn_it) learnwand(obj); return(damage); } @@ -2194,16 +2281,18 @@ struct obj *obj; /* wand or spell */ */ case WAN_PROBING: probe_monster(u.usteed); - makeknown(WAN_PROBING); + learnwand(obj); steedhit = TRUE; break; case WAN_TELEPORTATION: case SPE_TELEPORT_AWAY: /* you go together */ tele(); - if(Teleport_control || !couldsee(u.ux0, u.uy0) || - (distu(u.ux0, u.uy0) >= 16)) - makeknown(obj->otyp); + /* same criteria as when unmounted (zapyourself) */ + if ((Teleport_control && !Stunned) || + !couldsee(u.ux0, u.uy0) || + distu(u.ux0, u.uy0) >= 16) + learnwand(obj); steedhit = TRUE; break; @@ -2512,9 +2601,9 @@ struct obj *obj; impossible("weffects: unexpected spell or wand"); disclose = TRUE; } - if (disclose && was_unkn) { - makeknown(otyp); - more_experienced(0,10); + if (disclose) { + learnwand(obj); + if (was_unkn) more_experienced(0, 10); } return; } @@ -2711,30 +2800,34 @@ struct obj **pobj; /* object tossed/used, set to NULL break; } - if (weapon == ZAPPED_WAND && find_drawbridge(&x,&y)) + if (weapon == ZAPPED_WAND && find_drawbridge(&x,&y)) { + boolean learn_it = FALSE; + switch (obj->otyp) { case WAN_OPENING: case SPE_KNOCK: if (is_db_wall(bhitpos.x, bhitpos.y)) { if (cansee(x,y) || cansee(bhitpos.x,bhitpos.y)) - makeknown(obj->otyp); + learn_it = TRUE; open_drawbridge(x,y); } break; case WAN_LOCKING: case SPE_WIZARD_LOCK: - if ((cansee(x,y) || cansee(bhitpos.x, bhitpos.y)) - && levl[x][y].typ == DRAWBRIDGE_DOWN) - makeknown(obj->otyp); + if ((cansee(x,y) || cansee(bhitpos.x, bhitpos.y)) && + levl[x][y].typ == DRAWBRIDGE_DOWN) + learn_it = TRUE; close_drawbridge(x,y); break; case WAN_STRIKING: case SPE_FORCE_BOLT: if (typ != DRAWBRIDGE_UP) destroy_drawbridge(x,y); - makeknown(obj->otyp); + learn_it = TRUE; break; } + if (learn_it) learnwand(obj); + } mtmp = m_at(bhitpos.x, bhitpos.y); @@ -2833,10 +2926,10 @@ struct obj **pobj; /* object tossed/used, set to NULL case SPE_FORCE_BOLT: if (doorlock(obj, bhitpos.x, bhitpos.y)) { if (cansee(bhitpos.x, bhitpos.y) || - (obj->otyp == WAN_STRIKING)) - makeknown(obj->otyp); - if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN - && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) { + (obj->otyp == WAN_STRIKING && !Deaf)) + learnwand(obj); + if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN && + *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) { shopdoor = TRUE; add_damage(bhitpos.x, bhitpos.y, 400L); } -- 2.40.0