take into account lvl up heal when estimating attack prediction,

...patch by roger_wilco
This commit is contained in:
Jérémy Rosen 2008-07-07 18:48:42 +00:00
parent 5cde77954f
commit 7ff70c97a5
5 changed files with 64 additions and 8 deletions

View File

@ -39,6 +39,9 @@
wikiuser = "bruno"
email = "bruno_AT_wolff.to"
[/entry]
[entry]
name = "Cameron Morland"
[/entry]
[entry]
name = "Cédric Duval"
comment = "coder, internationalization manager"

View File

@ -625,6 +625,11 @@ battle_context::unit_stats::unit_stats(const unit &u, const gamemap::location& u
dloc = &u_loc;
}
// these can matter, even if we can't hit back!
experience = u.experience();
max_experience = u.max_experience();
level = u.level();
// Get the weapon characteristics, if any.
if (weapon) {
weapon->set_specials_context(*aloc, *dloc, &units, &map, &status, &teams, attacking, opp_weapon);

View File

@ -88,6 +88,8 @@ public:
*/
bool swarm; /**< Attack has swarm special. */
bool firststrike; /**< Attack has firststrike special. */
unsigned int experience, max_experience;
unsigned int level;
unsigned int rounds; /**< Berserk special can force us to fight more than one round. */
unsigned int hp; /**< Hitpoints of the unit at the beginning of the battle. */

View File

@ -494,10 +494,8 @@ unsigned combatant::hp_dist_size(const battle_context::unit_stats &u, const comb
}
// If this unit drains, HP can increase, so alloc full array.
if (u.drains) {
// Do this anyway in case we level up.
return u.max_hp + 1;
}
return u.hp+1;
}
combatant::combatant(const battle_context::unit_stats &u, const combatant *prev)
@ -587,7 +585,7 @@ void combatant::no_death_fight(combatant &opp)
{
if (summary[0].empty()) {
// Starts with a known HP, so Pascal's triangle.
summary[0] = std::vector<double>(u_.hp+1);
summary[0] = std::vector<double>(u_.max_hp+1);
summary[0][u_.hp] = 1.0;
for (unsigned int i = 0; i < opp.hit_chances_.size(); i++) {
for (int j = i; j >= 0; j--) {
@ -609,7 +607,7 @@ void combatant::no_death_fight(combatant &opp)
if (opp.summary[0].empty()) {
// Starts with a known HP, so Pascal's triangle.
opp.summary[0] = std::vector<double>(opp.u_.hp+1);
opp.summary[0] = std::vector<double>(opp.u_.max_hp+1);
opp.summary[0][opp.u_.hp] = 1.0;
for (unsigned int i = 0; i < hit_chances_.size(); i++) {
for (int j = i; j >= 0; j--) {
@ -634,7 +632,7 @@ void combatant::no_death_fight(combatant &opp)
void combatant::one_strike_fight(combatant &opp)
{
if (opp.summary[0].empty()) {
opp.summary[0] = std::vector<double>(opp.u_.hp+1);
opp.summary[0] = std::vector<double>(opp.u_.max_hp+1);
if (hit_chances_.size() == 1) {
opp.summary[0][opp.u_.hp] = 1.0 - hit_chances_[0];
opp.summary[0][maximum<int>(opp.u_.hp - u_.damage, 0)] = hit_chances_[0];
@ -655,7 +653,7 @@ void combatant::one_strike_fight(combatant &opp)
// If we killed opponent, it won't attack us.
double opp_alive_prob = 1.0 - opp.summary[0][0];
if (summary[0].empty()) {
summary[0] = std::vector<double>(u_.hp+1);
summary[0] = std::vector<double>(u_.max_hp+1);
if (opp.hit_chances_.size() == 1) {
summary[0][u_.hp] = 1.0 - opp.hit_chances_[0] * opp_alive_prob;
summary[0][maximum<int>(u_.hp - opp.u_.damage, 0)] = opp.hit_chances_[0] * opp_alive_prob;
@ -723,6 +721,48 @@ void combatant::complex_fight(combatant &opp, unsigned int rounds)
m.extract_results(summary, opp.summary);
}
void combatant::consider_levelup(combatant &opp) {
// adjust the probabilities to take into consideration the
// probability of us levelling up, and hence healing.
// We do not currently estimate how many HP we will have.
if (u_.experience + opp.u_.level >= u_.max_experience) {
// if we survive the combat, we will level up. So the probability
// of death is unchanged, but all other cases get merged into
// the fully healed case.
std::vector<double>::iterator i;
i = hp_dist.begin();
i++; // skip to the second value
for ( ; i != hp_dist.end(); i++) {
*i = 0;
}
// fully healed unless dead
hp_dist.back() = 1 - hp_dist.front();
} else if (u_.experience + ((opp.u_.level == 0) ? 4 : opp.u_.level * 8)
>= u_.max_experience) {
// if we kill, we will level up. So then the damage we had
// becomes less probable since it's now conditional on us not
// levelling up. This doesn't apply to the probability of us
// dying, of course.
float scalefactor =
(1 - hp_dist.front() - opp.hp_dist.front()) / (1 - hp_dist.front());
std::vector<double>::iterator i;
i = hp_dist.begin();
i++; // skip to the second value
for( ; i != hp_dist.end(); i++) {
*i *= scalefactor;
}
// if we level up, we get fully healed. (FIXME: actually more so; we
// need to calculate how many HP we will gain)
hp_dist.back() += opp.hp_dist.front();
}
}
// Two man enter. One man leave!
// ... Or maybe two. But definitely not three.
// Of course, one could be a woman. Or both.
@ -804,6 +844,9 @@ void combatant::fight(combatant &opp)
opp.hp_dist[i] = opp.summary[0][i] + opp.summary[1][i];
}
consider_levelup(opp);
opp.consider_levelup(*this);
// Make sure we don't try to access the vectors out of bounds,
// drain increases HPs so we determine the number of HP here
// and make sure it stays within bounds

View File

@ -35,6 +35,9 @@ struct combatant
/** Simulate a fight! Can be called multiple times for cumulative calculations. */
void fight(combatant &opponent);
/** takes into account level up when calculating resulting HP after a fight */
void consider_levelup(combatant &opponent);
/** Resulting probability distribution (may NOT be as large as max_hp) */
std::vector<double> hp_dist;