From 9cf560d03a81da9a8fefb3a21add0b5343b9bcd7 Mon Sep 17 00:00:00 2001 From: Gawquon <71318452+gawquon@users.noreply.github.com> Date: Fri, 3 Mar 2023 02:35:05 -0500 Subject: [PATCH] PM adjustments (#349) * Have to specify default pms * manufactories -> manufacturies * absolute cap on bureacracy generation * account for econ of scale throughput for admin gen * re-add smallestLargeBuilding check * economy of scale corrections * tech based paper * de-pragma * paper - sulphur adjustment * ranges copy_if -> std copy_if to satisfy gnu? * More econ config comments * sulphur nudge * typo --- .../configurables/economy/buildings_map.txt | 3 +- .../configurables/economy/econ_defines.txt | 2 +- .../configurables/economy/national_budget.txt | 76 ++++++++++++++++--- .../economy/production_method_rules.txt | 52 ++++++++++--- .../economy/terrain_econ_modifiers.txt | 9 ++- .../ProductionMethodMapper.cpp | 57 +++++++++----- .../ProductionMethodMapper.h | 3 +- .../EconomyManager/Building/Building.h | 1 + .../V3World/EconomyManager/EconomyManager.cpp | 12 ++- .../Script/MathScript.cpp | 4 + .../Source/V3World/Loaders/TechLoader/Tech.h | 1 + .../V3World/Loaders/TechLoader/TechEntry.cpp | 3 + .../PoliticalManager/Country/Country.cpp | 37 +++++++-- .../PoliticalManager/Country/Country.h | 3 +- .../ProductionMethodMapperTests.cpp | 12 +++ .../MathScriptTests.cpp | 7 ++ .../TechLoaderTests/TechEntryTests.cpp | 2 + 17 files changed, 218 insertions(+), 66 deletions(-) diff --git a/EU4ToVic3/Data_Files/configurables/economy/buildings_map.txt b/EU4ToVic3/Data_Files/configurables/economy/buildings_map.txt index 8676fe80c..46d65cd79 100644 --- a/EU4ToVic3/Data_Files/configurables/economy/buildings_map.txt +++ b/EU4ToVic3/Data_Files/configurables/economy/buildings_map.txt @@ -1,4 +1,5 @@ # NOTE: These do not make more buildings appear, they just adjust State level CP spending priority. +# Meaning States will want to spend a greater portion of their budget on boosted buildings. # EU4 Building -> V3 building(s) it boosts. # Ex. 1 link = { eu4 = building vic3 = { building } } @@ -21,7 +22,7 @@ link = { eu4 = textile vic3 = { building_textile_mills - building_furniture_manufactories + building_furniture_manufacturies } } diff --git a/EU4ToVic3/Data_Files/configurables/economy/econ_defines.txt b/EU4ToVic3/Data_Files/configurables/economy/econ_defines.txt index 55f89cf96..52d9e7a2d 100644 --- a/EU4ToVic3/Data_Files/configurables/economy/econ_defines.txt +++ b/EU4ToVic3/Data_Files/configurables/economy/econ_defines.txt @@ -2,7 +2,7 @@ # They are calibrated based on Vanilla Vic3. # (0 <-> INTMAX) -# Total # of CP in the globe +# Total # of Construction Points(CP) in the globe global_construction_points = 1500000 vn_global_construction_points = 871050 diff --git a/EU4ToVic3/Data_Files/configurables/economy/national_budget.txt b/EU4ToVic3/Data_Files/configurables/economy/national_budget.txt index 30598c251..e6bb8a7b5 100644 --- a/EU4ToVic3/Data_Files/configurables/economy/national_budget.txt +++ b/EU4ToVic3/Data_Files/configurables/economy/national_budget.txt @@ -3,8 +3,31 @@ # Sector weights may be modified by Vic3 laws, colonial status -# The national budget forms the country's opinon of what should be built, -# but still must face the realities of technology/resource availability and the desire of the states. +# The national budget forms the country's opinion of what should be built, but still must face the realities of technology/resource availability and the desire of the states. +# When a state asks to build logging camps, the nation will check if there still is an extraction budget left before giving its assent. +# If the state and the nation can't agree on any building, the state's opinion will win out. The state builds what it wants and takes the cost out of the largest budget remaining. +# This happens most often when there is budget for a resource that just does not exist in a state. + +# State: "I'd like to build a farm." +# Nation: "We're out of farm budget." +# State: "How about a mine?." +# Nation: "Out of mine budget. We have only have whaling budget left. Do you want some whaling wharfs?" +# State: "... I'm a landlocked state, screw you I'm building a farm and our oversized whaling industry is paying for it!" + +# There can be as many or as few sectors as you want, and they must have at minimum a defined non-negative weight and at least one vic3_building. +# Every vic3_building possible to start the game with should belong to one and only one sector. +# example_sector = { +# weight = 4 # Base weight of the sector +# industrial = yes # wieght is modified by civlevel and industry score (see configurables/westernization.txt) +# +# building_1 # Anytime a state builds building_1, the cost is taken from example_sector budget +# building_2 # Anytime a state builds building_2, the cost is taken from example_sector budget +# +# add = { # Modifiers to base weight based on a single trigger. Supports add/multiply +# value = 2 # Value of the addend/multiplier +# vic3_law = law_example_law # Trigger for modifier. Supported triggers are vic3_law, vic3_tech, is_colony, is_trade_company, is_eu4_gp, industry_score_less_than +# } +#} construction = { weight = 0.15 @@ -13,7 +36,7 @@ construction = { } infrastructure = { - weight = 3 + weight = 3.5 building_port building_railway @@ -80,6 +103,15 @@ military_mining = { building_lead_mine building_sulfur_mine + + add = { + value = 1 + is_eu4_gp = yes + } + add = { + value = 0.5 + vic3_tech = mechanical_tools + } } plantation = { @@ -120,13 +152,29 @@ shipwrights = { building_shipyards } +paper_industry = { + weight = 1 + + building_paper_mills + + add = { + value = 7 + vic3_tech = centralization + } + + add = { + value = 7 + vic3_tech = central_archives + } +} + light_industry = { - weight = 21 + weight = 16 building_textile_mills building_furniture_manufacturies building_glassworks - building_paper_mills + # Industry score from configurables/westernization.txt. No effect if no EuroCentrism multiply = { @@ -161,9 +209,9 @@ tooling_industry = { building_tooling_workshops - add = { - value = 2.5 - is_eu4_gp = yes + add = { + value = 2.5 + is_eu4_gp = yes } } @@ -186,8 +234,12 @@ heavy_industry = { building_motor_industry building_munition_plants - add = { - value = 4 - is_eu4_gp = yes - } + add = { + value = 4 + is_eu4_gp = yes + } + multiply = { + value = 0 + industry_score_less_than = 3 + } } \ No newline at end of file diff --git a/EU4ToVic3/Data_Files/configurables/economy/production_method_rules.txt b/EU4ToVic3/Data_Files/configurables/economy/production_method_rules.txt index cbc8a062c..ed8c7d652 100644 --- a/EU4ToVic3/Data_Files/configurables/economy/production_method_rules.txt +++ b/EU4ToVic3/Data_Files/configurables/economy/production_method_rules.txt @@ -2,7 +2,7 @@ # The percent is the percent of building levels that will try to move off of default to adopt the defined PM. It is assumed to be 1(100%) unless specified. # building_government_administration # SPECIAL CASE government administration links will be ignored even if defined. -### Devlopment +##### Development building_port = { pm = { name = pm_basic_port } } @@ -14,7 +14,7 @@ building_naval_base = { pm = { name = pm_power_of_the_purse } } -### Urban +##### Urban building_tooling_workshops = { pm = { name = pm_pig_iron } } @@ -22,11 +22,15 @@ building_glassworks = { pm = { name = pm_leaded_glass } } building_paper_mills = { - pm = { name = pm_sulfite_pulping } + pm = { name = pm_sulfite_pulping percent = 0.4 } } -building_furniture_manufactories = { +building_furniture_manufacturies = { pm = { name = pm_lathe } - pm = { name = pm_luxury_furniture percent = 0.5} + pm = { name = pm_luxury_furniture percent = 0.5 } +} +building_textile_mills = { + pm = { name = pm_dye_workshops percent = 0.05 } + pm = { name = pm_craftsman_sewing percent = 0.1 } } building_shipyards = { pm = { name = pm_military_shipbuilding_wooden } @@ -41,13 +45,37 @@ building_chemical_plants = { pm = { name = pm_leblanc_process } } -### Rural +##### Rural building_logging_camp = { pm = { name = pm_saw_mills } - pm = { name = pm_hardwood percent = 0.33 } + pm = { name = pm_hardwood percent = 0.4 } +} +### Farms +building_rye_farm = { + pm = { name = pm_potatoes percent = 0.15 } +} +building_wheat_farm = { + pm = { name = pm_citrus_orchards percent = 0.2 } +} +building_millet_farm = { + pm = { name = pm_fig_orchards percent = 0.2 } +} +building_maize_farm = { + pm = { name = pm_citrus_orchards percent = 0.2 } +} +building_rice_farm = { + pm = { name = pm_fig_orchards percent = 0.1 } +} +### Mines +building_coal_mine = { + pm = { name = pm_atmospheric_engine_pump_building_coal_mine } +} +building_iron_mine = { + pm = { name = pm_atmospheric_engine_pump_building_iron_mine } +} +building_gold_mine = { + pm = { name = pm_atmospheric_engine_pump_building_gold_mine } +} +building_sulfur_mine = { + pm = { name = pm_atmospheric_engine_pump_building_sulfur_mine } } - -# Farms need more code support due to clashing pm names -#building_rye_farm = { -# pm = { name = pm_potatoes percent = 0.15 } -#} \ No newline at end of file diff --git a/EU4ToVic3/Data_Files/configurables/economy/terrain_econ_modifiers.txt b/EU4ToVic3/Data_Files/configurables/economy/terrain_econ_modifiers.txt index 253453b22..98ab130f4 100644 --- a/EU4ToVic3/Data_Files/configurables/economy/terrain_econ_modifiers.txt +++ b/EU4ToVic3/Data_Files/configurables/economy/terrain_econ_modifiers.txt @@ -21,11 +21,12 @@ coastal = { building_shipyards = 0.2 building_tooling_workshops = 0.2 building_textile_mills = 0.2 - building_furniture_manufactories = 0.2 + building_furniture_manufacturies = 0.15 building_university = 0.2 building_glassworks = 0.1 building_paper_mills = 0.1 building_logging_camp = 0.1 + building_steel_mills = 0.02 } desert = { @@ -46,7 +47,7 @@ forest = { priority = 0.1 building_paper_mills = 0.3 - building_furniture_manufactories = 0.2 + building_furniture_manufacturies = 0.05 building_arms_industry = 0.15 building_shipyards = 0.1 building_glassworks = 0.1 @@ -54,6 +55,7 @@ forest = { building_university = 0.05 building_logging_camp = 0.7 building_fishing_wharf = 0.1 + building_munition_plants = 0.05 } hills = { @@ -96,7 +98,6 @@ mountain = { building_coal_mine = 0.7 building_gold_mine = 1 building_opium_plantation = 0.3 - building_chemical_plants = 0.1 building_munition_plants = 0.05 building_arts_academy = 0.3 building_tooling_workshops = 0.2 @@ -120,7 +121,7 @@ plains = { building_cotton_plantation = 0.3 building_silk_plantation = 0.3 building_tea_plantation = 0.3 - building_furniture_manufactories = 0.2 + building_furniture_manufacturies = 0.2 building_barracks = 0.2 building_railway = 0.1 building_food_industry = 0.1 diff --git a/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.cpp b/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.cpp index 0093406ed..094b08e41 100644 --- a/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.cpp +++ b/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.cpp @@ -46,11 +46,20 @@ void mappers::ProductionMethodMapper::applyRules(const V3::Country& country, for (const auto& rule: buildingToRules.at(buildingType)) { auto selectedBuildings = pickBuildings(builtBuildings, rule.percent); - const std::string selectedPM = pickPM(country, rule.pm, PMs, PMGroups); // select PM + if (selectedBuildings.empty()) + continue; + + const auto& buildingPMGroups = selectedBuildings[0]->getPMGroups(); + const auto [defaultPM, selectedPM] = pickPM(country, rule.pm, buildingPMGroups, PMs, PMGroups); // select PM // For each building in the vector, add the PMs to it - for (const auto& selectedBuilding: selectedBuildings) - selectedBuilding->addPM(selectedPM); + for (const auto& builtBuilding: builtBuildings) + { + if (std::ranges::find(selectedBuildings, builtBuilding) != selectedBuildings.end()) + builtBuilding->addPM(selectedPM); + else + builtBuilding->addPM(defaultPM); + } } } } @@ -101,7 +110,7 @@ std::vector> mappers::ProductionMethodMapper::pick // Select all buildings with level <= target std::vector> selectedBuildings; std::copy_if(buildings.begin(), buildings.end(), std::back_inserter(selectedBuildings), [target](const std::shared_ptr& building) { - return building->getLevel() <= target; + return building->getLevel() <= target && building->getLevel() > 0; }); if (std::accumulate(selectedBuildings.begin(), selectedBuildings.end(), 0, sumBuildingLevels) > target) @@ -111,32 +120,35 @@ std::vector> mappers::ProductionMethodMapper::pick // Now return either selectedBuildings, or a single building if the sum of selectedBuildings // is further from target than the smallest building larger than target. - std::shared_ptr smallestLargerBuilding = nullptr; - int smallestLargerBuildingLevel = INT_MAX; + + // Get smallest building larger than the target number + int smallestLargeBuildingLevel = INT_MAX; + std::shared_ptr smallestLargeBuilding = nullptr; for (const auto& building: buildings) { - if (building->getLevel() > target && building->getLevel() < smallestLargerBuildingLevel) + if (building->getLevel() > target && building->getLevel() < smallestLargeBuildingLevel) { - smallestLargerBuilding = building; - smallestLargerBuildingLevel = building->getLevel(); + smallestLargeBuildingLevel = building->getLevel(); + smallestLargeBuilding = building; } } - if (smallestLargerBuilding) + if (!smallestLargeBuilding) + return selectedBuildings; + const int selectedSum = std::accumulate(selectedBuildings.begin(), selectedBuildings.end(), 0, sumBuildingLevels); + if (smallestLargeBuildingLevel - target < std::abs(target - selectedSum)) { - if (smallestLargerBuildingLevel - target < target - std::accumulate(selectedBuildings.begin(), selectedBuildings.end(), 0, sumBuildingLevels)) - { - selectedBuildings.clear(); - selectedBuildings.push_back(smallestLargerBuilding); - } + selectedBuildings.clear(); + selectedBuildings.push_back(smallestLargeBuilding); } return selectedBuildings; } -std::string mappers::ProductionMethodMapper::pickPM(const V3::Country& country, +std::pair mappers::ProductionMethodMapper::pickPM(const V3::Country& country, const std::string& targetName, + const std::set& buildingPMGroups, const std::map& PMs, const std::map& PMGroups) { @@ -144,6 +156,11 @@ std::string mappers::ProductionMethodMapper::pickPM(const V3::Country& country, // This is just a basic version that will support every use-case we currently care about. for (const auto& PMGroup: PMGroups | std::views::values) { + if (!buildingPMGroups.contains(PMGroup.getName())) + { + continue; // We're only checking PMGroups that are present in the building we're working on + } + if (std::ranges::find(PMGroup.getPMs(), targetName) != PMGroup.getPMs().end()) { // Validate every PM in group @@ -152,7 +169,7 @@ std::string mappers::ProductionMethodMapper::pickPM(const V3::Country& country, if (!PMs.contains(PM)) { Log(LogLevel::Error) << "Unknown PM: " << PM << "."; - return ""; + return {"", ""}; } } @@ -161,9 +178,9 @@ std::string mappers::ProductionMethodMapper::pickPM(const V3::Country& country, for (auto PM: PMGroup.getPMs()) { if (!country.hasAnyOfTech(PMs.at(PM).getUnlockingTechs())) - return pick; + return {PMGroup.getPMs()[0], pick}; if (PM == targetName) - return PM; + return {PMGroup.getPMs()[0], PM}; pick = PM; } } @@ -171,7 +188,7 @@ std::string mappers::ProductionMethodMapper::pickPM(const V3::Country& country, Log(LogLevel::Error) << "Could not find a PM group for PM: " << targetName << "."; - return ""; + return {"", ""}; } ////////////////////////////////////////// Subset-sum fxns diff --git a/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.h b/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.h index ee5af8889..7ae82d5d4 100644 --- a/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.h +++ b/EU4ToVic3/Source/Mappers/BuildingMapper/ProductionMethodMapper/ProductionMethodMapper.h @@ -31,8 +31,9 @@ class ProductionMethodMapper: commonItems::parser [[nodiscard]] static std::set getCountryBuildingTypes(const V3::Country& country); [[nodiscard]] static std::vector> getBuiltBuildings(const V3::Country& country, const std::string& buildingType); [[nodiscard]] static std::vector> pickBuildings(const std::vector>& buildings, double percent); - [[nodiscard]] static std::string pickPM(const V3::Country& country, + [[nodiscard]] static std::pair pickPM(const V3::Country& country, const std::string& targetName, + const std::set& buildingPMGroups, const std::map& PMs, const std::map& PMGroups); diff --git a/EU4ToVic3/Source/V3World/EconomyManager/Building/Building.h b/EU4ToVic3/Source/V3World/EconomyManager/Building/Building.h index c1700b985..2e9060a7d 100644 --- a/EU4ToVic3/Source/V3World/EconomyManager/Building/Building.h +++ b/EU4ToVic3/Source/V3World/EconomyManager/Building/Building.h @@ -13,6 +13,7 @@ class Building: commonItems::parser void setLevel(const int theLevel) { level = theLevel; } void setWeight(const double theWeight) { weight = theWeight; } void addPM(const std::string& pm) { PMs.emplace(pm); } + void setPMGroups(const std::set& pmgs) { PMGroups = pmgs; } [[nodiscard]] const auto& getName() const { return name; } [[nodiscard]] const auto& getBuildingGroup() const { return buildingGroup; } diff --git a/EU4ToVic3/Source/V3World/EconomyManager/EconomyManager.cpp b/EU4ToVic3/Source/V3World/EconomyManager/EconomyManager.cpp index 28a28b29d..f41f83b0f 100644 --- a/EU4ToVic3/Source/V3World/EconomyManager/EconomyManager.cpp +++ b/EU4ToVic3/Source/V3World/EconomyManager/EconomyManager.cpp @@ -74,8 +74,9 @@ void V3::EconomyManager::establishBureaucracy(const PoliticalManager& politicalM continue; } - // Give 5% extra for trade routes - const double generationTarget = country->calculateBureaucracyUsage(politicalManager.getLawsMap()) * 1.05; + // Give 5% extra for trade routes - cap at +400 + const double usage = country->calculateBureaucracyUsage(politicalManager.getLawsMap()); + const double generationTarget = std::min(usage * 1.05, usage + 400) - 100; // Use the PM with the most generation available int PMGeneration = 35; @@ -85,10 +86,7 @@ void V3::EconomyManager::establishBureaucracy(const PoliticalManager& politicalM PMGeneration = PMs.at(PMName).getBureaucracy(); } - // find # of buildings, 100 base value generation - const int numAdmins = static_cast(std::ceil((generationTarget - 100) / PMGeneration)); - - country->distributeGovAdmins(numAdmins); + country->distributeGovAdmins(generationTarget, PMGeneration, techMap.getTechs()); } Log(LogLevel::Info) << "<> Bureaucracy Established."; } @@ -109,8 +107,8 @@ void V3::EconomyManager::hardcodePorts() const auto port = std::make_shared(); port->setName("building_port"); + port->setPMGroups({"pmg_base_building_port"}); port->setLevel(1); - port->addPM("pm_basic_port"); // Until PM setting is off the ground subState->addBuilding(port); ++counter; diff --git a/EU4ToVic3/Source/V3World/Loaders/NationalBudgetLoader/Script/MathScript.cpp b/EU4ToVic3/Source/V3World/Loaders/NationalBudgetLoader/Script/MathScript.cpp index 814a0277e..dc0a280fe 100644 --- a/EU4ToVic3/Source/V3World/Loaders/NationalBudgetLoader/Script/MathScript.cpp +++ b/EU4ToVic3/Source/V3World/Loaders/NationalBudgetLoader/Script/MathScript.cpp @@ -37,6 +37,10 @@ bool V3::MathScript::isValid(const Country& country) const { return country.getProcessedData().laws.contains(triggerValue); } + if (trigger == "vic3_tech") + { + return country.getProcessedData().techs.contains(triggerValue); + } if (trigger == "is_eu4_gp") { return country.getSourceCountry()->isGP() == (triggerValue == "yes"); diff --git a/EU4ToVic3/Source/V3World/Loaders/TechLoader/Tech.h b/EU4ToVic3/Source/V3World/Loaders/TechLoader/Tech.h index 6a2f176a4..7264f4550 100644 --- a/EU4ToVic3/Source/V3World/Loaders/TechLoader/Tech.h +++ b/EU4ToVic3/Source/V3World/Loaders/TechLoader/Tech.h @@ -7,6 +7,7 @@ struct Tech { int infrastructureMax = 0; double infrastructureMult = 0.0; + int throughputMax = 0; std::map maxBuildingLevels; }; } // namespace V3 diff --git a/EU4ToVic3/Source/V3World/Loaders/TechLoader/TechEntry.cpp b/EU4ToVic3/Source/V3World/Loaders/TechLoader/TechEntry.cpp index d99ba80c4..fa7c26b8a 100644 --- a/EU4ToVic3/Source/V3World/Loaders/TechLoader/TechEntry.cpp +++ b/EU4ToVic3/Source/V3World/Loaders/TechLoader/TechEntry.cpp @@ -35,5 +35,8 @@ void V3::TechEntry::registerKeys() Log(LogLevel::Error) << "Found a max level modifier, but could not parse it: " << modifier; } }); + modifierParser.registerKeyword("building_economy_of_scale_level_cap_add", [this](std::istream& theStream) { + tech.throughputMax = commonItems::getInt(theStream); + }); modifierParser.registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); } diff --git a/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.cpp b/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.cpp index 534c55bf1..970fccc48 100644 --- a/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.cpp +++ b/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.cpp @@ -102,6 +102,18 @@ double V3::Country::getTechInfraMult(const std::map& techMap) }); } +int V3::Country::getThroughputMax(const std::map& techMap) const +{ + // 20 is base level Economy of Scale NOT a define. + return 20 + std::accumulate(processedData.techs.begin(), processedData.techs.end(), 0, [this, techMap](int sum, const std::string& techName) { + if (const auto& tech = getTechFromMap(techName, techMap); tech) + { + return sum + tech.value().throughputMax; + } + return sum; + }); +} + bool V3::Country::hasAnyOfTech(const std::set& techs) const { if (techs.empty()) @@ -146,27 +158,38 @@ int V3::Country::getGovBuildingMax(const std::string& building, const std::map& techMap) const { const auto topSubstates = topPercentileStatesByPop(0.3); const auto topPop = getPopCount(topSubstates); - // Pass out buildings by pop proportion of this subset of States, can't round, so truncate and hand out remainders later. - int assigned = 0; + // Pass out buildings by pop proportion of this subset of States. Generate production targets and account for throughput bonuses. + double generated = 0; for (const auto& substate: topSubstates) { const double popProportion = static_cast(substate->getSubStatePops().getPopCount()) / topPop; - const int levels = static_cast(popProportion * numGovAdmins); + const double stateTarget = target * popProportion; + + // Calc levels for generation + int levels = static_cast(stateTarget * 100 / 101 / PMGeneration); + double generation = levels * PMGeneration; + if (const int throughputMax = getThroughputMax(techMap); levels > throughputMax) + { + levels = static_cast(stateTarget / (PMGeneration + PMGeneration * (throughputMax / 100.0))); + generation = levels * PMGeneration * (1 + throughputMax / 100.0); + } const auto govAdmin = std::make_shared(); govAdmin->setName("building_government_administration"); govAdmin->setLevel(levels); substate->addBuilding(govAdmin); - assigned += levels; + + generated += generation; } // Handing out remainders, should be less than # of topSubstates + // Treating throughput bonuses as negligible here for (const auto& substate: topSubstates) { auto isGovAdmin = [](const std::shared_ptr& b) { @@ -177,9 +200,9 @@ void V3::Country::distributeGovAdmins(const int numGovAdmins) const { const auto levels = govAdmin->get()->getLevel(); govAdmin->get()->setLevel(levels + 1); - ++assigned; + generated += PMGeneration; - if (numGovAdmins - assigned <= 0) + if (target <= generated + PMGeneration) { break; } diff --git a/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.h b/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.h index 832dd2bdc..9902d3853 100644 --- a/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.h +++ b/EU4ToVic3/Source/V3World/PoliticalManager/Country/Country.h @@ -194,12 +194,13 @@ class Country: commonItems::parser [[nodiscard]] static double yearCapFactor(const date& targetDate); [[nodiscard]] int getTechInfraCap(const std::map& techMap) const; [[nodiscard]] double getTechInfraMult(const std::map& techMap) const; + [[nodiscard]] int getThroughputMax(const std::map& techMap) const; [[nodiscard]] bool hasAnyOfTech(const std::set& techs) const; [[nodiscard]] int getGovBuildingMax(const std::string& building, const std::map& lawsMap, const std::map& techMap) const; - void distributeGovAdmins(int numGovAdmins) const; + void distributeGovAdmins(double target, int PMGeneration, const std::map& techMap) const; [[nodiscard]] std::vector> topPercentileStatesByPop(double percentile) const; [[nodiscard]] double calculateBureaucracyUsage(const std::map& lawsMap) const; void addSector(const std::string& sectorName, const std::shared_ptr& sector) { processedData.industrySectors.emplace(sectorName, sector); } diff --git a/EU4ToVic3Tests/MapperTests/BuildingMapperTests/ProductionMethodMapperTests.cpp b/EU4ToVic3Tests/MapperTests/BuildingMapperTests/ProductionMethodMapperTests.cpp index ac1e3b397..ac025576d 100644 --- a/EU4ToVic3Tests/MapperTests/BuildingMapperTests/ProductionMethodMapperTests.cpp +++ b/EU4ToVic3Tests/MapperTests/BuildingMapperTests/ProductionMethodMapperTests.cpp @@ -41,6 +41,13 @@ auto sumForestry = [](const int sum, const std::shared_ptr s) { return sum + s->getBuildings()[0]->getLevel(); // Only built logging camps return sum; }; + +// Building pmgs +const std::set lumberPmgs = {"pmg_base_building_logging_camp", + "pmg_hardwood", + "pmg_equipment", + "pmg_transportation_building_logging_camp", + "pmg_ownership_capital_building_logging_camp"}; } // namespace TEST(Mappers_ProductionMethodMapperTests, RulesCanBeLoaded) @@ -70,6 +77,7 @@ TEST(Mappers_ProductionMethodMapperTests, ApplyRules) auto subState = std::make_shared(); auto lumberCamp = std::make_shared(); lumberCamp->setName("building_logging_camp"); + lumberCamp->setPMGroups(lumberPmgs); lumberCamp->setLevel(lvl); subState->addBuilding(lumberCamp); country.addSubState(subState); @@ -95,6 +103,7 @@ TEST(Mappers_ProductionMethodMapperTests, ApplyRulesInexactOverClosest) auto subState = std::make_shared(); auto lumberCamp = std::make_shared(); lumberCamp->setName("building_logging_camp"); + lumberCamp->setPMGroups(lumberPmgs); lumberCamp->setLevel(lvl); subState->addBuilding(lumberCamp); country.addSubState(subState); @@ -119,6 +128,7 @@ TEST(Mappers_ProductionMethodMapperTests, ApplyRulesInexactUnderClosest) auto subState = std::make_shared(); auto lumberCamp = std::make_shared(); lumberCamp->setName("building_logging_camp"); + lumberCamp->setPMGroups(lumberPmgs); lumberCamp->setLevel(lvl); subState->addBuilding(lumberCamp); country.addSubState(subState); @@ -143,6 +153,7 @@ TEST(Mappers_ProductionMethodMapperTests, ApplyRulesSmallestLargeBuildingIsClose auto subState = std::make_shared(); auto lumberCamp = std::make_shared(); lumberCamp->setName("building_logging_camp"); + lumberCamp->setPMGroups(lumberPmgs); lumberCamp->setLevel(lvl); subState->addBuilding(lumberCamp); country.addSubState(subState); @@ -167,6 +178,7 @@ TEST(Mappers_ProductionMethodMapperTests, ApplyRulesUnderTeched) auto subState = std::make_shared(); auto lumberCamp = std::make_shared(); lumberCamp->setName("building_logging_camp"); + lumberCamp->setPMGroups(lumberPmgs); lumberCamp->setLevel(lvl); subState->addBuilding(lumberCamp); country.addSubState(subState); diff --git a/EU4ToVic3Tests/V3WorldTests/LoaderTests/NationalBudgetLoaderTests/MathScriptTests.cpp b/EU4ToVic3Tests/V3WorldTests/LoaderTests/NationalBudgetLoaderTests/MathScriptTests.cpp index af3f62459..bf5513c1c 100644 --- a/EU4ToVic3Tests/V3WorldTests/LoaderTests/NationalBudgetLoaderTests/MathScriptTests.cpp +++ b/EU4ToVic3Tests/V3WorldTests/LoaderTests/NationalBudgetLoaderTests/MathScriptTests.cpp @@ -8,6 +8,7 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) { std::stringstream lawInput; + std::stringstream techInput; std::stringstream colonyInput; std::stringstream tcInput; std::stringstream GPInput; @@ -15,6 +16,7 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) std::stringstream invalidInput; lawInput << "\tvic3_law = law_serfdom"; + techInput << "\tvic3_tech = centralization"; colonyInput << "\tis_colony = yes"; tcInput << "\tis_trade_company = yes"; GPInput << "\tis_eu4_gp = yes"; @@ -23,6 +25,8 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) V3::MathScript law; law.loadMathScript(lawInput); + V3::MathScript tech; + tech.loadMathScript(techInput); V3::MathScript colony; colony.loadMathScript(colonyInput); V3::MathScript tc; @@ -38,6 +42,7 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) country.setSourceCountry(std::make_shared()); EXPECT_FALSE(law.isValid(country)); + EXPECT_FALSE(tech.isValid(country)); EXPECT_FALSE(colony.isValid(country)); EXPECT_FALSE(tc.isValid(country)); EXPECT_FALSE(gp.isValid(country)); @@ -47,6 +52,7 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) V3::ProcessedData data; data.laws.emplace("law_serfdom"); + data.techs.emplace("centralization"); data.industryFactor = 0.2; std::stringstream eu4Input; @@ -61,6 +67,7 @@ TEST(V3World_MathScriptTests, MathScriptTriggersAreRecognized) EXPECT_TRUE(law.isValid(country)); + EXPECT_TRUE(tech.isValid(country)); EXPECT_TRUE(colony.isValid(country)); EXPECT_TRUE(tc.isValid(country)); EXPECT_TRUE(gp.isValid(country)); diff --git a/EU4ToVic3Tests/V3WorldTests/LoaderTests/TechLoaderTests/TechEntryTests.cpp b/EU4ToVic3Tests/V3WorldTests/LoaderTests/TechLoaderTests/TechEntryTests.cpp index b08c5bd59..de8c2e2b8 100644 --- a/EU4ToVic3Tests/V3WorldTests/LoaderTests/TechLoaderTests/TechEntryTests.cpp +++ b/EU4ToVic3Tests/V3WorldTests/LoaderTests/TechLoaderTests/TechEntryTests.cpp @@ -19,6 +19,7 @@ TEST(V3World_TechEntryTests, TechCanBeLoaded) input << "\tstate_infrastructure_from_population_max_add = 5\n"; input << "\tstate_building_port_max_level_add = 2\n"; input << "\tstate_building_naval_base_max_level_add = 20\n"; + input << "\tbuilding_economy_of_scale_level_cap_add = 15\n"; input << "}\n "; const V3::TechEntry entry(input); const auto& tech = entry.getTech(); @@ -27,4 +28,5 @@ TEST(V3World_TechEntryTests, TechCanBeLoaded) EXPECT_EQ(5, tech.infrastructureMax); EXPECT_EQ(2, tech.maxBuildingLevels.at("building_port")); EXPECT_EQ(20, tech.maxBuildingLevels.at("building_naval_base")); + EXPECT_EQ(15, tech.throughputMax); }