added use_prng preference which adds a new experimental pseudo-RNG for casual campaign play

This commit is contained in:
David white 2018-05-09 22:30:07 -07:00 committed by Charles Dang
parent b89b89abea
commit 3886228447
4 changed files with 58 additions and 1 deletions

View file

@ -847,6 +847,11 @@ private:
bool update_display_;
bool OOS_error_;
bool use_prng_;
std::vector<bool> prng_attacker_;
std::vector<bool> prng_defender_;
};
attack::unit_info::unit_info(const map_location& loc, int weapon, unit_map& units)
@ -908,7 +913,13 @@ attack::attack(const map_location& attacker,
, errbuf_()
, update_display_(update_display)
, OOS_error_(false)
//new experimental prng mode.
, use_prng_(preferences::get("use_prng") == "yes" && randomness::generator->is_networked() == false)
{
if(use_prng_) {
std::cerr << "Using experimental PRNG for combat\n";
}
}
void attack::fire_event(const std::string& n)
@ -1032,7 +1043,39 @@ bool attack::perform_hit(bool attacker_turn, statistics::attack_context& stats)
int& abs_n = attacker_turn ? abs_n_attack_ : abs_n_defend_;
bool& update_fog = attacker_turn ? update_def_fog_ : update_att_fog_;
int ran_num = randomness::generator->get_random_int(0, 99);
int ran_num;
if(use_prng_) {
std::vector<bool>& prng_seq = attacker_turn ? prng_attacker_ : prng_defender_;
if(prng_seq.empty()) {
const int ntotal = attacker.cth_*attacker.n_attacks_;
int num_hits = ntotal/100;
const int additional_hit_chance = ntotal%100;
if(additional_hit_chance > 0 && randomness::generator->get_random_int(0, 99) < additional_hit_chance) {
++num_hits;
}
std::vector<int> indexes;
for(int i = 0; i != attacker.n_attacks_; ++i) {
prng_seq.push_back(false);
indexes.push_back(i);
}
for(int i = 0; i != num_hits; ++i) {
int n = randomness::generator->get_random_int(0, static_cast<int>(indexes.size())-1);
prng_seq[indexes[n]] = true;
indexes.erase(indexes.begin() + n);
}
}
bool does_hit = prng_seq.back();
prng_seq.pop_back();
ran_num = does_hit ? 0 : 99;
} else {
ran_num = randomness::generator->get_random_int(0, 99);
}
bool hits = (ran_num < attacker.cth_);
int damage = 0;

View file

@ -81,6 +81,13 @@ namespace randomness
uint32_t operator()() { return next_random(); }
static rng& default_instance();
/**
* Is this random source networked? If it is it's very important we do actually use
* this random source to stay in-sync.
*/
virtual bool is_networked() const { return false; }
protected:
virtual uint32_t next_random_impl() = 0;
unsigned int random_calls_;

View file

@ -50,4 +50,9 @@ namespace randomness
{
}
bool synced_rng::is_networked() const
{
return true;
}
}

View file

@ -30,6 +30,8 @@ namespace randomness
synced_rng(std::function<std::string()> seed_generator);
virtual ~synced_rng();
virtual bool is_networked() const;
protected:
virtual uint32_t next_random_impl();
private: