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