Make the calculation of swarm attacks more robust in case of future changes.

This commit is contained in:
J. Tyne 2012-10-20 15:47:19 +00:00
parent 1636e2cbad
commit 6b0c165c32
3 changed files with 13 additions and 9 deletions

View File

@ -81,7 +81,9 @@ struct battle_context_unit_stats
/// Calculates the number of blows we would have if we had @a new_hp
// instead of the recorded hp.
unsigned int calc_blows(unsigned new_hp) const
{ return swarm_min + (swarm_max - swarm_min) * new_hp / max_hp; }
{ return new_hp >= max_hp ? swarm_max :
swarm_min + (swarm_max-swarm_min) * new_hp / max_hp;
}
#if defined(BENCHMARK) || defined(CHECK)
/// Special constructor for the stand-alone version of attack_prediction.cpp.

View File

@ -1086,19 +1086,20 @@ combatant::combatant(const combatant &that, const battle_context_unit_stats &u)
namespace {
/**
* Returns the number of hit points greater than cur_hp, and at most max_hp+1,
* at which the unit would get another attack because of swarm (assuming that
* @a swarm_amt is swarm_max - swarm_min).
* Returns the number of hit points greater than cur_hp, and at most
* stats.max_hp+1, at which the unit would get another attack because
* of swarm.
* Helper function for split_summary().
*/
unsigned hp_for_next_attack(unsigned cur_hp, unsigned max_hp, unsigned swarm_amt)
unsigned hp_for_next_attack(unsigned cur_hp,
const battle_context_unit_stats & stats)
{
unsigned old_strikes = swarm_amt * cur_hp / max_hp;
unsigned old_strikes = stats.calc_blows(cur_hp);
// A formula would have to deal with rounding issues; instead
// loop until we find more strikes.
while ( ++cur_hp <= max_hp )
if ( swarm_amt * cur_hp / max_hp != old_strikes )
while ( ++cur_hp <= stats.max_hp )
if ( stats.calc_blows(cur_hp) != old_strikes )
break;
return cur_hp;
@ -1126,7 +1127,7 @@ std::vector<combatant::combat_slice> combatant::split_summary() const
do {
// Advance to the next slice.
const unsigned cur_begin = cur_end;
cur_end = hp_for_next_attack(cur_begin, u_.max_hp, u_.swarm_max-u_.swarm_min);
cur_end = hp_for_next_attack(cur_begin, u_);
// Add this slice.
combat_slice slice(summary, cur_begin, cur_end, u_.calc_blows(cur_begin));

View File

@ -638,6 +638,7 @@ void attack_type::set_specials_context(const map_location& loc, bool attacking)
* This returns two numbers because of the swarm special. The actual number of
* attacks depends on the unit's health and should be:
* min_attacks + (max_attacks - min_attacks) * (current hp) / (max hp)
* c.f. battle_context_unit_stats::calc_blows()
*/
void attack_type::modified_attacks(bool is_backstab, unsigned & min_attacks,
unsigned & max_attacks) const