516d8b7e3b82dd741bc0cdd9877b8c1ab723c833
2 * All the fighting gets done here
4 * @(#)fight.c 3.28 (Berkeley) 6/15/81
6 * Rogue: Exploring the Dungeons of Doom
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!");
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
;
108 * Since this is an attack, stop running and any healing that was
109 * going on at the time.
113 if (mp
->t_type
== 'M' && off(player
, ISBLIND
))
114 mp
->t_disguise
= 'M';
115 if (on(player
, ISBLIND
))
118 mname
= monsters
[mp
->t_type
-'A'].m_name
;
119 if (roll_em(&mp
->t_stats
, &pstats
, NULL
, FALSE
))
121 if (mp
->t_type
!= 'E')
123 if (pstats
.s_hpt
<= 0)
124 death(mp
->t_type
); /* Bye bye life ... */
125 if (off(*mp
, ISCANC
))
130 * If a rust monster hits, you lose armor
132 if (cur_armor
!= NULL
&& cur_armor
->o_ac
< 9)
135 msg("Your armor appears to be weaker now. Oh my!");
137 msg("Your armor weakens");
142 * The gaze of the floating eye hypnotizes you
144 if (on(player
, ISBLIND
))
148 addmsg("You are transfixed");
150 addmsg(" by the gaze of the floating eye.");
153 no_command
+= rnd(2)+2;
156 * Ants have poisonous bites
158 if (!save(VS_POISON
))
159 if (!ISWEARING(R_SUSTSTR
))
163 msg("You feel a sting in your arm and now feel weaker");
165 msg("A sting has weakened you");
169 msg("A sting momentarily weakens you");
171 msg("Sting has no effect");
174 * Wraiths might drain energy levels
180 if (pstats
.s_exp
== 0)
181 death('W'); /* All levels gone */
182 msg("You suddenly feel weaker.");
183 if (--pstats
.s_lvl
== 0)
189 pstats
.s_exp
= e_levels
[pstats
.s_lvl
-1]+1;
191 pstats
.s_hpt
-= fewer
;
193 if (pstats
.s_hpt
< 1)
200 * Violet fungi stops the poor guy from moving
202 player
.t_flags
|= ISHELD
;
203 sprintf(monsters
['F'-'A'].m_stats
.s_dmg
,"%dd1",++fung_hit
);
207 * Leperachaun steals some gold
209 register long lastpurse
;
214 purse
-= GOLDCALC
+ GOLDCALC
+ GOLDCALC
+ GOLDCALC
;
217 if (purse
!= lastpurse
)
218 msg("Your purse feels lighter");
219 remove_monster(&mp
->t_pos
, find_mons(mp
->t_pos
.y
, mp
->t_pos
.x
));
224 register struct linked_list
*list
, *steal
;
225 register struct object
*obj
;
229 * Nymph's steal a magic item, look through the pack
230 * and pick out one we like.
233 for (nobj
= 0, list
= pack
; list
!= NULL
; list
= next(list
))
235 obj
= (struct object
*) ldata(list
);
236 if (obj
!= cur_armor
&&
238 obj
!= cur_ring
[LEFT
] &&
239 obj
!= cur_ring
[RIGHT
] && /* Nymph bug fix */
246 register struct object
*obj
;
248 obj
= (struct object
*) ldata(steal
);
249 remove_monster(&mp
->t_pos
, find_mons(mp
->t_pos
.y
, mp
->t_pos
.x
));
251 if (obj
->o_count
> 1 && obj
->o_group
== 0)
257 msg("She stole %s!", inv_name(obj
, TRUE
));
258 obj
->o_count
= oc
- 1;
262 msg("She stole %s!", inv_name(obj
, TRUE
));
273 else if (mp
->t_type
!= 'E')
275 if (mp
->t_type
== 'F')
277 pstats
.s_hpt
-= fung_hit
;
278 if (pstats
.s_hpt
<= 0)
279 death(mp
->t_type
); /* Bye bye life ... */
284 * Check to see if this is a regenerating monster and let it heal if
287 if ((mp
!= NULL
) && (on(*mp
, ISREGEN
) && rnd(100) < 33))
291 flush_type(); /* flush typeahead */
304 * returns true if the swing hits
307 swing(at_lvl
, op_arm
, wplus
)
308 int at_lvl
, op_arm
, wplus
;
310 register int res
= rnd(20)+1;
311 register int need
= (21-at_lvl
)-op_arm
;
313 return (res
+wplus
>= need
);
318 * Check to see if the guy has gone up a level.
325 for (i
= 0; e_levels
[i
] != 0; i
++)
326 if (e_levels
[i
] > pstats
.s_exp
)
329 if (i
> pstats
.s_lvl
)
331 add
= roll(i
-pstats
.s_lvl
,10);
333 if ((pstats
.s_hpt
+= add
) > max_hp
)
334 pstats
.s_hpt
= max_hp
;
335 msg("Welcome to level %d", i
);
342 * Roll several attacks
345 roll_em(att
, def
, weap
, hurl
)
346 struct stats
*att
, *def
;
351 register int ndice
, nsides
, def_arm
;
352 register bool did_hit
= FALSE
;
353 register int prop_hplus
, prop_dplus
;
355 prop_hplus
= prop_dplus
= 0;
359 if ((weap
->o_flags
&ISMISL
) && cur_weapon
!= NULL
&&
360 cur_weapon
->o_which
== weap
->o_launch
)
362 cp
= weap
->o_hurldmg
;
363 prop_hplus
= cur_weapon
->o_hplus
;
364 prop_dplus
= cur_weapon
->o_dplus
;
367 cp
= (weap
->o_flags
&ISMISL
? weap
->o_damage
: weap
->o_hurldmg
);
372 * Drain a staff of striking
374 if (weap
->o_type
== STICK
&& weap
->o_which
== WS_HIT
375 && weap
->o_charges
== 0)
377 strcpy(weap
->o_damage
,"0d0");
378 weap
->o_hplus
= weap
->o_dplus
= 0;
384 int hplus
= prop_hplus
+ (weap
== NULL
? 0 : weap
->o_hplus
);
385 int dplus
= prop_dplus
+ (weap
== NULL
? 0 : weap
->o_dplus
);
387 if (weap
== cur_weapon
)
389 if (ISRING(LEFT
, R_ADDDAM
))
390 dplus
+= cur_ring
[LEFT
]->o_ac
;
391 else if (ISRING(LEFT
, R_ADDHIT
))
392 hplus
+= cur_ring
[LEFT
]->o_ac
;
393 if (ISRING(RIGHT
, R_ADDDAM
))
394 dplus
+= cur_ring
[RIGHT
]->o_ac
;
395 else if (ISRING(RIGHT
, R_ADDHIT
))
396 hplus
+= cur_ring
[RIGHT
]->o_ac
;
399 if ((cp
= strchr(cp
, 'd')) == NULL
)
404 if (cur_armor
!= NULL
)
405 def_arm
= cur_armor
->o_ac
;
407 def_arm
= def
->s_arm
;
408 if (ISRING(LEFT
, R_PROTECT
))
409 def_arm
-= cur_ring
[LEFT
]->o_ac
;
410 else if (ISRING(RIGHT
, R_PROTECT
))
411 def_arm
-= cur_ring
[RIGHT
]->o_ac
;
414 def_arm
= def
->s_arm
;
415 if (swing(att
->s_lvl
, def_arm
, hplus
+str_plus(&att
->s_str
)))
419 proll
= roll(ndice
, nsides
);
420 if (ndice
+ nsides
> 0 && proll
< 1)
421 debug("Damage for %dd%d came out %d.", ndice
, nsides
, proll
);
422 damage
= dplus
+ proll
+ add_dam(&att
->s_str
);
423 def
->s_hpt
-= max(0, damage
);
426 if ((cp
= strchr(cp
, '/')) == NULL
)
435 * The print name of a combatant
443 static char tbuf
[80];
448 else if (on(player
, ISBLIND
))
452 strcpy(tbuf
, "the ");
456 *tbuf
= toupper(*tbuf
);
462 * Print a message to indicate a succesful hit
466 register char *er
, *ee
;
470 addmsg(prname(er
, TRUE
));
476 case 0: s
= " scored an excellent hit on ";
478 when
2: s
= (er
== 0 ? " have injured " : " has injured ");
479 when
3: s
= (er
== 0 ? " swing and hit " : " swings and hits ");
483 addmsg(prname(ee
, FALSE
));
489 * Print a message to indicate a poor swing
493 register char *er
, *ee
;
497 addmsg(prname(er
, TRUE
));
498 switch (terse
? 0 : rnd(4))
500 case 0: s
= (er
== 0 ? " miss" : " misses");
501 when
1: s
= (er
== 0 ? " swing and miss" : " swings and misses");
502 when
2: s
= (er
== 0 ? " barely miss" : " barely misses");
503 when
3: s
= (er
== 0 ? " don't hit" : " doesn't hit");
507 addmsg(" %s", prname(ee
, FALSE
));
513 * See if a creature save against something
515 save_throw(which
, tp
)
521 need
= 14 + which
- tp
->t_stats
.s_lvl
/ 2;
522 return (roll(1, 20) >= need
);
527 * See if he saves against various nasty things
533 return save_throw(which
, &player
);
538 * compute bonus/penalties for strength on the "to hit" roll
544 if (str
->st_str
== 18)
546 if (str
->st_add
== 100)
548 if (str
->st_add
> 50)
551 if (str
->st_str
>= 17)
555 return str
->st_str
- 7;
560 * compute additional damage done for exceptionally high or low strength
566 if (str
->st_str
== 18)
568 if (str
->st_add
== 100)
570 if (str
->st_add
> 90)
572 if (str
->st_add
> 75)
574 if (str
->st_add
!= 0)
578 if (str
->st_str
> 15)
582 return str
->st_str
- 7;
587 * The guy just magically went up a level.
592 pstats
.s_exp
= e_levels
[pstats
.s_lvl
-1] + 1L;
598 * A missile hits a monster
602 register struct object
*weap
;
603 register char *mname
;
605 if (weap
->o_type
== WEAPON
)
606 msg("The %s hits the %s", w_names
[weap
->o_which
], mname
);
608 msg("You hit the %s.", mname
);
613 * A missile misses a monster
617 register struct object
*weap
;
618 register char *mname
;
620 if (weap
->o_type
== WEAPON
)
621 msg("The %s misses the %s", w_names
[weap
->o_which
], mname
);
623 msg("You missed the %s.", mname
);
627 * remove a monster from the screen
629 remove_monster(mp
, item
)
631 register struct linked_list
*item
;
633 mvwaddch(mw
, mp
->y
, mp
->x
, ' ');
634 mvwaddch(cw
, mp
->y
, mp
->x
, ((struct thing
*) ldata(item
))->t_oldch
);
641 * Returns true if an object radiates magic
645 register struct object
*obj
;
650 return obj
->o_ac
!= a_class
[obj
->o_which
];
652 return obj
->o_hplus
!= 0 || obj
->o_dplus
!= 0;
665 * Called to put a monster to death
669 register struct linked_list
*item
;
672 register struct thing
*tp
;
673 register struct linked_list
*pitem
, *nexti
;
675 tp
= (struct thing
*) ldata(item
);
678 addmsg(terse
? "Defeated " : "You have defeated ");
679 if (on(player
, ISBLIND
))
685 msg("%s.", monsters
[tp
->t_type
-'A'].m_name
);
688 pstats
.s_exp
+= tp
->t_stats
.s_exp
;
690 * Do adjustments if he went up a level
694 * If the monster was a violet fungi, un-hold him
699 player
.t_flags
&= ~ISHELD
;
701 strcpy(monsters
['F'-'A'].m_stats
.s_dmg
, "000d0");
704 register struct room
*rp
;
706 if ((rp
= roomin(&tp
->t_pos
)) == NULL
)
708 if (rp
->r_goldval
!= 0 || fallpos(&tp
->t_pos
,&rp
->r_gold
,FALSE
))
710 rp
->r_goldval
+= GOLDCALC
;
712 rp
->r_goldval
+= GOLDCALC
+ GOLDCALC
713 + GOLDCALC
+ GOLDCALC
;
714 mvwaddch(stdscr
, rp
->r_gold
.y
, rp
->r_gold
.x
, GOLD
);
715 if (!(rp
->r_flags
& ISDARK
))
718 mvwaddch(cw
, hero
.y
, hero
.x
, PLAYER
);
724 * Empty the monsters pack
727 while (pitem
!= NULL
)
729 register struct object
*obj
;
731 nexti
= next(tp
->t_pack
);
732 obj
= (struct object
*) ldata(pitem
);
733 obj
->o_pos
= tp
->t_pos
;
734 detach(tp
->t_pack
, pitem
);
739 * Get rid of the monster.
741 remove_monster(&tp
->t_pos
, item
);