Allow sharing of previous combatant status for AI.

Simplify average_hp() as pointed out by Decker2 (and return double).

Correct cumulative calc of poisoned/slowed.
This commit is contained in:
Rusty Russell 2006-05-15 00:03:18 +00:00
parent 6877bfcc5d
commit 47e4ec7038
2 changed files with 30 additions and 16 deletions

View file

@ -470,12 +470,23 @@ void prob_matrix::receive_blow_a(unsigned damage, unsigned slow_damage, double h
};
combatant::combatant(const battle_context::unit_stats &u)
combatant::combatant(const battle_context::unit_stats &u, combatant *prev)
: hp_dist(u.drains ? u.max_hp+1: u.hp+1),
untouched(1.0), poisoned(u.is_poisoned ? 1.0 : 0.0), slowed(u.is_slowed ? 1.0 : 0.0),
u_(u),
hit_chances_(u.num_blows, u.chance_to_hit / 100.0)
{
// We inherit current state from previous combatant.
if (prev) {
summary[0] = prev->summary[0];
summary[1] = prev->summary[1];
poisoned = prev->poisoned;
untouched = prev->untouched;
slowed = prev->slowed;
} else {
untouched = 1.0;
poisoned = u.is_poisoned ? 1.0 : 0.0;
slowed = u.is_slowed ? 1.0 : 0.0;
}
}
// For swarm, whether we get an attack depends on HP distribution from
@ -593,30 +604,33 @@ void combatant::fight(combatant &opp)
opp.hp_dist[i] = opp.summary[0][i] + opp.summary[1][i];
}
if (opp.u_.poisons && !u_.is_poisoned)
poisoned += untouched - hp_dist[u_.hp];
if (u_.poisons && !opp.u_.is_poisoned)
opp.poisoned += opp.untouched - opp.hp_dist[opp.u_.hp];
// Chance that we / they were touched this time.
double touched = untouched - hp_dist[u_.hp];
double opp_touched = opp.untouched - opp.hp_dist[opp.u_.hp];
if (opp.u_.poisons)
poisoned += (1 - poisoned) * touched;
if (u_.poisons)
opp.poisoned += (1 - opp.poisoned) * opp_touched;
if (opp.u_.slows && !u_.is_slowed)
slowed += untouched - hp_dist[u_.hp];
if (u_.slows && !opp.u_.is_slowed)
opp.slowed += opp.untouched - opp.hp_dist[opp.u_.hp];
if (opp.u_.slows)
slowed += (1 - slowed) * touched;
if (u_.slows)
opp.slowed += (1 - opp.slowed) * opp_touched;
// FIXME: This is approximate: we could drain, then get hit.
untouched = hp_dist[u_.hp];
opp.untouched = opp.hp_dist[opp.u_.hp];
}
unsigned int combatant::average_hp() const
double combatant::average_hp() const
{
double total = 0, sum = 0;
double total = 0;
// Since sum of probabilities is 1.0, we can just tally weights.
for (unsigned int i = 0; i < hp_dist.size(); i++) {
sum += hp_dist[i];
total += hp_dist[i] * i;
}
return (unsigned int)((total / sum) + 0.5);
return total;
}
#if defined(BENCHMARK) || defined(CHECK)

View file

@ -12,7 +12,7 @@
struct combatant
{
// Construct a combatant.
combatant(const battle_context::unit_stats &u);
combatant(const battle_context::unit_stats &u, combatant *prev = NULL);
// Simulate a fight! Can be called multiple times for cumulative calculations.
void fight(combatant &opponent);
@ -30,7 +30,7 @@ struct combatant
double slowed;
// What's the average hp (weighted average of hp_dist).
unsigned int average_hp() const;
double average_hp() const;
private:
// We must adjust for swarm after every combat.