Source:SLASH'EM 0.0.7E7F2/mcastu.c

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.

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