mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-03 20:10:38 +00:00
doxygen, comments
This commit is contained in:
parent
4af4f8ec27
commit
304c1f93fe
@ -13,9 +13,13 @@
|
||||
|
||||
Full algorithm by Yogin. Typing and optimization by Rusty.
|
||||
|
||||
This code has lots of debugging. It is there for a reason: this
|
||||
code is kinda tricky. Do not remove it.
|
||||
This code has lots of debugging. It is there for a reason:
|
||||
this code is kinda tricky. Do not remove it.
|
||||
*/
|
||||
|
||||
//! @file attack_prediction.cpp
|
||||
//! Simulate combat to calculate attacks. Standalone program, benchmark.
|
||||
|
||||
#include "attack_prediction.hpp"
|
||||
|
||||
#include <cstring> // For memset
|
||||
@ -23,8 +27,9 @@
|
||||
|
||||
#include "wassert.hpp"
|
||||
|
||||
// Compile with -O3 -DBENCHMARK for speed testing, -DCHECK for testing
|
||||
// correctness (run tools/wesnoth-attack-sim.c --check on output)
|
||||
// Compile with -O3 -DBENCHMARK for speed testing,
|
||||
// -DCHECK for testing correctness
|
||||
// (run tools/wesnoth-attack-sim.c --check on output)
|
||||
#if !defined(BENCHMARK) && !defined(CHECK)
|
||||
#include "util.hpp"
|
||||
#else
|
||||
@ -44,7 +49,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
// A matrix of A's hitpoints vs B's hitpoints.
|
||||
//! A matrix of A's hitpoints vs B's hitpoints.
|
||||
struct prob_matrix
|
||||
{
|
||||
// Simple matrix, both known HP.
|
||||
@ -78,8 +83,7 @@ struct prob_matrix
|
||||
void dump() const;
|
||||
|
||||
// We need four matrices, or "planes", reflecting the possible
|
||||
// "slowed" states (neither slowed, A slowed, B slowed, both
|
||||
// slowed).
|
||||
// "slowed" states (neither slowed, A slowed, B slowed, both slowed).
|
||||
enum {
|
||||
NEITHER_SLOWED,
|
||||
A_SLOWED,
|
||||
@ -108,7 +112,7 @@ private:
|
||||
void shift_rows(unsigned dst, unsigned src,
|
||||
unsigned damage, double prob, bool drain);
|
||||
|
||||
// FIXME: rename using _ at end.
|
||||
//! @todo FIXME: rename using _ at end.
|
||||
unsigned int rows, cols;
|
||||
double *plane[4];
|
||||
|
||||
@ -157,7 +161,7 @@ prob_matrix::prob_matrix(unsigned int a_max_hp, unsigned int b_max_hp,
|
||||
|
||||
// Transfer HP distribution from A?
|
||||
if (!a_summary[0].empty()) {
|
||||
// FIXME: Can optimize here.
|
||||
// @todo FIXME: Can optimize here.
|
||||
min_row[NEITHER_SLOWED] = 0;
|
||||
min_row[A_SLOWED] = 0;
|
||||
min_col[A_SLOWED] = b_hp - 1;
|
||||
@ -182,8 +186,8 @@ prob_matrix::prob_matrix(unsigned int a_max_hp, unsigned int b_max_hp,
|
||||
debug(("B has fought before\n"));
|
||||
dump();
|
||||
} else {
|
||||
// if a unit has drain it might end with more HP than before
|
||||
// make sure we don't access the matrix in invalid positions
|
||||
// If a unit has drain it might end with more HP than before.
|
||||
// Make sure we don't access the matrix in invalid positions.
|
||||
a_hp = minimum<unsigned int>(a_hp, rows - 1);
|
||||
b_hp = minimum<unsigned int>(b_hp, cols - 1);
|
||||
val(NEITHER_SLOWED, a_hp, b_hp) = 1.0;
|
||||
@ -316,8 +320,8 @@ void prob_matrix::shift_rows(unsigned dst, unsigned src,
|
||||
}
|
||||
}
|
||||
|
||||
// Shift prob_matrix to reflect probability 'hit_chance' that damage (up
|
||||
// to) 'damage' is done to 'b'.
|
||||
// Shift prob_matrix to reflect probability 'hit_chance'
|
||||
// that damage (up to) 'damage' is done to 'b'.
|
||||
void prob_matrix::receive_blow_b(unsigned damage, unsigned slow_damage, double hit_chance,
|
||||
bool a_slows, bool a_drains)
|
||||
{
|
||||
@ -330,7 +334,7 @@ void prob_matrix::receive_blow_b(unsigned damage, unsigned slow_damage, double h
|
||||
if (!plane[src])
|
||||
continue;
|
||||
|
||||
// If a slows us we go from 0=>2, 1=>3, 2=>2 3=>3.
|
||||
// If A slows us, we go from 0=>2, 1=>3, 2=>2 3=>3.
|
||||
if (a_slows)
|
||||
dst = (src|2);
|
||||
else
|
||||
@ -442,8 +446,8 @@ double prob_matrix::dead_prob() const
|
||||
return prob;
|
||||
}
|
||||
|
||||
// Shift matrix to reflect probability 'hit_chance' that damage (up
|
||||
// to) 'damage' is done to 'a'.
|
||||
// Shift matrix to reflect probability 'hit_chance'
|
||||
// that damage (up to) 'damage' is done to 'a'.
|
||||
void prob_matrix::receive_blow_a(unsigned damage, unsigned slow_damage, double hit_chance,
|
||||
bool b_slows, bool b_drains)
|
||||
{
|
||||
@ -456,7 +460,7 @@ void prob_matrix::receive_blow_a(unsigned damage, unsigned slow_damage, double h
|
||||
if (!plane[src])
|
||||
continue;
|
||||
|
||||
// If b slows us we go from 0=>1, 1=>1, 2=>3 3=>3.
|
||||
// If B slows us, we go from 0=>1, 1=>1, 2=>3 3=>3.
|
||||
if (b_slows)
|
||||
dst = (src|1);
|
||||
else
|
||||
@ -478,7 +482,7 @@ void prob_matrix::receive_blow_a(unsigned damage, unsigned slow_damage, double h
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // end anon namespace
|
||||
|
||||
unsigned combatant::hp_dist_size(const battle_context::unit_stats &u, const combatant *prev)
|
||||
{
|
||||
@ -523,9 +527,9 @@ combatant::combatant(const combatant &that, const battle_context::unit_stats &u)
|
||||
|
||||
|
||||
|
||||
// For swarm, whether we get an attack depends on HP distribution from
|
||||
// previous combat. So we roll this into our P(hitting), since no
|
||||
// attack is equivalent to missing.
|
||||
// For swarm, whether we get an attack depends on HP distribution
|
||||
// from previous combat. So we roll this into our P(hitting),
|
||||
// since no attack is equivalent to missing.
|
||||
void combatant::adjust_hitchance()
|
||||
{
|
||||
if (summary[0].empty() || u_.swarm_min == u_.swarm_max)
|
||||
@ -559,7 +563,7 @@ void combatant::adjust_hitchance()
|
||||
debug(("\n"));
|
||||
}
|
||||
|
||||
// Minimum hp we could possibly have.
|
||||
// Minimum HP we could possibly have.
|
||||
unsigned combatant::min_hp() const
|
||||
{
|
||||
if (summary[0].empty())
|
||||
@ -679,7 +683,7 @@ void combatant::complex_fight(combatant &opp, unsigned int rounds)
|
||||
unsigned int b_damage = opp.u_.damage, b_slow_damage = opp.u_.slow_damage;
|
||||
|
||||
// To simulate stoning, we set to amount which kills, and re-adjust after.
|
||||
// FIXME: This doesn't work for rolling calculations, just first battle.
|
||||
//! @todo FIXME: This doesn't work for rolling calculations, just first battle.
|
||||
if (u_.stones)
|
||||
a_damage = a_slow_damage = opp.u_.max_hp;
|
||||
if (opp.u_.stones)
|
||||
@ -715,8 +719,9 @@ void combatant::complex_fight(combatant &opp, unsigned int rounds)
|
||||
}
|
||||
|
||||
// Two man enter. One man leave!
|
||||
// ... Or maybe two. But definitely not three. Of course, one could
|
||||
// be a woman. Or both. And neither could be human, too.
|
||||
// ... Or maybe two. But definitely not three.
|
||||
// Of course, one could be a woman. Or both.
|
||||
// And neither could be human, too.
|
||||
// Um, ok, it was a stupid thing to say.
|
||||
void combatant::fight(combatant &opp)
|
||||
{
|
||||
@ -794,8 +799,9 @@ void combatant::fight(combatant &opp)
|
||||
opp.hp_dist[i] = opp.summary[0][i] + opp.summary[1][i];
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
const unsigned int hp = minimum<unsigned int>(u_.hp, hp_dist.size() - 1);
|
||||
const unsigned int opp_hp = minimum<unsigned int>(opp.u_.hp, opp.hp_dist.size() - 1);
|
||||
|
||||
@ -812,7 +818,7 @@ void combatant::fight(combatant &opp)
|
||||
if (u_.slows)
|
||||
opp.slowed += (1 - opp.slowed) * opp_touched;
|
||||
|
||||
// FIXME: This is approximate: we could drain, then get hit.
|
||||
//! @todo FIXME: This is approximate: we could drain, then get hit.
|
||||
untouched = hp_dist[hp];
|
||||
opp.untouched = opp.hp_dist[opp_hp];
|
||||
}
|
||||
@ -829,8 +835,8 @@ double combatant::average_hp(unsigned int healing) const
|
||||
}
|
||||
|
||||
#if defined(BENCHMARK) || defined(CHECK)
|
||||
// We create a significant number of nasty-to-calculate units, and
|
||||
// test each one against the others.
|
||||
// We create a significant number of nasty-to-calculate units,
|
||||
// and test each one against the others.
|
||||
#define NUM_UNITS 50
|
||||
|
||||
// Stolen from glibc headers sys/time.h
|
||||
@ -900,8 +906,8 @@ static void run(unsigned specific_battle)
|
||||
if (specific_battle && battle != specific_battle)
|
||||
continue;
|
||||
u[j]->fight(*u[i]);
|
||||
// We need this here, because swarm means out num hits
|
||||
// can change.
|
||||
// We need this here, because swarm means
|
||||
// out num hits can change.
|
||||
u[i]->set_effectiveness((i % 7) + 2, 0.3 + (i % 6)*0.1,
|
||||
(i % 8) == 0);
|
||||
u[k]->fight(*u[i]);
|
||||
|
@ -12,6 +12,9 @@
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
//! @file attack_prediction.hpp
|
||||
//!
|
||||
|
||||
#ifndef ATTACK_PREDICTION_H_INCLUDED
|
||||
#define ATTACK_PREDICTION_H_INCLUDED
|
||||
|
||||
@ -21,60 +24,61 @@
|
||||
#include "actions.hpp"
|
||||
|
||||
// This encapsulates all we need to know for this combat.
|
||||
//! All combat-related infos.
|
||||
struct combatant
|
||||
{
|
||||
// Construct a combatant.
|
||||
//! Construct a combatant.
|
||||
combatant(const battle_context::unit_stats &u, const combatant *prev = NULL);
|
||||
|
||||
// Copy constructor
|
||||
//! Copy constructor
|
||||
combatant(const combatant &that, const battle_context::unit_stats &u);
|
||||
|
||||
// Simulate a fight! Can be called multiple times for cumulative calculations.
|
||||
//! Simulate a fight! Can be called multiple times for cumulative calculations.
|
||||
void fight(combatant &opponent);
|
||||
|
||||
// Resulting probability distribution (may NOT be as large as max_hp)
|
||||
//! Resulting probability distribution (may NOT be as large as max_hp)
|
||||
std::vector<double> hp_dist;
|
||||
|
||||
// Resulting chance we were not hit by this opponent (important if it poisons)
|
||||
//! Resulting chance we were not hit by this opponent (important if it poisons)
|
||||
double untouched;
|
||||
|
||||
// Resulting chance we are poisoned.
|
||||
//! Resulting chance we are poisoned.
|
||||
double poisoned;
|
||||
|
||||
// Resulting chance we are slowed.
|
||||
//! Resulting chance we are slowed.
|
||||
double slowed;
|
||||
|
||||
// What's the average hp (weighted average of hp_dist).
|
||||
//! What's the average hp (weighted average of hp_dist).
|
||||
double average_hp(unsigned int healing = 0) const;
|
||||
|
||||
private:
|
||||
combatant(const combatant &that);
|
||||
combatant& operator=(const combatant &);
|
||||
|
||||
// Minimum hp we could possibly have.
|
||||
//! Minimum hp we could possibly have.
|
||||
unsigned min_hp() const;
|
||||
|
||||
// HP distribution we could end up with.
|
||||
//! HP distribution we could end up with.
|
||||
static unsigned hp_dist_size(const battle_context::unit_stats &u, const combatant *prev);
|
||||
|
||||
// Combat without chance of death, berserk, slow or drain is simple.
|
||||
//! Combat without chance of death, berserk, slow or drain is simple.
|
||||
void no_death_fight(combatant &opponent);
|
||||
|
||||
// Combat with <= 1 strike each is simple, too.
|
||||
//! Combat with <= 1 strike each is simple, too.
|
||||
void one_strike_fight(combatant &opponent);
|
||||
|
||||
// All other cases.
|
||||
//! All other cases.
|
||||
void complex_fight(combatant &opponent, unsigned int rounds);
|
||||
|
||||
// We must adjust for swarm after every combat.
|
||||
//! We must adjust for swarm after every combat.
|
||||
void adjust_hitchance();
|
||||
|
||||
const battle_context::unit_stats &u_;
|
||||
|
||||
// Usually uniform, but if we have swarm, then can be different.
|
||||
//! Usually uniform, but if we have swarm, then can be different.
|
||||
std::vector<double> hit_chances_;
|
||||
|
||||
// Summary of matrix used to calculate last battle (unslowed & slowed).
|
||||
//! Summary of matrix used to calculate last battle (unslowed & slowed).
|
||||
std::vector<double> summary[2];
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user