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.5 2006/08/21 19:45:32 pavalos Exp $ */
7 extern struct permonst li_dog
, dog
, la_dog
;
9 static boolean far_noise
;
10 static long noisetime
;
12 static void monstone(struct monst
*);
14 /* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */
16 hitmm(struct monst
*magr
, struct monst
*mdef
)
18 struct permonst
*pa
= magr
->data
, *pd
= mdef
->data
;
22 if(index("Eauy", pa
->mlet
)) return(0);
23 if(magr
->mfroz
) return(0); /* riv05!a3 */
24 tmp
= pd
->ac
+ pa
->mlevel
;
25 if(mdef
->mconf
|| mdef
->mfroz
|| mdef
->msleep
){
27 if(mdef
->msleep
) mdef
->msleep
= 0;
30 if(ht
) mdef
->msleep
= 0;
31 vis
= (cansee(magr
->mx
,magr
->my
) && cansee(mdef
->mx
,mdef
->my
));
34 if(mdef
->mimic
) seemimic(mdef
);
35 if(magr
->mimic
) seemimic(magr
);
36 sprintf(buf
,"%s %s", Monnam(magr
),
37 ht
? "hits" : "misses");
38 pline("%s %s.", buf
, monnam(mdef
));
40 boolean far
= (dist(magr
->mx
, magr
->my
) > 15);
41 if(far
!= far_noise
|| moves
-noisetime
> 10) {
44 pline("You hear some noises%s.",
45 far
? " in the distance" : "");
49 if(magr
->data
->mlet
== 'c' && !magr
->cham
) {
51 if(vis
) pline("%s is turned to stone!", Monnam(mdef
));
53 pline("You have a peculiarly sad feeling for a moment, then it passes.");
57 if((mdef
->mhp
-= d(pa
->damn
,pa
->damd
)) < 1) {
58 magr
->mhpmax
+= 1 + rn2(pd
->mlevel
+1);
59 if(magr
->mtame
&& magr
->mhpmax
> 8*pa
->mlevel
){
60 if(pa
== &li_dog
) magr
->data
= pa
= &dog
;
61 else if(pa
== &dog
) magr
->data
= pa
= &la_dog
;
63 if(vis
) pline("%s is killed!", Monnam(mdef
));
65 pline("You have a sad feeling for a moment, then it passes.");
73 /* drop (perhaps) a cadaver and remove monster */
75 mondied(struct monst
*mdef
)
77 struct permonst
*pd
= mdef
->data
;
78 if(letter(pd
->mlet
) && rn2(3)){
79 mkobj_at(pd
->mlet
,mdef
->mx
,mdef
->my
);
80 if(cansee(mdef
->mx
,mdef
->my
)){
82 atl(mdef
->mx
,mdef
->my
,fobj
->olet
);
89 /* drop a rock and remove monster */
91 monstone(struct monst
*mdef
)
93 if(index(mlarge
, mdef
->data
->mlet
))
94 mksobj_at(ENORMOUS_ROCK
, mdef
->mx
, mdef
->my
);
96 mksobj_at(ROCK
, mdef
->mx
, mdef
->my
);
97 if(cansee(mdef
->mx
, mdef
->my
)){
99 atl(mdef
->mx
,mdef
->my
,fobj
->olet
);
105 fightm(struct monst
*mtmp
)
108 for(mon
= fmon
; mon
; mon
= mon
->nmon
) if(mon
!= mtmp
) {
109 if(DIST(mon
->mx
,mon
->my
,mtmp
->mx
,mtmp
->my
) < 3)
111 return(hitmm(mtmp
,mon
));
116 /* u is hit by sth, but not a monster */
118 thitu(int tlev
, int dam
, const char *name
)
122 if(u
.uac
+ tlev
<= rnd(20)) {
123 if(Blind
) pline("It misses.");
124 else pline("You are almost hit by %s!", buf
);
127 if(Blind
) pline("You are hit!");
128 else pline("You are hit by %s!", buf
);
134 char mlarge
[] = "bCDdegIlmnoPSsTUwY',&";
136 /* return TRUE if mon still alive */
138 hmon(struct monst
*mon
, struct obj
*obj
, int thrown
)
144 tmp
= rnd(2); /* attack with bare hands */
145 if(mon
->data
->mlet
== 'c' && !uarmg
){
146 pline("You hit the cockatrice with your bare hands.");
147 pline("You turn to stone ...");
150 } else if(obj
->olet
== WEAPON_SYM
|| obj
->otyp
== PICK_AXE
) {
151 if(obj
== uwep
&& (obj
->otyp
> SPEAR
|| obj
->otyp
< BOOMERANG
))
154 if(index(mlarge
, mon
->data
->mlet
)) {
155 tmp
= rnd(objects
[obj
->otyp
].wldam
);
156 if(obj
->otyp
== TWO_HANDED_SWORD
) tmp
+= d(2,6);
157 else if(obj
->otyp
== FLAIL
) tmp
+= rnd(4);
159 tmp
= rnd(objects
[obj
->otyp
].wsdam
);
162 if(!thrown
&& obj
== uwep
&& obj
->otyp
== BOOMERANG
164 pline("As you hit %s, the boomerang breaks into splinters.",
167 setworn((struct obj
*) 0, obj
->owornmask
);
168 obfree(obj
, (struct obj
*) 0);
172 if(mon
->data
->mlet
== 'O' && obj
->otyp
== TWO_HANDED_SWORD
&&
173 !strcmp(ONAME(obj
), "Orcrist"))
175 } else switch(obj
->otyp
) {
176 case HEAVY_IRON_BALL
:
177 tmp
= rnd(25); break;
178 case EXPENSIVE_CAMERA
:
179 pline("You succeed in destroying your camera. Congratulations!");
182 setworn((struct obj
*) 0, obj
->owornmask
);
183 obfree(obj
, (struct obj
*) 0);
185 case DEAD_COCKATRICE
:
186 pline("You hit %s with the cockatrice corpse.",
188 if(mon
->data
->mlet
== 'c') {
193 pline("%s is turned to stone!", Monnam(mon
));
196 case CLOVE_OF_GARLIC
: /* no effect against demons */
197 if(index(UNDEAD
, mon
->data
->mlet
))
202 /* non-weapons can damage because of their weight */
203 /* (but not too much) */
210 /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */
212 tmp
+= u
.udaminc
+ dbon();
214 if((tmp
-= u
.uswldtim
) <= 0) {
215 pline("Your arms are no longer able to hit.");
225 if(mon
->mtame
&& (!mon
->mflee
|| mon
->mfleetim
)) {
226 mon
->mflee
= 1; /* Rick Richardson */
227 mon
->mfleetim
+= 10*rnd(tmp
);
232 /* this assumes that we cannot throw plural things */
233 hit( xname(obj
) /* or: objects[obj->otyp].oc_name */,
236 pline("You hit it.");
238 pline("You hit %s%s", monnam(mon
), exclam(tmp
));
241 if(u
.umconf
&& !thrown
) {
243 pline("Your hands stop glowing blue.");
244 if(!mon
->mfroz
&& !mon
->msleep
)
245 pline("%s appears confused.",Monnam(mon
));
250 return(TRUE
); /* mon still alive */
253 /* try to attack; return FALSE if monster evaded */
254 /* u.dx and u.dy must be set */
256 attack(struct monst
*mtmp
)
259 boolean malive
= TRUE
;
260 struct permonst
*mdat
;
263 u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */
265 if(mdat
->mlet
== 'L' && !mtmp
->mfroz
&& !mtmp
->msleep
&&
266 !mtmp
->mconf
&& mtmp
->mcansee
&& !rn2(7) &&
267 (m_move(mtmp
, 0) == 2 /* he died */ || /* he moved: */
268 mtmp
->mx
!= u
.ux
+u
.dx
|| mtmp
->my
!= u
.uy
+u
.dy
))
272 if(!u
.ustuck
&& !mtmp
->mflee
) u
.ustuck
= mtmp
;
273 switch(levl
[u
.ux
+u
.dx
][u
.uy
+u
.dy
].scrsym
){
275 pline("The door actually was a Mimic.");
278 pline("The chest was a Mimic!");
281 pline("Wait! That's a Mimic!");
283 wakeup(mtmp
); /* clears mtmp->mimic */
289 if(mtmp
->mhide
&& mtmp
->mundetected
){
292 mtmp
->mundetected
= 0;
293 if((obj
= o_at(mtmp
->mx
,mtmp
->my
)) && !Blind
)
294 pline("Wait! There's a %s hiding under %s!",
295 mdat
->mname
, doname(obj
));
299 tmp
= u
.uluck
+ u
.ulevel
+ mdat
->ac
+ abon();
301 if(uwep
->olet
== WEAPON_SYM
|| uwep
->otyp
== PICK_AXE
)
303 if(uwep
->otyp
== TWO_HANDED_SWORD
) tmp
-= 1;
304 else if(uwep
->otyp
== DAGGER
) tmp
+= 2;
305 else if(uwep
->otyp
== CRYSKNIFE
) tmp
+= 3;
306 else if(uwep
->otyp
== SPEAR
&&
307 index("XDne", mdat
->mlet
)) tmp
+= 2;
315 if(!rn2(10)) mtmp
->mfroz
= 0;
317 if(mtmp
->mflee
) tmp
+= 2;
318 if(u
.utrap
) tmp
-= 3;
320 /* with a lot of luggage, your agility diminishes */
321 tmp
-= (inv_weight() + 40)/20;
323 if(tmp
<= rnd(20) && !u
.uswallow
){
324 if(Blind
) pline("You miss it.");
325 else pline("You miss %s.",monnam(mtmp
));
327 /* we hit the monster; be careful: it might die! */
329 if((malive
= hmon(mtmp
,uwep
,0)) == TRUE
) {
330 /* monster still alive */
331 if(!rn2(25) && mtmp
->mhp
< mtmp
->mhpmax
/2) {
333 if(!rn2(3)) mtmp
->mfleetim
= rnd(100);
334 if(u
.ustuck
== mtmp
&& !u
.uswallow
)
339 cutworm(mtmp
, u
.ux
+u
.dx
, u
.uy
+u
.dy
,
340 uwep
? uwep
->otyp
: 0);
343 if(mdat
->mlet
== 'a') {
345 pline("You are splashed by the blob's acid!");
346 losehp_m(rnd(6), mtmp
);
347 if(!rn2(30)) corrode_armor();
349 if(!rn2(6)) corrode_weapon();
352 if(malive
&& mdat
->mlet
== 'E' && canseemon(mtmp
)
353 && !mtmp
->mcan
&& rn2(3)) {
355 pline("You are frozen by the floating eye's gaze!");
356 nomul((u
.ulevel
> 6 || rn2(4)) ? rn1(20,-21) : -200);
358 pline("The blinded floating eye cannot defend itself.");
359 if(!rn2(500)) if((int)u
.uluck
> LUCKMIN
) u
.uluck
--;