Skip to content

Commit

Permalink
Assign unassigned provinces to surrounding strategic regions. (#1673)
Browse files Browse the repository at this point in the history
  • Loading branch information
Idhrendur authored Dec 28, 2023
1 parent bf0971c commit 9213feb
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/HOI4World/HoI4World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ HoI4::World::World(const Vic2::World& sourceWorld,
theMapData = std::make_unique<Maps::MapData>(*provinceDefinitions, theConfiguration.getHoI4Path());
const auto theProvinces = importProvinces(theConfiguration);
theCoastalProvinces.init(*theMapData, theProvinces);
strategicRegions = StrategicRegions::Factory().importStrategicRegions(theConfiguration);
strategicRegions = StrategicRegions::Factory().ImportStrategicRegions(theConfiguration);
const auto defaultStates = DefaultStatesImporter().ImportDefaultStates(theConfiguration.getHoI4Path());
const ImpassableProvinces impassableProvinces(defaultStates);
states = std::make_unique<States>(sourceWorld,
Expand Down Expand Up @@ -191,7 +191,7 @@ HoI4::World::World(const Vic2::World& sourceWorld,
convertTechs();
states->convertResources(countries);
supplyZones->convertSupplyZones(*states);
strategicRegions->convert(*states);
strategicRegions->Convert(*states, *theMapData);
convertStrategies(sourceWorld, *states, provinceMapper);
Log(LogLevel::Progress) << "56%";

Expand Down
189 changes: 138 additions & 51 deletions src/HOI4World/Map/StrategicRegions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,201 @@
#include "external/common_items/OSCompatibilityLayer.h"
#include "src/HOI4World/States/HoI4State.h"
#include "src/HOI4World/States/HoI4States.h"
#include <ranges>
#include <set>



void HoI4::StrategicRegions::convert(const States& theStates)
namespace
{
Log(LogLevel::Info) << "\tConverting strategic regions";

for (const auto& state: theStates.getStates())
[[no_discard]] std::map<int, int> DetermineUsedRegions(const HoI4::State& state,
const std::map<int, int>& province_to_strategic_region_map)
{
std::map<int, int> used_regions; // region ID -> number of provinces in that region

for (auto province: state.getProvinces())
{
const auto usedRegions = determineUsedRegions(state.second);
const auto bestRegion = determineMostUsedRegion(usedRegions);
if (bestRegion)
auto mapping = province_to_strategic_region_map.find(province);
if (mapping == province_to_strategic_region_map.end())
{
addProvincesToRegion(*bestRegion, state.second);
Log(LogLevel::Warning) << "Province " << province << " had no original strategic region";
continue;
}

if (auto [iterator, success] = used_regions.emplace(mapping->second, 1); !success)
{
++iterator->second;
}
}

addLeftoverProvincesToRegions();
return used_regions;
}


std::map<int, int> HoI4::StrategicRegions::determineUsedRegions(const State& state)
[[no_discard]] std::optional<int> DetermineMostUsedRegion(const std::map<int, int>& used_regions)
{
std::map<int, int> usedRegions; // region ID -> number of provinces in that region
if (!used_regions.empty())
{
return std::ranges::max_element(used_regions, [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
return a.second < b.second;
})->first;
}

for (auto province: state.getProvinces())
return std::nullopt;
}


void AddProvinceToRegion(int region_number, int province_id, std::map<int, HoI4::StrategicRegion>& strategic_regions)
{
auto region = strategic_regions.find(region_number);
if (region == strategic_regions.end())
{
Log(LogLevel::Warning) << "Strategic region " << region_number << " was not in the list of regions.";
return;
}

region->second.addNewProvince(province_id);
}


[[no_discard]] std::set<int> DetermineAssignedProvinces(const std::map<int, HoI4::StrategicRegion>& strategic_regions)
{
std::set<int> assigned_provinces;
for (const HoI4::StrategicRegion& strategic_region: strategic_regions | std::ranges::views::values)
{
auto mapping = provinceToStrategicRegionMap.find(province);
if (mapping == provinceToStrategicRegionMap.end())
for (int province: strategic_region.getNewProvinces())
{
Log(LogLevel::Warning) << "Province " << province << " had no original strategic region";
continue;
assigned_provinces.insert(province);
}

usedRegions[mapping->second]++;
provinceToStrategicRegionMap.erase(mapping);
}

return usedRegions;
return assigned_provinces;
}


std::optional<int> HoI4::StrategicRegions::determineMostUsedRegion(const std::map<int, int>& usedRegions)
void AddSurroundedProvincesToRegions(const std::map<int, int>& original_province_to_strategic_region_map,
const std::set<int>& assigned_provinces,
const Maps::MapData& hoi4_map_data,
const std::map<int, int>& new_province_to_strategic_region_map,
std::map<int, HoI4::StrategicRegion>& strategic_regions)
{
if (!usedRegions.empty())
for (const auto& province: original_province_to_strategic_region_map | std::views::keys)
{
return std::max_element(usedRegions.begin(),
usedRegions.end(),
[](const std::pair<int, int>& a, const std::pair<int, int>& b) {
return a.second < b.second;
})
->first;
}
// this only applies to unassigned provinces
if (assigned_provinces.contains(province))
{
continue;
}

return std::nullopt;
bool has_unassigned_neighbor = false;
std::map<int, int> used_regions; // region ID -> number of provinces in that region
for (const int neighbor: hoi4_map_data.GetNeighbors(province))
{
// unassigned neighbors indicate oceans, which means this case doesn't apply
if (!assigned_provinces.contains(neighbor))
{
has_unassigned_neighbor = true;
break;
}

const auto itr = new_province_to_strategic_region_map.find(neighbor);
used_regions[itr->second]++;
}

if (has_unassigned_neighbor)
{
continue;
}

if (const auto best_region = DetermineMostUsedRegion(used_regions); best_region)
{
AddProvinceToRegion(*best_region, province, strategic_regions);
}
}
}


void HoI4::StrategicRegions::addLeftoverProvincesToRegions()
void AddLeftoverProvincesToRegions(const std::set<int>& assigned_provinces,
const std::map<int, int>& province_to_strategic_region_map,
std::map<int, HoI4::StrategicRegion>& strategic_regions)
{
for (const auto& mapping: provinceToStrategicRegionMap)
for (const auto& [province, strategic_region]: province_to_strategic_region_map)
{
addProvinceToRegion(mapping.second, mapping.first);
if (assigned_provinces.contains(province))
{
continue;
}
AddProvinceToRegion(strategic_region, province, strategic_regions);
}
}


void HoI4::StrategicRegions::addProvincesToRegion(int regionNumber, const State& state)
void AddProvincesToRegion(int regionNumber,
const HoI4::State& state,
std::map<int, HoI4::StrategicRegion>& strategic_regions)
{
for (const auto& province: state.getProvinces())
{
addProvinceToRegion(regionNumber, province);
AddProvinceToRegion(regionNumber, province, strategic_regions);
}
}

} // namespace



void HoI4::StrategicRegions::addProvinceToRegion(int regionNumber, int provinceId)
void HoI4::StrategicRegions::Convert(const States& the_states, const Maps::MapData& hoi4_map_data)
{
auto region = strategicRegions.find(regionNumber);
if (region == strategicRegions.end())
Log(LogLevel::Info) << "\tConverting strategic regions";

for (const auto& state: the_states.getStates())
{
Log(LogLevel::Warning) << "Strategic region " << regionNumber << " was not in the list of regions.";
return;
const auto used_regions = DetermineUsedRegions(state.second, original_province_to_strategic_region_map_);
const auto best_region = DetermineMostUsedRegion(used_regions);
if (best_region)
{
AddProvincesToRegion(*best_region, state.second, strategic_regions_);
}
}

std::map<int, int> temp_province_to_strategic_region_map;
for (const auto& [region_number, region]: strategic_regions_)
{
for (auto province: region.getNewProvinces())
{
temp_province_to_strategic_region_map.emplace(province, region_number);
}
}

region->second.addNewProvince(provinceId);
AddSurroundedProvincesToRegions(original_province_to_strategic_region_map_,
DetermineAssignedProvinces(strategic_regions_),
hoi4_map_data,
temp_province_to_strategic_region_map,
strategic_regions_);
AddLeftoverProvincesToRegions(DetermineAssignedProvinces(strategic_regions_),
original_province_to_strategic_region_map_,
strategic_regions_);
}



std::unique_ptr<HoI4::StrategicRegions> HoI4::StrategicRegions::Factory::importStrategicRegions(
const Configuration& theConfiguration)
std::unique_ptr<HoI4::StrategicRegions> HoI4::StrategicRegions::Factory::ImportStrategicRegions(
const Configuration& configuration)
{
std::map<int, StrategicRegion> strategicRegions;
std::map<int, int> provinceToStrategicRegionMap;
std::map<int, StrategicRegion> strategic_regions;
std::map<int, int> province_to_strategic_region_map;

for (const auto& filename:
commonItems::GetAllFilesInFolder(theConfiguration.getHoI4Path() + "/map/strategicregions/"))
for (const auto& filename: commonItems::GetAllFilesInFolder(configuration.getHoI4Path() + "/map/strategicregions/"))
{
auto newRegion = StrategicRegion(filename, theConfiguration);
strategicRegions.insert(std::make_pair(newRegion.getID(), newRegion));
auto new_region = StrategicRegion(filename, configuration);
strategic_regions.insert(std::make_pair(new_region.getID(), new_region));

for (auto province: newRegion.getOldProvinces())
for (auto province: new_region.getOldProvinces())
{
provinceToStrategicRegionMap.insert(std::make_pair(province, newRegion.getID()));
province_to_strategic_region_map.insert(std::make_pair(province, new_region.getID()));
}
}

return std::make_unique<StrategicRegions>(std::move(strategicRegions), std::move(provinceToStrategicRegionMap));
return std::make_unique<StrategicRegions>(std::move(strategic_regions), std::move(province_to_strategic_region_map));
}
28 changes: 12 additions & 16 deletions src/HOI4World/Map/StrategicRegions.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,30 @@ class StrategicRegions
{
public:
class Factory;
StrategicRegions(std::map<int, StrategicRegion>&& strategicRegions,
std::map<int, int>&& provinceToStrategicRegionMap):
strategicRegions(strategicRegions),
provinceToStrategicRegionMap(provinceToStrategicRegionMap)
StrategicRegions(std::map<int, StrategicRegion> strategic_regions,
std::map<int, int> province_to_strategic_region_map):
strategic_regions_(std::move(strategic_regions)),
original_province_to_strategic_region_map_(std::move(province_to_strategic_region_map))
{
new_province_to_strategic_region_map_ = original_province_to_strategic_region_map_;
}

[[nodiscard]] const auto& getStrategicRegions() const { return strategicRegions; }
[[nodiscard]] const auto& getProvinceToStrategicRegionMap() const { return provinceToStrategicRegionMap; }
[[nodiscard]] const auto& GetStrategicRegions() const { return strategic_regions_; }
[[nodiscard]] const auto& GetProvinceToStrategicRegionMap() const { return new_province_to_strategic_region_map_; }

void convert(const States& theStates);
void Convert(const States& states, const Maps::MapData& hoi4_map_data);

private:
std::map<int, int> determineUsedRegions(const State& state);
[[nodiscard]] static std::optional<int> determineMostUsedRegion(const std::map<int, int>& usedRegions);
void addLeftoverProvincesToRegions();
void addProvincesToRegion(int regionNumber, const State& state);
void addProvinceToRegion(int regionNumber, int provinceId);

std::map<int, StrategicRegion> strategicRegions;
std::map<int, int> provinceToStrategicRegionMap;
std::map<int, StrategicRegion> strategic_regions_;
std::map<int, int> original_province_to_strategic_region_map_;
std::map<int, int> new_province_to_strategic_region_map_;
};


class StrategicRegions::Factory
{
public:
static std::unique_ptr<StrategicRegions> importStrategicRegions(const Configuration& theConfiguration);
static std::unique_ptr<StrategicRegions> ImportStrategicRegions(const Configuration& configuration);
};

} // namespace HoI4
Expand Down
2 changes: 1 addition & 1 deletion src/HOI4World/States/HoI4States.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ void HoI4::States::createMatchingHoI4State(const Vic2::State& vic2State,
const auto allProvinces = getProvincesInState(vic2State, stateOwner, provinceMapper);
const auto initialConnectedProvinceSets = getConnectedProvinceSets(allProvinces, mapData, provinces);
auto finalConnectedProvinceSets =
consolidateProvinceSets(initialConnectedProvinceSets, strategicRegions.getProvinceToStrategicRegionMap());
consolidateProvinceSets(initialConnectedProvinceSets, strategicRegions.GetProvinceToStrategicRegionMap());

for (const auto& connectedProvinces: finalConnectedProvinceSets)
{
Expand Down
2 changes: 1 addition & 1 deletion src/OutHoi4/Map/OutStrategicRegions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void HoI4::outputStrategicRegions(const StrategicRegions& strategicRegions, cons
{
throw std::runtime_error("Could not create output/" + outputName + "/map/strategicregions");
}
for (const auto& strategicRegion: strategicRegions.getStrategicRegions() | std::views::values)
for (const auto& strategicRegion: strategicRegions.GetStrategicRegions() | std::views::values)
{
outputStrategicRegion(strategicRegion, "output/" + outputName + "/map/strategicregions/");
}
Expand Down

0 comments on commit 9213feb

Please sign in to comment.