Soul layer: imprints, warmth echoes, and consequences
Ports the Unity POC soul systems into the sim: - Warmth echoes: villagers remember who fed them (+0.15) and who turned them away (-0.25). Ask-for-food targeting runs on memory, not omniscience; the remembered-cold are not asked. Echoes fade daily. - Refusing the hungry while holding food marks the refuser (others-regard debris) and is logged; empty-handed is not refusal. - Harvesting below the 50% commons line marks the taker per unit taken. - Soul-to-soul atmospheric pressure (SoulFieldSystem port): encased souls darken nearby atmospheres, clear souls lighten them. - Debris costs biologically: nourishment drains faster and meals restore less as the soul encases. - Instrumentation: avg_debris + refusals in daily stats; per-villager nourish/health/debris; refusals in the contact log; map dots dim with encasement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,38 @@ public partial class GameManager : Node2D
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Soul-to-soul atmospheric pressure (ported from the Unity POC's
|
||||
/// SoulFieldSystem): souls in proximity press on each other's
|
||||
/// atmospheres. An encased soul darkens the room; a clear soul makes
|
||||
/// it slightly easier for everyone near them to radiate. Both
|
||||
/// directions apply; the net effect depends on relative debris.
|
||||
/// </summary>
|
||||
private void ApplySoulPressure()
|
||||
{
|
||||
const float radius = 8f;
|
||||
const float strength = 0.00004f;
|
||||
|
||||
for (int i = 0; i < Npcs.Count; i++)
|
||||
{
|
||||
for (int j = i + 1; j < Npcs.Count; j++)
|
||||
{
|
||||
var a = Npcs[i];
|
||||
var b = Npcs[j];
|
||||
float dist = a.Position.DistanceTo(b.Position);
|
||||
if (dist > radius) continue;
|
||||
|
||||
float falloff = 1f - dist / radius;
|
||||
|
||||
float fromA = Mathf.Lerp(-strength, strength, a.Imprint.Total) * falloff;
|
||||
b.Imprint.ExternalPerception = Mathf.Clamp(b.Imprint.ExternalPerception + fromA, 0f, 1f);
|
||||
|
||||
float fromB = Mathf.Lerp(-strength, strength, b.Imprint.Total) * falloff;
|
||||
a.Imprint.ExternalPerception = Mathf.Clamp(a.Imprint.ExternalPerception + fromB, 0f, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Where the community's feet actually are — new communal
|
||||
/// buildings are founded here, not at a scripted town center.</summary>
|
||||
public Vector2 CommunityCentroid()
|
||||
@@ -113,11 +145,15 @@ public partial class GameManager : Node2D
|
||||
foreach (var npc in Npcs)
|
||||
npc.Tick(World, this);
|
||||
|
||||
ApplySoulPressure();
|
||||
|
||||
if (TotalTicks % 1440 == 0)
|
||||
{
|
||||
World.RegenerateDaily(SeasonFoodMult, SeasonWoodMult);
|
||||
foreach (var building in Buildings)
|
||||
building.DailyUpkeep();
|
||||
foreach (var npc in Npcs)
|
||||
npc.FadeEchoes(0.005f);
|
||||
StatsLogger.LogDay(this);
|
||||
if (Day % 10 == 0)
|
||||
GD.Print($"[WorldSim] Day {Day} complete.");
|
||||
|
||||
Reference in New Issue
Block a user