diff --git a/.github/workflows/bump_version.yml b/.github/workflows/bump_version.yml index 104fcc104..951edcdec 100644 --- a/.github/workflows/bump_version.yml +++ b/.github/workflows/bump_version.yml @@ -14,4 +14,4 @@ jobs: uses: anothrNick/github-tag-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DEFAULT_BUMP: minor \ No newline at end of file + DEFAULT_BUMP: patch \ No newline at end of file diff --git a/Fronter b/Fronter index 8d82cc0ca..afa303df7 160000 --- a/Fronter +++ b/Fronter @@ -1 +1 @@ -Subproject commit 8d82cc0ca634a21e37c96ac252c171fd408e11c3 +Subproject commit afa303df7270cb322ff5e115c90be5ff462d42ab diff --git a/ImperatorToCK3/Data_Files/configurables/succession_law_map.txt b/ImperatorToCK3/Data_Files/configurables/succession_law_map.txt new file mode 100644 index 000000000..3f578b456 --- /dev/null +++ b/ImperatorToCK3/Data_Files/configurables/succession_law_map.txt @@ -0,0 +1,37 @@ +# IMP-CK3 SUCCESSION LAW MAPPINGS # +# link = { imp = [law] ck3 = [law] } +# The CK3 law is output in the title's history +# folder, right after the line defining +# the holder, as succession_laws = { [law] } + +# CK3 has default succession laws + +# For mappings with multiple ck3 laws, all laws will be written out + + +# Monarchy + +link = { imp = agnatic_succession_law ck3 = male_only_law ck3 = single_heir_succession_law } +link = { imp = cognatic_succession_law ck3 = male_preference_law } +link = { imp = agnatic_seniority_succession_law ck3 = single_heir_dynasty_house } +link = { imp = egyption_succession_law ck3 = equal_law } + +# Republic + +link = { imp = republican_election_1 ck3 = city_succession_law } +link = { imp = republican_election_2 ck3 = saxon_elective_succession_law } +link = { imp = republican_election_3 ck3 = city_succession_law } +link = { imp = republican_election_4 ck3 = princely_elective_succession_law } + +# Rome + +link = { imp = leges_genuciae ck3 = city_succession_law } +link = { imp = senatus_consultum_ultimum ck3 = saxon_elective_succession_law } +link = { imp = lex_antonia ck3 = city_succession_law } +link = { imp = princeps_civitatis ck3 = princely_elective_succession_law } + +# Tribal + +link = { imp = personal_loyalty_law ck3 = high_partition_succession_law } +link = { imp = increased_council_powers ck3 = scandinavian_elective_succession_law } +link = { imp = absolute_authority ck3 = gaelic_elective_succession_law } \ No newline at end of file diff --git a/ImperatorToCK3/ImperatorToCK3.vcxproj b/ImperatorToCK3/ImperatorToCK3.vcxproj index 31a0c2860..c1e38a972 100644 --- a/ImperatorToCK3/ImperatorToCK3.vcxproj +++ b/ImperatorToCK3/ImperatorToCK3.vcxproj @@ -295,6 +295,8 @@ + + @@ -392,6 +394,8 @@ + + @@ -533,6 +537,12 @@ $(OutDir)configurables + + + $(OutDir)configurables + $(OutDir)configurables + + diff --git a/ImperatorToCK3/ImperatorToCK3.vcxproj.filters b/ImperatorToCK3/ImperatorToCK3.vcxproj.filters index 4fdf520e6..375c7473a 100644 --- a/ImperatorToCK3/ImperatorToCK3.vcxproj.filters +++ b/ImperatorToCK3/ImperatorToCK3.vcxproj.filters @@ -106,6 +106,9 @@ {8d84171d-cbd1-49e5-aba5-9b0fc315fab3} + + {7daa7234-4e79-4a3a-85f0-2720e6abb08c} + @@ -391,6 +394,12 @@ CK3Outputter + + Mappers\SuccessionLawMapper + + + Mappers\SuccessionLawMapper + @@ -665,6 +674,12 @@ Imperator\Provinces + + Mappers\SuccessionLawMapper + + + Mappers\SuccessionLawMapper + @@ -755,5 +770,8 @@ Resources\configurables + + Resources\configurables + \ No newline at end of file diff --git a/ImperatorToCK3/Source/CK3/CK3World.cpp b/ImperatorToCK3/Source/CK3/CK3World.cpp index 070742531..216925fda 100644 --- a/ImperatorToCK3/Source/CK3/CK3World.cpp +++ b/ImperatorToCK3/Source/CK3/CK3World.cpp @@ -95,7 +95,7 @@ void CK3::World::importImperatorCountries(const Imperator::World& impWorld) { void CK3::World::importImperatorCountry(const std::pair>& country) { // Create a new title auto newTitle = std::make_shared(); - newTitle->initializeFromTag(country.second, localizationMapper, landedTitles, provinceMapper, coaMapper, tagTitleMapper, governmentMapper); + newTitle->initializeFromTag(country.second, localizationMapper, landedTitles, provinceMapper, coaMapper, tagTitleMapper, governmentMapper, successionLawMapper); const auto& name = newTitle->getName(); if (auto titleItr = getTitles().find(name); titleItr!=getTitles().end()) { diff --git a/ImperatorToCK3/Source/CK3/CK3World.h b/ImperatorToCK3/Source/CK3/CK3World.h index d0f6e6a51..eb728e421 100644 --- a/ImperatorToCK3/Source/CK3/CK3World.h +++ b/ImperatorToCK3/Source/CK3/CK3World.h @@ -15,6 +15,7 @@ #include "Mappers/GovernmentMapper/GovernmentMapper.h" #include "Mappers/RegionMapper/CK3RegionMapper.h" #include "Mappers/RegionMapper/ImperatorRegionMapper.h" +#include "Mappers/SuccessionLawMapper/SuccessionLawMapper.h" #include "Character/CK3Character.h" #include "Dynasties/Dynasty.h" #include "Province/CK3Province.h" @@ -78,6 +79,7 @@ class World { mappers::GovernmentMapper governmentMapper; std::shared_ptr<mappers::CK3RegionMapper> ck3RegionMapper; std::shared_ptr<mappers::ImperatorRegionMapper> imperatorRegionMapper; + mappers::SuccessionLawMapper successionLawMapper; TitlesHistory titlesHistory; diff --git a/ImperatorToCK3/Source/CK3/Titles/Title.cpp b/ImperatorToCK3/Source/CK3/Titles/Title.cpp index 892116ebd..6cbae7b69 100644 --- a/ImperatorToCK3/Source/CK3/Titles/Title.cpp +++ b/ImperatorToCK3/Source/CK3/Titles/Title.cpp @@ -6,6 +6,7 @@ #include "Mappers/CoaMapper/CoaMapper.h" #include "Mappers/TagTitleMapper/TagTitleMapper.h" #include "Mappers/GovernmentMapper/GovernmentMapper.h" +#include "Mappers/SuccessionLawMapper/SuccessionLawMapper.h" #include "Log.h" #include "ParserHelpers.h" #include "CommonRegexes.h" @@ -72,8 +73,14 @@ void CK3::Title::registerKeys() { } -void CK3::Title::initializeFromTag(std::shared_ptr<Imperator::Country> theCountry, mappers::LocalizationMapper& localizationMapper, LandedTitles& landedTitles, mappers::ProvinceMapper& provinceMapper, - mappers::CoaMapper& coaMapper, mappers::TagTitleMapper& tagTitleMapper, mappers::GovernmentMapper& governmentMapper) +void CK3::Title::initializeFromTag(std::shared_ptr<Imperator::Country> theCountry, + mappers::LocalizationMapper& localizationMapper, + LandedTitles& landedTitles, + mappers::ProvinceMapper& provinceMapper, + mappers::CoaMapper& coaMapper, + mappers::TagTitleMapper& tagTitleMapper, + mappers::GovernmentMapper& governmentMapper, + mappers::SuccessionLawMapper& successionLawMapper) { importedOrUpdatedFromImperator = true; @@ -115,12 +122,15 @@ void CK3::Title::initializeFromTag(std::shared_ptr<Imperator::Country> theCountr government = governmentMapper.getCK3GovernmentForImperatorGovernment(*imperatorCountry->getGovernment()); // ------------------ determine color - auto colorOpt = imperatorCountry->getColor1(); - if (colorOpt) - color1 = *colorOpt; - colorOpt = imperatorCountry->getColor2(); - if (colorOpt) - color2 = *colorOpt; + const auto& colorOpt1 = imperatorCountry->getColor1(); + if (colorOpt1) + color1 = *colorOpt1; + const auto& colorOpt2 = imperatorCountry->getColor2(); + if (colorOpt2) + color2 = *colorOpt2; + + // determine successions laws + successionLaws = successionLawMapper.getCK3LawsForImperatorLaws(imperatorCountry->getLaws()); // ------------------ determine CoA coa = coaMapper.getCoaForFlagName(imperatorCountry->getFlag()); diff --git a/ImperatorToCK3/Source/CK3/Titles/Title.h b/ImperatorToCK3/Source/CK3/Titles/Title.h index b62399fc8..9fc313b19 100644 --- a/ImperatorToCK3/Source/CK3/Titles/Title.h +++ b/ImperatorToCK3/Source/CK3/Titles/Title.h @@ -25,6 +25,7 @@ class TagTitleMapper; class CoaMapper; class ProvinceMapper; class GovernmentMapper; +class SuccessionLawMapper; } // namespace mappers namespace CK3 { @@ -43,7 +44,9 @@ class Title: commonItems::parser, public std::enable_shared_from_this<Title> mappers::ProvinceMapper& provinceMapper, mappers::CoaMapper& coaMapper, mappers::TagTitleMapper& tagTitleMapper, - mappers::GovernmentMapper& governmentMapper); + mappers::GovernmentMapper& governmentMapper, + mappers::SuccessionLawMapper& successionLawMapper + ); void updateFromTitle(const std::shared_ptr<Title>& otherTitle); void loadTitles(std::istream& theStream); @@ -55,6 +58,7 @@ class Title: commonItems::parser, public std::enable_shared_from_this<Title> void setDeFactoLiege(const std::shared_ptr<Title>& liegeTitle); [[nodiscard]] const auto& getName() const { return titleName; } + [[nodiscard]] const auto& getSuccessionLaws() const { return successionLaws; } [[nodiscard]] auto isImportedOrUpdatedFromImperator() const { return importedOrUpdatedFromImperator; } [[nodiscard]] const auto& getDeJureLiege() const { return deJureLiege; } @@ -98,6 +102,7 @@ class Title: commonItems::parser, public std::enable_shared_from_this<Title> void trySetAdjectiveLoc(mappers::LocalizationMapper& localizationMapper); std::string titleName; // e.g. d_latium + std::set<std::string> successionLaws; bool importedOrUpdatedFromImperator = false; std::optional<commonItems::Color> color1; diff --git a/ImperatorToCK3/Source/CK3Outputter/outTitles.cpp b/ImperatorToCK3/Source/CK3Outputter/outTitles.cpp index 95730b6e6..02fe783a8 100644 --- a/ImperatorToCK3/Source/CK3Outputter/outTitles.cpp +++ b/ImperatorToCK3/Source/CK3Outputter/outTitles.cpp @@ -23,7 +23,16 @@ void CK3::outputTitleHistory(const std::shared_ptr<Title>& title, std::ofstream& if (title->government) outputStream << "\t\tgovernment = " << *title->government << "\n"; - + + const auto& succLaws = title->getSuccessionLaws(); + if (!succLaws.empty()) { + outputStream << "\t\tsuccession_laws = {\n"; + for (const auto& law : succLaws) { + outputStream << "\t\t\t" << law << "\n"; + } + outputStream << "\t\t}\n"; + } + outputStream << "\t}\n"; } outputStream << "}\n"; diff --git a/ImperatorToCK3/Source/CK3Outputter/outVersion.cpp b/ImperatorToCK3/Source/CK3Outputter/outVersion.cpp index 618a9299e..d1449980a 100644 --- a/ImperatorToCK3/Source/CK3Outputter/outVersion.cpp +++ b/ImperatorToCK3/Source/CK3Outputter/outVersion.cpp @@ -13,7 +13,7 @@ std::ostream& mappers::operator<<(std::ostream& output, const VersionParser& ver output << "\n\n"; output << "************ -= The Paradox Converters Team =- ********************\n"; - output << "* Converter build based on commit " << commitID << "\"\n"; + output << "* Converter build based on commit " << commitID << "\n"; output << "* " << versionParser.descriptionLine << "\n"; output << "* Built on " << __TIMESTAMP__ << "\n"; output << "*********** + Imperator: Rome To Crusader Kings III + **************\n"; diff --git a/ImperatorToCK3/Source/Imperator/Countries/Country.cpp b/ImperatorToCK3/Source/Imperator/Countries/Country.cpp index e5c048dce..365680ddb 100644 --- a/ImperatorToCK3/Source/Imperator/Countries/Country.cpp +++ b/ImperatorToCK3/Source/Imperator/Countries/Country.cpp @@ -2,6 +2,15 @@ +const std::set<std::string>& Imperator::Country::getLaws() const { + if (governmentType == GovernmentType::monarchy) + return monarchyLaws; + else if (governmentType == GovernmentType::republic) + return republicLaws; + else // governmentType == GovernmentType::tribal + return tribalLaws; +} + Imperator::countryRankEnum Imperator::Country::getCountryRank() const { if (provinceCount == 0) return countryRankEnum::migrantHorde; if (provinceCount == 1) return countryRankEnum::cityState; diff --git a/ImperatorToCK3/Source/Imperator/Countries/Country.h b/ImperatorToCK3/Source/Imperator/Countries/Country.h index b3abad6af..6bf376b8b 100644 --- a/ImperatorToCK3/Source/Imperator/Countries/Country.h +++ b/ImperatorToCK3/Source/Imperator/Countries/Country.h @@ -32,53 +32,60 @@ enum class countryRankEnum { migrantHorde, cityState, localPower, regionalPower, class Family; class Province; class Country { - public: - class Factory; - Country() = default; - - [[nodiscard]] auto getID() const { return ID; } - [[nodiscard]] auto getMonarch() const { return monarch; } - [[nodiscard]] const std::string& getTag() const { return tag; } - [[nodiscard]] const auto& getName() const { return name; } - [[nodiscard]] const auto& getFlag() const { return flag; } - [[nodiscard]] const auto& getCountryType() const { return countryType; } - [[nodiscard]] const auto& getCapital() const { return capital; } - [[nodiscard]] const auto& getGovernment() const { return government; } - [[nodiscard]] const auto& getCurrencies() const { return currencies; } - [[nodiscard]] const auto& getColor1() const { return color1; } - [[nodiscard]] const auto& getColor2() const { return color2; } - [[nodiscard]] const auto& getColor3() const { return color3; } - [[nodiscard]] const auto& getFamilies() const { return families; } - [[nodiscard]] const auto& getCK3Title() const { return ck3Title; } - - [[nodiscard]] countryRankEnum getCountryRank() const; - - void setFamilies(const std::map<unsigned long long, std::shared_ptr<Family>>& newFamilies) { families = newFamilies; } - - void registerProvince(const std::shared_ptr<Province>& province) { provinces.insert(province); ++provinceCount; } - void setCK3Title(const std::shared_ptr<CK3::Title>& theTitle) { ck3Title = theTitle; } - - private: - uint64_t ID = 0; - std::optional<unsigned long long> monarch; // >=0 are valid - std::string tag; - std::string name; - std::string flag; - countryTypeEnum countryType = countryTypeEnum::real; - std::optional<unsigned long long> capital; - std::optional<std::string> government; +public: + class Factory; + Country() = default; + + enum class GovernmentType { monarchy, republic, tribal }; + + [[nodiscard]] auto getID() const { return ID; } + [[nodiscard]] auto getMonarch() const { return monarch; } + [[nodiscard]] const std::string& getTag() const { return tag; } + [[nodiscard]] const auto& getName() const { return name; } + [[nodiscard]] const auto& getFlag() const { return flag; } + [[nodiscard]] const auto& getCountryType() const { return countryType; } + [[nodiscard]] const auto& getCapital() const { return capital; } + [[nodiscard]] const auto& getGovernment() const { return government; } + [[nodiscard]] const std::set<std::string>& getLaws() const; + [[nodiscard]] const auto& getCurrencies() const { return currencies; } + [[nodiscard]] const auto& getColor1() const { return color1; } + [[nodiscard]] const auto& getColor2() const { return color2; } + [[nodiscard]] const auto& getColor3() const { return color3; } + [[nodiscard]] const auto& getFamilies() const { return families; } + [[nodiscard]] const auto& getCK3Title() const { return ck3Title; } + + [[nodiscard]] countryRankEnum getCountryRank() const; + + void setFamilies(const std::map<unsigned long long, std::shared_ptr<Family>>& newFamilies) { families = newFamilies; } + + void registerProvince(const std::shared_ptr<Province>& province) { provinces.insert(province); ++provinceCount; } + void setCK3Title(const std::shared_ptr<CK3::Title>& theTitle) { ck3Title = theTitle; } + +private: + uint64_t ID = 0; + std::optional<unsigned long long> monarch; // >=0 are valid + std::string tag; + std::string name; + std::string flag; + countryTypeEnum countryType = countryTypeEnum::real; + std::optional<unsigned long long> capital; + std::optional<std::string> government; + GovernmentType governmentType = GovernmentType::monarchy; + std::set<std::string> monarchyLaws; + std::set<std::string> republicLaws; + std::set<std::string> tribalLaws; + + std::optional<commonItems::Color> color1; + std::optional<commonItems::Color> color2; + std::optional<commonItems::Color> color3; + CurrenciesStruct currencies; + + std::map<unsigned long long, std::shared_ptr<Family>> families; - std::optional<commonItems::Color> color1; - std::optional<commonItems::Color> color2; - std::optional<commonItems::Color> color3; - CurrenciesStruct currencies; + std::set<std::shared_ptr<Province>> provinces; + unsigned int provinceCount = 0; // used to determine country rank - std::map<unsigned long long, std::shared_ptr<Family>> families; - - std::set<std::shared_ptr<Province>> provinces; - unsigned int provinceCount = 0; // used to determine country rank - - std::shared_ptr<CK3::Title> ck3Title; + std::shared_ptr<CK3::Title> ck3Title; }; } // namespace Imperator diff --git a/ImperatorToCK3/Source/Imperator/Countries/CountryFactory.cpp b/ImperatorToCK3/Source/Imperator/Countries/CountryFactory.cpp index 7fbee22e5..227e3ec59 100644 --- a/ImperatorToCK3/Source/Imperator/Countries/CountryFactory.cpp +++ b/ImperatorToCK3/Source/Imperator/Countries/CountryFactory.cpp @@ -7,6 +7,20 @@ + +std::string monarchyLawRegexStr = "succession_law|monarchy_military_reforms|monarchy_maritime_laws|monarchy_economic_law|monarchy_citizen_law" +"|monarchy_religious_laws|monarchy_legitimacy_laws|monarchy_contract_law|monarchy_divinity_statutes|jewish_monarchy_divinity_statutes|monarchy_subject_laws"; +std::string republicLawRegexStr = "republic_military_recruitment_laws_rom|republic_election_reforms_rom|corruption_laws_rom|republican_mediterranean_laws_rom|republican_religious_laws_rom|republic_integration_laws_rom|republic_citizen_laws_rom|republican_land_reforms_rom" +"|republic_military_recruitment_laws|republic_election_reforms|corruption_laws|republican_mediterranean_laws|republican_religious_laws|republic_integration_laws|republic_citizen_laws|republican_land_reforms"; +std::string tribalLawRegexStr = "tribal_religious_law|tribal_currency_laws|tribal_centralization_law|tribal_authority_laws|tribal_autonomy_laws|tribal_domestic_laws" +"|tribal_decentralized_laws|tribal_centralized_laws|tribal_super_decentralized_laws|tribal_super_centralized_laws"; + + +std::set<std::string> monarchyGovernments{ "dictatorship", "despotic_monarchy", "aristocratic_monarchy", "stratocratic_monarchy", "theocratic_monarchy", "plutocratic_monarchy", "imperium", "imperial_cult" }; +std::set<std::string> republicGovernments{ "aristocratic_republic", "theocratic_republic", "oligarchic_republic", "democratic_republic", "plutocratic_republic", "athenian_republic" }; +std::set<std::string> tribalGovernments{ "tribal_chiefdom", "tribal_kingdom", "tribal_federation" }; + + Imperator::Country::Factory::Factory() { registerKeyword("tag", [this](std::istream& theStream){ country->tag = commonItems::getString(theStream); @@ -29,8 +43,7 @@ Imperator::Country::Factory::Factory() { country->countryType = countryTypeEnum::mercenaries; else if (countryTypeStr == "real") country->countryType = countryTypeEnum::real; - else - { + else { Log(LogLevel::Error) << "Unrecognized country type: " << countryTypeStr << ", defaulting to real."; country->countryType = countryTypeEnum::real; } @@ -61,7 +74,15 @@ Imperator::Country::Factory::Factory() { country->capital = capitalProvID; }); registerKeyword("government_key", [this](std::istream& theStream) { - country->government = commonItems::getString(theStream); + auto governmentStr = commonItems::getString(theStream); + country->government = governmentStr; + // set government type + if (monarchyGovernments.contains(governmentStr)) + country->governmentType = GovernmentType::monarchy; + else if (republicGovernments.contains(governmentStr)) + country->governmentType = GovernmentType::republic; + else if (tribalGovernments.contains(governmentStr)) + country->governmentType = GovernmentType::tribal; }); registerKeyword("family", [this](std::istream& theStream) { country->families.emplace(commonItems::getULlong(theStream), nullptr); @@ -72,6 +93,15 @@ Imperator::Country::Factory::Factory() { registerKeyword("monarch", [this](std::istream& theStream) { country->monarch = commonItems::getULlong(theStream); }); + registerRegex(monarchyLawRegexStr, [this](const std::string& unused, std::istream& theStream) { + country->monarchyLaws.emplace(commonItems::getString(theStream)); + }); + registerRegex(republicLawRegexStr, [this](const std::string& unused, std::istream& theStream) { + country->republicLaws.emplace(commonItems::getString(theStream)); + }); + registerRegex(tribalLawRegexStr, [this](const std::string& unused, std::istream& theStream) { + country->tribalLaws.emplace(commonItems::getString(theStream)); + }); registerMatcher(commonItems::catchallRegexMatch, commonItems::ignoreItem); } diff --git a/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.cpp b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.cpp new file mode 100644 index 000000000..226442ef3 --- /dev/null +++ b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.cpp @@ -0,0 +1,49 @@ +#include "SuccessionLawMapper.h" +#include "SuccessionLawMapping.h" +#include "Log.h" +#include "ParserHelpers.h" +#include "CommonRegexes.h" + + + +mappers::SuccessionLawMapper::SuccessionLawMapper() { + LOG(LogLevel::Info) << "-> Parsing succession law mappings."; + registerKeys(); + parseFile("configurables/succession_law_map.txt"); + clearRegisteredKeywords(); + LOG(LogLevel::Info) << "<> Loaded " << impToCK3SuccessionLawMap.size() << " succession law links."; +} + + +mappers::SuccessionLawMapper::SuccessionLawMapper(std::istream& theStream) { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); +} + + +void mappers::SuccessionLawMapper::registerKeys() { + registerKeyword("link", [this](std::istream& theStream) { + const SuccessionLawMapping mapping(theStream); + if (mapping.ck3SuccessionLaws.empty()) + throw std::runtime_error("SuccessionLawMapper: link with no CK3 successions laws"); + + auto [iterator, inserted] = impToCK3SuccessionLawMap.emplace(mapping.impLaw, mapping.ck3SuccessionLaws); + if (!inserted) { + iterator->second.insert(mapping.ck3SuccessionLaws.begin(), mapping.ck3SuccessionLaws.end()); + } + }); + registerMatcher(commonItems::catchallRegexMatch, commonItems::ignoreItem); +} + + +std::set<std::string> mappers::SuccessionLawMapper::getCK3LawsForImperatorLaws(const std::set<std::string>& laws) const { + std::set<std::string> lawsToReturn; + for (const auto& impLaw : laws) { + const auto& mapItr = impToCK3SuccessionLawMap.find(impLaw); + if (mapItr != impToCK3SuccessionLawMap.end()) { + lawsToReturn.insert(mapItr->second.begin(), mapItr->second.end()); + } + } + return lawsToReturn; +} \ No newline at end of file diff --git a/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.h b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.h new file mode 100644 index 000000000..759e0d942 --- /dev/null +++ b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapper.h @@ -0,0 +1,32 @@ +#ifndef SUCCESSION_LAW_MAPPER_H +#define SUCCESSION_LAW_MAPPER_H + + + +#include "Parser.h" +#include <map> +#include <set> +#include <string> + + + +namespace mappers { + +class SuccessionLawMapper: commonItems::parser { +public: + SuccessionLawMapper(); + explicit SuccessionLawMapper(std::istream& theStream); + + [[nodiscard]] std::set<std::string> getCK3LawsForImperatorLaws(const std::set<std::string>& laws) const; + +private: + void registerKeys(); + + std::map<std::string, std::set<std::string>> impToCK3SuccessionLawMap; +}; + +} // namespace mappers + + + +#endif // SUCCESSION_LAW_MAPPER_H diff --git a/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.cpp b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.cpp new file mode 100644 index 000000000..1389855f5 --- /dev/null +++ b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.cpp @@ -0,0 +1,18 @@ +#include "SuccessionLawMapping.h" +#include "ParserHelpers.h" +#include "CommonRegexes.h" + + + +mappers::SuccessionLawMapping::SuccessionLawMapping(std::istream& theStream) { + registerKeyword("imp", [this](std::istream& theStream) { + impLaw = commonItems::getString(theStream); + }); + registerKeyword("ck3", [this](std::istream& theStream) { + ck3SuccessionLaws.emplace(commonItems::getString(theStream)); + }); + registerMatcher(commonItems::catchallRegexMatch, commonItems::ignoreItem); + + parseStream(theStream); + clearRegisteredKeywords(); +} \ No newline at end of file diff --git a/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.h b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.h new file mode 100644 index 000000000..46c6e2c12 --- /dev/null +++ b/ImperatorToCK3/Source/Mappers/SuccessionLawMapper/SuccessionLawMapping.h @@ -0,0 +1,25 @@ +#ifndef SUCCESSION_LAW_MAPPING_H +#define SUCCESSION_LAW_MAPPING_H + + + +#include "Parser.h" +#include <set> + + + +namespace mappers { + +class SuccessionLawMapping: commonItems::parser { +public: + explicit SuccessionLawMapping(std::istream& theStream); + + std::string impLaw; + std::set<std::string> ck3SuccessionLaws; +}; + +} // namespace mappers + + + +#endif // SUCCESSION_LAW_MAPPING_H \ No newline at end of file diff --git a/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj b/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj index 8d53bfb16..cf98b7309 100644 --- a/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj +++ b/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj @@ -237,6 +237,8 @@ <ClCompile Include="..\ImperatorToCK3\Source\Mappers\RegionMapper\ImperatorRegionMapper.cpp" /> <ClCompile Include="..\ImperatorToCK3\Source\Mappers\ReligionMapper\ReligionMapper.cpp" /> <ClCompile Include="..\ImperatorToCK3\Source\Mappers\ReligionMapper\ReligionMapping.cpp" /> + <ClCompile Include="..\ImperatorToCK3\Source\Mappers\SuccessionLawMapper\SuccessionLawMapper.cpp" /> + <ClCompile Include="..\ImperatorToCK3\Source\Mappers\SuccessionLawMapper\SuccessionLawMapping.cpp" /> <ClCompile Include="..\ImperatorToCK3\Source\Mappers\TagTitleMapper\TagTitleMapper.cpp" /> <ClCompile Include="..\ImperatorToCK3\Source\Mappers\TagTitleMapper\TagTitleMapping.cpp" /> <ClCompile Include="..\ImperatorToCK3\Source\Mappers\TraitMapper\TraitMapper.cpp" /> @@ -285,6 +287,7 @@ <ClCompile Include="MapperTests\RegionMapper\ImperatorRegionTests.cpp" /> <ClCompile Include="MapperTests\ReligionMapper\ReligionMapperTests.cpp" /> <ClCompile Include="MapperTests\ReligionMapper\ReligionMappingTests.cpp" /> + <ClCompile Include="MapperTests\SuccessionLawMapper\SuccessionLawMapperTests.cpp" /> <ClCompile Include="MapperTests\TagTitleMapper\TagTitleMapperTests.cpp" /> <ClCompile Include="MapperTests\TagTitleMapper\TagTitleMappingTests.cpp" /> <ClCompile Include="MapperTests\TraitMapper\TraitMapperTests.cpp" /> diff --git a/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj.filters b/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj.filters index 25995c1c4..86dd82c78 100644 --- a/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj.filters +++ b/ImperatorToCK3Tests/ImperatorToCK3Tests.vcxproj.filters @@ -103,6 +103,12 @@ <Filter Include="Sources\CK3\Dynasties"> <UniqueIdentifier>{dfa38371-681a-46c6-8573-0583a5d3e13a}</UniqueIdentifier> </Filter> + <Filter Include="MapperTests\SuccessionLawMapper"> + <UniqueIdentifier>{05fd17f7-3129-41d4-a7da-d9e17f728fbd}</UniqueIdentifier> + </Filter> + <Filter Include="Sources\Mappers\SuccessionLawMapper"> + <UniqueIdentifier>{8ab3f4fd-8983-48c5-878b-ee2ae73be637}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClCompile Include="ImperatorWorldTests\Families\FamilyTests.cpp"> @@ -480,6 +486,15 @@ <ClCompile Include="..\ImperatorToCK3\Source\Imperator\Provinces\Province.cpp"> <Filter>Sources</Filter> </ClCompile> + <ClCompile Include="MapperTests\SuccessionLawMapper\SuccessionLawMapperTests.cpp"> + <Filter>MapperTests\SuccessionLawMapper</Filter> + </ClCompile> + <ClCompile Include="..\ImperatorToCK3\Source\Mappers\SuccessionLawMapper\SuccessionLawMapper.cpp"> + <Filter>Sources\Mappers\SuccessionLawMapper</Filter> + </ClCompile> + <ClCompile Include="..\ImperatorToCK3\Source\Mappers\SuccessionLawMapper\SuccessionLawMapping.cpp"> + <Filter>Sources\Mappers\SuccessionLawMapper</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\ImperatorToCK3\Source\Imperator\Provinces\Province.h"> diff --git a/ImperatorToCK3Tests/ImperatorWorldTests/Countries/CountryTests.cpp b/ImperatorToCK3Tests/ImperatorWorldTests/Countries/CountryTests.cpp index 4b10fedb8..13f332e86 100644 --- a/ImperatorToCK3Tests/ImperatorWorldTests/Countries/CountryTests.cpp +++ b/ImperatorToCK3Tests/ImperatorWorldTests/Countries/CountryTests.cpp @@ -267,4 +267,41 @@ TEST(ImperatorWorld_CountryTests, correctCountryRankIsReturned) ASSERT_EQ(Imperator::countryRankEnum::regionalPower, theCountry4.getCountryRank()); ASSERT_EQ(Imperator::countryRankEnum::majorPower, theCountry5.getCountryRank()); ASSERT_EQ(Imperator::countryRankEnum::greatPower, theCountry6.getCountryRank()); -} \ No newline at end of file +} + + +TEST(ImperatorWorld_CountryTests, lawsDefaultToEmpty) { + std::stringstream input; + const auto theCountry = *Imperator::Country::Factory().getCountry(input, 42); + + ASSERT_TRUE(theCountry.getLaws().empty()); +} + + +TEST(ImperatorWorld_CountryTests, lawsCanBeSet) { + std::stringstream input; + input << "= {\n"; + input << "\tsuccession_law = lawA\n"; + input << "\ttribal_authority_laws = lawB\n"; + input << "\trepublican_mediterranean_laws = lawC\n"; + input << "\tmonarchy_legitimacy_laws = lawD\n"; + input << "}"; + const auto theCountry = *Imperator::Country::Factory().getCountry(input, 42); + + ASSERT_EQ(4, theCountry.getLaws().size()); + ASSERT_TRUE(theCountry.getLaws().contains("lawA")); + ASSERT_TRUE(theCountry.getLaws().contains("lawB")); + ASSERT_TRUE(theCountry.getLaws().contains("lawC")); + ASSERT_TRUE(theCountry.getLaws().contains("lawD")); +} + + +TEST(ImperatorWorld_CountryTests, wrongTypeLawsAreNotSet) { + std::stringstream input; + input << "= {\n"; + input << "\tnonexistent_law_type_laws = lawA\n"; + input << "}"; + const auto theCountry = *Imperator::Country::Factory().getCountry(input, 42); + + ASSERT_TRUE(theCountry.getLaws().empty()); +} diff --git a/ImperatorToCK3Tests/MapperTests/SuccessionLawMapper/SuccessionLawMapperTests.cpp b/ImperatorToCK3Tests/MapperTests/SuccessionLawMapper/SuccessionLawMapperTests.cpp new file mode 100644 index 000000000..161e0ed4b --- /dev/null +++ b/ImperatorToCK3Tests/MapperTests/SuccessionLawMapper/SuccessionLawMapperTests.cpp @@ -0,0 +1,41 @@ +#include "Mappers/SuccessionLawMapper/SuccessionLawMapper.h" +#include "gtest/gtest.h" +#include <sstream> + + + +TEST(Mappers_SuccessionLawMapperTests, nonMatchGivesEmptySet) +{ + std::stringstream input; + input << "link = { imp = implaw ck3 = ck3law }"; + const mappers::SuccessionLawMapper mapper(input); + + const auto& ck3Law = mapper.getCK3LawsForImperatorLaws({ "madeUpLaw" }); + ASSERT_TRUE(ck3Law.empty()); +} + + +TEST(Mappers_SuccessionLawMapperTests, ck3LawCanBeFound) +{ + std::stringstream input; + input << "link = { imp = implaw ck3 = ck3law }"; + const mappers::SuccessionLawMapper mapper(input); + + const auto& ck3Laws = mapper.getCK3LawsForImperatorLaws({ "implaw" }); + ASSERT_EQ(std::set<std::string>{"ck3law"}, ck3Laws); +} + + +TEST(Mappers_SuccessionLawMapperTests, multipleLawsCanBeReturned) +{ + std::stringstream input; + input << "link = { imp = implaw ck3 = ck3law ck3 = ck3law2 }\n"; + input << "link = { imp = implaw ck3 = ck3law3 }\n"; + input << "link = { imp = implaw2 ck3 = ck3law4 }\n"; + input << "link = { imp = implaw3 ck3 = ck3law5 }\n"; + const mappers::SuccessionLawMapper mapper(input); + + const auto& ck3Laws = mapper.getCK3LawsForImperatorLaws({ "implaw", "implaw3" }); + std::set<std::string> expectedReturnedLaws{ "ck3law", "ck3law2", "ck3law3", "ck3law5" }; + ASSERT_EQ(expectedReturnedLaws, ck3Laws); +} \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 0e0098728..7fb4f2b79 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: ImperatorToCK3.{build} +version: dev.{build} image: Visual Studio 2019 Preview configuration: Release build_script: @@ -27,4 +27,7 @@ deploy: repository: ParadoxGameConverters/ImperatorToCK3 artifact: ImperatorToCK3-$(APPVEYOR_REPO_TAG_NAME) prerelease: false - force_update: true \ No newline at end of file + force_update: true + on: + branch: master # release from master branch only + APPVEYOR_REPO_TAG: true # deploy on tag push only \ No newline at end of file