xref: /netbsd/games/hack/hack.mhitu.c (revision bf9ec67e)
1 /*	$NetBSD: hack.mhitu.c,v 1.5 2001/03/25 20:44:01 jsm Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.mhitu.c,v 1.5 2001/03/25 20:44:01 jsm Exp $");
10 #endif				/* not lint */
11 
12 #include "hack.h"
13 #include "extern.h"
14 
15 /*
16  * mhitu: monster hits you
17  *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
18  */
19 int
20 mhitu(mtmp)
21 	struct monst   *mtmp;
22 {
23 	const struct permonst *mdat = mtmp->data;
24 	int             tmp, ctmp;
25 
26 	nomul(0);
27 
28 	/* If swallowed, can only be affected by hissers and by u.ustuck */
29 	if (u.uswallow) {
30 		if (mtmp != u.ustuck) {
31 			if (mdat->mlet == 'c' && !rn2(13)) {
32 				pline("Outside, you hear %s's hissing!",
33 				      monnam(mtmp));
34 				pline("%s gets turned to stone!",
35 				      Monnam(u.ustuck));
36 				pline("And the same fate befalls you.");
37 				done_in_by(mtmp);
38 				/* "notreached": not return(1); */
39 			}
40 			return (0);
41 		}
42 		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
43 		case ',':
44 			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
45 				5, "The trapper");
46 			break;
47 		case '\'':
48 			youswld(mtmp, rnd(6), 7, "The lurker above");
49 			break;
50 		case 'P':
51 			youswld(mtmp, d(2, 4), 12, "The purple worm");
52 			break;
53 		default:
54 			/* This is not impossible! */
55 			pline("The mysterious monster totally digests you.");
56 			u.uhp = 0;
57 		}
58 		if (u.uhp < 1)
59 			done_in_by(mtmp);
60 		return (0);
61 	}
62 	if (mdat->mlet == 'c' && Stoned)
63 		return (0);
64 
65 	/* make eels visible the moment they hit/miss us */
66 	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
67 		mtmp->minvis = 0;
68 		pmon(mtmp);
69 	}
70 	if (!strchr("1&DuxynNF", mdat->mlet))
71 		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
72 	else
73 		tmp = 0;
74 	if (strchr(UNDEAD, mdat->mlet) && midnight())
75 		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));
76 
77 	ctmp = tmp && !mtmp->mcan &&
78 		(!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
79 	switch (mdat->mlet) {
80 	case '1':
81 		if (wiz_hit(mtmp))
82 			return (1);	/* he disappeared */
83 		break;
84 	case '&':
85 		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
86 			(void) makemon(PM_DEMON, u.ux, u.uy);
87 		} else {
88 			(void) hitu(mtmp, d(2, 6));
89 			(void) hitu(mtmp, d(2, 6));
90 			(void) hitu(mtmp, rnd(3));
91 			(void) hitu(mtmp, rnd(3));
92 			(void) hitu(mtmp, rn1(4, 2));
93 		}
94 		break;
95 	case ',':
96 		if (tmp)
97 			justswld(mtmp, "The trapper");
98 		break;
99 	case '\'':
100 		if (tmp)
101 			justswld(mtmp, "The lurker above");
102 		break;
103 	case ';':
104 		if (ctmp) {
105 			if (!u.ustuck && !rn2(10)) {
106 				pline("%s swings itself around you!",
107 				      Monnam(mtmp));
108 				u.ustuck = mtmp;
109 			} else if (u.ustuck == mtmp &&
110 				   levl[mtmp->mx][mtmp->my].typ == POOL) {
111 				pline("%s drowns you ...", Monnam(mtmp));
112 				done("drowned");
113 			}
114 		}
115 		break;
116 	case 'A':
117 		if (ctmp && rn2(2)) {
118 			if (Poison_resistance)
119 				pline("The sting doesn't seem to affect you.");
120 			else {
121 				pline("You feel weaker!");
122 				losestr(1);
123 			}
124 		}
125 		break;
126 	case 'C':
127 		(void) hitu(mtmp, rnd(6));
128 		break;
129 	case 'c':
130 		if (!rn2(5)) {
131 			pline("You hear %s's hissing!", monnam(mtmp));
132 			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
133 					       && !carrying(DEAD_LIZARD))) {
134 				Stoned = 5;
135 				/* pline("You get turned to stone!"); */
136 				/* done_in_by(mtmp); */
137 			}
138 		}
139 		break;
140 	case 'D':
141 		if (rn2(6) || mtmp->mcan) {
142 			(void) hitu(mtmp, d(3, 10));
143 			(void) hitu(mtmp, rnd(8));
144 			(void) hitu(mtmp, rnd(8));
145 			break;
146 		}
147 		kludge("%s breathes fire!", "The dragon");
148 		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
149 		break;
150 	case 'd':
151 		(void) hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
152 		break;
153 	case 'e':
154 		(void) hitu(mtmp, d(3, 6));
155 		break;
156 	case 'F':
157 		if (mtmp->mcan)
158 			break;
159 		kludge("%s explodes!", "The freezing sphere");
160 		if (Cold_resistance)
161 			pline("You don't seem affected by it.");
162 		else {
163 			xchar           dn;
164 			if (17 - (u.ulevel / 2) > rnd(20)) {
165 				pline("You get blasted!");
166 				dn = 6;
167 			} else {
168 				pline("You duck the blast...");
169 				dn = 3;
170 			}
171 			losehp_m(d(dn, 6), mtmp);
172 		}
173 		mondead(mtmp);
174 		return (1);
175 	case 'g':
176 		if (ctmp && multi >= 0 && !rn2(3)) {
177 			kludge("You are frozen by %ss juices", "the cube'");
178 			nomul(-rnd(10));
179 		}
180 		break;
181 	case 'h':
182 		if (ctmp && multi >= 0 && !rn2(5)) {
183 			nomul(-rnd(10));
184 			kludge("You are put to sleep by %ss bite!",
185 			       "the homunculus'");
186 		}
187 		break;
188 	case 'j':
189 		tmp = hitu(mtmp, rnd(3));
190 		tmp &= hitu(mtmp, rnd(3));
191 		if (tmp) {
192 			(void) hitu(mtmp, rnd(4));
193 			(void) hitu(mtmp, rnd(4));
194 		}
195 		break;
196 	case 'k':
197 		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) {
198 			poisoned("bee's sting", mdat->mname);
199 		}
200 		break;
201 	case 'L':
202 		if (tmp)
203 			stealgold(mtmp);
204 		break;
205 	case 'N':
206 		if (mtmp->mcan && !Blind) {
207 			pline("%s tries to seduce you, but you seem not interested.",
208 			      Amonnam(mtmp, "plain"));
209 			if (rn2(3))
210 				rloc(mtmp);
211 		} else if (steal(mtmp)) {
212 			rloc(mtmp);
213 			mtmp->mflee = 1;
214 		}
215 		break;
216 	case 'n':
217 		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
218 			pline("%s hits! (I hope you don't mind)",
219 			      Monnam(mtmp));
220 			u.uhp += rnd(7);
221 			if (!rn2(7))
222 				u.uhpmax++;
223 			if (u.uhp > u.uhpmax)
224 				u.uhp = u.uhpmax;
225 			flags.botl = 1;
226 			if (!rn2(50))
227 				rloc(mtmp);
228 		} else {
229 			(void) hitu(mtmp, d(2, 6));
230 			(void) hitu(mtmp, d(2, 6));
231 		}
232 		break;
233 	case 'o':
234 		tmp = hitu(mtmp, rnd(6));
235 		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
236 		    !u.ustuck && rn2(2)) {
237 			u.ustuck = mtmp;
238 			kludge("%s has grabbed you!", "The owlbear");
239 			u.uhp -= d(2, 8);
240 		} else if (u.ustuck == mtmp) {
241 			u.uhp -= d(2, 8);
242 			pline("You are being crushed.");
243 		}
244 		break;
245 	case 'P':
246 		if (ctmp && !rn2(4))
247 			justswld(mtmp, "The purple worm");
248 		else
249 			(void) hitu(mtmp, d(2, 4));
250 		break;
251 	case 'Q':
252 		(void) hitu(mtmp, rnd(2));
253 		(void) hitu(mtmp, rnd(2));
254 		break;
255 	case 'R':
256 		if (tmp && uarmh && !uarmh->rustfree &&
257 		    (int) uarmh->spe >= -1) {
258 			pline("Your helmet rusts!");
259 			uarmh->spe--;
260 		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
261 			   uarm->otyp < STUDDED_LEATHER_ARMOR &&
262 			   (int) uarm->spe >= -1) {
263 			pline("Your armor rusts!");
264 			uarm->spe--;
265 		}
266 		break;
267 	case 'S':
268 		if (ctmp && !rn2(8)) {
269 			poisoned("snake's bite", mdat->mname);
270 		}
271 		break;
272 	case 's':
273 		if (tmp && !rn2(8)) {
274 			poisoned("scorpion's sting", mdat->mname);
275 		}
276 		(void) hitu(mtmp, rnd(8));
277 		(void) hitu(mtmp, rnd(8));
278 		break;
279 	case 'T':
280 		(void) hitu(mtmp, rnd(6));
281 		(void) hitu(mtmp, rnd(6));
282 		break;
283 	case 't':
284 		if (!rn2(5))
285 			rloc(mtmp);
286 		break;
287 	case 'u':
288 		mtmp->mflee = 1;
289 		break;
290 	case 'U':
291 		(void) hitu(mtmp, d(3, 4));
292 		(void) hitu(mtmp, d(3, 4));
293 		break;
294 	case 'v':
295 		if (ctmp && !u.ustuck)
296 			u.ustuck = mtmp;
297 		break;
298 	case 'V':
299 		if (tmp)
300 			u.uhp -= 4;
301 		if (ctmp)
302 			losexp();
303 		break;
304 	case 'W':
305 		if (ctmp)
306 			losexp();
307 		break;
308 #ifndef NOWORM
309 	case 'w':
310 		if (tmp)
311 			wormhit(mtmp);
312 #endif	/* NOWORM */
313 		break;
314 	case 'X':
315 		(void) hitu(mtmp, rnd(5));
316 		(void) hitu(mtmp, rnd(5));
317 		(void) hitu(mtmp, rnd(5));
318 		break;
319 	case 'x':
320 		{
321 			long            side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
322 			pline("%s pricks in your %s leg!",
323 			      Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
324 			set_wounded_legs(side, rnd(50));
325 			losehp_m(2, mtmp);
326 			break;
327 		}
328 	case 'y':
329 		if (mtmp->mcan)
330 			break;
331 		mondead(mtmp);
332 		if (!Blind) {
333 			pline("You are blinded by a blast of light!");
334 			Blind = d(4, 12);
335 			seeoff(0);
336 		}
337 		return (1);
338 	case 'Y':
339 		(void) hitu(mtmp, rnd(6));
340 		break;
341 	}
342 	if (u.uhp < 1)
343 		done_in_by(mtmp);
344 	return (0);
345 }
346 
347 int
348 hitu(mtmp, dam)
349 	struct monst   *mtmp;
350 	int dam;
351 {
352 	int tmp, res;
353 
354 	nomul(0);
355 	if (u.uswallow)
356 		return (0);
357 
358 	if (mtmp->mhide && mtmp->mundetected) {
359 		mtmp->mundetected = 0;
360 		if (!Blind) {
361 			struct obj     *obj;
362 			if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL)
363 				pline("%s was hidden under %s!",
364 				      Xmonnam(mtmp), doname(obj));
365 		}
366 	}
367 	tmp = u.uac;
368 	/* give people with Ac = -10 at least some vulnerability */
369 	if (tmp < 0) {
370 		dam += tmp;	/* decrease damage */
371 		if (dam <= 0)
372 			dam = 1;
373 		tmp = -rn2(-tmp);
374 	}
375 	tmp += mtmp->data->mlevel;
376 	if (multi < 0)
377 		tmp += 4;
378 	if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee)
379 		tmp -= 2;
380 	if (mtmp->mtrapped)
381 		tmp -= 2;
382 	if (tmp <= rnd(20)) {
383 		if (Blind)
384 			pline("It misses.");
385 		else
386 			pline("%s misses.", Monnam(mtmp));
387 		res = 0;
388 	} else {
389 		if (Blind)
390 			pline("It hits!");
391 		else
392 			pline("%s hits!", Monnam(mtmp));
393 		losehp_m(dam, mtmp);
394 		res = 1;
395 	}
396 	stop_occupation();
397 	return (res);
398 }
399