From 5a35533ce6cbd47431ec9f469fcc4c421443d5f3 Mon Sep 17 00:00:00 2001 From: Philippe Plantier Date: Sat, 15 May 2004 15:29:44 +0000 Subject: [PATCH] * Fixing crash on the multi-hex tile code, ... ...when there is a map only containing blank lines * Optimizing the multi-hex calculations, making them ways faster. --- src/builder.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++------ src/builder.hpp | 3 +++ src/map.cpp | 21 ++++++++++++++++++- src/map.hpp | 3 +++ 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/builder.cpp b/src/builder.cpp index 29b58bb40bf..c368896e5e8 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -42,6 +42,8 @@ const std::vector *terrain_builder::get_terrain_at(const gamemap void terrain_builder::rebuild_terrain(const gamemap::location &loc) { tile_map_.clear(); + terrain_by_type_.clear(); + // For now, rebuild the whole map on each rebuilt_terrain. This is highly slow and // inefficient, but this is simple build_terrains(); @@ -170,8 +172,12 @@ void terrain_builder::parse_mapstring(const std::string &mapstring, struct build std::vector::const_iterator line = lines.begin(); //Strips trailing empty lines - while(std::find_if(line->begin(),line->end(),config::notspace) == line->end()) + while(line != lines.end() && std::find_if(line->begin(),line->end(),config::notspace) == line->end()) { line++; + } + //Break if there only are blank lines + if(line == lines.end()) + return; //If the strings starts with a space, the first line is an odd line, else it is an even one if((*line)[0] == ' ') @@ -304,6 +310,9 @@ void terrain_builder::parse_config(const config &cfg) bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule, const gamemap::location &loc) { + if(!loc.valid()) + return false; + if(rule.location_constraints.valid() && rule.location_constraints != loc) return false; @@ -398,14 +407,49 @@ void terrain_builder::build_terrains() log_scope("terrain_builder::build_terrains"); + //builds the terrain_by_type_ cache + for(int x = -1; x <= map_.x(); ++x) { + for(int y = -1; y <= map_.y(); ++y) { + const gamemap::location loc(x,y); + const gamemap::TERRAIN t = map_.get_terrain(loc); + + terrain_by_type_[t].push_back(loc); + } + } + for(building_ruleset::const_iterator rule = building_rules_.begin(); rule != building_rules_.end(); ++rule) { - for(int x = -1; x <= map_.x(); ++x) { - for(int y = -1; y <= map_.y(); ++y) { - const gamemap::location loc(x,y); - if(rule_matches(*rule, loc)) - apply_rule(*rule, loc); + //find a constraint that contains an unique terrain type on the current + //rule + building_rule::constraint_set::const_iterator constraint; + for(constraint = rule->constraints.begin(); + constraint != rule->constraints.end(); ++constraint) { + + if(constraint->second.terrain_types.size() == 1 && (constraint->second.terrain_types[0] != '*')) { + break; + } + } + + if(constraint != rule->constraints.end()) { + gamemap::TERRAIN c = constraint->second.terrain_types[0]; + gamemap::location loc = constraint->second.loc; + const std::vector& locations = terrain_by_type_[c]; + + for(std::vector::const_iterator itor = locations.begin(); + itor != locations.end(); ++itor) { + + if(rule_matches(*rule, *itor - loc)) { + apply_rule(*rule, *itor - loc); + } + } + } else { + for(int x = -1; x <= map_.x(); ++x) { + for(int y = -1; y <= map_.y(); ++y) { + const gamemap::location loc(x,y); + if(rule_matches(*rule, loc)) + apply_rule(*rule, loc); + } } } } diff --git a/src/builder.hpp b/src/builder.hpp index 22342f9fea9..0c45ff5f08d 100644 --- a/src/builder.hpp +++ b/src/builder.hpp @@ -104,6 +104,9 @@ private: const gamemap& map_; tilemap tile_map_; + typedef std::map > terrain_by_type_map; + terrain_by_type_map terrain_by_type_; + typedef std::vector building_ruleset; building_ruleset building_rules_; diff --git a/src/map.cpp b/src/map.cpp index 840abec682f..82467a340ed 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -147,6 +147,15 @@ bool gamemap::location::operator<(const gamemap::location& a) const return x < a.x || x == a.x && y < a.y; } +gamemap::location gamemap::location::operator-() const +{ + location ret; + ret.x = -x; + ret.y = -y; + + return ret; +} + gamemap::location gamemap::location::operator+(const gamemap::location& a) const { gamemap::location ret = *this; @@ -154,7 +163,7 @@ gamemap::location gamemap::location::operator+(const gamemap::location& a) const return ret; } -gamemap::location &gamemap::location::operator+=(const gamemap::location &a) +gamemap::location& gamemap::location::operator+=(const gamemap::location &a) { bool parity = (x & 1) != 0; @@ -169,6 +178,16 @@ gamemap::location &gamemap::location::operator+=(const gamemap::location &a) return *this; } +gamemap::location gamemap::location::operator-(const gamemap::location &a) const +{ + return operator+(-a); +} + +gamemap::location& gamemap::location::operator-=(const gamemap::location &a) +{ + return operator+=(-a); +} + gamemap::location gamemap::location::get_direction( gamemap::location::DIRECTION dir) const { diff --git a/src/map.hpp b/src/map.hpp index b17c29dcbf8..c89b7e4fc79 100644 --- a/src/map.hpp +++ b/src/map.hpp @@ -69,8 +69,11 @@ public: bool operator==(const location& a) const; bool operator!=(const location& a) const; // Adds an absolute location to a "delta" location + location operator-() const; location operator+(const location &a) const; location &operator+=(const location &a); + location operator-(const location &a) const; + location &operator-=(const location &a); location get_direction(DIRECTION d) const;