Skip to content

Commit

Permalink
Government office conversion (#2014) #minor
Browse files Browse the repository at this point in the history
The program now converts Imperator government officials to court
chaplains, chancellors, stewards, marshals, bodyguards, court
physicians, court tutors and chroniclers.

closes #89
  • Loading branch information
IhateTrains authored Jun 27, 2024
1 parent cb19b4b commit 88e1358
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 53 deletions.
5 changes: 3 additions & 2 deletions ImperatorToCK3.UnitTests/Imperator/Jobs/JobsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using commonItems.Colors;
using commonItems.Mods;
using ImperatorToCK3.CommonUtils.Map;
using ImperatorToCK3.Imperator.Characters;
using ImperatorToCK3.Imperator.Countries;
using ImperatorToCK3.Imperator.Geography;
using ImperatorToCK3.Mappers.Region;
Expand Down Expand Up @@ -41,7 +42,7 @@ public void GovernorshipsCanBeRead() {
var reader = new BufferedReader(
"province_job={who=1 governorship=galatia_region} province_job={who=2 governorship=galatia_region}"
);
var jobs = new ImperatorToCK3.Imperator.Jobs.JobsDB(reader, countryCollection, irRegionMapper);
var jobs = new ImperatorToCK3.Imperator.Jobs.JobsDB(reader, new CharacterCollection(), countryCollection, irRegionMapper);
Assert.Collection(jobs.Governorships,
item1 => Assert.Equal((ulong)1, item1.Country.Id),
item2 => Assert.Equal((ulong)2, item2.Country.Id)
Expand All @@ -55,7 +56,7 @@ public void IgnoredTokensAreLogged() {
var reader = new BufferedReader(
"useless_job = {}"
);
_ = new ImperatorToCK3.Imperator.Jobs.JobsDB(reader, countryCollection, irRegionMapper);
_ = new ImperatorToCK3.Imperator.Jobs.JobsDB(reader, new CharacterCollection(), countryCollection, irRegionMapper);

Assert.Contains("Ignored Jobs tokens: useless_job", output.ToString());
}
Expand Down
1 change: 1 addition & 0 deletions ImperatorToCK3.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Petair/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Phrygian/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Playset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pontifex/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Provs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Qahtanite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rakaly/@EntryIndexedValue">True</s:Boolean>
Expand Down
18 changes: 16 additions & 2 deletions ImperatorToCK3/CK3/Religions/Faith.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace ImperatorToCK3.CK3.Religions;

public sealed class Faith : IIdentifiable<string>, IPDXSerializable {
public string Id { get; }
public Religion Religion { get; }
public Religion Religion { get; set; }
public Color? Color { get; }
public string? ReligiousHeadTitleId { get; }
public OrderedSet<string> DoctrineIds { get; }
Expand Down Expand Up @@ -74,10 +74,24 @@ public string Serialize(string indent, bool withBraces) {

public string? GetDoctrineIdForDoctrineCategoryId(string doctrineCategoryId) {
var category = Religion.ReligionCollection.DoctrineCategories[doctrineCategoryId];
return GetDoctrineIdForDoctrineCategory(category);
}

private string? GetDoctrineIdForDoctrineCategory(DoctrineCategory category) {
var potentialDoctrineIds = category.DoctrineIds;

// Look in faith first. If not found, look in religion.
var matchingInFaith = DoctrineIds.Intersect(potentialDoctrineIds).LastOrDefault();
return matchingInFaith ?? Religion.DoctrineIds.Intersect(potentialDoctrineIds).LastOrDefault();
}

public bool HasDoctrine(string doctrineId) {
var category = Religion.ReligionCollection.DoctrineCategories
.FirstOrDefault(category => category.DoctrineIds.Contains(doctrineId));
if (category is null) {
return false;
}

return GetDoctrineIdForDoctrineCategory(category) == doctrineId;
}
}
1 change: 1 addition & 0 deletions ImperatorToCK3/CK3/Religions/ReligionCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public void LoadConverterFaiths(string converterFaithsPath, ColorFactory colorFa
// Otherwise, add the converter faith's religion.
if (TryGetValue(religionId, out var religion)) {
foreach (var faith in optReligion.Faiths) {
faith.Religion = religion;
religion.Faiths.Add(faith);
}
} else {
Expand Down
61 changes: 61 additions & 0 deletions ImperatorToCK3/CK3/Titles/LandedTitles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using ImperatorToCK3.CK3.Characters;
using ImperatorToCK3.CK3.Cultures;
using ImperatorToCK3.CK3.Provinces;
using ImperatorToCK3.CK3.Religions;
using ImperatorToCK3.CommonUtils;
using ImperatorToCK3.CommonUtils.Map;
using ImperatorToCK3.Imperator.Countries;
Expand Down Expand Up @@ -1244,6 +1245,66 @@ private void DistributeExcessDevelopment(Date date) {
}
}
}

/// <summary>
/// Import Imperator officials as council members and courtiers.
/// https://imperator.paradoxwikis.com/Position
/// https://ck3.paradoxwikis.com/Council
/// https://ck3.paradoxwikis.com/Court#Court_positions
/// </summary>
public void ImportImperatorGovernmentOffices(ICollection<OfficeJob> irOfficeJobs, ReligionCollection religionCollection, Date bookmarkDate) {
Logger.Info("Converting government offices...");
var titlesFromImperator = GetCountriesImportedFromImperator();

var councilPositionToSourcesDict = new Dictionary<string, string[]> {
["councillor_court_chaplain"] = ["office_augur", "office_pontifex", "office_high_priest_monarchy", "office_high_priest", "office_wise_person"],
["councillor_chancellor"] = ["office_censor", "office_foreign_minister", "office_arbitrator", "office_elder"],
["councillor_steward"] = ["office_praetor", "office_magistrate", "office_steward", "office_tribune_of_the_treasury"],
["councillor_marshal"] = ["office_tribune_of_the_soldiers", "office_marshal", "office_master_of_the_guard", "office_warchief", "office_bodyguard"],
["councillor_spymaster"] = [], // No equivalents found in Imperator.
};

// Court positions.
var courtPositionToSourcesDict = new Dictionary<string, string[]> {
["bodyguard_court_position"] = ["office_master_of_the_guard", "office_bodyguard"],
["court_physician_court_position"] = ["office_physician", "office_republic_physician", "office_apothecary"],
["court_tutor_court_position"] = ["office_royal_tutor"],
["chronicler_court_position"] = ["office_philosopher"], // From I:R wiki: "supervises libraries and the gathering and protection of knowledge"
["court_cave_hermit_position"] = ["office_wise_person"]
};

string[] ignoredOfficeTypes = ["office_plebeian_aedile"];

// Log all unhandled office types.
var irOfficeTypesFromSave = irOfficeJobs.Select(j => j.OfficeType).ToHashSet();
var handledOfficeTypes = councilPositionToSourcesDict.Values.SelectMany(v => v).Concat(courtPositionToSourcesDict.Values.SelectMany(v => v)).Concat(ignoredOfficeTypes).ToHashSet();
var unmappedOfficeTypes = irOfficeTypesFromSave.Where(officeType => !handledOfficeTypes.Contains(officeType)).ToList();
if (unmappedOfficeTypes.Count > 0) {
Logger.Error($"Unmapped office types: {string.Join(", ", unmappedOfficeTypes)}");
}

foreach (var title in titlesFromImperator) {
var country = title.ImperatorCountry!;
var ck3Ruler = country.Monarch?.CK3Character;
if (ck3Ruler is null) {
continue;
}

// Make sure the ruler actually holds something in CK3.
if (this.All(t => t.GetHolderId(bookmarkDate) != ck3Ruler.Id)) {
continue;
}

var convertibleJobs = irOfficeJobs.Where(j => j.CountryId == country.Id).ToList();
if (convertibleJobs.Count == 0) {
continue;
}

var alreadyEmployedCharacters = new HashSet<string>();
title.AppointCouncilMembersFromImperator(religionCollection, councilPositionToSourcesDict, convertibleJobs, alreadyEmployedCharacters, ck3Ruler, bookmarkDate);
title.AppointCourtierPositionsFromImperator(courtPositionToSourcesDict, convertibleJobs, alreadyEmployedCharacters, ck3Ruler, bookmarkDate);
}
}

public IEnumerable<Title> GetCountriesImportedFromImperator() {
return this.Where(t => t.ImperatorCountry is not null);
Expand Down
Loading

0 comments on commit 88e1358

Please sign in to comment.