Skip to content

Commit 42b0d76

Browse files
authored
Don't change de jure for kingdoms that are mostly outside of the I:R map (#3129) #minor
1 parent 1475829 commit 42b0d76

3 files changed

Lines changed: 166 additions & 15 deletions

File tree

ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,23 @@ public LandedTitlesTests() {
7070
cultures = new CultureCollection(colorFactory, pillars, ck3ModFlags);
7171
}
7272

73+
private static void WithTemporaryHeritageEmpireMap(Action action, string fileContents = "") {
74+
const string heritageMapPath = "configurables/heritage_empires_map.txt";
75+
var originalHeritageMap = File.Exists(heritageMapPath) ? File.ReadAllText(heritageMapPath) : null;
76+
Directory.CreateDirectory("configurables");
77+
File.WriteAllText(heritageMapPath, fileContents);
78+
79+
try {
80+
action();
81+
} finally {
82+
if (originalHeritageMap is null) {
83+
File.Delete(heritageMapPath);
84+
} else {
85+
File.WriteAllText(heritageMapPath, originalHeritageMap);
86+
}
87+
}
88+
}
89+
7390
[Fact]
7491
public void TitlesDefaultToEmpty() {
7592
var reader = new BufferedReader(string.Empty);
@@ -664,15 +681,17 @@ public void KingdomUsesNextDominantHeritageWhenMostDominantOneCannotProvideEmpir
664681
titles["c_county3"].SetHolder(mongolHolder, date);
665682
titles["c_xia_county"].SetHolder(mongolHolder, date);
666683

667-
var heritageMapPath = Path.Combine("configurables", "heritage_empires_map.txt");
684+
string heritageMapPath = "configurables/heritage_empires_map.txt";
668685
var originalHeritageMap = File.Exists(heritageMapPath) ? File.ReadAllText(heritageMapPath) : null;
669686
Directory.CreateDirectory("configurables");
670687
File.WriteAllText(heritageMapPath,
671688
"heritage_chinese = none\n" +
672689
"heritage_mongolic = e_mongolia\n");
673690

674691
try {
675-
titles.SetDeJureKingdomsAndAbove(date, cultureCollection, characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB());
692+
var provinceMapper = new ProvinceMapper();
693+
provinceMapper.LoadMappings(provinceMappingsPath);
694+
titles.SetDeJureKingdomsAndAbove(date, cultureCollection, characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB(), provinceMapper);
676695

677696
Assert.Equal("e_mongolia", titles["k_test"].DeJureLiege?.Id);
678697
} finally {
@@ -684,6 +703,98 @@ public void KingdomUsesNextDominantHeritageWhenMostDominantOneCannotProvideEmpir
684703
}
685704
}
686705

706+
[Fact]
707+
public void KingdomMostlyOutsideImperatorMapKeepsExistingDeJureSetup() {
708+
var date = new Date(867, 1, 1);
709+
var titles = new Title.LandedTitles();
710+
titles.LoadTitles(new BufferedReader(
711+
"h_old = { e_old = { k_protected = { d_protected = { capital = c_protected1 c_protected1 = { b_protected1 = { province = 1 } } c_protected2 = { b_protected2 = { province = 100 } } c_protected3 = { b_protected3 = { province = 101 } } } } } }\n" +
712+
"h_new = { e_new = { k_new = { } } }\n"
713+
), colorFactory);
714+
715+
var characters = new CharacterCollection();
716+
var holder = new Character("1", "Holder", new Date(800, 1, 1), characters);
717+
characters.Add(holder);
718+
719+
foreach (var countyId in new[] { "c_protected1", "c_protected2", "c_protected3" }) {
720+
titles[countyId].SetHolder(holder, date);
721+
titles[countyId].SetDeFactoLiege(titles["k_new"], date);
722+
}
723+
titles["k_new"].SetDeFactoLiege(titles["e_new"], date);
724+
titles["e_new"].SetDeFactoLiege(titles["h_new"], date);
725+
726+
var provinceMapper = new ProvinceMapper();
727+
provinceMapper.LoadMappings(provinceMappingsPath);
728+
729+
WithTemporaryHeritageEmpireMap(() =>
730+
titles.SetDeJureKingdomsAndAbove(date, new TestCK3CultureCollection(), characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB(), provinceMapper)
731+
);
732+
733+
Assert.Equal("k_protected", titles["d_protected"].DeJureLiege?.Id);
734+
Assert.Equal("e_old", titles["k_protected"].DeJureLiege?.Id);
735+
Assert.Equal("h_old", titles["k_protected"].GetDeJureLiegeOfRank(TitleRank.hegemony)?.Id);
736+
}
737+
738+
[Fact]
739+
public void KingdomAtFiftyPercentOutsideImperatorMapStillUsesDynamicDeJureSetup() {
740+
var date = new Date(867, 1, 1);
741+
var titles = new Title.LandedTitles();
742+
titles.LoadTitles(new BufferedReader(
743+
"e_old = { k_test = { d_test = { capital = c_test1 c_test1 = { b_test1 = { province = 1 } } c_test2 = { b_test2 = { province = 100 } } } } }\n" +
744+
"e_new = { k_target = { } }\n"
745+
), colorFactory);
746+
747+
var characters = new CharacterCollection();
748+
var holder = new Character("1", "Holder", new Date(800, 1, 1), characters);
749+
characters.Add(holder);
750+
751+
foreach (var countyId in new[] { "c_test1", "c_test2" }) {
752+
titles[countyId].SetHolder(holder, date);
753+
titles[countyId].SetDeFactoLiege(titles["k_target"], date);
754+
}
755+
titles["k_target"].SetDeFactoLiege(titles["e_new"], date);
756+
757+
var provinceMapper = new ProvinceMapper();
758+
provinceMapper.LoadMappings(provinceMappingsPath);
759+
760+
WithTemporaryHeritageEmpireMap(() =>
761+
titles.SetDeJureKingdomsAndAbove(date, new TestCK3CultureCollection(), characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB(), provinceMapper)
762+
);
763+
764+
Assert.Equal("k_target", titles["d_test"].DeJureLiege?.Id);
765+
}
766+
767+
[Fact]
768+
public void ProtectedKingdomIsNotExcludedFromDisconnectedEmpireSplitting() {
769+
var date = new Date(867, 1, 1);
770+
var titles = new Title.LandedTitles();
771+
titles.LoadTitles(new BufferedReader(
772+
"e_old = { " +
773+
"k_mutable = { d_mutable = { capital = c_mutable c_mutable = { b_mutable = { province = 4 } } } } " +
774+
"k_protected = { d_protected = { capital = c_protected1 c_protected1 = { b_protected1 = { province = 1 } } c_protected2 = { b_protected2 = { province = 100 } } c_protected3 = { b_protected3 = { province = 101 } } } } " +
775+
"}\n"
776+
), colorFactory);
777+
778+
var characters = new CharacterCollection();
779+
var holder = new Character("1", "Holder", new Date(800, 1, 1), characters);
780+
characters.Add(holder);
781+
782+
foreach (var countyId in new[] { "c_mutable", "c_protected1", "c_protected2", "c_protected3" }) {
783+
titles[countyId].SetHolder(holder, date);
784+
titles[countyId].SetDeFactoLiege(titles["e_old"], date);
785+
}
786+
787+
var provinceMapper = new ProvinceMapper();
788+
provinceMapper.LoadMappings(provinceMappingsPath);
789+
790+
WithTemporaryHeritageEmpireMap(() =>
791+
titles.SetDeJureKingdomsAndAbove(date, new TestCK3CultureCollection(), characters, new MapData(ck3ModFS), new CK3RegionMapper(), new TestCK3LocDB(), provinceMapper)
792+
);
793+
794+
Assert.Equal("e_IRTOCK3_from_c_protected1", titles["k_protected"].DeJureLiege?.Id);
795+
Assert.True(titles.ContainsKey("e_IRTOCK3_from_c_protected1"));
796+
}
797+
687798
[Fact]
688799
public void RemoveBreaksAllLinks() {
689800
var landedTitles = new Title.LandedTitles();

ImperatorToCK3/CK3/Titles/LandedTitles.cs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,15 +1098,54 @@ public void RemoveInvalidLandlessTitles(Date ck3BookmarkDate) {
10981098
Logger.IncrementProgress();
10991099
}
11001100

1101-
private void SetDeJureKingdoms(CK3LocDB ck3LocDB, Date ck3BookmarkDate) {
1101+
private static FrozenSet<string> GetKingdomIdsWithMajorityOutsideImperatorMap(IEnumerable<Title> deJureKingdoms, ProvinceMapper provinceMapper) {
1102+
var protectedKingdomIds = new HashSet<string>();
1103+
foreach (var kingdom in deJureKingdoms) {
1104+
var kingdomProvinceIds = kingdom.GetDeJureVassalsAndBelow("c").Values
1105+
.SelectMany(c => c.CountyProvinceIds)
1106+
.ToFrozenSet();
1107+
if (kingdomProvinceIds.Count == 0) {
1108+
continue;
1109+
}
1110+
1111+
var provincesOutsideImperatorMap = kingdomProvinceIds.Count(provinceId => provinceMapper.GetImperatorProvinceNumbers(provinceId).Count == 0);
1112+
if (provincesOutsideImperatorMap * 2 <= kingdomProvinceIds.Count) {
1113+
continue;
1114+
}
1115+
1116+
protectedKingdomIds.Add(kingdom.Id);
1117+
Logger.Debug($"Preserving de jure setup for kingdom {kingdom.Id}: {provincesOutsideImperatorMap}/{kingdomProvinceIds.Count} provinces are outside the Imperator map.");
1118+
}
1119+
1120+
return protectedKingdomIds.ToFrozenSet();
1121+
}
1122+
1123+
private static bool IsInChinaDeJureHierarchy(Title title) {
1124+
return string.Equals(title.GetDeJureLiegeOfRank(TitleRank.hegemony)?.Id, "h_china", StringComparison.Ordinal);
1125+
}
1126+
1127+
private static bool KingdomShouldKeepExistingDeJureSetup(Title kingdom, FrozenSet<string> protectedKingdomIds) {
1128+
// Don't change the de jure inside h_china, to avoid messing with the Dynastic Cycle and shit.
1129+
return IsInChinaDeJureHierarchy(kingdom) || protectedKingdomIds.Contains(kingdom.Id);
1130+
}
1131+
1132+
private static bool DuchyShouldKeepExistingDeJureSetup(Title duchy, FrozenSet<string> protectedKingdomIds) {
1133+
if (IsInChinaDeJureHierarchy(duchy)) {
1134+
return true;
1135+
}
1136+
1137+
var currentKingdom = duchy.GetDeJureLiegeOfRank(TitleRank.kingdom);
1138+
return currentKingdom is not null && protectedKingdomIds.Contains(currentKingdom.Id);
1139+
}
1140+
1141+
private void SetDeJureKingdoms(CK3LocDB ck3LocDB, Date ck3BookmarkDate, FrozenSet<string> protectedKingdomIds) {
11021142
Logger.Info("Setting de jure kingdoms...");
11031143

11041144
var duchies = this.Where(t => t.Rank == TitleRank.duchy).ToFrozenSet();
11051145
var duchiesWithDeJureVassals = duchies.Where(d => d.DeJureVassals.Count > 0).ToFrozenSet();
11061146

11071147
foreach (var duchy in duchiesWithDeJureVassals) {
1108-
// Don't change the de jure inside h_china, to avoid messing with the Dynastic Cycle and shit.
1109-
if (string.Equals(duchy.DeJureLiege?.DeJureLiege?.DeJureLiege?.Id, "h_china", StringComparison.Ordinal)) {
1148+
if (DuchyShouldKeepExistingDeJureSetup(duchy, protectedKingdomIds)) {
11101149
continue;
11111150
}
11121151

@@ -1176,23 +1215,23 @@ private void SetDeJureKingdoms(CK3LocDB ck3LocDB, Date ck3BookmarkDate) {
11761215
Logger.IncrementProgress();
11771216
}
11781217

1179-
private void SetDeJureEmpiresAndHegemonies(CultureCollection ck3Cultures, CharacterCollection ck3Characters, MapData ck3MapData, CK3RegionMapper ck3RegionMapper, CK3LocDB ck3LocDB, Date ck3BookmarkDate) {
1218+
private void SetDeJureEmpiresAndHegemonies(CultureCollection ck3Cultures, CharacterCollection ck3Characters, MapData ck3MapData, CK3RegionMapper ck3RegionMapper, CK3LocDB ck3LocDB, Date ck3BookmarkDate, FrozenSet<string> protectedKingdomIds) {
11801219
Logger.Info("Setting de jure empires...");
11811220
var deJureKingdoms = GetDeJureKingdoms();
1182-
var deJureKingdomsOutsideChina = deJureKingdoms
1183-
.Where(k => !string.Equals(k.DeJureLiege?.DeJureLiege?.Id, "h_china", StringComparison.Ordinal))
1221+
var mutableDeJureKingdoms = deJureKingdoms
1222+
.Where(k => !KingdomShouldKeepExistingDeJureSetup(k, protectedKingdomIds))
11841223
.ToImmutableArray();
11851224

1186-
TryToAssignKingdomsToExistingEmpires(deJureKingdomsOutsideChina, ck3BookmarkDate);
1225+
TryToAssignKingdomsToExistingEmpires(mutableDeJureKingdoms, ck3BookmarkDate);
11871226

1188-
SetDeJureEmpiresWithinHegemonies(deJureKingdomsOutsideChina, ck3RegionMapper, ck3LocDB, ck3BookmarkDate);
1227+
SetDeJureEmpiresWithinHegemonies(mutableDeJureKingdoms, ck3RegionMapper, ck3LocDB, ck3BookmarkDate);
11891228

11901229
// For kingdoms that still have no de jure empire, create empires based on dominant culture of the realms
11911230
// holding land in that de jure kingdom.
11921231
var removableEmpireIds = new HashSet<string>();
11931232
var kingdomToDominantHeritagesDict = new Dictionary<string, ImmutableArray<Pillar>>();
11941233
var heritageToEmpireDict = GetHeritageIdToExistingTitleDict();
1195-
CreateEmpiresBasedOnDominantHeritages(deJureKingdomsOutsideChina, ck3Cultures, ck3Characters, removableEmpireIds, kingdomToDominantHeritagesDict, heritageToEmpireDict, ck3LocDB, ck3BookmarkDate);
1234+
CreateEmpiresBasedOnDominantHeritages(mutableDeJureKingdoms, ck3Cultures, ck3Characters, removableEmpireIds, kingdomToDominantHeritagesDict, heritageToEmpireDict, ck3LocDB, ck3BookmarkDate);
11961235

11971236
Logger.Debug("Building kingdom adjacencies dict...");
11981237
// Create a cache of province IDs per kingdom.
@@ -1814,9 +1853,10 @@ private void SetHegemonyCapitals(Date ck3BookmarkDate) {
18141853
}
18151854
}
18161855

1817-
public void SetDeJureKingdomsAndAbove(Date ck3BookmarkDate, CultureCollection ck3Cultures, CharacterCollection ck3Characters, MapData ck3MapData, CK3RegionMapper ck3RegionMapper, CK3LocDB ck3LocDB) {
1818-
SetDeJureKingdoms(ck3LocDB, ck3BookmarkDate);
1819-
SetDeJureEmpiresAndHegemonies(ck3Cultures, ck3Characters, ck3MapData, ck3RegionMapper, ck3LocDB, ck3BookmarkDate);
1856+
public void SetDeJureKingdomsAndAbove(Date ck3BookmarkDate, CultureCollection ck3Cultures, CharacterCollection ck3Characters, MapData ck3MapData, CK3RegionMapper ck3RegionMapper, CK3LocDB ck3LocDB, ProvinceMapper provinceMapper) {
1857+
var protectedKingdomIds = GetKingdomIdsWithMajorityOutsideImperatorMap(GetDeJureKingdoms(), provinceMapper);
1858+
SetDeJureKingdoms(ck3LocDB, ck3BookmarkDate, protectedKingdomIds);
1859+
SetDeJureEmpiresAndHegemonies(ck3Cultures, ck3Characters, ck3MapData, ck3RegionMapper, ck3LocDB, ck3BookmarkDate, protectedKingdomIds);
18201860
}
18211861

18221862
/// <summary>

ImperatorToCK3/CK3/World.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ internal World(Imperator.World impWorld, Configuration config, Thread? irCoaExtr
355355
LandedTitles.RemoveInvalidLandlessTitles(config.CK3BookmarkDate);
356356
Logger.IncrementProgress();
357357
if (!config.StaticDeJure) {
358-
LandedTitles.SetDeJureKingdomsAndAbove(config.CK3BookmarkDate, Cultures, Characters, MapData, CK3RegionMapper, LocDB);
358+
LandedTitles.SetDeJureKingdomsAndAbove(config.CK3BookmarkDate, Cultures, Characters, MapData, CK3RegionMapper, LocDB, provinceMapper);
359359
}
360360

361361
Dynasties.SetCoasForRulingDynasties(LandedTitles, config.CK3BookmarkDate);

0 commit comments

Comments
 (0)