1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.fight.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.fight.c,v 1.5 1999/11/16 10:26:36 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.fight.c,v 1.4 2005/05/22 03:37:05 y0netan1 Exp $ */
7 extern struct permonst li_dog
, dog
, la_dog
;
9 extern struct obj
*mkobj_at();
11 static boolean far_noise
;
12 static long noisetime
;
14 /* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */
15 hitmm(magr
,mdef
) struct monst
*magr
,*mdef
; {
16 struct permonst
*pa
= magr
->data
, *pd
= mdef
->data
;
20 if(index("Eauy", pa
->mlet
)) return(0);
21 if(magr
->mfroz
) return(0); /* riv05!a3 */
22 tmp
= pd
->ac
+ pa
->mlevel
;
23 if(mdef
->mconf
|| mdef
->mfroz
|| mdef
->msleep
){
25 if(mdef
->msleep
) mdef
->msleep
= 0;
27 hit
= (tmp
> rnd(20));
28 if(hit
) mdef
->msleep
= 0;
29 vis
= (cansee(magr
->mx
,magr
->my
) && cansee(mdef
->mx
,mdef
->my
));
32 if(mdef
->mimic
) seemimic(mdef
);
33 if(magr
->mimic
) seemimic(magr
);
34 (void) sprintf(buf
,"%s %s", Monnam(magr
),
35 hit
? "hits" : "misses");
36 pline("%s %s.", buf
, monnam(mdef
));
38 boolean far
= (dist(magr
->mx
, magr
->my
) > 15);
39 if(far
!= far_noise
|| moves
-noisetime
> 10) {
42 pline("You hear some noises%s.",
43 far
? " in the distance" : "");
47 if(magr
->data
->mlet
== 'c' && !magr
->cham
) {
49 if(vis
) pline("%s is turned to stone!", Monnam(mdef
));
51 pline("You have a peculiarly sad feeling for a moment, then it passes.");
55 if((mdef
->mhp
-= d(pa
->damn
,pa
->damd
)) < 1) {
56 magr
->mhpmax
+= 1 + rn2(pd
->mlevel
+1);
57 if(magr
->mtame
&& magr
->mhpmax
> 8*pa
->mlevel
){
58 if(pa
== &li_dog
) magr
->data
= pa
= &dog
;
59 else if(pa
== &dog
) magr
->data
= pa
= &la_dog
;
61 if(vis
) pline("%s is killed!", Monnam(mdef
));
63 pline("You have a sad feeling for a moment, then it passes.");
71 /* drop (perhaps) a cadaver and remove monster */
72 mondied(mdef
) struct monst
*mdef
; {
73 struct permonst
*pd
= mdef
->data
;
74 if(letter(pd
->mlet
) && rn2(3)){
75 (void) mkobj_at(pd
->mlet
,mdef
->mx
,mdef
->my
);
76 if(cansee(mdef
->mx
,mdef
->my
)){
78 atl(mdef
->mx
,mdef
->my
,fobj
->olet
);
85 /* drop a rock and remove monster */
86 monstone(mdef
) struct monst
*mdef
; {
88 if(index(mlarge
, mdef
->data
->mlet
))
89 mksobj_at(ENORMOUS_ROCK
, mdef
->mx
, mdef
->my
);
91 mksobj_at(ROCK
, mdef
->mx
, mdef
->my
);
92 if(cansee(mdef
->mx
, mdef
->my
)){
94 atl(mdef
->mx
,mdef
->my
,fobj
->olet
);
100 fightm(mtmp
) struct monst
*mtmp
; {
102 for(mon
= fmon
; mon
; mon
= mon
->nmon
) if(mon
!= mtmp
) {
103 if(DIST(mon
->mx
,mon
->my
,mtmp
->mx
,mtmp
->my
) < 3)
105 return(hitmm(mtmp
,mon
));
110 /* u is hit by sth, but not a monster */
117 if(u
.uac
+ tlev
<= rnd(20)) {
118 if(Blind
) pline("It misses.");
119 else pline("You are almost hit by %s!", buf
);
122 if(Blind
) pline("You are hit!");
123 else pline("You are hit by %s!", buf
);
129 char mlarge
[] = "bCDdegIlmnoPSsTUwY',&";
132 hmon(mon
,obj
,thrown
) /* return TRUE if mon still alive */
138 boolean hittxt
= FALSE
;
141 tmp
= rnd(2); /* attack with bare hands */
142 if(mon
->data
->mlet
== 'c' && !uarmg
){
143 pline("You hit the cockatrice with your bare hands.");
144 pline("You turn to stone ...");
147 } else if(obj
->olet
== WEAPON_SYM
|| obj
->otyp
== PICK_AXE
) {
148 if(obj
== uwep
&& (obj
->otyp
> SPEAR
|| obj
->otyp
< BOOMERANG
))
151 if(index(mlarge
, mon
->data
->mlet
)) {
152 tmp
= rnd(objects
[obj
->otyp
].wldam
);
153 if(obj
->otyp
== TWO_HANDED_SWORD
) tmp
+= d(2,6);
154 else if(obj
->otyp
== FLAIL
) tmp
+= rnd(4);
156 tmp
= rnd(objects
[obj
->otyp
].wsdam
);
159 if(!thrown
&& obj
== uwep
&& obj
->otyp
== BOOMERANG
161 pline("As you hit %s, the boomerang breaks into splinters.",
164 setworn((struct obj
*) 0, obj
->owornmask
);
165 obfree(obj
, (struct obj
*) 0);
169 if(mon
->data
->mlet
== 'O' && obj
->otyp
== TWO_HANDED_SWORD
&&
170 !strcmp(ONAME(obj
), "Orcrist"))
172 } else switch(obj
->otyp
) {
173 case HEAVY_IRON_BALL
:
174 tmp
= rnd(25); break;
175 case EXPENSIVE_CAMERA
:
176 pline("You succeed in destroying your camera. Congratulations!");
179 setworn((struct obj
*) 0, obj
->owornmask
);
180 obfree(obj
, (struct obj
*) 0);
182 case DEAD_COCKATRICE
:
183 pline("You hit %s with the cockatrice corpse.",
185 if(mon
->data
->mlet
== 'c') {
190 pline("%s is turned to stone!", Monnam(mon
));
193 case CLOVE_OF_GARLIC
: /* no effect against demons */
194 if(index(UNDEAD
, mon
->data
->mlet
))
199 /* non-weapons can damage because of their weight */
200 /* (but not too much) */
207 /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */
209 tmp
+= u
.udaminc
+ dbon();
211 if((tmp
-= u
.uswldtim
) <= 0) {
212 pline("Your arms are no longer able to hit.");
222 if(mon
->mtame
&& (!mon
->mflee
|| mon
->mfleetim
)) {
223 mon
->mflee
= 1; /* Rick Richardson */
224 mon
->mfleetim
+= 10*rnd(tmp
);
229 /* this assumes that we cannot throw plural things */
230 hit( xname(obj
) /* or: objects[obj->otyp].oc_name */,
233 pline("You hit it.");
235 pline("You hit %s%s", monnam(mon
), exclam(tmp
));
238 if(u
.umconf
&& !thrown
) {
240 pline("Your hands stop glowing blue.");
241 if(!mon
->mfroz
&& !mon
->msleep
)
242 pline("%s appears confused.",Monnam(mon
));
247 return(TRUE
); /* mon still alive */
250 /* try to attack; return FALSE if monster evaded */
251 /* u.dx and u.dy must be set */
256 boolean malive
= TRUE
;
257 struct permonst
*mdat
;
260 u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */
262 if(mdat
->mlet
== 'L' && !mtmp
->mfroz
&& !mtmp
->msleep
&&
263 !mtmp
->mconf
&& mtmp
->mcansee
&& !rn2(7) &&
264 (m_move(mtmp
, 0) == 2 /* he died */ || /* he moved: */
265 mtmp
->mx
!= u
.ux
+u
.dx
|| mtmp
->my
!= u
.uy
+u
.dy
))
269 if(!u
.ustuck
&& !mtmp
->mflee
) u
.ustuck
= mtmp
;
270 switch(levl
[u
.ux
+u
.dx
][u
.uy
+u
.dy
].scrsym
){
272 pline("The door actually was a Mimic.");
275 pline("The chest was a Mimic!");
278 pline("Wait! That's a Mimic!");
280 wakeup(mtmp
); /* clears mtmp->mimic */
286 if(mtmp
->mhide
&& mtmp
->mundetected
){
289 mtmp
->mundetected
= 0;
290 if((obj
= o_at(mtmp
->mx
,mtmp
->my
)) && !Blind
)
291 pline("Wait! There's a %s hiding under %s!",
292 mdat
->mname
, doname(obj
));
296 tmp
= u
.uluck
+ u
.ulevel
+ mdat
->ac
+ abon();
298 if(uwep
->olet
== WEAPON_SYM
|| uwep
->otyp
== PICK_AXE
)
300 if(uwep
->otyp
== TWO_HANDED_SWORD
) tmp
-= 1;
301 else if(uwep
->otyp
== DAGGER
) tmp
+= 2;
302 else if(uwep
->otyp
== CRYSKNIFE
) tmp
+= 3;
303 else if(uwep
->otyp
== SPEAR
&&
304 index("XDne", mdat
->mlet
)) tmp
+= 2;
312 if(!rn2(10)) mtmp
->mfroz
= 0;
314 if(mtmp
->mflee
) tmp
+= 2;
315 if(u
.utrap
) tmp
-= 3;
317 /* with a lot of luggage, your agility diminishes */
318 tmp
-= (inv_weight() + 40)/20;
320 if(tmp
<= rnd(20) && !u
.uswallow
){
321 if(Blind
) pline("You miss it.");
322 else pline("You miss %s.",monnam(mtmp
));
324 /* we hit the monster; be careful: it might die! */
326 if((malive
= hmon(mtmp
,uwep
,0)) == TRUE
) {
327 /* monster still alive */
328 if(!rn2(25) && mtmp
->mhp
< mtmp
->mhpmax
/2) {
330 if(!rn2(3)) mtmp
->mfleetim
= rnd(100);
331 if(u
.ustuck
== mtmp
&& !u
.uswallow
)
336 cutworm(mtmp
, u
.ux
+u
.dx
, u
.uy
+u
.dy
,
337 uwep
? uwep
->otyp
: 0);
340 if(mdat
->mlet
== 'a') {
342 pline("You are splashed by the blob's acid!");
343 losehp_m(rnd(6), mtmp
);
344 if(!rn2(30)) corrode_armor();
346 if(!rn2(6)) corrode_weapon();
349 if(malive
&& mdat
->mlet
== 'E' && canseemon(mtmp
)
350 && !mtmp
->mcan
&& rn2(3)) {
352 pline("You are frozen by the floating eye's gaze!");
353 nomul((u
.ulevel
> 6 || rn2(4)) ? rn1(20,-21) : -200);
355 pline("The blinded floating eye cannot defend itself.");
356 if(!rn2(500)) if((int)u
.uluck
> LUCKMIN
) u
.uluck
--;