Wikihack
Advertisement

Below is the full text to mcastu.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mcastu.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)mcastu.c	3.4	2003/01/08	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    /* monster mage spells */
8.    #define MGC_PSI_BOLT	 0
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
20.   #define MGC_CREATE_POOL	12
21.   #define MGC_CALL_UNDEAD	13
22.   
23.   /* monster cleric spells */
24.   #define CLC_OPEN_WOUNDS	 0
25.   #define CLC_CURE_SELF	 1
26.   #define CLC_CONFUSE_YOU	 2
27.   #define CLC_PARALYZE	 3
28.   #define CLC_BLIND_YOU	 4
29.   #define CLC_INSECTS	 5
30.   #define CLC_CURSE_ITEMS	 6
31.   #define CLC_LIGHTNING	 7
32.   #define CLC_FIRE_PILLAR	 8
33.   #define CLC_GEYSER	 9
34.   
35.   STATIC_DCL void FDECL(cursetxt,(struct monst *,BOOLEAN_P));
36.   STATIC_DCL int FDECL(choose_magic_spell, (int));
37.   STATIC_DCL int FDECL(choose_clerical_spell, (int));
38.   STATIC_DCL void FDECL(cast_wizard_spell,(struct monst *, int,int));
39.   STATIC_DCL void FDECL(cast_cleric_spell,(struct monst *, int,int));
40.   STATIC_DCL boolean FDECL(is_undirected_spell,(unsigned int,int));
41.   STATIC_DCL boolean FDECL(spell_would_be_useless,(struct monst *,unsigned int,int));
42.   
43.   #ifdef OVL0
44.   
45.   extern const char * const flash_types[];	/* from zap.c */
46.   
47.   /* feedback when frustrated monster couldn't cast a spell */
48.   STATIC_OVL
49.   void
50.   cursetxt(mtmp, undirected)
51.   struct monst *mtmp;
52.   boolean undirected;
53.   {
54.   	if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
55.   	    const char *point_msg;  /* spellcasting monsters are impolite */
56.   
57.   	    if (undirected)
58.   		point_msg = "all around, then curses";
59.   	    else if ((Invis && !perceives(mtmp->data) &&
60.   			(mtmp->mux != u.ux || mtmp->muy != u.uy)) ||
61.   		    (youmonst.m_ap_type == M_AP_OBJECT &&
62.   			youmonst.mappearance == STRANGE_OBJECT) ||
63.   		    u.uundetected)
64.   		point_msg = "and curses in your general direction";
65.   	    else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
66.   		point_msg = "and curses at your displaced image";
67.   	    else
68.   		point_msg = "at you, then curses";
69.   
70.   	    pline("%s points %s.", Monnam(mtmp), point_msg);
71.   	} else if ((!(moves % 4) || !rn2(4))) {
72.   	    if (flags.soundok) Norep("You hear a mumbled curse.");
73.   	}
74.   }
75.   
76.   #endif /* OVL0 */
77.   #ifdef OVLB
78.   
79.   /* convert a level based random selection into a specific mage spell;
80.      inappropriate choices will be screened out by spell_would_be_useless() */
81.   STATIC_OVL int
82.   choose_magic_spell(spellval)
83.   int spellval;
84.   {
85.       switch (spellval) {
86.       case 22:
87.       case 21:
88.       case 20:
89.   	return MGC_DEATH_TOUCH;
90.       case 19:
91.       case 18:
92.   	return MGC_CLONE_WIZ;
93.       case 17:
94.       case 16:
95.       case 15:
96.   	return MGC_SUMMON_MONS;
97.       case 14:
98.       case 13:
99.   	return MGC_AGGRAVATION;
100.      case 12:
101.  	return MGC_CREATE_POOL;
102.      case 11:
103.      case 10:
104.  	return MGC_CURSE_ITEMS;
105.      case 9:
106.  	return MGC_CALL_UNDEAD;
107.      case 8:
108.  	return MGC_DESTRY_ARMR;
109.      case 7:
110.      case 6:
111.  	return MGC_WEAKEN_YOU;
112.      case 5:
113.      case 4:
114.  	return MGC_DISAPPEAR;
115.      case 3:
116.  	return MGC_STUN_YOU;
117.      case 2:
118.  	return MGC_HASTE_SELF;
119.      case 1:
120.  	return MGC_CURE_SELF;
121.      case 0:
122.      default:
123.  	return MGC_PSI_BOLT;
124.      }
125.  }
126.  
127.  /* convert a level based random selection into a specific cleric spell */
128.  STATIC_OVL int
129.  choose_clerical_spell(spellnum)
130.  int spellnum;
131.  {
132.      switch (spellnum) {
133.      case 13:
134.  	return CLC_GEYSER;
135.      case 12:
136.  	return CLC_FIRE_PILLAR;
137.      case 11:
138.  	return CLC_LIGHTNING;
139.      case 10:
140.      case 9:
141.  	return CLC_CURSE_ITEMS;
142.      case 8:
143.  	return CLC_INSECTS;
144.      case 7:
145.      case 6:
146.  	return CLC_BLIND_YOU;
147.      case 5:
148.      case 4:
149.  	return CLC_PARALYZE;
150.      case 3:
151.      case 2:
152.  	return CLC_CONFUSE_YOU;
153.      case 1:
154.  	return CLC_CURE_SELF;
155.      case 0:
156.      default:
157.  	return CLC_OPEN_WOUNDS;
158.      }
159.  }
160.  
161.  /* return values:
162.   * 1: successful spell
163.   * 0: unsuccessful spell
164.   */
165.  int
166.  castmu(mtmp, mattk, thinks_it_foundyou, foundyou)
167.  	register struct monst *mtmp;
168.  	register struct attack *mattk;
169.  	boolean thinks_it_foundyou;
170.  	boolean foundyou;
171.  {
172.  	int	dmg, ml = mtmp->m_lev;
173.  	int ret;
174.  	int spellnum = 0;
175.  	int spellev, chance, difficulty, splcaster, learning;
176.  
177.  	/* Three cases:
178.  	 * -- monster is attacking you.  Search for a useful spell.
179.  	 * -- monster thinks it's attacking you.  Search for a useful spell,
180.  	 *    without checking for undirected.  If the spell found is directed,
181.  	 *    it fails with cursetxt() and loss of mspec_used.
182.  	 * -- monster isn't trying to attack.  Select a spell once.  Don't keep
183.  	 *    searching; if that spell is not useful (or if it's directed),
184.  	 *    return and do something else. 
185.  	 * Since most spells are directed, this means that a monster that isn't
186.  	 * attacking casts spells only a small portion of the time that an
187.  	 * attacking monster does.
188.  	 */
189.  	if ((mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) && ml) {
190.  	    int cnt = 40;
191.  
192.  	    do {
193.  		spellnum = rn2(ml);
194.  		/* Casting level is limited by available energy */
195.  		spellev = spellnum / 7 + 1;
196.  		if (spellev > 10) spellev = 10;
197.  		if (spellev * 5 > mtmp->m_en) {
198.  		    spellev = mtmp->m_en / 5;
199.  		    spellnum = (spellev - 1) * 7 + 1;
200.  		}
201.  		if (mattk->adtyp == AD_SPEL)
202.  		    spellnum = choose_magic_spell(spellnum);
203.  		else
204.  		    spellnum = choose_clerical_spell(spellnum);
205.  		/* not trying to attack?  don't allow directed spells */
206.  		if (!thinks_it_foundyou) {
207.  		    if (!is_undirected_spell(mattk->adtyp, spellnum) ||
208.  			spell_would_be_useless(mtmp, mattk->adtyp, spellnum)) {
209.  			if (foundyou)
210.  			    impossible("spellcasting monster found you and doesn't know it?");
211.  			return 0;
212.  		    }
213.  		    break;
214.  		}
215.  	    } while(--cnt > 0 &&
216.  		    spell_would_be_useless(mtmp, mattk->adtyp, spellnum));
217.  	    if (cnt == 0) return 0;
218.  	} else {
219.  	    /* Casting level is limited by available energy */
220.  	    spellev = ml / 7 + 1;
221.  	    if (spellev > 10) spellev = 10;
222.  	    if (spellev * 5 > mtmp->m_en) {
223.  		spellev = mtmp->m_en / 5;
224.  		ml = (spellev - 1) * 7 + 1;
225.  	    }
226.  	}
227.  
228.  	/* monster unable to cast spells? */
229.  	if (mtmp->mcan || mtmp->m_en < 5 || mtmp->mspec_used || !ml) {
230.  	    cursetxt(mtmp, is_undirected_spell(mattk->adtyp, spellnum));
231.  	    return(0);
232.  	}
233.  
234.  	if (mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) {
235.  	    /*
236.  	     * Spell use (especially MGC) is more common in Slash'EM.
237.  	     * Still using mspec_used, just so monsters don't go bonkers.
238.  	     */
239.  #if 0
240.  	    mtmp->mspec_used = 10 - mtmp->m_lev;
241.  	    if (mtmp->mspec_used < 2) mtmp->mspec_used = 2;
242.  #endif
243.  	    mtmp->mspec_used = rn2(15) - mtmp->m_lev;
244.  	    if (mattk->adtyp == AD_SPEL)
245.  		mtmp->mspec_used = mtmp->mspec_used > 0 ? 2 : 0;
246.  	    else if (mtmp->mspec_used < 2) mtmp->mspec_used = 2;
247.  	}
248.  
249.  	/* monster can cast spells, but is casting a directed spell at the
250.  	   wrong place?  If so, give a message, and return.  Do this *after*
251.  	   penalizing mspec_used. */
252.  	if (!foundyou && thinks_it_foundyou &&
253.  		!is_undirected_spell(mattk->adtyp, spellnum)) {
254.  	    pline("%s casts a spell at %s!",
255.  		canseemon(mtmp) ? Monnam(mtmp) : "Something",
256.  		levl[mtmp->mux][mtmp->muy].typ == WATER
257.  		    ? "empty water" : "thin air");
258.  	    return(0);
259.  	}
260.  
261.  	nomul(0);
262.  
263.  	mtmp->m_en -= spellev * 5; /* Use up the energy now */
264.  
265.  	/* We should probably do similar checks to what is done for
266.  	 * the player - armor, etc.
267.  	 * Checks for armour and other intrinsic ability change splcaster
268.  	 * Difficulty and experience affect chance
269.  	 * Assume that monsters only cast spells that they know well
270.  	 */
271.  	splcaster = 15 - (mtmp->m_lev / 2); /* Base for a wizard is 5...*/
272.  
273.  	if (splcaster < 5) splcaster = 5;
274.  	if (splcaster > 20) splcaster = 20;
275.  
276.  	chance = 11 * (mtmp->m_lev > 25 ? 18 : (12 + (mtmp->m_lev / 5)));
277.  	chance++ ;  /* Minimum chance of 1 */
278.  
279.  	difficulty = (spellev - 1) * 4 - (mtmp->m_lev - 1);
280.  	    /* law of diminishing returns sets in quickly for
281.  	     * low-level spells.  That is, higher levels quickly
282.  	     * result in almost no gain
283.  	     */
284.  	learning = 15 * (-difficulty / spellev);
285.  	chance += learning > 20 ? 20 : learning;
286.  
287.  	/* clamp the chance */
288.  	if (chance < 0) chance = 0;
289.  	if (chance > 120) chance = 120;
290.  
291.  	/* combine */
292.  	chance = chance * (20-splcaster) / 15 - splcaster;
293.  
294.  	/* Clamp to percentile */
295.  	if (chance > 100) chance = 100;
296.  	if (chance < 0) chance = 0;
297.  
298.  #if 0
299.  	if(rn2(ml*10) < (mtmp->mconf ? 100 : 20)) {	/* fumbled attack */
300.  #else
301.  	if (mtmp->mconf || rnd(100) > chance) { /* fumbled attack */
302.  #endif
303.  	    if (canseemon(mtmp) && flags.soundok)
304.  		pline_The("air crackles around %s.", mon_nam(mtmp));
305.  	    return(0);
306.  	}
307.  	if (canspotmon(mtmp) || !is_undirected_spell(mattk->adtyp, spellnum)) {
308.  	    pline("%s casts a spell%s!",
309.  		  canspotmon(mtmp) ? Monnam(mtmp) : "Something",
310.  		  is_undirected_spell(mattk->adtyp, spellnum) ? "" :
311.  		  (Invisible && !perceives(mtmp->data) && 
312.  		   (mtmp->mux != u.ux || mtmp->muy != u.uy)) ?
313.  		  " at a spot near you" :
314.  		  (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) ?
315.  		  " at your displaced image" :
316.  		  " at you");
317.  	}
318.  
319.  /*
320.   *	As these are spells, the damage is related to the level
321.   *	of the monster casting the spell.
322.   */
323.  	if (!foundyou) {
324.  	    dmg = 0;
325.  	    if (mattk->adtyp != AD_SPEL && mattk->adtyp != AD_CLRC) {
326.  		impossible(
327.  	      "%s casting non-hand-to-hand version of hand-to-hand spell %d?",
328.  			   Monnam(mtmp), mattk->adtyp);
329.  		return(0);
330.  	    }
331.  	} else if (mattk->damd)
332.  	    dmg = d((int)((ml/2) + mattk->damn), (int)mattk->damd);
333.  	else dmg = d((int)((ml/2) + 1), 6);
334.  	if (Half_spell_damage) dmg = (dmg+1) / 2;
335.  
336.  	ret = 1;
337.  
338.  	switch (mattk->adtyp) {
339.  
340.  	    case AD_FIRE:
341.  		pline("You're enveloped in flames.");
342.  		if(Fire_resistance) {
343.  			shieldeff(u.ux, u.uy);
344.  			pline("But you resist the effects.");
345.  			dmg = 0;
346.  		}
347.  		if (Slimed) {
348.  			pline("The slime is burned away!");
349.  			Slimed =0;
350.  		}
351.  		burn_away_slime();
352.  		break;
353.  	    case AD_COLD:
354.  		pline("You're covered in frost.");
355.  		if(Cold_resistance) {
356.  			shieldeff(u.ux, u.uy);
357.  			pline("But you resist the effects.");
358.  			dmg = 0;
359.  		}
360.  		break;
361.  	    case AD_MAGM:
362.  		You("are hit by a shower of missiles!");
363.  		if(Antimagic) {
364.  			shieldeff(u.ux, u.uy);
365.  			pline_The("missiles bounce off!");
366.  			dmg = 0;
367.  		}
368.  		break;
369.  	    case AD_SPEL:	/* wizard spell */
370.  	    case AD_CLRC:       /* clerical spell */
371.  	    {
372.  		if (mattk->adtyp == AD_SPEL)
373.  		    cast_wizard_spell(mtmp, dmg, spellnum);
374.  		else
375.  		    cast_cleric_spell(mtmp, dmg, spellnum);
376.  		dmg = 0; /* done by the spell casting functions */
377.  		break;
378.  	    }
379.  	}
380.  	if(dmg) mdamageu(mtmp, dmg);
381.  	return(ret);
382.  }
383.  
384.  /* monster wizard and cleric spellcasting functions */
385.  /*
386.     If dmg is zero, then the monster is not casting at you.
387.     If the monster is intentionally not casting at you, we have previously
388.     called spell_would_be_useless() and spellnum should always be a valid
389.     undirected spell.
390.     If you modify either of these, be sure to change is_undirected_spell()
391.     and spell_would_be_useless().
392.   */
393.  STATIC_OVL
394.  void
395.  cast_wizard_spell(mtmp, dmg, spellnum)
396.  struct monst *mtmp;
397.  int dmg;
398.  int spellnum;
399.  {
400.      if (dmg == 0 && !is_undirected_spell(AD_SPEL, spellnum)) {
401.  	impossible("cast directed wizard spell (%d) with dmg=0?", spellnum);
402.  	return;
403.      }
404.  
405.      switch (spellnum) {
406.      case MGC_DEATH_TOUCH:
407.  	pline("Oh no, %s's using the touch of death!", mhe(mtmp));
408.  	if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
409.  	    You("seem no deader than before.");
410.  	} else if (!Antimagic && rn2(mtmp->m_lev) > 12) {
411.  	    if (Hallucination) {
412.  		You("have an out of body experience.");
413.  	    } else {
414.  		killer_format = KILLED_BY_AN;
415.  		killer = "touch of death";
416.  		done(DIED);
417.  	    }
418.  	} else {
419.  	    if (Antimagic) shieldeff(u.ux, u.uy);
420.  	    pline("Lucky for you, it didn't work!");
421.  	}
422.  	dmg = 0;
423.  	break;
424.      case MGC_CREATE_POOL:
425.  	if (levl[u.ux][u.uy].typ == ROOM || levl[u.ux][u.uy].typ == CORR) {
426.  	    pline("A pool appears beneath you!");
427.  	    levl[u.ux][u.uy].typ = POOL;
428.  	    del_engr_at(u.ux, u.uy);
429.  	    water_damage(level.objects[u.ux][u.uy], FALSE, TRUE);
430.  	    spoteffects(FALSE);  /* possibly drown, notice objects */
431.  	}
432.  	else
433.  	    impossible("bad pool creation?");
434.  	dmg = 0;
435.  	break;
436.      case MGC_CLONE_WIZ:
437.  	if (mtmp->iswiz && flags.no_of_wizards == 1) {
438.  	    pline("Double Trouble...");
439.  	    clonewiz();
440.  	    dmg = 0;
441.  	} else
442.  	    impossible("bad wizard cloning?");
443.  	break;
444.      case MGC_SUMMON_MONS:
445.      {
446.  	int count;
447.  
448.  	count = nasty(mtmp);	/* summon something nasty */
449.  	if (mtmp->iswiz)
450.  	    verbalize("Destroy the thief, my pet%s!", plur(count));
451.  	else {
452.  	    const char *mappear =
453.  		(count == 1) ? "A monster appears" : "Monsters appear";
454.  
455.  	    /* messages not quite right if plural monsters created but
456.  	       only a single monster is seen */
457.  	    if (Invisible && !perceives(mtmp->data) &&
458.  				    (mtmp->mux != u.ux || mtmp->muy != u.uy))
459.  		pline("%s around a spot near you!", mappear);
460.  	    else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
461.  		pline("%s around your displaced image!", mappear);
462.  	    else
463.  		pline("%s from nowhere!", mappear);
464.  	}
465.  	dmg = 0;
466.  	break;
467.      }
468.  	case MGC_CALL_UNDEAD:
469.  	{
470.  		coord mm;   
471.  		mm.x = u.ux;   
472.  		mm.y = u.uy;   
473.  		pline("Undead creatures are called forth from the grave!");   
474.  		mkundead(&mm, FALSE, NO_MINVENT);   
475.  	}
476.  	dmg = 0;   
477.  	break;   
478.      case MGC_AGGRAVATION:
479.  	You_feel("that monsters are aware of your presence.");
480.  	aggravate();
481.  	dmg = 0;
482.  	break;
483.      case MGC_CURSE_ITEMS:
484.  	You_feel("as if you need some help.");
485.  	rndcurse();
486.  	dmg = 0;
487.  	break;
488.      case MGC_DESTRY_ARMR:
489.  	if (Antimagic) {
490.  	    shieldeff(u.ux, u.uy);
491.  	    pline("A field of force surrounds you!");
492.  	} else if (!destroy_arm(some_armor(&youmonst))) {
493.  	    Your("skin itches.");
494.  	}
495.  	dmg = 0;
496.  	break;
497.      case MGC_WEAKEN_YOU:		/* drain strength */
498.  	if (Antimagic) {
499.  	    shieldeff(u.ux, u.uy);
500.  	    You_feel("momentarily weakened.");
501.  	} else {
502.  	    You("suddenly feel weaker!");
503.  	    dmg = mtmp->m_lev - 6;
504.  	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
505.  	    losestr(rnd(dmg));
506.  	    if (u.uhp < 1)
507.  		done_in_by(mtmp);
508.  	}
509.  	dmg = 0;
510.  	break;
511.      case MGC_DISAPPEAR:		/* makes self invisible */
512.  	if (!mtmp->minvis && !mtmp->invis_blkd) {
513.  	    if (canseemon(mtmp))
514.  		pline("%s suddenly %s!", Monnam(mtmp),
515.  		      !See_invisible ? "disappears" : "becomes transparent");
516.  	    mon_set_minvis(mtmp);
517.  	    dmg = 0;
518.  	} else
519.  	    impossible("no reason for monster to cast disappear spell?");
520.  	break;
521.      case MGC_STUN_YOU:
522.  	if (Antimagic || Free_action) {
523.  	    shieldeff(u.ux, u.uy);
524.  	    if (!Stunned)
525.  		You_feel("momentarily disoriented.");
526.  	    make_stunned(1L, FALSE);
527.  	} else {
528.  	    You(Stunned ? "struggle to keep your balance." : "reel...");
529.  	    dmg = d(ACURR(A_DEX) < 12 ? 6 : 4, 4);
530.  	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
531.  	    make_stunned(HStun + dmg, FALSE);
532.  	}
533.  	dmg = 0;
534.  	break;
535.      case MGC_HASTE_SELF:
536.  	mon_adjust_speed(mtmp, 1, (struct obj *)0);
537.  	dmg = 0;
538.  	break;
539.      case MGC_CURE_SELF:
540.  	if (mtmp->mhp < mtmp->mhpmax) {
541.  	    if (canseemon(mtmp))
542.  		pline("%s looks better.", Monnam(mtmp));
543.  	    /* note: player healing does 6d4; this used to do 1d8 */
544.  	    if ((mtmp->mhp += d(3,6)) > mtmp->mhpmax)
545.  		mtmp->mhp = mtmp->mhpmax;
546.  	    dmg = 0;
547.  	}
548.  	break;
549.      case MGC_PSI_BOLT:
550.  	/* prior to 3.4.0 Antimagic was setting the damage to 1--this
551.  	   made the spell virtually harmless to players with magic res. */
552.  	if (Antimagic) {
553.  	    shieldeff(u.ux, u.uy);
554.  	    dmg = (dmg + 1) / 2;
555.  	}
556.  	if (dmg <= 5)
557.  	    You("get a slight %sache.", body_part(HEAD));
558.  	else if (dmg <= 10)
559.  	    Your("brain is on fire!");
560.  	else if (dmg <= 20)
561.  	    Your("%s suddenly aches painfully!", body_part(HEAD));
562.  	else
563.  	    Your("%s suddenly aches very painfully!", body_part(HEAD));
564.  	break;
565.      default:
566.  	impossible("mcastu: invalid magic spell (%d)", spellnum);
567.  	dmg = 0;
568.  	break;
569.      }
570.  
571.      if (dmg) mdamageu(mtmp, dmg);
572.  }
573.  
574.  STATIC_OVL
575.  void
576.  cast_cleric_spell(mtmp, dmg, spellnum)
577.  struct monst *mtmp;
578.  int dmg;
579.  int spellnum;
580.  {
581.      if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) {
582.  	impossible("cast directed cleric spell (%d) with dmg=0?", spellnum);
583.  	return;
584.      }
585.  
586.      switch (spellnum) {
587.      case CLC_GEYSER:
588.  	/* this is physical damage, not magical damage */
589.  	pline("A sudden geyser slams into you from nowhere!");
590.  	dmg = d(8, 6);
591.  	if (Half_physical_damage) dmg = (dmg + 1) / 2;
592.  	break;
593.      case CLC_FIRE_PILLAR:
594.  	pline("A pillar of fire strikes all around you!");
595.  	if (Fire_resistance) {
596.  	    shieldeff(u.ux, u.uy);
597.  	    dmg = 0;
598.  	} else
599.  	    dmg = d(8, 6);
600.  	if (Half_spell_damage) dmg = (dmg + 1) / 2;
601.  	burn_away_slime();
602.  	(void) burnarmor(&youmonst);
603.  	destroy_item(SCROLL_CLASS, AD_FIRE);
604.  	destroy_item(POTION_CLASS, AD_FIRE);
605.  	destroy_item(SPBOOK_CLASS, AD_FIRE);
606.  	(void) burn_floor_paper(u.ux, u.uy, TRUE, FALSE);
607.  	break;
608.      case CLC_LIGHTNING:
609.      {
610.  	boolean reflects;
611.  
612.  	/* WAC add lightning strike effect */
613.  	zap_strike_fx(u.ux, u.uy, AD_ELEC - 1);
614.  	pline("A bolt of lightning strikes down at you from above!");
615.  	reflects = ureflects("It bounces off your %s%s.", "");
616.  	if (!Blind) {
617.  	    pline("You are blinded by the flash!");
618.  	    make_blinded(Half_spell_damage ? 10L : 20L, FALSE);
619.  	}
620.  	if (reflects || Shock_resistance) {
621.  	    shieldeff(u.ux, u.uy);
622.  	    dmg = 0;
623.  	    if (reflects)
624.  		break;
625.  	} else
626.  	    dmg = d(8, 6);
627.  	if (Half_spell_damage) dmg = (dmg + 1) / 2;
628.  	destroy_item(WAND_CLASS, AD_ELEC);
629.  	destroy_item(RING_CLASS, AD_ELEC);
630.  	break;
631.      }
632.      case CLC_CURSE_ITEMS:
633.  	You_feel("as if you need some help.");
634.  	rndcurse();
635.  	dmg = 0;
636.  	break;
637.      case CLC_INSECTS:
638.        {
639.  	/* Try for insects, and if there are none
640.  	   left, go for (sticks to) snakes.  -3. */
641.  	struct permonst *pm = mkclass(S_ANT,0);
642.  	struct monst *mtmp2 = (struct monst *)0;
643.  	char let = (pm ? S_ANT : S_SNAKE);
644.  	boolean success;
645.  	int i;
646.  	coord bypos;
647.  	int quan;
648.  
649.  	quan = (mtmp->m_lev < 2) ? 1 : rnd((int)mtmp->m_lev / 2);
650.  	if (quan < 3) quan = 3;
651.  	success = pm ? TRUE : FALSE;
652.  	for (i = 0; i <= quan; i++) {
653.  	    if (!enexto(&bypos, mtmp->mux, mtmp->muy, mtmp->data))
654.  		break;
655.  	    if ((pm = mkclass(let,0)) != 0 &&
656.  		    (mtmp2 = makemon(pm, bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
657.  		success = TRUE;
658.  		mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0;
659.  		set_malign(mtmp2);
660.  	    }
661.  	}
662.  	/* Not quite right:
663.           * -- message doesn't always make sense for unseen caster (particularly
664.  	 *    the first message)
665.           * -- message assumes plural monsters summoned (non-plural should be
666.           *    very rare, unlike in nasty())
667.           * -- message assumes plural monsters seen
668.           */
669.  	if (!success)
670.  	    pline("%s casts at a clump of sticks, but nothing happens.",
671.  		Monnam(mtmp));
672.  	else if (let == S_SNAKE)
673.  	    pline("%s transforms a clump of sticks into snakes!",
674.  		Monnam(mtmp));
675.  	else if (Invisible && !perceives(mtmp->data) &&
676.  				(mtmp->mux != u.ux || mtmp->muy != u.uy))
677.  	    pline("%s summons insects around a spot near you!",
678.  		Monnam(mtmp));
679.  	else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
680.  	    pline("%s summons insects around your displaced image!",
681.  		Monnam(mtmp));
682.  	else
683.  	    pline("%s summons insects!", Monnam(mtmp));
684.  	dmg = 0;
685.  	break;
686.        }
687.      case CLC_BLIND_YOU:
688.  	/* note: resists_blnd() doesn't apply here */
689.  	if (!Blinded) {
690.  	    int num_eyes = eyecount(youmonst.data);
691.  	    pline("Scales cover your %s!",
692.  		  (num_eyes == 1) ?
693.  		  body_part(EYE) : makeplural(body_part(EYE)));
694.  	    make_blinded(Half_spell_damage ? 100L : 200L, FALSE);
695.  	    if (!Blind) Your(vision_clears);
696.  	    dmg = 0;
697.  	} else
698.  	    impossible("no reason for monster to cast blindness spell?");
699.  	break;
700.      case CLC_PARALYZE:
701.  	if (Antimagic || Free_action) {
702.  	    shieldeff(u.ux, u.uy);
703.  	    if (multi >= 0)
704.  		You("stiffen briefly.");
705.  	    nomul(-1);
706.  	} else {
707.  	    if (multi >= 0)
708.  		You("are frozen in place!");
709.  	    dmg = 4 + (int)mtmp->m_lev;
710.  	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
711.  	    nomul(-dmg);
712.  	}
713.  	nomovemsg = 0;
714.  	dmg = 0;
715.  	break;
716.      case CLC_CONFUSE_YOU:
717.  	if (Antimagic) {
718.  	    shieldeff(u.ux, u.uy);
719.  	    You_feel("momentarily dizzy.");
720.  	} else {
721.  	    boolean oldprop = !!Confusion;
722.  
723.  	    dmg = (int)mtmp->m_lev;
724.  	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
725.  	    make_confused(HConfusion + dmg, TRUE);
726.  	    if (Hallucination)
727.  		You_feel("%s!", oldprop ? "trippier" : "trippy");
728.  	    else
729.  		You_feel("%sconfused!", oldprop ? "more " : "");
730.  	}
731.  	dmg = 0;
732.  	break;
733.      case CLC_CURE_SELF:
734.  	if (mtmp->mhp < mtmp->mhpmax) {
735.  	    if (canseemon(mtmp))
736.  		pline("%s looks better.", Monnam(mtmp));
737.  	    /* note: player healing does 6d4; this used to do 1d8 */
738.  	    if ((mtmp->mhp += d(3,6)) > mtmp->mhpmax)
739.  		mtmp->mhp = mtmp->mhpmax;
740.  	    dmg = 0;
741.  	}
742.  	break;
743.      case CLC_OPEN_WOUNDS:
744.  	if (Antimagic) {
745.  	    shieldeff(u.ux, u.uy);
746.  	    dmg = (dmg + 1) / 2;
747.  	}
748.  	if (dmg <= 5)
749.  	    Your("skin itches badly for a moment.");
750.  	else if (dmg <= 10)
751.  	    pline("Wounds appear on your body!");
752.  	else if (dmg <= 20)
753.  	    pline("Severe wounds appear on your body!");
754.  	else
755.  	    Your("body is covered with painful wounds!");
756.  	break;
757.      default:
758.  	impossible("mcastu: invalid clerical spell (%d)", spellnum);
759.  	dmg = 0;
760.  	break;
761.      }
762.  
763.      if (dmg) mdamageu(mtmp, dmg);
764.  }
765.  
766.  STATIC_DCL
767.  boolean
768.  is_undirected_spell(adtyp, spellnum)
769.  unsigned int adtyp;
770.  int spellnum;
771.  {
772.      if (adtyp == AD_SPEL) {
773.  	switch (spellnum) {
774.  	case MGC_CLONE_WIZ:
775.  	case MGC_SUMMON_MONS:
776.  	case MGC_AGGRAVATION:
777.  	case MGC_DISAPPEAR:
778.  	case MGC_HASTE_SELF:
779.  	case MGC_CURE_SELF:
780.  	case MGC_CALL_UNDEAD:
781.  	    return TRUE;
782.  	default:
783.  	    break;
784.  	}
785.      } else if (adtyp == AD_CLRC) {
786.  	switch (spellnum) {
787.  	case CLC_INSECTS:
788.  	case CLC_CURE_SELF:
789.  	    return TRUE;
790.  	default:
791.  	    break;
792.  	}
793.      }
794.      return FALSE;
795.  }
796.  
797.  /* Some spells are useless under some circumstances. */
798.  STATIC_DCL
799.  boolean
800.  spell_would_be_useless(mtmp, adtyp, spellnum)
801.  struct monst *mtmp;
802.  unsigned int adtyp;
803.  int spellnum;
804.  {
805.      /* Some spells don't require the player to really be there and can be cast
806.       * by the monster when you're invisible, yet still shouldn't be cast when
807.       * the monster doesn't even think you're there.
808.       * This check isn't quite right because it always uses your real position.
809.       * We really want something like "if the monster could see mux, muy".
810.       */
811.      boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my);
812.  
813.      if (adtyp == AD_SPEL) {
814.  	/* aggravate monsters, etc. won't be cast by peaceful monsters */
815.  	if (mtmp->mpeaceful && (spellnum == MGC_AGGRAVATION ||
816.                 spellnum == MGC_SUMMON_MONS || spellnum == MGC_CLONE_WIZ ||
817.                 spellnum == MGC_CALL_UNDEAD))
818.  	    return TRUE;
819.  	/* haste self when already fast */
820.  	if (mtmp->permspeed == MFAST && spellnum == MGC_HASTE_SELF)
821.  	    return TRUE;
822.  	/* invisibility when already invisible */
823.  	if ((mtmp->minvis || mtmp->invis_blkd) && spellnum == MGC_DISAPPEAR)
824.  	    return TRUE;
825.  	/* peaceful monster won't cast invisibility if you can't see invisible,
826.  	   same as when monsters drink potions of invisibility.  This doesn't
827.  	   really make a lot of sense, but lets the player avoid hitting
828.  	   peaceful monsters by mistake */
829.  	if (mtmp->mpeaceful && !See_invisible && spellnum == MGC_DISAPPEAR)
830.  	    return TRUE;
831.  	/* healing when already healed */
832.  	if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF)
833.  	    return TRUE;
834.  	/* don't summon monsters if it doesn't think you're around */
835.  	if (!mcouldseeu && (spellnum == MGC_SUMMON_MONS ||
836.  		spellnum == MGC_CALL_UNDEAD ||
837.  		(!mtmp->iswiz && spellnum == MGC_CLONE_WIZ)))
838.  	    return TRUE;
839.  	/* only lichs can cast call undead */
840.  	if (mtmp->data->mlet != S_LICH && spellnum == MGC_CALL_UNDEAD)
841.  	    return TRUE;
842.  	/* pools can only be created in certain locations and then only
843.  	 * rarely unless you're carrying the amulet.
844.  	 */
845.  	if ((levl[u.ux][u.uy].typ != ROOM && levl[u.ux][u.uy].typ != CORR
846.  		|| !u.uhave.amulet && rn2(10)) && spellnum == MGC_CREATE_POOL)
847.  	    return TRUE;
848.  	if ((!mtmp->iswiz || flags.no_of_wizards > 1)
849.  						&& spellnum == MGC_CLONE_WIZ)
850.  	    return TRUE;
851.      } else if (adtyp == AD_CLRC) {
852.  	/* summon insects/sticks to snakes won't be cast by peaceful monsters */
853.  	if (mtmp->mpeaceful && spellnum == CLC_INSECTS)
854.  	    return TRUE;
855.  	/* healing when already healed */
856.  	if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF)
857.  	    return TRUE;
858.  	/* don't summon insects if it doesn't think you're around */
859.  	if (!mcouldseeu && spellnum == CLC_INSECTS)
860.  	    return TRUE;
861.  	/* blindness spell on blinded player */
862.  	if (Blinded && spellnum == CLC_BLIND_YOU)
863.  	    return TRUE;
864.      }
865.      return FALSE;
866.  }
867.  
868.  #endif /* OVLB */
869.  #ifdef OVL0
870.  
871.  /* convert 1..10 to 0..9; add 10 for second group (spell casting) */
872.  #define ad_to_typ(k) (10 + (int)k - 1)
873.  
874.  int
875.  buzzmu(mtmp, mattk)		/* monster uses spell (ranged) */
876.  	register struct monst *mtmp;
877.  	register struct attack  *mattk;
878.  {
879.  	/* don't print constant stream of curse messages for 'normal'
880.  	   spellcasting monsters at range */
881.  	if (mattk->adtyp > AD_SPC2)
882.  	    return(0);
883.  
884.  	if (mtmp->mcan) {
885.  	    cursetxt(mtmp, FALSE);
886.  	    return(0);
887.  	}
888.  	if(lined_up(mtmp) && rn2(3)) {
889.  	    nomul(0);
890.  	    if(mattk->adtyp && (mattk->adtyp < 11)) { /* no cf unsigned >0 */
891.  		if(canseemon(mtmp))
892.  		    pline("%s zaps you with a %s!", Monnam(mtmp),
893.  			  flash_types[ad_to_typ(mattk->adtyp)]);
894.  		buzz(-ad_to_typ(mattk->adtyp), (int)mattk->damn,
895.  		     mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
896.  	    } else impossible("Monster spell %d cast", mattk->adtyp-1);
897.  	}
898.  	return(1);
899.  }
900.  
901.  #endif /* OVL0 */
902.  
903.  /*mcastu.c*/
Advertisement