Run 10: organic recovery achieved - minerals are not a commons
Recovery blocker was material, not motivational. Two fixes: (1) harvest floors and commons debris apply only to living, regenerating resources - stone does not regrow, so "leave half" merely stranded the world supply and kept the homeless homeless forever; minerals now quarry to depletion for every soul equally. (2) Matter conservation: idle variety-gathering touches only renewables, and packs may only shed what the land replaces - lossy make-room had milled 900+ stone to dust during demand flapping. Verified over 260 headless days: year-1 winter still wrecks the naive town, it rebuilds in 20 days, famine survivors found the first granaries from hunger memory, and year-2 winter passes with zero ruins on stored reserves. The town has a history now: naive youth, catastrophe, learning, resilient maturity. Remaining tuning in FINDINGS.md: granary sprawl, post-famine nourishment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+19
-3
@@ -78,6 +78,11 @@ public class Npc
|
||||
/// who they are becoming. Indexed by (int)NpcState.</summary>
|
||||
public int[] StateTicksToday = new int[5];
|
||||
|
||||
// --- Diagnostics (read-only views for the stats logger) ---------------
|
||||
public MaterialKind CurrentDemand(GameManager gm) => PickGatherTarget(gm);
|
||||
public int RoughNights => _unshelteredRests;
|
||||
public bool HungerMemory => _hungerMemory;
|
||||
|
||||
public NpcState DominantStateToday()
|
||||
{
|
||||
int best = 0;
|
||||
@@ -116,6 +121,17 @@ public class Npc
|
||||
private static readonly MaterialKind[] GatherKinds =
|
||||
{ MaterialKind.Wood, MaterialKind.Stone, MaterialKind.Clay };
|
||||
|
||||
// Idle variety only touches what regrows. Minerals are mined on purpose
|
||||
// (construction, a roof of your own) — never as a hobby. Run 10 taught
|
||||
// us that idle mining + lossy packs can mill a world's stone to dust.
|
||||
private static readonly MaterialKind[] VarietyKinds =
|
||||
{ MaterialKind.Wood, MaterialKind.Food };
|
||||
|
||||
// What a pack may shed to make room: only matter the land replaces.
|
||||
// Set-down stone is stone destroyed — and the world doesn't make more.
|
||||
private static readonly MaterialKind[] DroppableKinds =
|
||||
{ MaterialKind.Wood, MaterialKind.Food, MaterialKind.Clay };
|
||||
|
||||
/// <summary>
|
||||
/// One simulation tick = one in-game minute (SPEC §9).
|
||||
/// Order per SPEC §10: vitals check → day/night bias → state behavior → fatigue.
|
||||
@@ -253,9 +269,9 @@ public class Npc
|
||||
return MaterialKind.Wood;
|
||||
}
|
||||
|
||||
MaterialKind best = GatherKinds[(int)(Mathf.Abs(PersonalityModifier) * 100f) % GatherKinds.Length];
|
||||
MaterialKind best = VarietyKinds[(int)(Mathf.Abs(PersonalityModifier) * 100f) % VarietyKinds.Length];
|
||||
float least = float.MaxValue;
|
||||
foreach (var kind in GatherKinds)
|
||||
foreach (var kind in VarietyKinds)
|
||||
{
|
||||
Inventory.TryGetValue(kind, out float have);
|
||||
if (have < least) { least = have; best = kind; }
|
||||
@@ -292,7 +308,7 @@ public class Npc
|
||||
Inventory.TryGetValue(demanded, out float haveDemanded);
|
||||
if (haveDemanded >= EffectiveCapacity * 0.25f) return;
|
||||
|
||||
foreach (var kind in GatherKinds)
|
||||
foreach (var kind in DroppableKinds)
|
||||
{
|
||||
if (kind == demanded) continue;
|
||||
if (TotalCarried() <= EffectiveCapacity * 0.5f) break;
|
||||
|
||||
Reference in New Issue
Block a user