Add camera inventory audit and expand event catalog actions.
- 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
This commit is contained in:
parent
ef561b87d8
commit
f10424c5df
10 changed files with 657 additions and 95 deletions
|
|
@ -7326,6 +7326,13 @@ public static class AgentHarness
|
|||
+ $"kinds={kinds.Count}";
|
||||
break;
|
||||
}
|
||||
case "camera_a_inventory_ok":
|
||||
{
|
||||
CameraAInventoryResult inv = CameraAInventoryHarness.RunAudit(HarnessDir());
|
||||
pass = inv.Passed;
|
||||
detail = inv.Detail;
|
||||
break;
|
||||
}
|
||||
case "library_ambient_policy_ok":
|
||||
{
|
||||
// Signal-only libraries: ambient dials must be B; phenotypes all B;
|
||||
|
|
|
|||
278
IdleSpectator/CameraAInventoryHarness.cs
Normal file
278
IdleSpectator/CameraAInventoryHarness.cs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
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', ' ');
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +51,37 @@ public static partial class EventCatalog
|
|||
["warrior_army_follow_leader"] = "follow their leader",
|
||||
["warrior_train_with_dummy"] = "train with a dummy",
|
||||
["warrior_try_join_army_group"] = "try to join an army",
|
||||
["warrior_army_leader_move_to_attack_target"] = "lead the army to attack",
|
||||
|
||||
// Founding / territory
|
||||
["try_to_start_new_civilization"] = "start a new civilization",
|
||||
["build_civ_city_here"] = "found a city here",
|
||||
["claim_land"] = "claim this land",
|
||||
["king_check_new_city_foundation"] = "found a new city",
|
||||
["bee_create_hive"] = "create a hive",
|
||||
|
||||
// Life / pack
|
||||
["sexual_reproduction_try"] = "try to reproduce",
|
||||
["asexual_reproduction_budding"] = "reproduce by budding",
|
||||
["asexual_reproduction_divine"] = "reproduce by divine means",
|
||||
["asexual_reproduction_fission"] = "reproduce by fission",
|
||||
["asexual_reproduction_parthenogenesis"] = "reproduce by parthenogenesis",
|
||||
["asexual_reproduction_spores"] = "reproduce by spores",
|
||||
["asexual_reproduction_vegetative"] = "reproduce vegetatively",
|
||||
["family_group_follow"] = "follow their family group",
|
||||
["family_group_join_or_new_herd"] = "join or form a herd",
|
||||
["family_group_leave"] = "leave their family group",
|
||||
|
||||
// Spectacle / dark / civic
|
||||
["attack_golden_brain"] = "attack the golden brain",
|
||||
["make_skeleton"] = "raise a skeleton",
|
||||
["status_soul_harvested"] = "have their soul harvested",
|
||||
["possessed_following"] = "follow under possession",
|
||||
["try_to_take_city_item"] = "try to take a city item",
|
||||
["put_out_fire"] = "put out a fire",
|
||||
["burn_tumors"] = "burn tumors",
|
||||
["try_to_launch_fireworks"] = "launch fireworks",
|
||||
["try_affect_dreams"] = "affect dreams",
|
||||
};
|
||||
|
||||
/// <summary>Drop cached rows so the next Ensure re-applies JSON overlays.</summary>
|
||||
|
|
@ -68,26 +99,6 @@ public static partial class EventCatalog
|
|||
}
|
||||
|
||||
string s = id.ToLowerInvariant();
|
||||
// Pure AI ticks / daily fluff - not story beats.
|
||||
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 false;
|
||||
}
|
||||
|
||||
// Intent-only: setDecisionCooldown fires before a Plot exists (and often never does).
|
||||
// Real plot tips come from PlotInterestFeed / live World.plots.
|
||||
|
|
@ -96,7 +107,15 @@ public static partial class EventCatalog
|
|||
return false;
|
||||
}
|
||||
|
||||
// Daily AI / check ticks. Foundation checks stay eligible for Signal tokens.
|
||||
if (IsFluffDecision(s))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasToken(s, "war")
|
||||
|| HasToken(s, "king")
|
||||
|| HasToken(s, "leader")
|
||||
|| s.Contains("rebellion")
|
||||
|| s.Contains("revolt")
|
||||
|| s.Contains("alliance")
|
||||
|
|
@ -114,14 +133,79 @@ public static partial class EventCatalog
|
|||
|| s.Contains("banish")
|
||||
|| s.Contains("steal")
|
||||
|| s.Contains("kill_unruly")
|
||||
|| HasToken(s, "king")
|
||||
|| HasToken(s, "leader")
|
||||
|| s.Contains("clan")
|
||||
|| s.Contains("religion")
|
||||
|| s.Contains("culture")
|
||||
|| s.Contains("baby_make")
|
||||
|| s.Contains("have_child")
|
||||
|| s.Contains("birth");
|
||||
|| s.Contains("birth")
|
||||
|| s.Contains("reproduction")
|
||||
|| s.Contains("civilization")
|
||||
|| s.Contains("civ_city")
|
||||
|| s.Contains("claim_land")
|
||||
|| s.Contains("golden_brain")
|
||||
|| s.Contains("make_skeleton")
|
||||
|| s.Contains("soul_harvest")
|
||||
|| s.Contains("possessed")
|
||||
|| s.Contains("create_hive")
|
||||
|| s.Contains("fireworks")
|
||||
|| s.Contains("affect_dreams")
|
||||
|| s.Contains("family_group")
|
||||
|| s.Contains("take_city_item")
|
||||
|| s.Contains("put_out_fire")
|
||||
|| s.Contains("burn_tumors");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure AI ticks / daily fluff. Not story beats.
|
||||
/// <c>city_foundation</c> checks are excluded so kings can Signal founding intent.
|
||||
/// </summary>
|
||||
private static bool IsFluffDecision(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (s.Contains("city_foundation"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.StartsWith("check_", StringComparison.Ordinal)
|
||||
|| s.Contains("_check_")
|
||||
|| s.EndsWith("_check", StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return s.Contains("idle")
|
||||
|| s.Contains("walking")
|
||||
|| s.Contains("sleep")
|
||||
|| s.Contains("play")
|
||||
|| s.Contains("jump")
|
||||
|| s.Contains("flip")
|
||||
|| s.Contains("diet_")
|
||||
|| s.Contains("reflection")
|
||||
|| s.Contains("poop")
|
||||
|| s.Contains("follow_parent")
|
||||
|| s.Contains("follow_desire")
|
||||
|| s.Contains("move_random")
|
||||
|| s.Contains("random_move")
|
||||
|| s.Contains("random_fun")
|
||||
|| s.Contains("random_swim")
|
||||
|| s.Contains("random_teleport")
|
||||
|| s.Contains("random_emotion")
|
||||
|| s.Contains("warrior_random")
|
||||
|| s.Contains("captain_waiting")
|
||||
|| s.Contains("captain_idle")
|
||||
|| s.Contains("_waiting")
|
||||
|| s == "wait5"
|
||||
|| s.Contains("swim_to")
|
||||
|| s.Contains("move_to_water")
|
||||
|| s.Contains("bored_sleep")
|
||||
|| s.Contains("monophasic")
|
||||
|| s.Contains("polyphasic");
|
||||
}
|
||||
|
||||
/// <summary>Underscore-token match so <c>war</c> does not hit <c>warrior</c>.</summary>
|
||||
|
|
|
|||
|
|
@ -143,6 +143,17 @@ public static partial class EventCatalog
|
|||
}
|
||||
|
||||
string s = id.ToLowerInvariant();
|
||||
// God-tool editors / drip brushes stay B.
|
||||
if (s.Contains("_edit")
|
||||
|| s.Contains("traits_")
|
||||
|| s.Contains("equipment_rain")
|
||||
|| s.EndsWith("_brush", StringComparison.Ordinal)
|
||||
|| s.Contains("draw_")
|
||||
|| s.Contains("paint"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return s.Contains("meteor")
|
||||
|| s.Contains("earthquake")
|
||||
|| s.Contains("tornado")
|
||||
|
|
@ -150,12 +161,28 @@ public static partial class EventCatalog
|
|||
|| s.Contains("nuke")
|
||||
|| s.Contains("bomb")
|
||||
|| s.Contains("rain_blood")
|
||||
|| s.Contains("blood_rain")
|
||||
|| s.Contains("hell")
|
||||
|| s.Contains("lightning")
|
||||
|| s.Contains("storm")
|
||||
|| s.Contains("acid")
|
||||
|| s.Contains("fire")
|
||||
|| s.Contains("disaster");
|
||||
|| s.Contains("disaster")
|
||||
|| s.Contains("dragon")
|
||||
|| s.Contains("demon")
|
||||
|| s.Contains("plague")
|
||||
|| s.Contains("zombie")
|
||||
|| s.Contains("crabzilla")
|
||||
|| s == "ufo"
|
||||
|| s.Contains("god_finger")
|
||||
|| s.Contains("cold_one")
|
||||
|| s.Contains("heatray")
|
||||
|| s.Contains("curse")
|
||||
|| s.Contains("lava")
|
||||
|| s.Contains("ash")
|
||||
|| s.Contains("golden_brain")
|
||||
|| s.Contains("corrupted_brain")
|
||||
|| s.Contains("infection");
|
||||
}
|
||||
|
||||
private static void Ensure()
|
||||
|
|
@ -218,7 +245,8 @@ public static partial class EventCatalog
|
|||
}
|
||||
|
||||
string s = id.ToLowerInvariant();
|
||||
// Top-tier materials from live items library (mythril/adamantine) plus named relics.
|
||||
// High / mid-spectacle materials from live items library plus named relics.
|
||||
// Leather/wood/copper/iron stay ambient B.
|
||||
return s.Contains("legendary")
|
||||
|| s.Contains("mythic")
|
||||
|| s.Contains("mythril")
|
||||
|
|
@ -230,7 +258,12 @@ public static partial class EventCatalog
|
|||
|| s.Contains("dragon")
|
||||
|| s.Contains("nuke")
|
||||
|| s.Contains("excalibur")
|
||||
|| s.Contains("wonder");
|
||||
|| s.Contains("wonder")
|
||||
|| s.Contains("silver")
|
||||
|| s.Contains("steel")
|
||||
|| s.Contains("_bone")
|
||||
|| s.StartsWith("bone_", StringComparison.Ordinal)
|
||||
|| s.EndsWith("_bone", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static void Ensure()
|
||||
|
|
@ -306,7 +339,12 @@ public static partial class EventCatalog
|
|||
|| s.Contains("undead")
|
||||
|| s.Contains("dragon")
|
||||
|| s.Contains("evolve")
|
||||
|| s.Contains("mutate");
|
||||
|| s.Contains("mutate")
|
||||
|| s.Contains("mutation")
|
||||
|| s.Contains("death")
|
||||
|| s.Contains("blood")
|
||||
|| s.Contains("horror")
|
||||
|| s.Contains("tentacle");
|
||||
}
|
||||
|
||||
private static void Ensure()
|
||||
|
|
@ -379,10 +417,25 @@ public static partial class EventCatalog
|
|||
d.AmbientStrength,
|
||||
signalIds: null,
|
||||
d.SignalStrength,
|
||||
signalPredicate: id => id != null && (id.Contains("warfare") || id.Contains("magic") || id.Contains("mutation")),
|
||||
signalPredicate: IsSignalGene,
|
||||
ambientCreatesInterest: d.AmbientCreatesInterest);
|
||||
}
|
||||
|
||||
private static bool IsSignalGene(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string s = id.ToLowerInvariant();
|
||||
return s.Contains("warfare")
|
||||
|| s.Contains("magic")
|
||||
|| s.Contains("mutation")
|
||||
|| s.Contains("mutagen")
|
||||
|| s.Contains("damage");
|
||||
}
|
||||
|
||||
public static IEnumerable<string> AuthoredIds
|
||||
{
|
||||
get
|
||||
|
|
@ -501,7 +554,17 @@ public static partial class EventCatalog
|
|||
|| s.Contains("hunger")
|
||||
|| s.Contains("rebell")
|
||||
|| s.Contains("disaster")
|
||||
|| s.Contains("angry");
|
||||
|| s.Contains("angry")
|
||||
|| s.Contains("cursed")
|
||||
|| s.Contains("forever_")
|
||||
|| s.Contains("tumor")
|
||||
|| s.Contains("mutant")
|
||||
|| s.Contains("evolution")
|
||||
|| s.Contains("old_age")
|
||||
|| s.Contains("kingdom_expansion")
|
||||
|| s.Contains("border_steal")
|
||||
|| s.Contains("civ_army")
|
||||
|| s.Contains("exploding");
|
||||
}
|
||||
|
||||
public static IEnumerable<string> AuthoredIds
|
||||
|
|
@ -596,7 +659,18 @@ public static partial class EventCatalog
|
|||
|| s.Contains("zealot")
|
||||
|| s.Contains("fanatic")
|
||||
|| s.Contains("schism")
|
||||
|| s.Contains("royal");
|
||||
|| s.Contains("royal")
|
||||
|| s.Contains("conscript")
|
||||
|| s.Contains("join_or_die")
|
||||
|| s.Contains("necro")
|
||||
|| s.Contains("evil")
|
||||
|| s.Contains("shattered")
|
||||
|| s.Contains("titan")
|
||||
|| s.Contains("ethno")
|
||||
|| s.Contains("flame")
|
||||
|| s.Contains("ice_weapon")
|
||||
|| s.Contains("shotgun")
|
||||
|| s.Contains("blaster");
|
||||
}
|
||||
|
||||
public static class CultureTrait
|
||||
|
|
|
|||
|
|
@ -1994,6 +1994,7 @@ internal static class HarnessScenarios
|
|||
Step("dea1", "assert", expect: "domain_event_audit"),
|
||||
Step("dea1b", "assert", expect: "library_asset_labels_ok"),
|
||||
Step("dea1c", "assert", expect: "library_ambient_policy_ok"),
|
||||
Step("dea1d", "assert", expect: "camera_a_inventory_ok"),
|
||||
Step("dea2", "snapshot")
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,131 @@
|
|||
"id": "warrior_try_join_army_group",
|
||||
"action": "try to join an army",
|
||||
"strength": 64
|
||||
},
|
||||
{
|
||||
"id": "warrior_army_leader_move_to_attack_target",
|
||||
"action": "lead the army to attack",
|
||||
"strength": 72
|
||||
},
|
||||
{
|
||||
"id": "try_to_start_new_civilization",
|
||||
"action": "start a new civilization",
|
||||
"strength": 90
|
||||
},
|
||||
{
|
||||
"id": "build_civ_city_here",
|
||||
"action": "found a city here",
|
||||
"strength": 86
|
||||
},
|
||||
{
|
||||
"id": "claim_land",
|
||||
"action": "claim this land",
|
||||
"strength": 70
|
||||
},
|
||||
{
|
||||
"id": "king_check_new_city_foundation",
|
||||
"action": "found a new city",
|
||||
"strength": 88
|
||||
},
|
||||
{
|
||||
"id": "bee_create_hive",
|
||||
"action": "create a hive",
|
||||
"strength": 68
|
||||
},
|
||||
{
|
||||
"id": "sexual_reproduction_try",
|
||||
"action": "try to reproduce",
|
||||
"strength": 66
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_budding",
|
||||
"action": "reproduce by budding",
|
||||
"strength": 64
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_divine",
|
||||
"action": "reproduce by divine means",
|
||||
"strength": 78
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_fission",
|
||||
"action": "reproduce by fission",
|
||||
"strength": 64
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_parthenogenesis",
|
||||
"action": "reproduce by parthenogenesis",
|
||||
"strength": 66
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_spores",
|
||||
"action": "reproduce by spores",
|
||||
"strength": 64
|
||||
},
|
||||
{
|
||||
"id": "asexual_reproduction_vegetative",
|
||||
"action": "reproduce vegetatively",
|
||||
"strength": 62
|
||||
},
|
||||
{
|
||||
"id": "family_group_follow",
|
||||
"action": "follow their family group",
|
||||
"strength": 52
|
||||
},
|
||||
{
|
||||
"id": "family_group_join_or_new_herd",
|
||||
"action": "join or form a herd",
|
||||
"strength": 58
|
||||
},
|
||||
{
|
||||
"id": "family_group_leave",
|
||||
"action": "leave their family group",
|
||||
"strength": 56
|
||||
},
|
||||
{
|
||||
"id": "attack_golden_brain",
|
||||
"action": "attack the golden brain",
|
||||
"strength": 92
|
||||
},
|
||||
{
|
||||
"id": "make_skeleton",
|
||||
"action": "raise a skeleton",
|
||||
"strength": 80
|
||||
},
|
||||
{
|
||||
"id": "status_soul_harvested",
|
||||
"action": "have their soul harvested",
|
||||
"strength": 86
|
||||
},
|
||||
{
|
||||
"id": "possessed_following",
|
||||
"action": "follow under possession",
|
||||
"strength": 74
|
||||
},
|
||||
{
|
||||
"id": "try_to_take_city_item",
|
||||
"action": "try to take a city item",
|
||||
"strength": 66
|
||||
},
|
||||
{
|
||||
"id": "put_out_fire",
|
||||
"action": "put out a fire",
|
||||
"strength": 60
|
||||
},
|
||||
{
|
||||
"id": "burn_tumors",
|
||||
"action": "burn tumors",
|
||||
"strength": 62
|
||||
},
|
||||
{
|
||||
"id": "try_to_launch_fireworks",
|
||||
"action": "launch fireworks",
|
||||
"strength": 58
|
||||
},
|
||||
{
|
||||
"id": "try_affect_dreams",
|
||||
"action": "affect dreams",
|
||||
"strength": 56
|
||||
}
|
||||
],
|
||||
"species": [
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "IdleSpectator",
|
||||
"author": "dazed",
|
||||
"version": "0.28.25",
|
||||
"version": "0.28.27",
|
||||
"description": "AFK Idle Spectator (I) + Lore (L). Killer button retargets dossier to the killer.",
|
||||
"GUID": "com.dazed.idlespectator"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@ Authored 1:1 libraries match live counts with zero missing/orphan ids.
|
|||
Live+dial libraries are fully seeded.
|
||||
`mutation_gaps.tsv` is empty (`gaps=0`).
|
||||
|
||||
The feeling of “lots of events/tips we are not tracking” is mostly **tip quality and Layer A noise**, not missing catalog rows:
|
||||
Id inventory and interesting Layer A policy are in good shape as of **0.28.27** (`camera_a_inventory`: **219 A / 924 B** on library+decision domains; decisions **37** camera with phrases).
|
||||
|
||||
1. Library Labels still interpolate raw `{id}` (`culture gains xenophobic`, `forges armor_leather`).
|
||||
2. Large ambient-A surfaces (items, genes, phenotypes, subspecies traits, meta traits, world laws) own the camera with generic templates.
|
||||
3. Building **complete / wonder finish** still has no Layer A wire (destroy/consume only).
|
||||
4. Meta-trait domains are live-seeded and TSV-audited but **not fail-gated** by `domain_event_audit`.
|
||||
Remaining feel of thin tips is mostly **soak share / strength vs filler**, not missing catalog rows:
|
||||
|
||||
1. Library Labels use display names (Wave 1); keep watching for weak verbs.
|
||||
2. Ambient CI stays false; Signal predicates own library A (expanded 0.28.27).
|
||||
3. Building civ complete / wonder A is wired.
|
||||
4. Meta-trait domains are fail-gated by `domain_event_audit` + `camera_a_inventory_ok`.
|
||||
|
||||
Tips here means watch tip / orange reason Labels from interest feeds, not dossier chip hover tooltips.
|
||||
|
||||
|
|
@ -60,27 +62,32 @@ Seeded via `LiveLibraryInterest.EnsureSeeded` + JSON `libraries.*` dials.
|
|||
|
||||
| Domain | Live | Camera A | Dial label template | Notes | Priority |
|
||||
|--------|-----:|---------:|---------------------|-------|----------|
|
||||
| decisions | 127 | 12 | `{a} decides to {action}` | 12 camera ids have action phrases; 2 JSON overlays are non-camera (`try_new_plot`, `warrior_train_with_dummy`) | P1 only if new interesting decisions appear |
|
||||
| spells | 12 | 12 | `{a} casts {id}` | 7 signalIds @86; 5 ambient A @44 | P1 display names; P2 signal set |
|
||||
| powers | 339 | 23 | `God power: {id}` | ambient CI=false; spectacle predicate | P1 display names |
|
||||
| items | 111 | 111 | `{a} forges {id}` | ambient A; “forges” weak for armor/non-craft | P1 tip quality |
|
||||
| genes | 47 | 47 | `{a} gains gene {id}` | ambient A | P1 names; P2 demote ambient spam |
|
||||
| phenotypes | 52 | 52 | `{a} shows {id}` | ambient A | P1 names; P2 demote ambient spam |
|
||||
| world_laws | 49 | 49 | `Law changed: {id}` | ambient A | P1 names |
|
||||
| subspecies_traits | 204 | 204 | `{a} evolves {id}` | ambient A | P1 names; P2 Signal heuristics |
|
||||
| decisions | 127 | **37** | `{a} decides to {action}` | Signal tokens + authored phrases; fluff/`try_new_plot` B; dump `.harness/camera-a-inventory.tsv` | P3 expanded 0.28.27 |
|
||||
| spells | 12 | 6 | `{a} casts {id}` | Signal spectacle only; FX spells B | P3 |
|
||||
| powers | 339 | **41** | `God power: {id}` | ambient CI=false; widened spectacle + creature powers; UI `_edit` B | P3 expanded 0.28.27 |
|
||||
| items | 111 | **42** | `{a} gains {id}` | Signal mythril/adamantine + silver/steel/bone; leather/iron B | P3 expanded 0.28.27 |
|
||||
| genes | 47 | **7** | `{a} gains gene {id}` | warfare/damage/mutagen Signal | P3 expanded 0.28.27 |
|
||||
| phenotypes | 52 | 0 | `{a} shows {id}` | all B | P3 |
|
||||
| world_laws | 49 | **17** | `Law changed: {id}` | dramatic + forever_/cursed/army/expansion… | P3 expanded 0.28.27 |
|
||||
| subspecies_traits | 204 | **21** | `{a} evolves {id}` | dramatic + mutation/death/blood/horror | P3 expanded 0.28.27 |
|
||||
| biomes | 29 | 0 | `Biome shifts: {id}` | ambient CI=false | P3 stay B |
|
||||
| culture_traits | 78 | 78 | `{a} culture gains {id}` | ~14 dramatic @74; rest ambient @34 | P1 names; hygiene gate |
|
||||
| religion_traits | 40 | 40 | `{a} faith gains {id}` | dramatic heuristic | P1 names; hygiene gate |
|
||||
| clan_traits | 29 | 29 | `{a} clan gains {id}` | dramatic heuristic | P1 names; hygiene gate |
|
||||
| language_traits | 26 | 26 | `{a} tongue gains {id}` | dramatic heuristic | P1 names; hygiene gate |
|
||||
| culture_traits | 78 | **27** | `{a} culture gains {id}` | dramatic + conscript/necro/craft weapons… | P3 expanded 0.28.27 |
|
||||
| religion_traits | 40 | 6 | `{a} faith gains {id}` | dramatic heuristic | P3 |
|
||||
| clan_traits | 29 | 13 | `{a} clan gains {id}` | dramatic heuristic | P3 |
|
||||
| language_traits | 26 | 2 | `{a} tongue gains {id}` | dramatic heuristic | P3 |
|
||||
|
||||
Decision camera set (all have authored action phrases):
|
||||
`try_to_steal_money`, `kill_unruly_clan_members`, `banish_unruly_clan_members`, `find_lover`,
|
||||
`king_change_kingdom_{language,culture,religion}`, `leader_change_city_{language,culture,religion}`,
|
||||
`warrior_try_join_army_group`, `warrior_army_follow_leader`.
|
||||
**Library+decision Layer A inventory (0.28.27):** live dump total **219 A / 924 B** across 13 domains (`camera_a_inventory_ok`).
|
||||
|
||||
Spell signalIds (strength 86): `summon_lightning`, `summon_tornado`, `cast_curse`, `cast_fire`, `cast_blood_rain`, `summon_meteor`, `teleport`.
|
||||
Ambient-A spells @44: `cast_silence`, `cast_grass_seeds`, `spawn_vegetation`, `spawn_skeleton`, `cast_shield`, `cast_cure`.
|
||||
### Decision camera classes (0.28.27)
|
||||
|
||||
Allow-token Signal after fluff filter (not 127 ambient).
|
||||
Authored action phrases required for every A id (`domain_event_audit` decision_prose).
|
||||
|
||||
Classes: founding/territory (`civilization`, `civ_city`, `claim_land`, `city_foundation`), reproduction/pack (`reproduction`, `family_group`), army/war/politics (existing), spectacle/dark (`golden_brain`, `make_skeleton`, `soul_harvest`, `possessed`), civic soft (`put_out_fire`, `burn_tumors`, `fireworks`, `affect_dreams`), hive (`create_hive`).
|
||||
|
||||
Stay B: `try_new_plot*`, diet/sleep/random/check ticks, `warrior_train_with_dummy`, boat trade/fish, house/job/tax chores.
|
||||
|
||||
Spell Signal: spectacle summons/curses/fire/teleport/meteor; FX silence/shield/cure/grass/vegetation/skeleton stay B.
|
||||
|
||||
## Patch-only / no catalog rows
|
||||
|
||||
|
|
@ -156,6 +163,14 @@ Status (2026-07-17): **implemented** in mod `0.28.14`.
|
|||
3. `Building.completeConstruction` wires Layer A for `Building_Civ` (temple/statue spectacle strength bump).
|
||||
4. `domain_event_audit` fail-gates culture/religion/clan/language trait diffs; `library_asset_labels_ok` dumps `.harness/library-asset-labels.tsv`.
|
||||
|
||||
### Interesting A expansion (Phases 0–2)
|
||||
|
||||
Status (2026-07-17): **implemented** in mod `0.28.27`.
|
||||
|
||||
1. `camera_a_inventory_ok` dumps `.harness/camera-a-inventory.tsv` (nested in `domain_event_audit`).
|
||||
2. Decisions: fluff filter refined; Signal classes for founding/reproduction/pack/spectacle; **37** camera A with authored phrases.
|
||||
3. Library Signal widened (power/item/gene/worldLaw/subspecies/meta); ambient CI stays false; phenotypes/biomes stay 0 A.
|
||||
|
||||
### Wave 2 - Signal / ambient A tuning
|
||||
|
||||
Status (2026-07-17): **implemented** in mod `0.28.16`.
|
||||
|
|
|
|||
|
|
@ -9,44 +9,21 @@ traits 116 authored 0 116 wired authored_labels P3
|
|||
disasters 17 authored 0 via_worldlog wired authored_labels P3 disaster_war_audit PASS
|
||||
war_types_library 5 authored 0 dials wired authored_labels P3
|
||||
relationship 11 authored_discrete 0 11 wired authored_labels P3 no AssetManager lib
|
||||
decisions_library 127 live+dial 0 12 wired 12_action_phrases P1 try_new_plot and warrior_train_with_dummy authored non-camera
|
||||
spells 12 live+dial 0 12 wired raw_id_in_label P1 7 signalIds@86; 5 ambient@44
|
||||
powers 339 live+dial 0 23 wired raw_id_in_label P1 ambient CI=false
|
||||
items 111 live+dial 0 111 wired raw_id_forges_verb P1 ambient A; forge verb weak
|
||||
genes 47 live+dial 0 47 wired raw_id_in_label P1/P2 ambient A spam risk
|
||||
phenotypes 52 live+dial 0 52 wired raw_id_in_label P1/P2 ambient A spam risk
|
||||
world_laws_library 49 live+dial 0 49 wired raw_id_in_label P1/P2 ambient A
|
||||
subspecies_traits 204 live+dial 0 204 wired raw_id_in_label P1/P2 ambient A
|
||||
biome_library 29 live+dial 0 0 wired raw_id_template P3 ambient CI=false
|
||||
culture_traits 78 live+dial 0 78 wired raw_id_in_label P1 TSV audited; not fail-gated
|
||||
religion_traits 40 live+dial 0 40 wired raw_id_in_label P1 TSV audited; not fail-gated
|
||||
clan_traits 29 live+dial 0 29 wired raw_id_in_label P1 TSV audited; not fail-gated
|
||||
language_traits 26 live+dial 0 26 wired raw_id_in_label P1 TSV audited; not fail-gated
|
||||
decisions_library 127 live+dial 0 37 wired 37_action_phrases P3 expanded 0.28.27; camera-a-inventory.tsv
|
||||
spells 12 live+dial 0 6 wired display_names P3 Signal spectacle; 6 FX B
|
||||
powers 339 live+dial 0 41 wired display_names P3 Signal widened 0.28.27; ambient CI=false
|
||||
items 111 live+dial 0 42 wired gains_verb P3 Signal mythril/adamantine/silver/steel/bone
|
||||
genes 47 live+dial 0 7 wired display_names P3 warfare/damage/mutagen Signal
|
||||
phenotypes 52 live+dial 0 0 wired display_names P3 all B
|
||||
world_laws_library 49 live+dial 0 17 wired display_names P3 dramatic + forever_/cursed/army…
|
||||
subspecies_traits 204 live+dial 0 21 wired display_names P3 dramatic + mutation/death/blood
|
||||
biome_library 29 live+dial 0 0 wired display_names P3 ambient CI=false
|
||||
culture_traits 78 live+dial 0 27 wired display_names P3 dramatic widened 0.28.27
|
||||
religion_traits 40 live+dial 0 6 wired display_names P3
|
||||
clan_traits 29 live+dial 0 13 wired display_names P3
|
||||
language_traits 26 live+dial 0 2 wired display_names P3
|
||||
buildings 618 patch_only n/a consume_and_civ_complete partial EventReason.BuildingEat_BuildingComplete P3 civ complete/wonder A; destroy demoted B
|
||||
boats n/a patch_only n/a trade_unload wired EventReason.Boat P3 load skipped
|
||||
combat n/a csharp_policy n/a pair_keys wired EventReason.Fight P3
|
||||
architecture_library 53 none n/a 0 covered_by_building_activity n/a P3
|
||||
city_build_orders 3 none n/a 0 covered_by_building_activity n/a P3
|
||||
kingdoms_traits 5 none n/a 0 covered_by_trait_meta_feeds n/a P3
|
||||
items_modifiers 59 none n/a 0 covered_by_item_feed n/a P3
|
||||
combat_action_library 11 none n/a 0 covered_by_spell_combat_feeds n/a P2 only if distinct beats
|
||||
loyalty_library 29 none n/a 0 covered_by_worldlog_happiness n/a P3
|
||||
opinion_library 24 none n/a 0 covered_by_worldlog_happiness n/a P3
|
||||
knowledge_library 11 none n/a 0 covered_by_worldlog_happiness n/a P3
|
||||
communication_library 10 none n/a 0 covered_by_worldlog_happiness n/a P3
|
||||
story_library 1 none n/a 0 covered_by_worldlog_happiness n/a P3
|
||||
citizen_job_library 13 none n/a 0 covered_by_activity_dossier n/a P3
|
||||
professions 5 none n/a 0 covered_by_activity_dossier n/a P3
|
||||
personalities 5 none n/a 0 covered_by_activity_dossier n/a P3
|
||||
tasks_actor 217 none n/a 0 activity_taxonomy n/a P3 unmappedTasks=0
|
||||
actor_library 322 scoring_overlay n/a 0 species_discovery n/a P3 taxonomy PASS
|
||||
plot_category_library 9 none n/a 0 category_only n/a P3
|
||||
AllianceManager.removeObject n/a worldlog 0 via_alliance_dissolved worldlog_covers authored_worldlog P3 not mutation gap
|
||||
KingdomManager.removeObject n/a worldlog 0 via_kingdom_destroyed worldlog_covers authored_worldlog P3 not mutation gap
|
||||
building_complete_wonder n/a patch n/a civ_complete Building.completeConstruction EventReason.BuildingComplete P3 temple/statue spectacle strength
|
||||
World.era_manager_poll n/a wired n/a era_change WorldAgeManager.startNextAge EventCatalog.Era P3 update→startNextAge already emits
|
||||
World.earthquake_manager_poll n/a wired n/a quake_sticky Earthquake.startQuake EarthquakeActive P3 holds while isQuakeActive
|
||||
combat_action_library 11 covered_by_spell_combat n/a 0 CombatActionLibrary.tryToCastSpell n/a P3 no separate catalog
|
||||
story_knowledge_opinion n/a covered_by_worldlog_happiness n/a 0 n/a n/a P3 Wave3 closed
|
||||
personalities_professions 5+5 covered_by_activity_dossier n/a 0 n/a n/a P3 Wave3 closed
|
||||
camera_a_inventory 1143 harness 0 219 wired camera-a-inventory.tsv P3 A=219 B=924 domains=13; gate camera_a_inventory_ok
|
||||
mutation_gaps 0 harness 0 n/a gaps_empty n/a P3 managers=57 libraryAssets=2893
|
||||
|
|
|
|||
|
|
|
@ -52,10 +52,11 @@ Only true brief FX, cooldowns, civic Aggregates, and god-tool / biome spam stay
|
|||
| Relationship | 11 | all interesting discrete |
|
||||
| Plot / Era / War / Book | 28 / 11 / 5 / 12 | all A |
|
||||
| Trait | 116 | all CI |
|
||||
| Decision | 127 live / 14 prose overlays | 12 camera-interesting |
|
||||
| Spell / Item / Gene / Phenotype / WorldLaw / SubspeciesTrait | live | Signal-only A (ambient CI=false); phenotypes all B |
|
||||
| Culture / Religion / Clan / LanguageTrait | live dials | Signal-only via dramatic heuristic |
|
||||
| Power / Biome | live | Signal predicate only / ambient CI=false |
|
||||
| Decision | 127 live / 37 prose overlays | **37** camera-interesting (0.28.27) |
|
||||
| Spell / Item / Gene / Phenotype / WorldLaw / SubspeciesTrait | live | Signal-only A: spell 6 / item 42 / gene 7 / phenotype 0 / law 17 / subsp 21 |
|
||||
| Culture / Religion / Clan / LanguageTrait | live dials | Signal dramatic: 27 / 6 / 13 / 2 |
|
||||
| Power / Biome | live | Power Signal **41**; biome 0 (ambient CI=false) |
|
||||
| Library+decision inventory dump | 1143 rows | **219 A / 924 B** (`.harness/camera-a-inventory.tsv`) |
|
||||
| Building / Boat | none | destroy/consume/trade/unload; damage/load skipped |
|
||||
|
||||
## Wired hooks (major)
|
||||
|
|
|
|||
Loading…
Reference in a new issue