- Introduce "camera_a_inventory_ok" check in AgentHarness for inventory audits - Add new actions to event catalog for civilization founding and reproduction - Update decision catalog to include new action phrases and signal predicates - Increment version to 0.28.27 in mod.json
278 lines
9 KiB
C#
278 lines
9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
public sealed class CameraAInventoryResult
|
|
{
|
|
public bool Passed;
|
|
public string Detail = "";
|
|
public int Total;
|
|
public int CameraA;
|
|
public int CameraB;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Live dump of Layer A vs B fate for decisions + library dial domains.
|
|
/// Source of truth for Signal / decision promote work (never promote from memory).
|
|
/// </summary>
|
|
public static class CameraAInventoryHarness
|
|
{
|
|
public static CameraAInventoryResult RunAudit(string outputDirectory)
|
|
{
|
|
var lines = new List<string>
|
|
{
|
|
"domain\tid\tdisplay\tlayer\tstrength\treason"
|
|
};
|
|
int total = 0;
|
|
int cameraA = 0;
|
|
int cameraB = 0;
|
|
var summary = new StringBuilder();
|
|
|
|
AppendDomain(
|
|
lines,
|
|
ref total,
|
|
ref cameraA,
|
|
ref cameraB,
|
|
summary,
|
|
"decisions",
|
|
"decision",
|
|
ActivityAssetCatalog.EnumerateLiveDecisionIds(),
|
|
id => EventCatalog.Decision.GetOrFallback(id),
|
|
id => EventCatalog.Decision.IsCameraWorthy(id)
|
|
? (EventCatalog.Decision.TryGetAuthoredActionPhrase(id, out _)
|
|
? "signal_predicate+phrase"
|
|
: "signal_predicate")
|
|
: ReasonDecisionB(id));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"spells", "spell",
|
|
ActivityAssetCatalog.EnumerateLiveSpellIds(),
|
|
EventCatalog.Spell.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Spell.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"powers", "power",
|
|
ActivityAssetCatalog.EnumerateLivePowerIds(),
|
|
EventCatalog.Power.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Power.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"items", "item",
|
|
ActivityAssetCatalog.EnumerateLiveItemIds(),
|
|
EventCatalog.Item.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Item.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"genes", "gene",
|
|
ActivityAssetCatalog.EnumerateLiveGeneIds(),
|
|
EventCatalog.Gene.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Gene.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"phenotypes", "phenotype",
|
|
ActivityAssetCatalog.EnumerateLivePhenotypeIds(),
|
|
EventCatalog.Phenotype.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Phenotype.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"world_laws", "worldlaw",
|
|
ActivityAssetCatalog.EnumerateLiveWorldLawIds(),
|
|
EventCatalog.WorldLaw.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.WorldLaw.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"subspecies_traits", "subspecies_trait",
|
|
ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(),
|
|
EventCatalog.SubspeciesTrait.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.SubspeciesTrait.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"biomes", "biome",
|
|
ActivityAssetCatalog.EnumerateLiveBiomeIds(),
|
|
EventCatalog.Biome.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.Biome.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"culture_traits", "culture_trait",
|
|
ActivityAssetCatalog.EnumerateLiveCultureTraitIds(),
|
|
EventCatalog.CultureTrait.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.CultureTrait.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"religion_traits", "religion_trait",
|
|
ActivityAssetCatalog.EnumerateLiveReligionTraitIds(),
|
|
EventCatalog.ReligionTrait.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.ReligionTrait.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"clan_traits", "clan_trait",
|
|
ActivityAssetCatalog.EnumerateLiveClanTraitIds(),
|
|
EventCatalog.ClanTrait.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.ClanTrait.GetOrFallback(id)));
|
|
|
|
AppendDomain(
|
|
lines, ref total, ref cameraA, ref cameraB, summary,
|
|
"language_traits", "language_trait",
|
|
ActivityAssetCatalog.EnumerateLiveLanguageTraitIds(),
|
|
EventCatalog.LanguageTrait.GetOrFallback,
|
|
id => ReasonLibrary(EventCatalog.LanguageTrait.GetOrFallback(id)));
|
|
|
|
try
|
|
{
|
|
if (!string.IsNullOrEmpty(outputDirectory))
|
|
{
|
|
Directory.CreateDirectory(outputDirectory);
|
|
File.WriteAllLines(Path.Combine(outputDirectory, "camera-a-inventory.tsv"), lines);
|
|
File.WriteAllText(
|
|
Path.Combine(outputDirectory, "camera-a-inventory-summary.txt"),
|
|
summary.ToString());
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// diagnostic dump only
|
|
}
|
|
|
|
bool passed = total > 0 && cameraA > 0;
|
|
return new CameraAInventoryResult
|
|
{
|
|
Passed = passed,
|
|
Total = total,
|
|
CameraA = cameraA,
|
|
CameraB = cameraB,
|
|
Detail = $"total={total} A={cameraA} B={cameraB} domains=13"
|
|
};
|
|
}
|
|
|
|
private static void AppendDomain(
|
|
List<string> lines,
|
|
ref int total,
|
|
ref int cameraA,
|
|
ref int cameraB,
|
|
StringBuilder summary,
|
|
string domain,
|
|
string displayKind,
|
|
List<string> ids,
|
|
Func<string, DiscreteEventEntry> getEntry,
|
|
Func<string, string> reasonFor)
|
|
{
|
|
if (ids == null)
|
|
{
|
|
ids = new List<string>();
|
|
}
|
|
|
|
int a = 0;
|
|
int b = 0;
|
|
for (int i = 0; i < ids.Count; i++)
|
|
{
|
|
string id = ids[i];
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
DiscreteEventEntry entry = getEntry(id);
|
|
bool isA = entry != null
|
|
&& EventCatalog.IsCameraWorthy(entry);
|
|
string layer = isA ? "A" : "B";
|
|
if (isA)
|
|
{
|
|
a++;
|
|
cameraA++;
|
|
}
|
|
else
|
|
{
|
|
b++;
|
|
cameraB++;
|
|
}
|
|
|
|
total++;
|
|
string display = domain == "decisions"
|
|
? EventReason.HumanizeId(id)
|
|
: LibraryAssetNames.DisplayName(displayKind, id);
|
|
display = SanitizeTsv(display);
|
|
float strength = entry != null ? entry.EventStrength : 0f;
|
|
string reason = SanitizeTsv(reasonFor(id) ?? "");
|
|
lines.Add(
|
|
domain + "\t" + id + "\t" + display + "\t" + layer + "\t"
|
|
+ strength.ToString("0.#") + "\t" + reason);
|
|
}
|
|
|
|
summary.AppendLine(domain + "\tlive=" + ids.Count + "\tA=" + a + "\tB=" + b);
|
|
}
|
|
|
|
private static string ReasonLibrary(DiscreteEventEntry entry)
|
|
{
|
|
if (entry == null)
|
|
{
|
|
return "missing";
|
|
}
|
|
|
|
if (entry.IsFallback)
|
|
{
|
|
return "fallback";
|
|
}
|
|
|
|
return entry.CreatesInterest ? "signal" : "ambient";
|
|
}
|
|
|
|
private static string ReasonDecisionB(string id)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
return "empty";
|
|
}
|
|
|
|
string s = id.ToLowerInvariant();
|
|
if (s == "try_new_plot" || s.StartsWith("try_new_plot_", StringComparison.Ordinal))
|
|
{
|
|
return "deny_plot_intent";
|
|
}
|
|
|
|
if (s.Contains("idle")
|
|
|| s.Contains("walking")
|
|
|| s.Contains("check")
|
|
|| s.Contains("wait")
|
|
|| s.Contains("sleep")
|
|
|| s.Contains("random")
|
|
|| s.Contains("play")
|
|
|| s.Contains("jump")
|
|
|| s.Contains("flip")
|
|
|| s.Contains("diet_")
|
|
|| s.Contains("move")
|
|
|| s.Contains("swim")
|
|
|| s.Contains("follow_parent")
|
|
|| s.Contains("follow_desire")
|
|
|| s.Contains("reflection")
|
|
|| s.Contains("poop"))
|
|
{
|
|
return "deny_fluff";
|
|
}
|
|
|
|
return "no_signal_token";
|
|
}
|
|
|
|
private static string SanitizeTsv(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
return "";
|
|
}
|
|
|
|
return value.Replace('\t', ' ').Replace('\n', ' ').Replace('\r', ' ');
|
|
}
|
|
}
|