1 /* NetHack 3.6 mcastu.c $NHDT-Date: 1436753517 2015/07/13 02:11:57 $ $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 /* monster mage spells */
9 #define MGC_CURE_SELF 1
10 #define MGC_HASTE_SELF 2
11 #define MGC_STUN_YOU 3
12 #define MGC_DISAPPEAR 4
13 #define MGC_WEAKEN_YOU 5
14 #define MGC_DESTRY_ARMR 6
15 #define MGC_CURSE_ITEMS 7
16 #define MGC_AGGRAVATION 8
17 #define MGC_SUMMON_MONS 9
18 #define MGC_CLONE_WIZ 10
19 #define MGC_DEATH_TOUCH 11
21 /* monster cleric spells */
22 #define CLC_OPEN_WOUNDS 0
23 #define CLC_CURE_SELF 1
24 #define CLC_CONFUSE_YOU 2
25 #define CLC_PARALYZE 3
26 #define CLC_BLIND_YOU 4
28 #define CLC_CURSE_ITEMS 6
29 #define CLC_LIGHTNING 7
30 #define CLC_FIRE_PILLAR 8
33 STATIC_DCL
void FDECL(cursetxt
, (struct monst
*, BOOLEAN_P
));
34 STATIC_DCL
int FDECL(choose_magic_spell
, (int));
35 STATIC_DCL
int FDECL(choose_clerical_spell
, (int));
36 STATIC_DCL
void FDECL(cast_wizard_spell
, (struct monst
*, int, int));
37 STATIC_DCL
void FDECL(cast_cleric_spell
, (struct monst
*, int, int));
38 STATIC_DCL boolean
FDECL(is_undirected_spell
, (unsigned int, int));
40 FDECL(spell_would_be_useless
, (struct monst
*, unsigned int, int));
42 extern const char *const flash_types
[]; /* from zap.c */
44 /* feedback when frustrated monster couldn't cast a spell */
47 cursetxt(mtmp
, undirected
)
51 if (canseemon(mtmp
) && couldsee(mtmp
->mx
, mtmp
->my
)) {
52 const char *point_msg
; /* spellcasting monsters are impolite */
55 point_msg
= "all around, then curses";
56 else if ((Invis
&& !perceives(mtmp
->data
)
57 && (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
58 || is_obj_mappear(&youmonst
, STRANGE_OBJECT
)
60 point_msg
= "and curses in your general direction";
61 else if (Displaced
&& (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
62 point_msg
= "and curses at your displaced image";
64 point_msg
= "at you, then curses";
66 pline("%s points %s.", Monnam(mtmp
), point_msg
);
67 } else if ((!(moves
% 4) || !rn2(4))) {
69 Norep("You hear a mumbled curse.");
73 /* convert a level based random selection into a specific mage spell;
74 inappropriate choices will be screened out by spell_would_be_useless() */
76 choose_magic_spell(spellval
)
79 /* for 3.4.3 and earlier, val greater than 22 selected the default spell
81 while (spellval
> 24 && rn2(25))
82 spellval
= rn2(spellval
);
87 if (Antimagic
|| Hallucination
)
89 /* else FALL THROUGH */
93 return MGC_DEATH_TOUCH
;
100 return MGC_SUMMON_MONS
;
103 return MGC_AGGRAVATION
;
107 return MGC_CURSE_ITEMS
;
110 return MGC_DESTRY_ARMR
;
113 return MGC_WEAKEN_YOU
;
116 return MGC_DISAPPEAR
;
120 return MGC_HASTE_SELF
;
122 return MGC_CURE_SELF
;
129 /* convert a level based random selection into a specific cleric spell */
131 choose_clerical_spell(spellnum
)
134 /* for 3.4.3 and earlier, num greater than 13 selected the default spell
136 while (spellnum
> 15 && rn2(16))
137 spellnum
= rn2(spellnum
);
143 return CLC_OPEN_WOUNDS
;
144 /* else FALL THROUGH */
148 return CLC_FIRE_PILLAR
;
150 return CLC_LIGHTNING
;
153 return CLC_CURSE_ITEMS
;
158 return CLC_BLIND_YOU
;
164 return CLC_CONFUSE_YOU
;
166 return CLC_CURE_SELF
;
169 return CLC_OPEN_WOUNDS
;
174 * 1: successful spell
175 * 0: unsuccessful spell
178 castmu(mtmp
, mattk
, thinks_it_foundyou
, foundyou
)
179 register struct monst
*mtmp
;
180 register struct attack
*mattk
;
181 boolean thinks_it_foundyou
;
184 int dmg
, ml
= mtmp
->m_lev
;
189 * -- monster is attacking you. Search for a useful spell.
190 * -- monster thinks it's attacking you. Search for a useful spell,
191 * without checking for undirected. If the spell found is directed,
192 * it fails with cursetxt() and loss of mspec_used.
193 * -- monster isn't trying to attack. Select a spell once. Don't keep
194 * searching; if that spell is not useful (or if it's directed),
195 * return and do something else.
196 * Since most spells are directed, this means that a monster that isn't
197 * attacking casts spells only a small portion of the time that an
198 * attacking monster does.
200 if ((mattk
->adtyp
== AD_SPEL
|| mattk
->adtyp
== AD_CLRC
) && ml
) {
205 if (mattk
->adtyp
== AD_SPEL
)
206 spellnum
= choose_magic_spell(spellnum
);
208 spellnum
= choose_clerical_spell(spellnum
);
209 /* not trying to attack? don't allow directed spells */
210 if (!thinks_it_foundyou
) {
211 if (!is_undirected_spell(mattk
->adtyp
, spellnum
)
212 || spell_would_be_useless(mtmp
, mattk
->adtyp
, spellnum
)) {
215 "spellcasting monster found you and doesn't know it?");
221 && spell_would_be_useless(mtmp
, mattk
->adtyp
, spellnum
));
226 /* monster unable to cast spells? */
227 if (mtmp
->mcan
|| mtmp
->mspec_used
|| !ml
) {
228 cursetxt(mtmp
, is_undirected_spell(mattk
->adtyp
, spellnum
));
232 if (mattk
->adtyp
== AD_SPEL
|| mattk
->adtyp
== AD_CLRC
) {
233 mtmp
->mspec_used
= 10 - mtmp
->m_lev
;
234 if (mtmp
->mspec_used
< 2)
235 mtmp
->mspec_used
= 2;
238 /* monster can cast spells, but is casting a directed spell at the
239 wrong place? If so, give a message, and return. Do this *after*
240 penalizing mspec_used. */
241 if (!foundyou
&& thinks_it_foundyou
242 && !is_undirected_spell(mattk
->adtyp
, spellnum
)) {
243 pline("%s casts a spell at %s!",
244 canseemon(mtmp
) ? Monnam(mtmp
) : "Something",
245 levl
[mtmp
->mux
][mtmp
->muy
].typ
== WATER
? "empty water"
251 if (rn2(ml
* 10) < (mtmp
->mconf
? 100 : 20)) { /* fumbled attack */
252 if (canseemon(mtmp
) && !Deaf
)
253 pline_The("air crackles around %s.", mon_nam(mtmp
));
256 if (canspotmon(mtmp
) || !is_undirected_spell(mattk
->adtyp
, spellnum
)) {
257 pline("%s casts a spell%s!",
258 canspotmon(mtmp
) ? Monnam(mtmp
) : "Something",
259 is_undirected_spell(mattk
->adtyp
, spellnum
)
261 : (Invisible
&& !perceives(mtmp
->data
)
262 && (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
263 ? " at a spot near you"
265 && (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
266 ? " at your displaced image"
271 * As these are spells, the damage is related to the level
272 * of the monster casting the spell.
276 if (mattk
->adtyp
!= AD_SPEL
&& mattk
->adtyp
!= AD_CLRC
) {
278 "%s casting non-hand-to-hand version of hand-to-hand spell %d?",
279 Monnam(mtmp
), mattk
->adtyp
);
282 } else if (mattk
->damd
)
283 dmg
= d((int) ((ml
/ 2) + mattk
->damn
), (int) mattk
->damd
);
285 dmg
= d((int) ((ml
/ 2) + 1), 6);
286 if (Half_spell_damage
)
291 switch (mattk
->adtyp
) {
293 pline("You're enveloped in flames.");
294 if (Fire_resistance
) {
295 shieldeff(u
.ux
, u
.uy
);
296 pline("But you resist the effects.");
302 pline("You're covered in frost.");
303 if (Cold_resistance
) {
304 shieldeff(u
.ux
, u
.uy
);
305 pline("But you resist the effects.");
310 You("are hit by a shower of missiles!");
312 shieldeff(u
.ux
, u
.uy
);
313 pline_The("missiles bounce off!");
316 dmg
= d((int) mtmp
->m_lev
/ 2 + 1, 6);
318 case AD_SPEL
: /* wizard spell */
319 case AD_CLRC
: /* clerical spell */
321 if (mattk
->adtyp
== AD_SPEL
)
322 cast_wizard_spell(mtmp
, dmg
, spellnum
);
324 cast_cleric_spell(mtmp
, dmg
, spellnum
);
325 dmg
= 0; /* done by the spell casting functions */
334 /* monster wizard and cleric spellcasting functions */
336 If dmg is zero, then the monster is not casting at you.
337 If the monster is intentionally not casting at you, we have previously
338 called spell_would_be_useless() and spellnum should always be a valid
340 If you modify either of these, be sure to change is_undirected_spell()
341 and spell_would_be_useless().
345 cast_wizard_spell(mtmp
, dmg
, spellnum
)
350 if (dmg
== 0 && !is_undirected_spell(AD_SPEL
, spellnum
)) {
351 impossible("cast directed wizard spell (%d) with dmg=0?", spellnum
);
356 case MGC_DEATH_TOUCH
:
357 pline("Oh no, %s's using the touch of death!", mhe(mtmp
));
358 if (nonliving(youmonst
.data
) || is_demon(youmonst
.data
)) {
359 You("seem no deader than before.");
360 } else if (!Antimagic
&& rn2(mtmp
->m_lev
) > 12) {
362 You("have an out of body experience.");
364 killer
.format
= KILLED_BY_AN
;
365 Strcpy(killer
.name
, "touch of death");
370 shieldeff(u
.ux
, u
.uy
);
371 pline("Lucky for you, it didn't work!");
376 if (mtmp
->iswiz
&& context
.no_of_wizards
== 1) {
377 pline("Double Trouble...");
381 impossible("bad wizard cloning?");
383 case MGC_SUMMON_MONS
: {
386 count
= nasty(mtmp
); /* summon something nasty */
388 verbalize("Destroy the thief, my pet%s!", plur(count
));
390 const char *mappear
=
391 (count
== 1) ? "A monster appears" : "Monsters appear";
393 /* messages not quite right if plural monsters created but
394 only a single monster is seen */
395 if (Invisible
&& !perceives(mtmp
->data
)
396 && (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
397 pline("%s around a spot near you!", mappear
);
398 else if (Displaced
&& (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
399 pline("%s around your displaced image!", mappear
);
401 pline("%s from nowhere!", mappear
);
406 case MGC_AGGRAVATION
:
407 You_feel("that monsters are aware of your presence.");
411 case MGC_CURSE_ITEMS
:
412 You_feel("as if you need some help.");
416 case MGC_DESTRY_ARMR
:
418 shieldeff(u
.ux
, u
.uy
);
419 pline("A field of force surrounds you!");
420 } else if (!destroy_arm(some_armor(&youmonst
))) {
421 Your("skin itches.");
425 case MGC_WEAKEN_YOU
: /* drain strength */
427 shieldeff(u
.ux
, u
.uy
);
428 You_feel("momentarily weakened.");
430 You("suddenly feel weaker!");
431 dmg
= mtmp
->m_lev
- 6;
432 if (Half_spell_damage
)
436 done_in_by(mtmp
, DIED
);
440 case MGC_DISAPPEAR
: /* makes self invisible */
441 if (!mtmp
->minvis
&& !mtmp
->invis_blkd
) {
443 pline("%s suddenly %s!", Monnam(mtmp
),
444 !See_invisible
? "disappears" : "becomes transparent");
445 mon_set_minvis(mtmp
);
448 impossible("no reason for monster to cast disappear spell?");
451 if (Antimagic
|| Free_action
) {
452 shieldeff(u
.ux
, u
.uy
);
454 You_feel("momentarily disoriented.");
455 make_stunned(1L, FALSE
);
457 You(Stunned
? "struggle to keep your balance." : "reel...");
458 dmg
= d(ACURR(A_DEX
) < 12 ? 6 : 4, 4);
459 if (Half_spell_damage
)
461 make_stunned((HStun
& TIMEOUT
) + (long) dmg
, FALSE
);
466 mon_adjust_speed(mtmp
, 1, (struct obj
*) 0);
470 if (mtmp
->mhp
< mtmp
->mhpmax
) {
472 pline("%s looks better.", Monnam(mtmp
));
473 /* note: player healing does 6d4; this used to do 1d8 */
474 if ((mtmp
->mhp
+= d(3, 6)) > mtmp
->mhpmax
)
475 mtmp
->mhp
= mtmp
->mhpmax
;
480 /* prior to 3.4.0 Antimagic was setting the damage to 1--this
481 made the spell virtually harmless to players with magic res. */
483 shieldeff(u
.ux
, u
.uy
);
487 You("get a slight %sache.", body_part(HEAD
));
489 Your("brain is on fire!");
491 Your("%s suddenly aches painfully!", body_part(HEAD
));
493 Your("%s suddenly aches very painfully!", body_part(HEAD
));
496 impossible("mcastu: invalid magic spell (%d)", spellnum
);
507 cast_cleric_spell(mtmp
, dmg
, spellnum
)
512 if (dmg
== 0 && !is_undirected_spell(AD_CLRC
, spellnum
)) {
513 impossible("cast directed cleric spell (%d) with dmg=0?", spellnum
);
519 /* this is physical damage (force not heat),
520 * not magical damage or fire damage
522 pline("A sudden geyser slams into you from nowhere!");
524 if (Half_physical_damage
)
527 case CLC_FIRE_PILLAR
:
528 pline("A pillar of fire strikes all around you!");
529 if (Fire_resistance
) {
530 shieldeff(u
.ux
, u
.uy
);
534 if (Half_spell_damage
)
537 (void) burnarmor(&youmonst
);
538 destroy_item(SCROLL_CLASS
, AD_FIRE
);
539 destroy_item(POTION_CLASS
, AD_FIRE
);
540 destroy_item(SPBOOK_CLASS
, AD_FIRE
);
541 (void) burn_floor_objects(u
.ux
, u
.uy
, TRUE
, FALSE
);
543 case CLC_LIGHTNING
: {
546 pline("A bolt of lightning strikes down at you from above!");
547 reflects
= ureflects("It bounces off your %s%s.", "");
548 if (reflects
|| Shock_resistance
) {
549 shieldeff(u
.ux
, u
.uy
);
555 if (Half_spell_damage
)
557 destroy_item(WAND_CLASS
, AD_ELEC
);
558 destroy_item(RING_CLASS
, AD_ELEC
);
559 (void) flashburn((long) rnd(100));
562 case CLC_CURSE_ITEMS
:
563 You_feel("as if you need some help.");
568 /* Try for insects, and if there are none
569 left, go for (sticks to) snakes. -3. */
570 struct permonst
*pm
= mkclass(S_ANT
, 0);
571 struct monst
*mtmp2
= (struct monst
*) 0;
572 char let
= (pm
? S_ANT
: S_SNAKE
);
573 boolean success
= FALSE
, seecaster
;
574 int i
, quan
, oldseen
, newseen
;
578 oldseen
= monster_census(TRUE
);
579 quan
= (mtmp
->m_lev
< 2) ? 1 : rnd((int) mtmp
->m_lev
/ 2);
582 for (i
= 0; i
<= quan
; i
++) {
583 if (!enexto(&bypos
, mtmp
->mux
, mtmp
->muy
, mtmp
->data
))
585 if ((pm
= mkclass(let
, 0)) != 0
586 && (mtmp2
= makemon(pm
, bypos
.x
, bypos
.y
, MM_ANGRY
)) != 0) {
588 mtmp2
->msleeping
= mtmp2
->mpeaceful
= mtmp2
->mtame
= 0;
592 newseen
= monster_census(TRUE
);
594 /* not canspotmon(), which includes unseen things sensed via warning
596 seecaster
= canseemon(mtmp
) || tp_sensemon(mtmp
) || Detect_monsters
;
600 char *arg
; /* [not const: upstart(N==1 ? an() : makeplural())] */
601 const char *what
= (let
== S_SNAKE
) ? "snake" : "insect";
603 if (newseen
<= oldseen
|| Unaware
) {
604 /* unseen caster fails or summons unseen critters,
605 or unconscious hero ("You dream that you hear...") */
606 You_hear("someone summoning %s.", makeplural(what
));
608 /* unseen caster summoned seen critter(s) */
609 arg
= (newseen
== oldseen
+ 1) ? an(what
) : makeplural(what
);
611 You_hear("someone summoning something, and %s %s.", arg
,
612 vtense(arg
, "appear"));
614 pline("%s %s.", upstart(arg
), vtense(arg
, "appear"));
617 /* seen caster, possibly producing unseen--or just one--critters;
618 hero is told what the caster is doing and doesn't necessarily
619 observe complete accuracy of that caster's results (in other
620 words, no need to fuss with visibility or singularization;
621 player is told what's happening even if hero is unconscious) */
623 fmt
= "%s casts at a clump of sticks, but nothing happens.";
624 else if (let
== S_SNAKE
)
625 fmt
= "%s transforms a clump of sticks into snakes!";
626 else if (Invisible
&& !perceives(mtmp
->data
)
627 && (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
628 fmt
= "%s summons insects around a spot near you!";
629 else if (Displaced
&& (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
))
630 fmt
= "%s summons insects around your displaced image!";
632 fmt
= "%s summons insects!";
634 pline(fmt
, Monnam(mtmp
));
640 /* note: resists_blnd() doesn't apply here */
642 int num_eyes
= eyecount(youmonst
.data
);
643 pline("Scales cover your %s!", (num_eyes
== 1)
645 : makeplural(body_part(EYE
)));
646 make_blinded(Half_spell_damage
? 100L : 200L, FALSE
);
648 Your1(vision_clears
);
651 impossible("no reason for monster to cast blindness spell?");
654 if (Antimagic
|| Free_action
) {
655 shieldeff(u
.ux
, u
.uy
);
657 You("stiffen briefly.");
659 multi_reason
= "paralyzed by a monster";
662 You("are frozen in place!");
663 dmg
= 4 + (int) mtmp
->m_lev
;
664 if (Half_spell_damage
)
667 multi_reason
= "paralyzed by a monster";
672 case CLC_CONFUSE_YOU
:
674 shieldeff(u
.ux
, u
.uy
);
675 You_feel("momentarily dizzy.");
677 boolean oldprop
= !!Confusion
;
679 dmg
= (int) mtmp
->m_lev
;
680 if (Half_spell_damage
)
682 make_confused(HConfusion
+ dmg
, TRUE
);
684 You_feel("%s!", oldprop
? "trippier" : "trippy");
686 You_feel("%sconfused!", oldprop
? "more " : "");
691 if (mtmp
->mhp
< mtmp
->mhpmax
) {
693 pline("%s looks better.", Monnam(mtmp
));
694 /* note: player healing does 6d4; this used to do 1d8 */
695 if ((mtmp
->mhp
+= d(3, 6)) > mtmp
->mhpmax
)
696 mtmp
->mhp
= mtmp
->mhpmax
;
700 case CLC_OPEN_WOUNDS
:
702 shieldeff(u
.ux
, u
.uy
);
706 Your("skin itches badly for a moment.");
708 pline("Wounds appear on your body!");
710 pline("Severe wounds appear on your body!");
712 Your("body is covered with painful wounds!");
715 impossible("mcastu: invalid clerical spell (%d)", spellnum
);
726 is_undirected_spell(adtyp
, spellnum
)
730 if (adtyp
== AD_SPEL
) {
733 case MGC_SUMMON_MONS
:
734 case MGC_AGGRAVATION
:
742 } else if (adtyp
== AD_CLRC
) {
754 /* Some spells are useless under some circumstances. */
757 spell_would_be_useless(mtmp
, adtyp
, spellnum
)
762 /* Some spells don't require the player to really be there and can be cast
763 * by the monster when you're invisible, yet still shouldn't be cast when
764 * the monster doesn't even think you're there.
765 * This check isn't quite right because it always uses your real position.
766 * We really want something like "if the monster could see mux, muy".
768 boolean mcouldseeu
= couldsee(mtmp
->mx
, mtmp
->my
);
770 if (adtyp
== AD_SPEL
) {
771 /* aggravate monsters, etc. won't be cast by peaceful monsters */
773 && (spellnum
== MGC_AGGRAVATION
|| spellnum
== MGC_SUMMON_MONS
774 || spellnum
== MGC_CLONE_WIZ
))
776 /* haste self when already fast */
777 if (mtmp
->permspeed
== MFAST
&& spellnum
== MGC_HASTE_SELF
)
779 /* invisibility when already invisible */
780 if ((mtmp
->minvis
|| mtmp
->invis_blkd
) && spellnum
== MGC_DISAPPEAR
)
782 /* peaceful monster won't cast invisibility if you can't see
784 same as when monsters drink potions of invisibility. This doesn't
785 really make a lot of sense, but lets the player avoid hitting
786 peaceful monsters by mistake */
787 if (mtmp
->mpeaceful
&& !See_invisible
&& spellnum
== MGC_DISAPPEAR
)
789 /* healing when already healed */
790 if (mtmp
->mhp
== mtmp
->mhpmax
&& spellnum
== MGC_CURE_SELF
)
792 /* don't summon monsters if it doesn't think you're around */
793 if (!mcouldseeu
&& (spellnum
== MGC_SUMMON_MONS
794 || (!mtmp
->iswiz
&& spellnum
== MGC_CLONE_WIZ
)))
796 if ((!mtmp
->iswiz
|| context
.no_of_wizards
> 1)
797 && spellnum
== MGC_CLONE_WIZ
)
799 /* aggravation (global wakeup) when everyone is already active */
800 if (spellnum
== MGC_AGGRAVATION
) {
801 struct monst
*nxtmon
;
803 for (nxtmon
= fmon
; nxtmon
; nxtmon
= nxtmon
->nmon
) {
804 if (DEADMONSTER(nxtmon
))
806 if ((nxtmon
->mstrategy
& STRAT_WAITFORU
) != 0
807 || nxtmon
->msleeping
|| !nxtmon
->mcanmove
)
810 /* if nothing needs to be awakened then this spell is useless
811 but caster might not realize that [chance to pick it then
812 must be very small otherwise caller's many retry attempts
813 will eventually end up picking it too often] */
815 return rn2(100) ? TRUE
: FALSE
;
817 } else if (adtyp
== AD_CLRC
) {
818 /* summon insects/sticks to snakes won't be cast by peaceful monsters
820 if (mtmp
->mpeaceful
&& spellnum
== CLC_INSECTS
)
822 /* healing when already healed */
823 if (mtmp
->mhp
== mtmp
->mhpmax
&& spellnum
== CLC_CURE_SELF
)
825 /* don't summon insects if it doesn't think you're around */
826 if (!mcouldseeu
&& spellnum
== CLC_INSECTS
)
828 /* blindness spell on blinded player */
829 if (Blinded
&& spellnum
== CLC_BLIND_YOU
)
835 /* convert 1..10 to 0..9; add 10 for second group (spell casting) */
836 #define ad_to_typ(k) (10 + (int) k - 1)
838 /* monster uses spell (ranged) */
841 register struct monst
*mtmp
;
842 register struct attack
*mattk
;
844 /* don't print constant stream of curse messages for 'normal'
845 spellcasting monsters at range */
846 if (mattk
->adtyp
> AD_SPC2
)
850 cursetxt(mtmp
, FALSE
);
853 if (lined_up(mtmp
) && rn2(3)) {
855 if (mattk
->adtyp
&& (mattk
->adtyp
< 11)) { /* no cf unsigned >0 */
857 pline("%s zaps you with a %s!", Monnam(mtmp
),
858 flash_types
[ad_to_typ(mattk
->adtyp
)]);
859 buzz(-ad_to_typ(mattk
->adtyp
), (int) mattk
->damn
, mtmp
->mx
,
860 mtmp
->my
, sgn(tbx
), sgn(tby
));
862 impossible("Monster spell %d cast", mattk
->adtyp
- 1);