2 * All the fighting gets done here
4 * @(#)fight.c 3.28 (Berkeley) 6/15/81
6 * Rogue: Exploring the Cavern of Cuties
7 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
10 * See the file LICENSE.TXT for full copyright and licensing information.
19 10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
20 40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L };
24 * The player attacks the monster.
27 fight(mp
, mn
, weap
, thrown
)
33 register struct thing
*tp
;
34 register struct linked_list
*item
;
35 register bool did_hit
= TRUE
;
38 * Find the monster we want to fight
40 if ((item
= find_mons(mp
->y
, mp
->x
)) == NULL
)
42 debug("Fight what @ %d,%d", mp
->y
, mp
->x
);
45 tp
= (struct thing
*) ldata(item
);
47 * Since we are fighting, things are not quiet so no healing takes
53 * Let him know it was really a mimic (if it was one).
55 if (tp
->t_type
== 'M' && tp
->t_disguise
!= 'M' && off(player
, ISBLIND
))
57 msg("Wait! That's a mimic!");
64 tp
->t_stats
.s_int
= 0;
66 if (on(player
, ISBLIND
))
69 mname
= monsters
[mn
-'A'].m_name
;
70 if (roll_em(&pstats
, &tp
->t_stats
, weap
, thrown
))
77 if (on(player
, CANHUH
))
79 msg("Your hands stop glowing red");
80 msg("The %s appears confused.", mname
);
82 player
.t_flags
&= ~CANHUH
;
84 if (tp
->t_stats
.s_hpt
<= 0)
99 * The monster attacks the player
103 register struct thing
*mp
;
105 register char *mname
;
107 // I'm not going to wait for you forever.
111 if (mp
->t_stats
.s_int
> INTERESTED
)
113 const char *msgs
[] = {
114 "The %s smiles at you.",
115 "The %s moves in a little closer.",
116 "The %s bites eir lip.",
117 "The %s looks at you expectantly.",
119 msg(rndchoice(msgs
), monsters
[mp
->t_type
-'A'].m_name
);
122 else if (2 * mp
->t_stats
.s_int
> rnd(INTERESTED
))
124 const char *msgs
[] = {
125 "The %s stares at you.",
127 "The %s takes a step towards you, then back.",
129 msg(rndchoice(msgs
), monsters
[mp
->t_type
-'A'].m_name
);
134 * Since this is an attack, stop running and any healing that was
135 * going on at the time.
139 if (mp
->t_type
== 'M' && off(player
, ISBLIND
))
140 mp
->t_disguise
= 'M';
141 if (on(player
, ISBLIND
))
144 mname
= monsters
[mp
->t_type
-'A'].m_name
;
145 if (roll_em(&mp
->t_stats
, &pstats
, NULL
, FALSE
))
147 if (mp
->t_type
!= 'E')
149 if (pstats
.s_hpt
<= 0)
150 death(mp
->t_type
); /* Bye bye life ... */
151 if (off(*mp
, ISCANC
))
156 * If a rust monster hits, you lose armor
158 if (cur_armor
!= NULL
&& cur_armor
->o_ac
< 9)
161 msg("Your armor appears to be weaker now. Oh my!");
163 msg("Your armor weakens");
168 * The gaze of the floating eye hypnotizes you
170 if (on(player
, ISBLIND
))
174 addmsg("You are transfixed");
176 addmsg(" by the gaze of the floating eye.");
179 no_command
+= rnd(2)+2;
182 * Ants have poisonous bites
184 if (!save(VS_POISON
))
185 if (!ISWEARING(R_SUSTSTR
))
189 msg("You feel a sting in your arm and now feel weaker");
191 msg("A sting has weakened you");
195 msg("A sting momentarily weakens you");
197 msg("Sting has no effect");
200 * Wraiths might drain energy levels
206 if (pstats
.s_exp
== 0)
207 death('W'); /* All levels gone */
208 msg("You suddenly feel weaker.");
209 if (--pstats
.s_lvl
== 0)
215 pstats
.s_exp
= e_levels
[pstats
.s_lvl
-1]+1;
217 pstats
.s_hpt
-= fewer
;
219 if (pstats
.s_hpt
< 1)
226 * Violet fungi stops the poor guy from moving
228 player
.t_flags
|= ISHELD
;
229 sprintf(monsters
['F'-'A'].m_stats
.s_dmg
,"%dd1",++fung_hit
);
233 * Leperachaun steals some gold
235 register long lastpurse
;
240 purse
-= GOLDCALC
+ GOLDCALC
+ GOLDCALC
+ GOLDCALC
;
243 if (purse
!= lastpurse
)
244 msg("Your purse feels lighter");
245 remove_monster(&mp
->t_pos
, find_mons(mp
->t_pos
.y
, mp
->t_pos
.x
));
250 register struct linked_list
*list
, *steal
;
251 register struct object
*obj
;
255 * Nymph's steal a magic item, look through the pack
256 * and pick out one we like.
259 for (nobj
= 0, list
= pack
; list
!= NULL
; list
= next(list
))
261 obj
= (struct object
*) ldata(list
);
262 if (obj
!= cur_armor
&&
264 obj
!= cur_ring
[LEFT
] &&
265 obj
!= cur_ring
[RIGHT
] && /* Nymph bug fix */
272 register struct object
*obj
;
274 obj
= (struct object
*) ldata(steal
);
275 remove_monster(&mp
->t_pos
, find_mons(mp
->t_pos
.y
, mp
->t_pos
.x
));
277 if (obj
->o_count
> 1 && obj
->o_group
== 0)
283 msg("She stole %s!", inv_name(obj
, TRUE
));
284 obj
->o_count
= oc
- 1;
288 msg("She stole %s!", inv_name(obj
, TRUE
));
299 else if (mp
->t_type
!= 'E')
301 if (mp
->t_type
== 'F')
303 pstats
.s_hpt
-= fung_hit
;
304 if (pstats
.s_hpt
<= 0)
305 death(mp
->t_type
); /* Bye bye life ... */
310 * Check to see if this is a regenerating monster and let it heal if
313 if ((mp
!= NULL
) && (on(*mp
, ISREGEN
) && rnd(100) < 33))
317 flush_type(); /* flush typeahead */
330 * returns true if the swing hits
333 swing(at_lvl
, op_arm
, wplus
)
334 int at_lvl
, op_arm
, wplus
;
336 register int res
= rnd(20)+1;
337 register int need
= (21-at_lvl
)-op_arm
;
339 return (res
+wplus
>= need
);
344 * Check to see if the guy has gone up a level.
351 for (i
= 0; e_levels
[i
] != 0; i
++)
352 if (e_levels
[i
] > pstats
.s_exp
)
355 if (i
> pstats
.s_lvl
)
357 add
= roll(i
-pstats
.s_lvl
,10);
359 if ((pstats
.s_hpt
+= add
) > max_hp
)
360 pstats
.s_hpt
= max_hp
;
361 msg("Welcome to level %d", i
);
368 * Roll several attacks
371 roll_em(att
, def
, weap
, hurl
)
372 struct stats
*att
, *def
;
377 register int ndice
, nsides
, def_arm
;
378 register bool did_hit
= FALSE
;
379 register int prop_hplus
, prop_dplus
;
381 prop_hplus
= prop_dplus
= 0;
385 if ((weap
->o_flags
&ISMISL
) && cur_weapon
!= NULL
&&
386 cur_weapon
->o_which
== weap
->o_launch
)
388 cp
= weap
->o_hurldmg
;
389 prop_hplus
= cur_weapon
->o_hplus
;
390 prop_dplus
= cur_weapon
->o_dplus
;
393 cp
= (weap
->o_flags
&ISMISL
? weap
->o_damage
: weap
->o_hurldmg
);
398 * Drain a staff of striking
400 if (weap
->o_type
== STICK
&& weap
->o_which
== WS_HIT
401 && weap
->o_charges
== 0)
403 strcpy(weap
->o_damage
,"0d0");
404 weap
->o_hplus
= weap
->o_dplus
= 0;
410 int hplus
= prop_hplus
+ (weap
== NULL
? 0 : weap
->o_hplus
);
411 int dplus
= prop_dplus
+ (weap
== NULL
? 0 : weap
->o_dplus
);
413 if (weap
== cur_weapon
)
415 if (ISRING(LEFT
, R_ADDDAM
))
416 dplus
+= cur_ring
[LEFT
]->o_ac
;
417 else if (ISRING(LEFT
, R_ADDHIT
))
418 hplus
+= cur_ring
[LEFT
]->o_ac
;
419 if (ISRING(RIGHT
, R_ADDDAM
))
420 dplus
+= cur_ring
[RIGHT
]->o_ac
;
421 else if (ISRING(RIGHT
, R_ADDHIT
))
422 hplus
+= cur_ring
[RIGHT
]->o_ac
;
425 if ((cp
= strchr(cp
, 'd')) == NULL
)
430 if (cur_armor
!= NULL
)
431 def_arm
= cur_armor
->o_ac
;
433 def_arm
= def
->s_arm
;
434 if (ISRING(LEFT
, R_PROTECT
))
435 def_arm
-= cur_ring
[LEFT
]->o_ac
;
436 else if (ISRING(RIGHT
, R_PROTECT
))
437 def_arm
-= cur_ring
[RIGHT
]->o_ac
;
440 def_arm
= def
->s_arm
;
441 if (swing(att
->s_lvl
, def_arm
, hplus
+str_plus(&att
->s_str
)))
445 proll
= roll(ndice
, nsides
);
446 if (ndice
+ nsides
> 0 && proll
< 1)
447 debug("Damage for %dd%d came out %d.", ndice
, nsides
, proll
);
448 damage
= dplus
+ proll
+ add_dam(&att
->s_str
);
449 def
->s_hpt
-= max(0, damage
);
452 if ((cp
= strchr(cp
, '/')) == NULL
)
461 * The print name of a combatant
469 static char tbuf
[80];
474 else if (on(player
, ISBLIND
))
478 strcpy(tbuf
, "the ");
482 *tbuf
= toupper(*tbuf
);
488 * Print a message to indicate a succesful hit
492 register char *er
, *ee
;
496 addmsg(prname(er
, TRUE
));
502 case 0: s
= " scored an excellent hit on ";
504 when
2: s
= (er
== 0 ? " have injured " : " has injured ");
505 when
3: s
= (er
== 0 ? " swing and hit " : " swings and hits ");
509 addmsg(prname(ee
, FALSE
));
515 * Print a message to indicate a poor swing
519 register char *er
, *ee
;
523 addmsg(prname(er
, TRUE
));
524 switch (terse
? 0 : rnd(4))
526 case 0: s
= (er
== 0 ? " miss" : " misses");
527 when
1: s
= (er
== 0 ? " swing and miss" : " swings and misses");
528 when
2: s
= (er
== 0 ? " barely miss" : " barely misses");
529 when
3: s
= (er
== 0 ? " don't hit" : " doesn't hit");
533 addmsg(" %s", prname(ee
, FALSE
));
539 * See if a creature save against something
541 save_throw(which
, tp
)
547 need
= 14 + which
- tp
->t_stats
.s_lvl
/ 2;
548 return (roll(1, 20) >= need
);
553 * See if he saves against various nasty things
559 return save_throw(which
, &player
);
564 * compute bonus/penalties for strength on the "to hit" roll
570 if (str
->st_str
== 18)
572 if (str
->st_add
== 100)
574 if (str
->st_add
> 50)
577 if (str
->st_str
>= 17)
581 return str
->st_str
- 7;
586 * compute additional damage done for exceptionally high or low strength
592 if (str
->st_str
== 18)
594 if (str
->st_add
== 100)
596 if (str
->st_add
> 90)
598 if (str
->st_add
> 75)
600 if (str
->st_add
!= 0)
604 if (str
->st_str
> 15)
608 return str
->st_str
- 7;
613 * The guy just magically went up a level.
618 pstats
.s_exp
= e_levels
[pstats
.s_lvl
-1] + 1L;
624 * A missile hits a monster
628 register struct object
*weap
;
629 register char *mname
;
631 if (weap
->o_type
== WEAPON
)
632 msg("The %s hits the %s", w_names
[weap
->o_which
], mname
);
634 msg("You hit the %s.", mname
);
639 * A missile misses a monster
643 register struct object
*weap
;
644 register char *mname
;
646 if (weap
->o_type
== WEAPON
)
647 msg("The %s misses the %s", w_names
[weap
->o_which
], mname
);
649 msg("You missed the %s.", mname
);
653 * remove a monster from the screen
655 remove_monster(mp
, item
)
657 register struct linked_list
*item
;
659 mvwaddch(mw
, mp
->y
, mp
->x
, ' ');
660 mvwaddch(cw
, mp
->y
, mp
->x
, ((struct thing
*) ldata(item
))->t_oldch
);
667 * Returns true if an object radiates magic
671 register struct object
*obj
;
676 return obj
->o_ac
!= a_class
[obj
->o_which
];
678 return obj
->o_hplus
!= 0 || obj
->o_dplus
!= 0;
691 * Called to put a monster to death
695 register struct linked_list
*item
;
698 register struct thing
*tp
;
699 register struct linked_list
*pitem
, *nexti
;
701 tp
= (struct thing
*) ldata(item
);
704 addmsg(terse
? "Defeated " : "You have defeated ");
705 if (on(player
, ISBLIND
))
711 msg("%s.", monsters
[tp
->t_type
-'A'].m_name
);
714 pstats
.s_exp
+= tp
->t_stats
.s_exp
;
716 * Do adjustments if he went up a level
720 * If the monster was a violet fungi, un-hold him
725 player
.t_flags
&= ~ISHELD
;
727 strcpy(monsters
['F'-'A'].m_stats
.s_dmg
, "000d0");
730 register struct room
*rp
;
732 if ((rp
= roomin(&tp
->t_pos
)) == NULL
)
734 if (rp
->r_goldval
!= 0 || fallpos(&tp
->t_pos
,&rp
->r_gold
,FALSE
))
736 rp
->r_goldval
+= GOLDCALC
;
738 rp
->r_goldval
+= GOLDCALC
+ GOLDCALC
739 + GOLDCALC
+ GOLDCALC
;
740 mvwaddch(stdscr
, rp
->r_gold
.y
, rp
->r_gold
.x
, GOLD
);
741 if (!(rp
->r_flags
& ISDARK
))
744 mvwaddch(cw
, hero
.y
, hero
.x
, PLAYER
);
750 * Empty the monsters pack
753 while (pitem
!= NULL
)
755 register struct object
*obj
;
757 nexti
= next(tp
->t_pack
);
758 obj
= (struct object
*) ldata(pitem
);
759 obj
->o_pos
= tp
->t_pos
;
760 detach(tp
->t_pack
, pitem
);
765 * Get rid of the monster.
767 remove_monster(&tp
->t_pos
, item
);