aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/map/Map.cpp
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-01-07 21:25:27 +0100
committer hop311 <hop3114@gmail.com>2024-01-07 21:30:44 +0100
commit34d9e9318387f2b2a0ae924a512f352540b84e07 (patch)
treea7cf192c714aa5553a244d7b16c04f833b626cb6 /src/openvic-simulation/map/Map.cpp
parent004abc9951d0a20d09027cde1d9b5b02bcc99fa0 (diff)
More impassable adjacencies + WVPM mod fixes
Diffstat (limited to 'src/openvic-simulation/map/Map.cpp')
-rw-r--r--src/openvic-simulation/map/Map.cpp93
1 files changed, 54 insertions, 39 deletions
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index a8cc4a0..27079f4 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -4,12 +4,11 @@
#include <cstddef>
#include <vector>
-#include "openvic-simulation/economy/Good.hpp"
#include "openvic-simulation/history/ProvinceHistory.hpp"
#include "openvic-simulation/types/Colour.hpp"
+#include "openvic-simulation/types/OrderedContainers.hpp"
#include "openvic-simulation/utility/BMP.hpp"
#include "openvic-simulation/utility/Logger.hpp"
-#include "openvic-simulation/types/OrderedContainers.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -84,6 +83,8 @@ Province::distance_t Map::calculate_distance_between(Province const& from, Provi
return fvec2_t { min_x, to_pos.y - from_pos.y}.length_squared().sqrt();
}
+using adjacency_t = Province::adjacency_t;
+
/* This is called for all adjacent pixel pairs and returns whether or not a new adjacency was add,
* hence the lack of error messages in the false return cases. */
bool Map::add_standard_adjacency(Province& from, Province& to) const {
@@ -100,10 +101,10 @@ bool Map::add_standard_adjacency(Province& from, Province& to) const {
const Province::distance_t distance = calculate_distance_between(from, to);
- using enum Province::adjacency_t::type_t;
+ using enum adjacency_t::type_t;
/* Default land-to-land adjacency */
- Province::adjacency_t::type_t type = LAND;
+ adjacency_t::type_t type = LAND;
if (from.is_water() != to.is_water()) {
/* Land-to-water adjacency */
type = COASTAL;
@@ -126,30 +127,28 @@ bool Map::add_standard_adjacency(Province& from, Province& to) const {
}
bool Map::add_special_adjacency(
- Province& from, Province& to, Province::adjacency_t::type_t type, Province const* through,
- Province::adjacency_t::data_t data
+ Province& from, Province& to, adjacency_t::type_t type, Province const* through, adjacency_t::data_t data
) const {
if (from == to) {
- Logger::error("Trying to add ", Province::adjacency_t::get_type_name(type), " adjacency from province ", from, " to itself!");
+ Logger::error("Trying to add ", adjacency_t::get_type_name(type), " adjacency from province ", from, " to itself!");
return false;
}
- using enum Province::adjacency_t::type_t;
+ using enum adjacency_t::type_t;
/* Check end points */
switch (type) {
case LAND:
- case IMPASSABLE:
case STRAIT:
if (from.is_water() || to.is_water()) {
- Logger::error(Province::adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has water endpoint(s)!");
+ Logger::error(adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has water endpoint(s)!");
return false;
}
break;
case WATER:
case CANAL:
if (!from.is_water() || !to.is_water()) {
- Logger::error(Province::adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has land endpoint(s)!");
+ Logger::error(adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has land endpoint(s)!");
return false;
}
break;
@@ -159,6 +158,12 @@ bool Map::add_special_adjacency(
return false;
}
break;
+ case IMPASSABLE:
+ /* Impassable is valid for all combinations of land and water:
+ * - land-land = replace existing land adjacency with impassable adjacency (blue borders)
+ * - land-water = delete existing coastal adjacency, preventing armies and navies from moving between the provinces
+ * - water-water = delete existing water adjacency, preventing navies from moving between the provinces */
+ break;
default:
Logger::error("Invalid adjacency type ", static_cast<uint32_t>(type));
return false;
@@ -169,56 +174,66 @@ bool Map::add_special_adjacency(
const bool water_expected = type == STRAIT;
if (through == nullptr || through->is_water() != water_expected) {
Logger::error(
- Province::adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has a ",
+ adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has a ",
(through == nullptr ? "null" : water_expected ? "land" : "water"), " through province ", through
);
return false;
}
} else if (through != nullptr) {
Logger::warning(
- Province::adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has a non-null through province ",
+ adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has a non-null through province ",
through
);
through = nullptr;
}
/* Check canal data */
- if (data != Province::adjacency_t::NO_CANAL && type != CANAL) {
+ if (data != adjacency_t::NO_CANAL && type != CANAL) {
Logger::warning(
- Province::adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has invalid data ",
+ adjacency_t::get_type_name(type), " adjacency from ", from, " to ", to, " has invalid data ",
static_cast<uint32_t>(data)
);
- data = Province::adjacency_t::NO_CANAL;
+ data = adjacency_t::NO_CANAL;
}
const Province::distance_t distance = calculate_distance_between(from, to);
const auto add_adjacency = [distance, type, through, data](Province& from, Province const& to) -> bool {
- Province::adjacency_t* existing_adjacency = from.get_adjacency_to(&to);
- if (existing_adjacency != nullptr) {
+ const std::vector<adjacency_t>::iterator existing_adjacency = std::find_if(
+ from.adjacencies.begin(), from.adjacencies.end(),
+ [&to](adjacency_t const& adj) -> bool { return adj.get_to() == &to; }
+ );
+ if (existing_adjacency != from.adjacencies.end()) {
if (type == existing_adjacency->get_type()) {
Logger::warning(
- "Adjacency from ", from, " to ", to, " already has type ", Province::adjacency_t::get_type_name(type), "!"
+ "Adjacency from ", from, " to ", to, " already has type ", adjacency_t::get_type_name(type), "!"
);
if (type != STRAIT && type != CANAL) {
/* Straits and canals might change through or data, otherwise we can exit early */
return true;
}
}
- if (type != IMPASSABLE && type != STRAIT && type != CANAL) {
- Logger::error(
- "Provinces ", from, " and ", to, " already have an existing ",
- Province::adjacency_t::get_type_name(existing_adjacency->get_type()), " adjacency, cannot create a ",
- Province::adjacency_t::get_type_name(type), " adjacency!"
- );
- return false;
- }
- if (type != existing_adjacency->get_type() && existing_adjacency->get_type() != (type == CANAL ? WATER : LAND)) {
- Logger::error(
- "Cannot convert ", Province::adjacency_t::get_type_name(existing_adjacency->get_type()), " adjacency from ", from,
- " to ", to, " to type ", Province::adjacency_t::get_type_name(type), "!"
- );
- return false;
+ if (type == IMPASSABLE) {
+ if (existing_adjacency->get_type() == WATER || existing_adjacency->get_type() == COASTAL) {
+ from.adjacencies.erase(existing_adjacency);
+ return true;
+ }
+ } else {
+ if (type != STRAIT && type != CANAL) {
+ Logger::error(
+ "Provinces ", from, " and ", to, " already have an existing ",
+ adjacency_t::get_type_name(existing_adjacency->get_type()), " adjacency, cannot create a ",
+ adjacency_t::get_type_name(type), " adjacency!"
+ );
+ return false;
+ }
+ if (type != existing_adjacency->get_type() && existing_adjacency->get_type() != (type == CANAL ? WATER : LAND)) {
+ Logger::error(
+ "Cannot convert ", adjacency_t::get_type_name(existing_adjacency->get_type()), " adjacency from ", from,
+ " to ", to, " to type ", adjacency_t::get_type_name(type), "!"
+ );
+ return false;
+ }
}
*existing_adjacency = { &to, distance, type, through, data };
return true;
@@ -783,30 +798,30 @@ bool Map::generate_and_load_province_adjacencies(std::vector<LineObject> const&
return;
}
- using enum Province::adjacency_t::type_t;
- static const string_map_t<Province::adjacency_t::type_t> type_map {
+ using enum adjacency_t::type_t;
+ static const string_map_t<adjacency_t::type_t> type_map {
{ "land", LAND }, { "sea", STRAIT }, { "impassable", IMPASSABLE }, { "canal", CANAL }
};
const std::string_view type_str = adjacency.get_value_for(2);
- const string_map_t<Province::adjacency_t::type_t>::const_iterator it = type_map.find(type_str);
+ const string_map_t<adjacency_t::type_t>::const_iterator it = type_map.find(type_str);
if (it == type_map.end()) {
Logger::error("Invalid adjacency type: \"", type_str, "\"");
ret = false;
return;
}
- const Province::adjacency_t::type_t type = it->second;
+ const adjacency_t::type_t type = it->second;
Province const* const through = get_province_by_identifier(adjacency.get_value_for(3));
const std::string_view data_str = adjacency.get_value_for(4);
bool successful = false;
const uint64_t data_uint = StringUtils::string_to_uint64(data_str, &successful);
- if (!successful || data_uint > std::numeric_limits<Province::adjacency_t::data_t>::max()) {
+ if (!successful || data_uint > std::numeric_limits<adjacency_t::data_t>::max()) {
Logger::error("Invalid adjacency data: \"", data_str, "\"");
ret = false;
return;
}
- const Province::adjacency_t::data_t data = data_uint;
+ const adjacency_t::data_t data = data_uint;
ret &= add_special_adjacency(*from, *to, type, through, data);
}