Place names: Faction.Places, Galaxy.NamePlaces and the place-names command
Each faction names the zones it owns from its own curated list (ruling faction-curated-place-names): the home zone takes Places[0], the rest follow in distance order, a spent or absent list falls back to unique catalogue designations. Galaxy.NamePlaces replaces the Markov GenerateNames body. The place-names command authors the 15-row table and, until commit 3, purges the NameFile records and GeonameFile links while their type still exists. The shipped catalog carries no Places yet (commit 2), so the tests that read shipped lists fail at this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0f5def1794
commit
740e1ee781
5 changed files with 435 additions and 24 deletions
|
|
@ -63,6 +63,19 @@ public class Faction
|
|||
// The faction's rules of engagement; null fights as FactionDoctrine.Default.
|
||||
[Inspectable, JsonProperty("doctrine"), Key(17)]
|
||||
public FactionDoctrine Doctrine;
|
||||
|
||||
// Curated place names in authored order; the home zone takes the first (ruling faction-curated-place-names).
|
||||
// Authored by AetherDb place-names, which restores the table on every apply.
|
||||
[Inspectable, JsonProperty("places"), Key(21)]
|
||||
public FactionPlace[] Places = Array.Empty<FactionPlace>();
|
||||
}
|
||||
|
||||
// Historical, narrative and strategic intent join as keys 2+ when economics-driven placement lands (ruling faction-curated-place-names).
|
||||
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
|
||||
public class FactionPlace
|
||||
{
|
||||
[Inspectable, JsonProperty("name"), Key(1)]
|
||||
public string Name;
|
||||
}
|
||||
|
||||
[CultDocument("aetheria.namefile", "1"), Inspectable, MessagePackObject]
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ public class Galaxy
|
|||
public uint Seed { get; }
|
||||
|
||||
private GalaxyZone[] _exitPath;
|
||||
private Dictionary<Faction, MarkovNameGenerator> _nameGenerators = new Dictionary<Faction, MarkovNameGenerator>();
|
||||
private readonly CultCache _cache;
|
||||
|
||||
public GalaxyZone[] ExitPath
|
||||
|
|
@ -131,7 +130,7 @@ public class Galaxy
|
|||
|
||||
CalculateFactionInfluence(progressCallback);
|
||||
|
||||
GenerateNames(cache, nameGeneratorSettings, ref random, progressCallback);
|
||||
NamePlaces(ref random, progressCallback);
|
||||
|
||||
progressCallback?.Invoke("Done!");
|
||||
if(progressCallback!=null) Thread.Sleep(500); // Inserting Delay to make it seem like it's doing more work lmao
|
||||
|
|
@ -259,7 +258,7 @@ public class Galaxy
|
|||
|
||||
CalculateFactionInfluence(progressCallback);
|
||||
|
||||
GenerateNames(cache, nameGeneratorSettings, ref random, progressCallback);
|
||||
NamePlaces(ref random, progressCallback);
|
||||
|
||||
// progressCallback?.Invoke("Weaving Narrative");
|
||||
// var processor = new StoryProcessor(playerSettings, narrativeDirectory, this, ref random, Log);
|
||||
|
|
@ -350,31 +349,37 @@ public class Galaxy
|
|||
}
|
||||
}
|
||||
|
||||
private void GenerateNames(CultCache cache,
|
||||
NameGeneratorSettings nameGeneratorSettings,
|
||||
ref Random random,
|
||||
Action<string> progressCallback = null)
|
||||
// Each faction names the zones it owns from its own curated list (ruling faction-curated-place-names): nearest its
|
||||
// home first, so the home zone takes the capital, which is Places[0]. A zone left over when a list is spent, and every
|
||||
// zone nobody owns, takes a catalogue designation. A name is never used twice, ignoring case.
|
||||
internal void NamePlaces(ref Random random, Action<string> progressCallback = null)
|
||||
{
|
||||
var used = new HashSet<string>();
|
||||
for (var i = 0; i < Factions.Length; i++)
|
||||
progressCallback?.Invoke("Naming places");
|
||||
var used = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var zone in Zones) zone.Name = null;
|
||||
|
||||
foreach (var faction in Factions)
|
||||
{
|
||||
progressCallback?.Invoke($"Feeding Markov Chains: {i + 1} / {Factions.Length}");
|
||||
//if(progressCallback!=null) Thread.Sleep(250); // Inserting Delay to make it seem like it's doing more work lmao
|
||||
var faction = Factions[i];
|
||||
_nameGenerators[faction] = new MarkovNameGenerator(ref random, cache.Get(faction.GeonameFile).Names, nameGeneratorSettings, used);
|
||||
if (!HomeZones.TryGetValue(faction, out var home)) continue;
|
||||
var places = (faction.Places ?? Array.Empty<FactionPlace>()).Select(p => p?.Name).Where(n => !string.IsNullOrEmpty(n)).ToArray();
|
||||
var next = 0;
|
||||
var owned = Zones.Select((zone, index) => (zone, index)).Where(z => z.zone.Owner == faction)
|
||||
.OrderBy(z => z.zone.Distance[home]).ThenBy(z => z.index);
|
||||
foreach (var (zone, _) in owned)
|
||||
{
|
||||
while (next < places.Length && used.Contains(places[next])) next++;
|
||||
if (next == places.Length) break;
|
||||
zone.Name = places[next];
|
||||
used.Add(places[next++]);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate zone name using the owner's name generator, otherwise assign catalogue ID
|
||||
foreach (var zone in Zones)
|
||||
foreach (var zone in Zones.Where(z => z.Name == null))
|
||||
{
|
||||
if (zone.Owner != null)
|
||||
{
|
||||
zone.Name = _nameGenerators[zone.Owner].NextName.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
zone.Name = $"EAC-{random.NextInt(9999).ToString()}";
|
||||
}
|
||||
string designation;
|
||||
do designation = $"EAC-{random.NextInt(9999)}";
|
||||
while (!used.Add(designation));
|
||||
zone.Name = designation;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue