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