Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assign unassigned provinces to surrounding strategic regions. #1673

Merged
merged 1 commit into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Idhrendur marked this conversation as resolved.
Show resolved Hide resolved
{
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)
Idhrendur marked this conversation as resolved.
Show resolved Hide resolved
{
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