Much more stable terrain variation randomization (fix bug #16612)

Hash the image name, so the only thing now affecting it is images
rename and change in the hash function (which still need some
polishing).
This commit is contained in:
Ali El Gariani 2010-09-02 19:26:56 +00:00
parent cbd806b51e
commit f4fd1eeaca
2 changed files with 48 additions and 17 deletions

View file

@ -906,14 +906,14 @@ void terrain_builder::add_off_map_rule(const std::string& image)
}
bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule,
const map_location &loc, const int rule_index, const terrain_constraint *type_checked) const
const map_location &loc, const terrain_constraint *type_checked) const
{
if(rule.location_constraints.valid() && rule.location_constraints != loc) {
return false;
}
if(rule.probability != -1) {
unsigned int random = get_noise(loc, rule_index) % 100;
unsigned int random = get_noise(loc, rule.get_hash()) % 100;
if(random > static_cast<unsigned int>(rule.probability)) {
return false;
}
@ -954,9 +954,9 @@ bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule,
return true;
}
void terrain_builder::apply_rule(const terrain_builder::building_rule &rule, const map_location &loc, const int rule_index)
void terrain_builder::apply_rule(const terrain_builder::building_rule &rule, const map_location &loc)
{
unsigned int rand_seed = get_noise(loc, rule_index);
unsigned int rand_seed = get_noise(loc, rule.get_hash());
foreach (const terrain_constraint &constraint, rule.constraints)
{
@ -979,6 +979,38 @@ void terrain_builder::apply_rule(const terrain_builder::building_rule &rule, con
}
}
// copied from text_surface::hash()
// but keep it separated because the needs are different
// and changing it will modify the map random variations
static unsigned int hash_str(const std::string& str)
{
unsigned int h = 0;
for(std::string::const_iterator it = str.begin(), it_end = str.end(); it != it_end; ++it)
h = ((h << 9) | (h >> (sizeof(int) * 8 - 9))) ^ (*it);
return h;
}
unsigned int terrain_builder::building_rule::get_hash() const
{
if(hash_ != DUMMY_HASH)
return hash_;
foreach(const terrain_constraint &constraint, constraints) {
foreach(const rule_image& ri, constraint.images) {
foreach(const rule_image_variant& variant, ri.variants) {
// we will often hash the same string, but that seems fast enough
hash_ += hash_str(variant.image_string);
}
}
}
//don't use the reserved dummy hash
if(hash_ == DUMMY_HASH)
hash_ = 105533; // just a random big prime number
return hash_;
}
void terrain_builder::build_terrains()
{
log_scope("terrain_builder::build_terrains");
@ -993,7 +1025,6 @@ void terrain_builder::build_terrains()
}
}
int rule_index = 0;
foreach (const building_rule &rule, building_rules_)
{
// Find the constraint that contains the less terrain of all terrain rules.
@ -1045,13 +1076,12 @@ void terrain_builder::build_terrains()
itor != locations->end(); ++itor) {
const map_location loc = itor->legacy_difference(min_constraint->loc);
if(rule_matches(rule, loc, rule_index, min_constraint)) {
apply_rule(rule, loc, rule_index);
if(rule_matches(rule, loc, min_constraint)) {
apply_rule(rule, loc);
}
}
}
++rule_index;
}
}

View file

@ -71,6 +71,8 @@ public:
*/
static const int UNITPOS = 36 + 18;
static const unsigned int DUMMY_HASH = 0;
/** A shorthand typedef for a list of animated image locators,
* the base data type returned by the get_terrain_at method.
*/
@ -355,7 +357,8 @@ private:
location_constraints(),
probability(0),
precedence(0),
local(false)
local(false),
hash_(DUMMY_HASH)
{}
/**
@ -389,6 +392,10 @@ private:
bool operator<(building_rule const &that) const
{ return precedence < that.precedence; }
unsigned int get_hash() const;
private:
mutable unsigned int hash_;
};
/**
@ -736,15 +743,10 @@ private:
* @param rule The rule to check.
* @param loc The location in the map where we want to check
* whether the rule matches.
* @param rule_index The index of the rule, relative to the start of
* the rule list. Rule indices are used for seeding
* the pseudo-random-number generator used for
* probability calculations.
* @param type_checked The constraint which we already know that its
* terrain types matches.
*/
bool rule_matches(const building_rule &rule, const map_location &loc,
const int rule_index, const terrain_constraint *type_checked) const;
bool rule_matches(const building_rule &rule, const map_location &loc, const terrain_constraint *type_checked) const;
/**
* Applies a rule at a given location: applies the result of a
@ -753,9 +755,8 @@ private:
*
* @param rule The rule to apply
* @param loc The location to which to apply the rule.
* @param rule_index The index of the rule used for seed generation
*/
void apply_rule(const building_rule &rule, const map_location &loc, const int rule_index);
void apply_rule(const building_rule &rule, const map_location &loc);
/**
* Calculates the list of terrains, and fills the tile_map_ member,