Source:NetHack 3.4.0/mcastu.c

Below is the full text to mcastu.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/mcastu.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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