Source:SLASH'EM 0.0.7E7F2/mcastu.c

From NetHackWiki
Revision as of 19:14, 7 March 2008 by Kernigh bot (talk | contribs) (SLASH'EM 0.0.7E7F2/mcastu.c moved to Source:SLASH'EM 0.0.7E7F2/mcastu.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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*/