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