aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/map/Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/map/Map.cpp')
-rw-r--r--src/openvic-simulation/map/Map.cpp172
1 files changed, 101 insertions, 71 deletions
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index 728fc42..3b06c66 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -7,6 +7,7 @@
#include "openvic-simulation/utility/Logger.hpp"
using namespace OpenVic;
+using namespace OpenVic::NodeTools;
Mapmode::Mapmode(const std::string_view new_identifier, index_t new_index, colour_func_t new_colour_func)
: HasIdentifier { new_identifier },
@@ -53,10 +54,6 @@ bool Map::add_province(const std::string_view identifier, colour_t colour) {
return provinces.add_item(std::move(new_province));
}
-void Map::lock_provinces() {
- provinces.lock();
-}
-
bool Map::set_water_province(const std::string_view identifier) {
if (water_provinces.is_locked()) {
Logger::error("The map's water provinces have already been locked!");
@@ -67,7 +64,7 @@ bool Map::set_water_province(const std::string_view identifier) {
Logger::error("Unrecognised water province identifier: ", identifier);
return false;
}
- if (province->is_water()) {
+ if (province->get_water()) {
Logger::warning("Province ", identifier, " is already a water province!");
return true;
}
@@ -98,63 +95,40 @@ bool Map::add_region(const std::string_view identifier, std::vector<std::string_
Logger::error("Invalid region identifier - empty!");
return false;
}
- Region new_region { identifier };
- bool ret = true;
+ Region::provinces_t provinces;
+ provinces.reserve(province_identifiers.size());
+ bool meta = false, ret = true;
for (const std::string_view province_identifier : province_identifiers) {
Province* province = get_province_by_identifier(province_identifier);
if (province != nullptr) {
- if (new_region.contains_province(province)) {
+ if (std::find(provinces.begin(), provinces.end(), province) != provinces.end()) {
Logger::error("Duplicate province identifier ", province_identifier, " in region ", identifier);
ret = false;
} else {
- size_t other_region_index = reinterpret_cast<size_t>(province->get_region());
- if (other_region_index != 0) {
- other_region_index--;
- if (other_region_index < regions.size())
- Logger::error("Cannot add province ", province_identifier, " to region ", identifier, " - it is already part of ", regions.get_item_by_index(other_region_index)->get_identifier());
- else
- Logger::error("Cannot add province ", province_identifier, " to region ", identifier, " - it is already part of an unknown region with index ", other_region_index);
- ret = false;
- } else if (!new_region.add_province(province)) {
- Logger::error("Failed to add province ", province_identifier, " to region ", identifier);
- ret = false;
+ if (province->get_has_region()) {
+ meta = true;
}
+ provinces.push_back(province);
}
} else {
Logger::error("Invalid province identifier ", province_identifier, " for region ", identifier);
ret = false;
}
}
- new_region.lock();
- if (new_region.empty()) {
- Logger::error("No valid provinces in list for ", identifier);
- return false;
+ if (provinces.empty()) {
+ Logger::warning("No valid provinces in list for ", identifier);
+ return ret;
}
- // Used to detect provinces listed in multiple regions, will
- // be corrected once regions is stable (i.e. lock_regions).
- Region* tmp_region_index = reinterpret_cast<Region*>(regions.size());
- for (Province* province : new_region.get_provinces())
- province->region = tmp_region_index;
- ret &= regions.add_item(std::move(new_region));
+ if (!meta) {
+ for (Province* province : provinces) {
+ province->has_region = true;
+ }
+ }
+ ret &= regions.add_item({ identifier, std::move(provinces), meta });
return ret;
}
-void Map::lock_regions() {
- regions.lock();
- for (Region& region : regions.get_items())
- for (Province* province : region.get_provinces())
- province->region = &region;
-}
-
-size_t Map::get_province_count() const {
- return provinces.size();
-}
-
-std::vector<Province> const& Map::get_provinces() const {
- return provinces.get_items();
-}
-
Province* Map::get_province_by_index(Province::index_t index) {
return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr;
}
@@ -163,14 +137,6 @@ Province const* Map::get_province_by_index(Province::index_t index) const {
return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr;
}
-Province* Map::get_province_by_identifier(const std::string_view identifier) {
- return provinces.get_item_by_identifier(identifier);
-}
-
-Province const* Map::get_province_by_identifier(const std::string_view identifier) const {
- return provinces.get_item_by_identifier(identifier);
-}
-
Province::index_t Map::get_index_from_colour(colour_t colour) const {
const colour_index_map_t::const_iterator it = colour_index_map.find(colour);
if (it != colour_index_map.end()) return it->second;
@@ -216,22 +182,6 @@ Province const* Map::get_selected_province() const {
return get_province_by_index(get_selected_province_index());
}
-Region* Map::get_region_by_identifier(const std::string_view identifier) {
- return regions.get_item_by_identifier(identifier);
-}
-
-Region const* Map::get_region_by_identifier(const std::string_view identifier) const {
- return regions.get_item_by_identifier(identifier);
-}
-
-size_t Map::get_region_count() const {
- return regions.size();
-}
-
-std::vector<Region> const& Map::get_regions() const {
- return regions.get_items();
-}
-
static colour_t colour_at(uint8_t const* colour_data, int32_t idx) {
idx *= 3;
return (colour_data[idx] << 16) | (colour_data[idx + 1] << 8) | colour_data[idx + 2];
@@ -336,6 +286,9 @@ bool Map::generate_province_shape_image(size_t new_width, size_t new_height, uin
Logger::error("Province image is missing ", missing, " province colours");
ret = false;
}
+
+ ret &= _generate_province_adjacencies();
+
return ret;
}
@@ -419,9 +372,6 @@ bool Map::setup(GoodManager const& good_manager, BuildingManager const& building
bool ret = true;
for (Province& province : provinces.get_items()) {
province.clear_pops();
- // Set all land provinces to have an RGO based on their index to test them
- if (!province.is_water() && good_manager.get_good_count() > 0)
- province.rgo = good_manager.get_good_by_index(province.get_index() % good_manager.get_good_count());
ret &= building_manager.generate_province_buildings(province);
}
return ret;
@@ -503,3 +453,83 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) {
lock_provinces();
return ret;
}
+
+bool Map::load_province_positions(BuildingManager const& building_manager, ast::NodeCPtr root) {
+ return expect_province_dictionary(
+ [&building_manager](Province& province, ast::NodeCPtr node) -> bool {
+ return province.load_positions(building_manager, node);
+ }
+ )(root);
+}
+
+bool Map::load_region_file(ast::NodeCPtr root) {
+ const bool ret = expect_dictionary_reserve_length(
+ regions,
+ [this](std::string_view region_identifier, ast::NodeCPtr region_node) -> bool {
+ std::vector<std::string_view> province_identifiers;
+ bool ret = expect_list_reserve_length(
+ province_identifiers,
+ expect_identifier([&province_identifiers](std::string_view identifier) -> bool {
+ province_identifiers.push_back(identifier);
+ return true;
+ })
+ )(region_node);
+ ret &= add_region(region_identifier, province_identifiers);
+ return ret;
+ }
+ )(root);
+ lock_regions();
+ for (Region& region : regions.get_items()) {
+ if (!region.meta) {
+ for (Province* province : region.get_provinces()) {
+ if (!province->get_has_region()) {
+ Logger::error("Province in non-meta region without has_region set: ", province->get_identifier());
+ province->has_region = true;
+ }
+ province->region = &region;
+ }
+ }
+ }
+ for (Province& province : provinces.get_items()) {
+ const bool region_null = province.get_region() == nullptr;
+ if (province.get_has_region() == region_null) {
+ Logger::error("Province has_region / region mismatch: has_region = ", province.get_has_region(), ", region = ", province.get_region());
+ province.has_region = !region_null;
+ }
+ }
+ return ret;
+}
+
+bool Map::_generate_province_adjacencies() {
+ bool changed = false;
+
+ auto generate_adjacency = [&] (shape_pixel_t cur_pixel, size_t x, size_t y) -> bool {
+ size_t idx = x + y * width;
+ shape_pixel_t neighbour_pixel = province_shape_image[idx];
+ if (cur_pixel.index != neighbour_pixel.index) {
+ Province* cur = get_province_by_index(cur_pixel.index);
+ Province* neighbour = get_province_by_index(neighbour_pixel.index);
+ if(cur != nullptr && neighbour != nullptr) {
+ cur->add_adjacency(neighbour, 0, 0);
+ neighbour->add_adjacency(cur, 0, 0);
+ return true;
+ } else Logger::error(
+ "Couldn't find province(s): current = ", cur, " (", cur_pixel.index,
+ "), neighbour = ", neighbour, " (", neighbour_pixel.index, ")"
+ );
+ }
+ return false;
+ };
+
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ shape_pixel_t cur = province_shape_image[x + y * width];
+ if(x + 1 < width)
+ changed |= generate_adjacency(cur, x + 1, y);
+ if(y + 1 < height)
+ changed |= generate_adjacency(cur, x, y + 1);
+ }
+ }
+
+ return changed;
+}