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:
parent
cbd806b51e
commit
f4fd1eeaca
2 changed files with 48 additions and 17 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue