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