Fix: the East builds private homes (an all-selfish town was homeless)
An all-selfish town had founded zero buildings ever - selfish souls never do communal work, and with no nature souls to build shelters they could freeride on, the whole East slept rough forever. That was too absolute: the East's design is "personal wealth infrastructure," not homelessness. Selfish souls now build a shelter for THEMSELVES after enough rough nights - private property, founded where they sleep (no clustering to the town center), never for anyone else. Required routing homeless-with-stone selfish souls into the Building state (three paths previously sent them straight to Socializing) and moving the homeless-stone gather rule ahead of the communal-only block. Result: East houses itself (11 private homesteads over a run) as scattered homes vs the others' clustered villages - a visible cultural signature. And the verdict sharpens: East is now fed and housed but still lowest knowledge and highest debris. Selfishness's cost is soul-marks and ignorance, not homelessness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+81
-7
@@ -370,6 +370,13 @@ public class Npc
|
||||
if (foodCarried < reserveTarget && (Nourishment < 0.8f || Soul.Accumulation > 0.5f))
|
||||
return MaterialKind.Food;
|
||||
|
||||
// Homeless too long → gather stone for a roof, whatever your soul.
|
||||
// Even the selfish build private shelter; they just won't build it
|
||||
// for anyone else. (Communal souls also queue this below, guarded by
|
||||
// whether the town already has a shelter under construction.)
|
||||
if (!IsCommunal && _unshelteredRests >= 3)
|
||||
return MaterialKind.Stone;
|
||||
|
||||
if (IsCommunal)
|
||||
{
|
||||
// Communal duty is to your own settlement — you heat your own
|
||||
@@ -508,8 +515,16 @@ public class Npc
|
||||
if (TotalCarried() >= EffectiveCapacity)
|
||||
{
|
||||
// A full pack means different things to different souls:
|
||||
// communal souls take it to the village; hoarders sit on it.
|
||||
if (!IsCommunal) { Enter(NpcState.Socializing); return; }
|
||||
// communal souls take it to the village; hoarders sit on it —
|
||||
// unless they're homeless and carrying stone, in which case even
|
||||
// a selfish soul goes to raise their own roof.
|
||||
if (!IsCommunal)
|
||||
{
|
||||
bool hasStone = Inventory.TryGetValue(MaterialKind.Stone, out float s) && s > 0f;
|
||||
if (_unshelteredRests >= 3 && hasStone) { Enter(NpcState.Building); return; }
|
||||
Enter(NpcState.Socializing);
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory.TryGetValue(demanded, out float haveDemanded);
|
||||
if (haveDemanded >= EffectiveCapacity * 0.25f) { Enter(NpcState.Building); return; }
|
||||
@@ -592,9 +607,14 @@ public class Npc
|
||||
Inventory.TryGetValue(_targetNode.Kind, out float have);
|
||||
Inventory[_targetNode.Kind] = have + taken;
|
||||
|
||||
// Enough of what's needed? Communal souls go deliver it.
|
||||
// Enough of what's needed? Communal souls go deliver it; a
|
||||
// homeless selfish soul with enough stone goes to build its own.
|
||||
Inventory.TryGetValue(PickGatherTarget(gm), out float demandedHave);
|
||||
if (IsCommunal && demandedHave >= EffectiveCapacity * 0.5f) Enter(NpcState.Building);
|
||||
if (IsCommunal && demandedHave >= EffectiveCapacity * 0.5f)
|
||||
Enter(NpcState.Building);
|
||||
else if (!IsCommunal && _unshelteredRests >= 3 &&
|
||||
Inventory.TryGetValue(MaterialKind.Stone, out float st) && st >= 10f)
|
||||
Enter(NpcState.Building);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,11 +648,65 @@ public class Npc
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A self-interested soul raising a roof for itself — private property,
|
||||
/// not communal service. Contributes to their own in-progress shelter,
|
||||
/// or founds one at their spot if carrying stone. This is why an
|
||||
/// all-selfish town (the East) has homes at all: not cooperation, just
|
||||
/// each person eventually housing themselves.
|
||||
/// </summary>
|
||||
private void FoundOwnShelter(GameManager gm)
|
||||
{
|
||||
// Contribute to an unfinished shelter near me (likely my own).
|
||||
Building? mine = null;
|
||||
float best = 900f; // within 30 units
|
||||
foreach (var b in gm.Buildings)
|
||||
{
|
||||
if (b.Town != HomeTown || b.IsComplete || b.Kind != BuildingKind.Shelter) continue;
|
||||
float d = Position.DistanceSquaredTo(b.Site);
|
||||
if (d < best) { best = d; mine = b; }
|
||||
}
|
||||
|
||||
if (mine == null)
|
||||
{
|
||||
// Found one where I sleep — the selfish homestead where they
|
||||
// please, no clustering toward the town's shared center.
|
||||
if (!Inventory.TryGetValue(MaterialKind.Stone, out float stone) || stone <= 0f)
|
||||
{
|
||||
Enter(NpcState.Gathering); // no stone yet — go get it
|
||||
return;
|
||||
}
|
||||
Vector2 spot = _hasHomeSpot ? _homeSpot : Position;
|
||||
mine = Building.NewShelter(spot);
|
||||
mine.Town = HomeTown;
|
||||
gm.Buildings.Add(mine);
|
||||
_unshelteredRests = 0;
|
||||
Godot.GD.Print($"[Homestead] day {gm.Day}: {Name} ({HomeTown}) raises a private roof.");
|
||||
}
|
||||
|
||||
Activity = "building my own shelter";
|
||||
MoveToward(mine.Site);
|
||||
if (Position.DistanceTo(mine.Site) < ArriveDist)
|
||||
{
|
||||
bool delivered = mine.Deliver(this);
|
||||
if (!delivered || mine.IsComplete) Enter(NpcState.Socializing);
|
||||
}
|
||||
}
|
||||
|
||||
private void TickBuilding(GameManager gm)
|
||||
{
|
||||
// Communal work is for communal souls. The others still sleep in the
|
||||
// shelters and eat from the granary — freeriding is the whole point.
|
||||
if (!IsCommunal) { Enter(NpcState.Socializing); return; }
|
||||
// Communal work is for communal souls — the others don't tend the
|
||||
// village's hearths or fill its granary. But even a selfish soul
|
||||
// builds a roof for ITSELF: a shelter is private property, and after
|
||||
// enough rough nights they'll raise one (the East's "personal wealth
|
||||
// infrastructure"). So non-communal souls pass only when personally
|
||||
// homeless, and only to found their own shelter — not to serve.
|
||||
if (!IsCommunal)
|
||||
{
|
||||
if (_unshelteredRests < 3) { Enter(NpcState.Socializing); return; }
|
||||
FoundOwnShelter(gm);
|
||||
return;
|
||||
}
|
||||
|
||||
// Serve your own settlement's buildings, nearest first:
|
||||
// construction → firewood → granary deposits → expansion.
|
||||
|
||||
Reference in New Issue
Block a user