Run 12: knowledge system, mortality, and the North's generational soul

SPEC §5 built: three skill domains (forage/woodcraft/masonry) that pay
off and grow by practice; proximity diffusion soul-calibrated by
absorption x teaching-drive; and mortality - the piece that makes
knowledge generational. Elders die (~150-230 days), everything unshared
dies with them, a youth comes of age near knowing nothing. North soul
(absorption 1.6, teaching 0.9) vs South (1.0, 0.3); East teaches no one.

Two findings: (1) headless soaks were contaminated by orphaned child
processes writing later runs' CSVs - fixed with StopAfterDays clean
self-terminate; (2) passive diffusion barely helped - the North's real
culture is the young seeking elders on purpose, so added deliberate
teacher-seeking and youths now cradle beside the wisest elder. North
now leads knowledge at every checkpoint, but a stable town approaches
the ceiling regardless, so teaching is a recovery advantage not an
equilibrium one. The crisis-recovery experiment is the real test, noted
in FINDINGS as next.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 16:27:28 -04:00
parent 3ffde3d9e9
commit 3e4e44c623
15 changed files with 7059 additions and 7171 deletions
+15 -4
View File
@@ -21,11 +21,12 @@ public static class StatsLogger
"avg_fatigue,avg_nourish,avg_health,carried," +
"gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
"shelters_done,ruins,avg_cond,upkeep_stock,burn_per_day,modules,granary_food," +
"avg_debris,refusals,incomplete_sites";
"avg_debris,refusals,incomplete_sites,avg_knowledge,deaths";
private const string NpcHeader =
"day,npc,name,soul,town,dominant,gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
"nourish,health,debris,demand,rough_nights,hunger_mem";
"nourish,health,debris,demand,rough_nights,hunger_mem," +
"age,know_forage,know_wood,know_masonry";
private const string GiftHeader =
"day,giver,giver_soul,receiver,receiver_soul,material,amount";
@@ -143,7 +144,12 @@ public static class StatsLogger
int incomplete = 0;
foreach (var b in gm.Buildings) if (!b.IsComplete) incomplete++;
row.Append(incomplete);
row.Append(incomplete).Append(',');
float knowSum = 0f;
foreach (var npc in gm.Npcs) knowSum += npc.Know.Total;
row.Append((knowSum / count).ToString("0.000", ci)).Append(',');
row.Append(gm.DeathsToday);
File.AppendAllText(_path, row + "\n");
@@ -170,7 +176,11 @@ public static class StatsLogger
.Append(npc.Imprint.Total.ToString("0.0000", ci)).Append(',')
.Append(npc.CurrentDemand(gm)).Append(',')
.Append(npc.RoughNights).Append(',')
.Append(npc.HungerMemory ? 1 : 0).Append('\n');
.Append(npc.HungerMemory ? 1 : 0).Append(',')
.Append(npc.AgeDays.ToString("0", ci)).Append(',')
.Append(npc.Know[KnowledgeDomain.Forage].ToString("0.000", ci)).Append(',')
.Append(npc.Know[KnowledgeDomain.Woodcraft].ToString("0.000", ci)).Append(',')
.Append(npc.Know[KnowledgeDomain.Masonry].ToString("0.000", ci)).Append('\n');
System.Array.Clear(npc.StateTicksToday, 0, npc.StateTicksToday.Length);
}
File.AppendAllText(_npcPath, npcRows.ToString());
@@ -179,5 +189,6 @@ public static class StatsLogger
gm.World.HarvestedToday = 0f;
TradeSystem.TradesToday = 0;
TradeSystem.RefusalsToday = 0;
gm.DeathsToday = 0;
}
}