1 /*	SCCS Id: @(#)mcastu.c	3.3	97/11/02	*/
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 STATIC_DCL void FDECL(cursetxt,(struct monst *));
8 
9 #ifdef OVL0
10 
11 extern const char *flash_types[];	/* from zap.c */
12 
13 /* feedback when frustrated monster couldn't cast a spell */
14 STATIC_OVL
15 void
cursetxt(mtmp)16 cursetxt(mtmp)
17 struct monst *mtmp;
18 {
19 	if (canseemon(mtmp)) {
20 	    const char *point_msg;  /* spellcasting monsters are impolite */
21 
22 	    if ((Invis && !perceives(mtmp->data) &&
23 			(mtmp->mux != u.ux || mtmp->muy != u.uy)) ||
24 		    (youmonst.m_ap_type == M_AP_OBJECT &&
25 			youmonst.mappearance == STRANGE_OBJECT) ||
26 		    u.uundetected)
27 		point_msg = "and curses in your general direction";
28 	    else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
29 		point_msg = "and curses at your displaced image";
30 	    else
31 		point_msg = "at you, then curses";
32 
33 	    pline("%s points %s.", Monnam(mtmp), point_msg);
34 	} else if ((!(moves % 4) || !rn2(4))) {
35 	    if (flags.soundok) Norep("You hear a mumbled curse.");
36 	}
37 }
38 
39 #endif /* OVL0 */
40 #ifdef OVLB
41 
42 int
castmu(mtmp,mattk)43 castmu(mtmp, mattk)	/* monster casts spell at you */
44 	register struct monst *mtmp;
45 	register struct attack *mattk;
46 {
47 	int	dmg, ml = mtmp->m_lev;
48 
49 	if(mtmp->mcan || mtmp->mspec_used || !ml) {  /* could not attack */
50 	    cursetxt(mtmp);
51 	    return(0);
52 	} else {
53 	    nomul(0);
54 	    if(rn2(ml*10) < (mtmp->mconf ? 100 : 20)) {	/* fumbled attack */
55 		if (canseemon(mtmp) && flags.soundok)
56 		    pline_The("air crackles around %s.", mon_nam(mtmp));
57 		return(0);
58 	    }
59 	}
60 /*
61  *	As these are spells, the damage is related to the level
62  *	of the monster casting the spell.
63  */
64 	if (mattk->damd)
65 		dmg = d((int)((ml/3) + mattk->damn), (int)mattk->damd);
66 	else dmg = d((int)((ml/3) + 1), 6);
67 	if (Half_spell_damage) dmg = (dmg+1) / 2;
68 
69 	switch(mattk->adtyp)   {
70 
71 	    case AD_FIRE:
72 		pline("You're enveloped in flames.");
73 		if(Fire_resistance) {
74 			shieldeff(u.ux, u.uy);
75 			pline("But you resist the effects.");
76 			dmg = 0;
77 		}
78 		burn_away_slime();
79 		break;
80 	    case AD_COLD:
81 		pline("You're covered in frost.");
82 		if(Cold_resistance) {
83 			shieldeff(u.ux, u.uy);
84 			pline("But you resist the effects.");
85 			dmg = 0;
86 		}
87 		break;
88 	    case AD_MAGM:
89 		You("are hit by a shower of missiles!");
90 		if(Antimagic) {
91 			shieldeff(u.ux, u.uy);
92 			pline_The("missiles bounce off!");
93 			dmg = 0;
94 		} else dmg = d((int)mtmp->m_lev/2 + 1,6);
95 		break;
96 	    case AD_SPEL:	/* random spell */
97 
98 		mtmp->mspec_used = 10 - mtmp->m_lev;
99 		if (mtmp->mspec_used < 2) mtmp->mspec_used = 2;
100 		switch(rn2((int)mtmp->m_lev)) {
101 		    case 22:
102 		    case 21:
103 		    case 20:
104 			pline("Oh no, %s's using the touch of death!",
105 			      humanoid(mtmp->data)
106 				  ? (mtmp->female ? "she" : "he")
107 				  : "it"
108 			     );
109 			if (nonliving(youmonst.data) || is_demon(youmonst.data))
110 			    You("seem no deader than before.");
111 			else if (!Antimagic && rn2(ml) > 12) {
112 
113 			    if(Hallucination)
114 				You("have an out of body experience.");
115 			    else  {
116 				killer_format = KILLED_BY_AN;
117 				killer = "touch of death";
118 				done(DIED);
119 			    }
120 			} else {
121 				if(Antimagic) shieldeff(u.ux, u.uy);
122 				pline("Lucky for you, it didn't work!");
123 			}
124 			dmg = 0;
125 			break;
126 		    case 19:
127 		    case 18:
128 			if(mtmp->iswiz && flags.no_of_wizards == 1) {
129 				pline("Double Trouble...");
130 				clonewiz();
131 				dmg = 0;
132 				break;
133 			} /* else fall into the next case */
134 		    case 17:
135 		    case 16:
136 		    case 15:
137 			if(mtmp->iswiz)
138 			    verbalize("Destroy the thief, my pets!");
139 			nasty(mtmp);	/* summon something nasty */
140 			/* fall into the next case */
141 		    case 14:		/* aggravate all monsters */
142 		    case 13:
143 			aggravate();
144 			dmg = 0;
145 			break;
146 		    case 12:		/* curse random items */
147 		    case 11:
148 		    case 10:
149 			rndcurse();
150 			dmg = 0;
151 			break;
152 		    case 9:
153 		    case 8:		/* destroy armor */
154 			if (Antimagic) {
155 				shieldeff(u.ux, u.uy);
156 				pline("A field of force surrounds you!");
157 			} else if(!destroy_arm(some_armor(&youmonst)))
158 				Your("skin itches.");
159 			dmg = 0;
160 			break;
161 		    case 7:
162 		    case 6:		/* drain strength */
163 			if(Antimagic) {
164 			    shieldeff(u.ux, u.uy);
165 			    You_feel("momentarily weakened.");
166 			} else {
167 			    You("suddenly feel weaker!");
168 			    dmg = ml - 6;
169 			    if(Half_spell_damage) dmg = (dmg+1) / 2;
170 			    losestr(rnd(dmg));
171 			    if(u.uhp < 1)
172 				done_in_by(mtmp);
173 			}
174 			dmg = 0;
175 			break;
176 		    case 5:		/* make invisible if not */
177 		    case 4:
178 			if (!mtmp->minvis && !mtmp->invis_blkd) {
179 			    if(canseemon(mtmp) && !See_invisible)
180 				pline("%s suddenly disappears!", Monnam(mtmp));
181 			    mon_set_minvis(mtmp);
182 			    dmg = 0;
183 			    break;
184 			} /* else fall into the next case */
185 		    case 3:		/* stun */
186 			if (Antimagic || Free_action) {
187 			    shieldeff(u.ux, u.uy);
188 			    if(!Stunned)
189 				You_feel("momentarily disoriented.");
190 			    make_stunned(1L, FALSE);
191 			} else {
192 			    if (Stunned)
193 				You("struggle to keep your balance.");
194 			    else
195 				You("reel...");
196 			    dmg = d(ACURR(A_DEX) < 12 ? 6 : 4, 4);
197 			    if(Half_spell_damage) dmg = (dmg+1) / 2;
198 			    make_stunned(HStun + dmg, FALSE);
199 			}
200 			dmg = 0;
201 			break;
202 		    case 2:		/* haste self */
203 			mon_adjust_speed(mtmp, 1);
204 			dmg = 0;
205 			break;
206 		    case 1:		/* cure self */
207 			if(mtmp->mhp < mtmp->mhpmax) {
208 			    if((mtmp->mhp += rnd(8)) > mtmp->mhpmax)
209 				mtmp->mhp = mtmp->mhpmax;
210 			    dmg = 0;
211 			    break;
212 			} /* else fall through to default case */
213 		    default:		/* psi bolt */
214 			if(Antimagic) {
215 			    shieldeff(u.ux, u.uy);
216 			    You("get a slight %sache.",body_part(HEAD));
217 			    dmg = 1;
218 			} else {
219 			    if (dmg <= 10)
220 				Your("brain is on fire!");
221 			    else Your("%s suddenly aches!", body_part(HEAD));
222 			}
223 			break;
224 		}
225 		break;
226 
227 	    case AD_CLRC:	/* clerical spell */
228 		mtmp->mspec_used = 10 - mtmp->m_lev;
229 		if (mtmp->mspec_used < 2) mtmp->mspec_used = 2;
230 		switch(rn2((int)mtmp->m_lev)) {
231 		    /* Other ideas: lightning bolts, towers of flame,
232 				    gush of water  -3. */
233 
234 		    default:		/* confuse */
235 			if(Antimagic) {
236 			    shieldeff(u.ux, u.uy);
237 			    You_feel("momentarily dizzy.");
238 			} else {
239 			    dmg = (int)mtmp->m_lev;
240 			    if(Half_spell_damage) dmg = (dmg+1) / 2;
241 			    make_confused(HConfusion + dmg, TRUE);
242 			}
243 			dmg = 0;
244 			break;
245 		    case 12:		/* curse random items */
246 		    case 11:
247 		    case 10:
248 			rndcurse();
249 			dmg = 0;
250 			break;
251 		    case 9:
252 		    case 8:		/* insects */
253 			/* Try for insects, and if there are none
254 			   left, go for (sticks to) snakes.  -3. */
255 			{
256 			int i;
257 			struct permonst *pm = mkclass(S_ANT,0);
258 			struct monst *mtmp2;
259 			char let = (pm ? S_ANT : S_SNAKE);
260 
261 			for (i = 0; i <= (int) mtmp->m_lev; i++)
262 			   if ((pm = mkclass(let,0)) &&
263 			(mtmp2 = makemon(pm, u.ux, u.uy, NO_MM_FLAGS))) {
264 				mtmp2->msleeping = mtmp2->mpeaceful =
265 					mtmp2->mtame = 0;
266 				set_malign(mtmp2);
267 			    }
268 			}
269 			dmg = 0;
270 			break;
271 		    case 6:
272 		    case 7:		/* blindness */
273 			/* note: resists_blnd() doesn't apply here */
274 			if (!Blinded) {
275 			    pline("Scales cover your %s!", makeplural(body_part(EYE)));
276 			    make_blinded(Half_spell_damage ? 100L:200L, FALSE);
277 			    dmg = 0;
278 			    break;
279 			}
280 		    case 4:
281 		    case 5:		/* wound */
282 			if(Antimagic) {
283 			    shieldeff(u.ux, u.uy);
284 			    Your("skin itches badly for a moment.");
285 			    dmg = 0;
286 			} else {
287 			    pline("Wounds appear on your body!");
288 			    dmg = d(2,8) + 1;
289 			    if (Half_spell_damage) dmg = (dmg+1) / 2;
290 			}
291 			break;
292 		    case 3:		/* hold */
293 			if (Antimagic || Free_action) {
294 			    shieldeff(u.ux, u.uy);
295 			    if(multi >= 0)
296 				You("stiffen briefly.");
297 			    nomul(-1);
298 			} else {
299 			    if (multi >= 0)
300 				You("are frozen in place!");
301 			    dmg = 4 + (int)mtmp->m_lev;
302 			    if (Half_spell_damage) dmg = (dmg+1) / 2;
303 			    nomul(-dmg);
304 			}
305 			dmg = 0;
306 			break;
307 		    case 2:
308 		    case 1:		/* cure self */
309 			if(mtmp->mhp < mtmp->mhpmax) {
310 			    if((mtmp->mhp += rnd(8)) > mtmp->mhpmax)
311 				mtmp->mhp = mtmp->mhpmax;
312 			    dmg = 0;
313 			    break;
314 			} /* else fall through to default case */
315 		}
316 	}
317 	if(dmg) mdamageu(mtmp, dmg);
318 	return(1);
319 }
320 
321 #endif /* OVLB */
322 #ifdef OVL0
323 
324 /* convert 1..10 to 0..9; add 10 for second group (spell casting) */
325 #define ad_to_typ(k) (10 + (int)k - 1)
326 
327 int
buzzmu(mtmp,mattk)328 buzzmu(mtmp, mattk)		/* monster uses spell (ranged) */
329 	register struct monst *mtmp;
330 	register struct attack  *mattk;
331 {
332 	if(mtmp->mcan || mattk->adtyp > AD_SPC2) {
333 	    cursetxt(mtmp);
334 	    return(0);
335 	}
336 	if(lined_up(mtmp) && rn2(3)) {
337 	    nomul(0);
338 	    if(mattk->adtyp && (mattk->adtyp < 11)) { /* no cf unsigned >0 */
339 		if(canseemon(mtmp))
340 		    pline("%s zaps you with a %s!", Monnam(mtmp),
341 			  flash_types[ad_to_typ(mattk->adtyp)]);
342 		buzz(-ad_to_typ(mattk->adtyp), (int)mattk->damn,
343 		     mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
344 	    } else impossible("Monster spell %d cast", mattk->adtyp-1);
345 	}
346 	return(1);
347 }
348 
349 #endif /* OVL0 */
350 
351 /*mcastu.c*/
352