Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c0c7088f8 | |||
| 9e8ee1d748 | |||
| 36f6ba1f1b | |||
| 10e772d087 | |||
| 6cbe4bcf83 | |||
| d7448c497d | |||
| 7de76fa45d | |||
| 3512b46235 | |||
| f9e22e872f |
@@ -7,3 +7,8 @@ export_presets.cfg
|
|||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
*.csproj.user
|
*.csproj.user
|
||||||
|
|
||||||
|
# Soak-test outputs — regenerated every run; findings are curated in FINDINGS.md
|
||||||
|
soak/*.csv
|
||||||
|
soak/*.csv.import
|
||||||
|
soak/*.translation
|
||||||
|
|||||||
+94
@@ -273,6 +273,100 @@ a falsifiable claim.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Run 13 — The full world: four towns, one engine
|
||||||
|
|
||||||
|
**Built:** world scaled 3× (768×768), all four towns at compass points
|
||||||
|
each running its own soul culture (North generational, South nature,
|
||||||
|
West materialist — new profile — East selfish); two new resources (Ore,
|
||||||
|
Herb — herbs are medicine, mended health; a reason to forage and a trade
|
||||||
|
good); a **spatial hash grid** so proximity queries stop being O(n²)
|
||||||
|
(3.6× headless speedup at ~80 NPCs, live view viable); and the first
|
||||||
|
social verb beyond work: **pair-bonds** (settled adults who keep warm
|
||||||
|
company pair up; warmth now accrues from proximity, not only gifts;
|
||||||
|
bonds break at death). Reproduction deferred (bonds-first, per plan).
|
||||||
|
|
||||||
|
**Result — the four-town thesis, fully realized on one engine:**
|
||||||
|
|
||||||
|
| Town | Nourish | Knowledge | Debris | Character |
|
||||||
|
|-------|---------|-----------|--------|-----------|
|
||||||
|
| North | 0.84 | **1.27** | 0.000 | wise, whole — teaching wins |
|
||||||
|
| South | **0.85** | 1.18 | 0.000 | content, clean, lives with the land |
|
||||||
|
| West | 0.80 | 1.24 | **0.227** | prosperous but soul-marked |
|
||||||
|
| East | 0.60 | 1.08 | 0.223 | scheming and hungriest — selfishness starves itself |
|
||||||
|
|
||||||
|
The two positive cultures stay soul-clean; the two negative carry real
|
||||||
|
debris. The North leads knowledge (its purpose); the East trails it and
|
||||||
|
is hungriest (teaches no one, shares nothing). 99 bonds, 80 deaths — a
|
||||||
|
living, pairing, generational population in four distinct societies, all
|
||||||
|
from behavior weights. Nothing is scripted; the cultures are emergent.
|
||||||
|
|
||||||
|
## Run 14 — Reproduction, and towns anchored to the compass
|
||||||
|
|
||||||
|
**Built:** children from bonds (Phase B). Death no longer auto-spawns a
|
||||||
|
replacement — people die and are gone; bonded, fed, adult pairs conceive
|
||||||
|
(logistic-damped toward a per-town carrying capacity, so population is a
|
||||||
|
band, not an explosion or a collapse). Population is now genuinely
|
||||||
|
dynamic: births vs deaths. Also anchored towns to their cardinal seeds —
|
||||||
|
the build-centroid is now 70% weighted to the fixed compass point, so
|
||||||
|
settlements stay planted (North founds at ~(388,139) by its (384,130)
|
||||||
|
seed) instead of drifting to map-center where foraging paths overlap
|
||||||
|
(West had wandered 100+ cells before).
|
||||||
|
|
||||||
|
**Tuning story (three failed calibrations, logged as the lesson):**
|
||||||
|
first pass exploded (80→211 by day 80 — young founders, nobody dying,
|
||||||
|
every couple breeding); over-damped to fix it and the world died out
|
||||||
|
(80→6, East extinct); the real bug was a *generational gap* — founders
|
||||||
|
aged out of fertility before their children matured and bonded, so
|
||||||
|
births stopped even as room opened. Fix: wide fertility window (to 85%
|
||||||
|
of life) + generous rate (0.12/couple/day × room). Population dynamics
|
||||||
|
are a control loop; the birth rate must track the death rate or the
|
||||||
|
system runs away in whichever direction it's biased.
|
||||||
|
|
||||||
|
**Result — reproduction sharpens the four-town thesis:** births (108) ≈
|
||||||
|
deaths (104), population settled in a healthy band (~68–109). And the
|
||||||
|
cultures now diverge in *demographics*, not just soul-state: North (26)
|
||||||
|
and South (22) thrive and stay soul-clean; West shrinks (16) with debris
|
||||||
|
creeping in; **East collapses to 4, starving (nourishment 0.00), highest
|
||||||
|
debris — selfishness now literally fails to sustain a population.** A
|
||||||
|
town that won't share or cooperate can't feed its people or raise a next
|
||||||
|
generation. The most damning verdict the sim has produced.
|
||||||
|
|
||||||
|
## Run 15 — Known-nodes exploration (addendum §4) + the O(n²) hunt
|
||||||
|
|
||||||
|
**Built (stage 1 of the exploration addendum):** per-NPC known-nodes — an
|
||||||
|
NPC gathers only from resource nodes it has personally sensed (radius 22)
|
||||||
|
or been told about. Founders seed with their home ground; children
|
||||||
|
inherit their parents' map; node knowledge diffuses between neighbors by
|
||||||
|
the same proximity rule as skills. When nothing known qualifies, a
|
||||||
|
starving NPC ventures outward (biased away from town anchor) and senses
|
||||||
|
as it goes — the non-random, needs-driven venture-out the addendum wants,
|
||||||
|
and the seed of first contact. Repopulation explicitly preserved: seeding
|
||||||
|
+ a survival food fallback keep towns fed (verified: all four 0.56–0.78
|
||||||
|
fed, population stable 86–109 over 240 days).
|
||||||
|
|
||||||
|
**Debug screen rebuilt:** the per-villager roster (one line per soul,
|
||||||
|
~68 rows overflowing the panel at four-town scale) replaced with a
|
||||||
|
per-town summary — population, fed%, knowledge, debris, state breakdown,
|
||||||
|
buildings, colored by culture, plus world births/deaths. Scales to any
|
||||||
|
population.
|
||||||
|
|
||||||
|
**The performance lesson, earned properly this time:** the sim slowed to
|
||||||
|
a crawl and I burned four rounds guessing (node index — no; periodic
|
||||||
|
sensing — barely; node cell-index — barely; gated diffusion — barely).
|
||||||
|
Then I added phase timers and *measured*: `npc.Tick` was 94% of cost and
|
||||||
|
grew O(n²) with population. The culprit was `TickResting` calling
|
||||||
|
`RestingOccupancy` (a full-population scan) once per building per resting
|
||||||
|
NPC — O(buildings × NPCs²) per tick. Fixed with a once-per-tick occupancy
|
||||||
|
cache on Building. Result: npc phase ~4× faster and now linear; full
|
||||||
|
240-day four-town run in **180s, faster than the pre-exploration
|
||||||
|
baseline** despite all the new systems. Lesson restated: profile first;
|
||||||
|
the bottleneck is never where you guess.
|
||||||
|
|
||||||
|
**Next:** stage 2 (soul-weighted venture-out + first contact); crisis-
|
||||||
|
recovery experiment; save/load; then the player pivot.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Soul layer: done and validated (runs 5–6). The expansion phase begins:
|
Soul layer: done and validated (runs 5–6). The expansion phase begins:
|
||||||
|
|
||||||
1. **Towns as spatial structure**: multiple settlements with their own
|
1. **Towns as spatial structure**: multiple settlements with their own
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[node name="Main" type="Node2D" unique_id=1549676286]
|
[node name="Main" type="Node2D" unique_id=1549676286]
|
||||||
script = ExtResource("1_gm")
|
script = ExtResource("1_gm")
|
||||||
TicksPerRealSecond = 1500.0
|
TicksPerRealSecond = 2000.0
|
||||||
StopAfterDays = 240
|
StopAfterDays = 240
|
||||||
|
|
||||||
[node name="Visualization" type="Node2D" parent="." unique_id=1946930493]
|
[node name="Visualization" type="Node2D" parent="." unique_id=1946930493]
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Soul Reincarnation World Simulation — Exploration & Town Distance Addendum
|
||||||
|
|
||||||
|
*Builds on the original design spec. Covers town isolation, needs-based exploration, and personal resource-node knowledge.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Problem Being Solved
|
||||||
|
|
||||||
|
Current state: all NPCs across all four towns can interact from tick one, before settlements have even formed, and NPCs have global knowledge of every resource node's location. This collapses the towns into one shared pool instead of four distinct cultural "echo chambers" that only make contact through deliberate exploration.
|
||||||
|
|
||||||
|
Goal: towns should develop in relative isolation first, with cross-town contact emerging naturally as a *result* of resource pressure and exploration — not something possible from the very first tick.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Town Distance / Isolation
|
||||||
|
|
||||||
|
- No artificial hard block on socializing is wanted — the fix should come from constraining *what NPCs know and can reach*, not from disabling interaction mechanically.
|
||||||
|
- Each town should function as its own local loop (gather/build/trade/socialize) until something pushes individuals beyond it.
|
||||||
|
- Cross-town contact becomes a real, observable event — first contact happens because someone *found* the other town, not because the simulation allowed it by default.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Needs-Based Exploration (not random chance)
|
||||||
|
|
||||||
|
Rejected: random per-NPC "wander" chance each day.
|
||||||
|
|
||||||
|
**Chosen approach:** exploration is driven by real resource supply/demand pressure, using the same soul-weighted decision system already used for gathering and trading. When an NPC's (or town's) locally known resources can't meet demand, venturing outward becomes the logical next step in the state machine — not a dice roll.
|
||||||
|
|
||||||
|
### How each town's soul philosophy should shape *when* and *how* they push outward:
|
||||||
|
|
||||||
|
- **South (Nature):** sustainable harvesting means local resources rarely deplete. They venture out **late**, mainly once population growth outpaces what the home area can regenerate. Reads as "we've outgrown this valley," not resource panic.
|
||||||
|
- **West (Materialistic):** status competition drives overconsumption of visible/display materials faster than regen. They push outward **early**, chasing new sources of status-signaling resources.
|
||||||
|
- **East (Selfish):** hoarding causes uneven, fast local depletion in pockets. Expect **individual** NPCs — not the whole town — to venture out well ahead of general need, as opportunistic scouts.
|
||||||
|
- **North (Generational):** expansion is driven by needing land for new family compounds as generations multiply. Their venturing is **deliberate/planned**, not reactive to scarcity.
|
||||||
|
|
||||||
|
### Mechanical shape
|
||||||
|
- Resource nodes: finite with regen (already implemented).
|
||||||
|
- Each soul type gets a consumption-rate multiplier against the shared regen rate.
|
||||||
|
- When an NPC's (or town's) local supply/demand ratio crosses a threshold, gathering-state logic starts pathing beyond the home radius toward the nearest *known* unclaimed resource — falling out of the existing soul-weighted decision system rather than requiring new randomness.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Personal Resource-Node Knowledge (No Global Map Access)
|
||||||
|
|
||||||
|
Current state: NPCs have full knowledge of all node locations in the world, so they beeline to the optimal node instead of exploring.
|
||||||
|
|
||||||
|
**Fix:** NPCs should only be able to act on resource nodes they have personally discovered. Discovery becomes the actual bottleneck driving exploration, not just resource pressure alone.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
- **Known-nodes list (per NPC):** an NPC's gathering/building logic only ever queries nodes on *their own* known list — never the global resource table.
|
||||||
|
- **Sensing radius:** a small "currently visible" radius each tick; any node that enters this radius gets added to the NPC's known-nodes list.
|
||||||
|
- **Wander-when-starved fallback:** when an NPC's known nodes are depleted/insufficient and nothing new is in sensing range, that's the concrete trigger for venture-out behavior — move outward (biased away from town center / toward unexplored territory) until sensing radius picks something up.
|
||||||
|
- **Reuse of existing systems:** the game's NPC class already tracks personal knowledge for trade relationships. Known-nodes should extend that same "personal knowledge" pattern rather than introduce a new system.
|
||||||
|
- Open question to resolve during implementation: is trade knowledge currently keyed NPC-to-NPC (trust relationships) or NPC-to-entity (things known to exist)? If the latter, known-nodes can likely reuse the identical data structure with a different entity type. If the former, known-nodes probably needs its own parallel structure, since location memory and trust-relationship memory are conceptually distinct.
|
||||||
|
- **Knowledge spread via proximity/social diffusion:** once one NPC discovers a new node, nearby townsfolk can learn about it through the same proximity/social diffusion mechanic already designed for skill/craft knowledge transfer (see original spec, Section 5). Discovery spreads organically through a town rather than becoming instantly global. No new diffusion system needs to be built — this is the same rule applied to a second knowledge type (locations, not skills).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Summary of Design Consistency
|
||||||
|
|
||||||
|
Both mechanics in this addendum deliberately reuse existing systems rather than introducing new ones:
|
||||||
|
|
||||||
|
| New behavior | Reuses |
|
||||||
|
|---|---|
|
||||||
|
| Needs-based venture-out trigger | Existing soul-weighted state machine (gathering/trading logic) |
|
||||||
|
| Per-NPC known-nodes memory | Existing personal-knowledge structure (currently used for trade) |
|
||||||
|
| Node-discovery spread between NPCs | Existing proximity/social knowledge-diffusion design (Section 5 of main spec) |
|
||||||
|
|
||||||
|
This keeps the engine soul-type-agnostic and modular, consistent with the original MVP design intent: new behaviors should come from tuning weights and thresholds on existing systems, not from bolting on new mechanics per feature.
|
||||||
@@ -94,6 +94,18 @@ public class Building
|
|||||||
|
|
||||||
/// <summary>How many can sleep here. Expansion adds beds — growth has a
|
/// <summary>How many can sleep here. Expansion adds beds — growth has a
|
||||||
/// human meaning, not just a bigger square.</summary>
|
/// human meaning, not just a bigger square.</summary>
|
||||||
|
/// <summary>Sleepers here, recomputed once per tick by GameManager —
|
||||||
|
/// so resting NPCs read a cached count instead of each re-scanning the
|
||||||
|
/// whole population per building (that was the sim's O(n²) hot spot).</summary>
|
||||||
|
public int Occupancy;
|
||||||
|
|
||||||
|
/// <summary>The two most-represented home-towns among this shelter's
|
||||||
|
/// current sleepers — for the map's household coloring. When two towns
|
||||||
|
/// share a roof (someone shacked up across cultures), the house is drawn
|
||||||
|
/// split. Recomputed with Occupancy each tick.</summary>
|
||||||
|
public string ResidentTownA = "";
|
||||||
|
public string ResidentTownB = "";
|
||||||
|
|
||||||
public int RestCapacity =>
|
public int RestCapacity =>
|
||||||
Kind == BuildingKind.Shelter && IsComplete && !IsRuined ? 3 + Modules : 0;
|
Kind == BuildingKind.Shelter && IsComplete && !IsRuined ? 3 + Modules : 0;
|
||||||
|
|
||||||
|
|||||||
+207
-71
@@ -19,18 +19,28 @@ public partial class GameManager : Node2D
|
|||||||
// centroid, buildings, and granary. NPCs affiliate with a home town
|
// centroid, buildings, and granary. NPCs affiliate with a home town
|
||||||
// but roam freely — the space between towns is where cultures meet.
|
// but roam freely — the space between towns is where cultures meet.
|
||||||
|
|
||||||
[Export] public int SouthPopulation = 12; // nature souls
|
[Export] public int TownPopulationEach = 16; // per settlement (~64 total, room to grow)
|
||||||
[Export(PropertyHint.Range, "0,15,1")]
|
|
||||||
public int SelfishCount = 3; // east souls living in the South
|
|
||||||
[Export] public int NorthPopulation = 10; // generational souls
|
|
||||||
|
|
||||||
public record TownDef(string Name, Vector2 Center, SoulType Soul);
|
public record TownDef(string Name, Vector2 Center, SoulType Soul);
|
||||||
|
|
||||||
|
// Four towns at the compass points of the world, each its own culture
|
||||||
|
// (per DESIGN.md): North reveres lineage, South lives with the land,
|
||||||
|
// West performs material wealth, East schemes for self.
|
||||||
public IReadOnlyList<TownDef> Towns => _towns;
|
public IReadOnlyList<TownDef> Towns => _towns;
|
||||||
private readonly List<TownDef> _towns = new()
|
private readonly List<TownDef> _towns = new()
|
||||||
{
|
{
|
||||||
new("South", new Vector2(128f, 190f), SoulType.Nature),
|
new("North", new Vector2(576f, 190f), SoulType.Generational),
|
||||||
new("North", new Vector2(128f, 62f), SoulType.Generational),
|
new("South", new Vector2(576f, 962f), SoulType.Nature),
|
||||||
|
new("West", new Vector2(190f, 576f), SoulType.Materialist),
|
||||||
|
new("East", new Vector2(962f, 576f), SoulType.Selfish),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static SoulProfile ProfileFor(SoulType t) => t switch
|
||||||
|
{
|
||||||
|
SoulType.Generational => SoulProfile.GenerationalSoul(),
|
||||||
|
SoulType.Nature => SoulProfile.NatureSoul(),
|
||||||
|
SoulType.Materialist => SoulProfile.MaterialistSoul(),
|
||||||
|
_ => SoulProfile.SelfishSoul(),
|
||||||
};
|
};
|
||||||
|
|
||||||
[Export(PropertyHint.Range, "1,2000,1")]
|
[Export(PropertyHint.Range, "1,2000,1")]
|
||||||
@@ -45,6 +55,10 @@ public partial class GameManager : Node2D
|
|||||||
public List<Npc> Npcs { get; } = new();
|
public List<Npc> Npcs { get; } = new();
|
||||||
public List<Building> Buildings { get; } = new();
|
public List<Building> Buildings { get; } = new();
|
||||||
|
|
||||||
|
/// <summary>Rebuilt each tick; proximity queries go through it so the
|
||||||
|
/// hot loops stay near-linear as population grows.</summary>
|
||||||
|
public SpatialGrid Grid { get; } = new(cellSize: 12f);
|
||||||
|
|
||||||
public long TotalTicks { get; private set; }
|
public long TotalTicks { get; private set; }
|
||||||
public int Day => (int)(TotalTicks / 1440);
|
public int Day => (int)(TotalTicks / 1440);
|
||||||
public int MinuteOfDay => (int)(TotalTicks % 1440);
|
public int MinuteOfDay => (int)(TotalTicks % 1440);
|
||||||
@@ -109,23 +123,16 @@ public partial class GameManager : Node2D
|
|||||||
LifeExpectancyDays = 150 + rng.Next(0, 80),
|
LifeExpectancyDays = 150 + rng.Next(0, 80),
|
||||||
};
|
};
|
||||||
npc.Know.Capacity = 1.0f + (float)rng.NextDouble();
|
npc.Know.Capacity = 1.0f + (float)rng.NextDouble();
|
||||||
|
// Founders know their home ground — the resources around the
|
||||||
|
// town seed. They begin with a working local map, not blind.
|
||||||
|
foreach (var node in World.NodesWithin(center, 130f))
|
||||||
|
npc.KnownNodes.Add(node);
|
||||||
Npcs.Add(npc);
|
Npcs.Add(npc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var town in _towns)
|
foreach (var town in _towns)
|
||||||
{
|
Spawn(town.Name, town.Center, ProfileFor(town.Soul), TownPopulationEach, town.Name);
|
||||||
if (town.Name == "South")
|
|
||||||
{
|
|
||||||
Spawn(town.Name, town.Center, SoulProfile.NatureSoul(), SouthPopulation, "South");
|
|
||||||
for (int i = 0; i < SelfishCount; i++)
|
|
||||||
Spawn(town.Name, town.Center, SoulProfile.SelfishSoul(), 1, "South");
|
|
||||||
}
|
|
||||||
else if (town.Name == "North")
|
|
||||||
{
|
|
||||||
Spawn(town.Name, town.Center, SoulProfile.GenerationalSoul(), NorthPopulation, "North");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>How many villagers (other than <paramref name="except"/>)
|
/// <summary>How many villagers (other than <paramref name="except"/>)
|
||||||
@@ -148,6 +155,23 @@ public partial class GameManager : Node2D
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>A town's fixed cardinal seed — its permanent home on the
|
||||||
|
/// map, unaffected by where its people happen to wander.</summary>
|
||||||
|
public Vector2 TownAnchor(string town)
|
||||||
|
{
|
||||||
|
foreach (var t in _towns)
|
||||||
|
if (t.Name == town) return t.Center;
|
||||||
|
return new Vector2(World.GridSize / 2f, World.GridSize / 2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>The soul culture of a named town (for map coloring).</summary>
|
||||||
|
public SoulType TownSoul(string town)
|
||||||
|
{
|
||||||
|
foreach (var t in _towns)
|
||||||
|
if (t.Name == town) return t.Soul;
|
||||||
|
return SoulType.Nature;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2 TownCentroid(string town)
|
public Vector2 TownCentroid(string town)
|
||||||
{
|
{
|
||||||
Vector2 sum = Vector2.Zero;
|
Vector2 sum = Vector2.Zero;
|
||||||
@@ -158,13 +182,13 @@ public partial class GameManager : Node2D
|
|||||||
sum += npc.Position;
|
sum += npc.Position;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count == 0)
|
if (count == 0) return TownAnchor(town);
|
||||||
{
|
|
||||||
foreach (var t in _towns)
|
// Anchor-weighted: the settlement's build-center stays near its
|
||||||
if (t.Name == town) return t.Center;
|
// cardinal seed even as villagers roam outward to distant resources.
|
||||||
return new Vector2(World.GridSize / 2f, World.GridSize / 2f);
|
// Towns keep their place on the compass instead of drifting to the
|
||||||
}
|
// middle of the map where everyone's foraging paths overlap.
|
||||||
return sum / count;
|
return (sum / count).Lerp(TownAnchor(town), 0.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
@@ -189,82 +213,169 @@ public partial class GameManager : Node2D
|
|||||||
const float radius = 8f;
|
const float radius = 8f;
|
||||||
const float strength = 0.00004f;
|
const float strength = 0.00004f;
|
||||||
|
|
||||||
for (int i = 0; i < Npcs.Count; i++)
|
// Spatial grid: each soul presses only on the few within reach,
|
||||||
|
// not on everyone. Directed pass (a→b for every nearby b) so each
|
||||||
|
// ordered pair is handled once from the source's side.
|
||||||
|
foreach (var a in Npcs)
|
||||||
{
|
{
|
||||||
for (int j = i + 1; j < Npcs.Count; j++)
|
Grid.ForEachNear(a.Position, radius, b =>
|
||||||
{
|
{
|
||||||
var a = Npcs[i];
|
if (b == a) return;
|
||||||
var b = Npcs[j];
|
|
||||||
float dist = a.Position.DistanceTo(b.Position);
|
float dist = a.Position.DistanceTo(b.Position);
|
||||||
if (dist > radius) continue;
|
if (dist > radius) return;
|
||||||
|
|
||||||
float falloff = 1f - dist / radius;
|
float falloff = 1f - dist / radius;
|
||||||
|
|
||||||
float fromA = Mathf.Lerp(-strength, strength, a.Imprint.Total) * falloff;
|
float fromA = Mathf.Lerp(-strength, strength, a.Imprint.Total) * falloff;
|
||||||
b.Imprint.ExternalPerception = Mathf.Clamp(b.Imprint.ExternalPerception + fromA, 0f, 1f);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Mortality: generations end, and what wasn't passed on ends too --
|
// --- Mortality & birth: generations end, and new ones are born --------
|
||||||
|
// Death no longer auto-spawns a replacement. People die and are simply
|
||||||
|
// gone; children come from bonded pairs (TickReproduction). Population
|
||||||
|
// is now births vs deaths — a town can grow, shrink, or die out.
|
||||||
|
|
||||||
public int DeathsToday { get; set; }
|
public int DeathsToday { get; set; }
|
||||||
|
public int BirthsToday { get; set; }
|
||||||
private int _bornCount;
|
private int _bornCount;
|
||||||
|
|
||||||
private void TickMortality()
|
private void TickMortality()
|
||||||
{
|
{
|
||||||
var dying = new List<Npc>();
|
|
||||||
foreach (var npc in Npcs)
|
|
||||||
{
|
|
||||||
npc.AgeDays += 1f;
|
|
||||||
if (npc.AgeDays >= npc.LifeExpectancyDays)
|
|
||||||
dying.Add(npc);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rng = new System.Random(Seed + (int)TotalTicks);
|
var rng = new System.Random(Seed + (int)TotalTicks);
|
||||||
|
|
||||||
foreach (var dead in Npcs.ToArray())
|
foreach (var dead in Npcs.ToArray())
|
||||||
{
|
{
|
||||||
if (!dying.Contains(dead)) continue;
|
dead.AgeDays += 1f;
|
||||||
|
if (dead.AgeDays < dead.LifeExpectancyDays) continue;
|
||||||
|
|
||||||
Npcs.Remove(dead);
|
Npcs.Remove(dead);
|
||||||
DeathsToday++;
|
DeathsToday++;
|
||||||
|
|
||||||
// Everything unshared dies with them: skills, memories, echoes.
|
// Everything unshared dies with them: skills, memories, echoes.
|
||||||
// What survives is what they taught, built, and stored.
|
// What survives is what they taught, built, stored — and bore.
|
||||||
foreach (var other in Npcs)
|
foreach (var other in Npcs)
|
||||||
other.ForgetPerson(dead);
|
other.ForgetPerson(dead);
|
||||||
|
|
||||||
// A youth comes of age in the same town, same culture, knowing
|
GD.Print($"[Passing] day {Day}: {dead.Name} dies at {dead.AgeDays:0} days " +
|
||||||
// almost nothing — but raised among the living, not in a void.
|
$"(knowledge {dead.Know.Total:0.00} lost).");
|
||||||
// They spawn beside the town's wisest elder, so the young begin
|
}
|
||||||
// life within reach of what the community still remembers. The
|
}
|
||||||
// town's knowledge is only what its living carry — but the young
|
|
||||||
// start where that knowledge is.
|
|
||||||
_bornCount++;
|
|
||||||
Npc? elder = null;
|
|
||||||
float bestKnow = -1f;
|
|
||||||
foreach (var other in Npcs)
|
|
||||||
if (other.HomeTown == dead.HomeTown && other.Know.Total > bestKnow)
|
|
||||||
{ bestKnow = other.Know.Total; elder = other; }
|
|
||||||
Vector2 cradle = elder?.Position ?? TownCentroid(dead.HomeTown);
|
|
||||||
|
|
||||||
var youth = new Npc
|
/// <summary>
|
||||||
|
/// Children come from bonds (Phase B). A bonded pair — both grown adults,
|
||||||
|
/// both fed, with a roof in town — may conceive once per season. The
|
||||||
|
/// child spawns beside its parents, inherits their town and culture, and
|
||||||
|
/// begins knowing almost nothing but growing up among those who do. This
|
||||||
|
/// is how a town persists: not by respawn-on-death, but by families.
|
||||||
|
/// </summary>
|
||||||
|
/// <summary>Rough carrying capacity per town — beds plus a margin the
|
||||||
|
/// land can feed. Births taper toward zero as a town fills it.</summary>
|
||||||
|
private const int TownCarryingCapacity = 28;
|
||||||
|
|
||||||
|
private void TickReproduction()
|
||||||
{
|
{
|
||||||
Name = $"{dead.HomeTown}_{(char)('A' + _bornCount % 26)}{_bornCount + 25}",
|
var rng = new System.Random(Seed * 7 + (int)TotalTicks);
|
||||||
HomeTown = dead.HomeTown,
|
var newborns = new List<Npc>();
|
||||||
Soul = dead.Soul, // raised in the culture that raised them
|
|
||||||
|
// Town populations, to damp births near carrying capacity.
|
||||||
|
var pop = new Dictionary<string, int>();
|
||||||
|
foreach (var npc in Npcs)
|
||||||
|
pop[npc.HomeTown] = pop.GetValueOrDefault(npc.HomeTown) + 1;
|
||||||
|
|
||||||
|
foreach (var a in Npcs)
|
||||||
|
{
|
||||||
|
var b = a.Partner;
|
||||||
|
if (b == null) continue;
|
||||||
|
if (a.GetHashCode() >= b.GetHashCode()) continue; // count each pair once
|
||||||
|
if (!a.IsAdult || !b.IsAdult) continue;
|
||||||
|
if (a.Nourishment < 0.5f || b.Nourishment < 0.5f) continue; // both fed
|
||||||
|
// Fertile from adulthood through most of life — a wide window so
|
||||||
|
// generations overlap and a town isn't one bad cohort from ruin.
|
||||||
|
if (a.AgeDays > a.LifeExpectancyDays * 0.85f) continue;
|
||||||
|
|
||||||
|
// Logistic damping: a full town barely breeds; an emptied one
|
||||||
|
// (after a plague) breeds back toward capacity. This is what
|
||||||
|
// keeps population in a band instead of exploding or dying out.
|
||||||
|
float townPop = pop.GetValueOrDefault(a.HomeTown);
|
||||||
|
float roomFactor = Mathf.Clamp(1f - townPop / TownCarryingCapacity, 0f, 1f);
|
||||||
|
if (roomFactor <= 0f) continue;
|
||||||
|
|
||||||
|
// High enough to outrun the founding cohort's die-off and keep
|
||||||
|
// generations overlapping; logistic damping caps the ceiling so
|
||||||
|
// it can't explode. Deliberately generous — a shrinking town is
|
||||||
|
// a worse failure than a full one.
|
||||||
|
double dailyChance = 0.12 * roomFactor;
|
||||||
|
if (rng.NextDouble() > dailyChance) continue;
|
||||||
|
|
||||||
|
_bornCount++;
|
||||||
|
var child = new Npc
|
||||||
|
{
|
||||||
|
Name = $"{a.HomeTown}_{(char)('a' + _bornCount % 26)}{_bornCount + 25}",
|
||||||
|
HomeTown = a.HomeTown,
|
||||||
|
Soul = a.Soul, // raised in the culture that bore them
|
||||||
PersonalityModifier = (float)(rng.NextDouble() * 0.4 - 0.2),
|
PersonalityModifier = (float)(rng.NextDouble() * 0.4 - 0.2),
|
||||||
Position = cradle + new Vector2(rng.Next(-4, 5), rng.Next(-4, 5)),
|
Position = a.Position + new Vector2(rng.Next(-3, 4), rng.Next(-3, 4)),
|
||||||
AgeDays = 0f,
|
AgeDays = 0f,
|
||||||
LifeExpectancyDays = 150 + rng.Next(0, 80),
|
LifeExpectancyDays = 150 + rng.Next(0, 80),
|
||||||
};
|
};
|
||||||
youth.Know.Capacity = 1.0f + (float)rng.NextDouble();
|
child.Know.Capacity = 1.0f + (float)rng.NextDouble();
|
||||||
Npcs.Add(youth);
|
// A child inherits its parents' map — the family's known grounds,
|
||||||
|
// passed down like everything else a generation hands forward.
|
||||||
|
foreach (var node in a.KnownNodes) child.KnownNodes.Add(node);
|
||||||
|
foreach (var node in b.KnownNodes) child.KnownNodes.Add(node);
|
||||||
|
// A child also inherits the family's known buildings — the homes
|
||||||
|
// and stores of the people who raised them.
|
||||||
|
foreach (var s in a.KnownStructures) child.KnownStructures.Add(s);
|
||||||
|
foreach (var s in b.KnownStructures) child.KnownStructures.Add(s);
|
||||||
|
newborns.Add(child);
|
||||||
|
BirthsToday++;
|
||||||
|
pop[a.HomeTown] = (int)townPop + 1; // count the newborn toward capacity
|
||||||
|
GD.Print($"[Birth] day {Day}: {a.Name} & {b.Name} ({a.HomeTown}) → {child.Name}.");
|
||||||
|
}
|
||||||
|
|
||||||
GD.Print($"[Passing] day {Day}: {dead.Name} dies at {dead.AgeDays:0} days " +
|
Npcs.AddRange(newborns);
|
||||||
$"(knowledge {dead.Know.Total:0.00} lost); {youth.Name} comes of age.");
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tally which home-towns sleep under each shelter, storing the top two.
|
||||||
|
/// A house with residents from two towns is a mixed household — someone
|
||||||
|
/// shacked up across cultures — and gets drawn split on the map.
|
||||||
|
/// </summary>
|
||||||
|
private void RecomputeHouseholds()
|
||||||
|
{
|
||||||
|
var counts = new Dictionary<Building, Dictionary<string, int>>();
|
||||||
|
|
||||||
|
foreach (var npc in Npcs)
|
||||||
|
{
|
||||||
|
if (npc.State != NpcState.Resting) continue;
|
||||||
|
Building? at = null; float best = 6.25f;
|
||||||
|
foreach (var b in Buildings)
|
||||||
|
{
|
||||||
|
if (b.RestCapacity <= 0) continue;
|
||||||
|
float d = npc.Position.DistanceSquaredTo(b.Site);
|
||||||
|
if (d < best) { best = d; at = b; }
|
||||||
|
}
|
||||||
|
if (at == null) continue;
|
||||||
|
if (!counts.TryGetValue(at, out var byTown))
|
||||||
|
counts[at] = byTown = new Dictionary<string, int>();
|
||||||
|
byTown[npc.HomeTown] = byTown.GetValueOrDefault(npc.HomeTown) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var b in Buildings)
|
||||||
|
{
|
||||||
|
b.ResidentTownA = "";
|
||||||
|
b.ResidentTownB = "";
|
||||||
|
if (!counts.TryGetValue(b, out var byTown)) continue;
|
||||||
|
|
||||||
|
string a = "", bTown = ""; int ca = 0, cb = 0;
|
||||||
|
foreach (var kv in byTown)
|
||||||
|
{
|
||||||
|
if (kv.Value > ca) { bTown = a; cb = ca; a = kv.Key; ca = kv.Value; }
|
||||||
|
else if (kv.Value > cb) { bTown = kv.Key; cb = kv.Value; }
|
||||||
|
}
|
||||||
|
b.ResidentTownA = a;
|
||||||
|
b.ResidentTownB = cb > 0 ? bTown : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +391,30 @@ public partial class GameManager : Node2D
|
|||||||
|
|
||||||
private void Tick()
|
private void Tick()
|
||||||
{
|
{
|
||||||
|
Grid.Rebuild(Npcs);
|
||||||
|
|
||||||
|
// Recompute shelter occupancy once per tick (was O(n²): each resting
|
||||||
|
// NPC re-scanned everyone, per building). Now: one pass, cached — each
|
||||||
|
// sleeper counts toward the nearest shelter they're actually inside.
|
||||||
|
foreach (var b in Buildings) b.Occupancy = 0;
|
||||||
|
foreach (var npc in Npcs)
|
||||||
|
{
|
||||||
|
if (npc.State != NpcState.Resting) continue;
|
||||||
|
Building? at = null; float best = 6.25f; // within 2.5 units
|
||||||
|
foreach (var b in Buildings)
|
||||||
|
{
|
||||||
|
if (b.RestCapacity <= 0) continue;
|
||||||
|
float d = npc.Position.DistanceSquaredTo(b.Site);
|
||||||
|
if (d < best) { best = d; at = b; }
|
||||||
|
}
|
||||||
|
if (at != null) at.Occupancy++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Household composition (which cultures share each roof) — for the
|
||||||
|
// map only, so it's cheap and refreshed occasionally, not every tick.
|
||||||
|
if (TotalTicks % 30 == 0)
|
||||||
|
RecomputeHouseholds();
|
||||||
|
|
||||||
TotalTicks++;
|
TotalTicks++;
|
||||||
|
|
||||||
foreach (var npc in Npcs)
|
foreach (var npc in Npcs)
|
||||||
@@ -295,9 +430,10 @@ public partial class GameManager : Node2D
|
|||||||
foreach (var npc in Npcs)
|
foreach (var npc in Npcs)
|
||||||
npc.FadeEchoes(0.005f);
|
npc.FadeEchoes(0.005f);
|
||||||
TickMortality();
|
TickMortality();
|
||||||
|
TickReproduction();
|
||||||
StatsLogger.LogDay(this);
|
StatsLogger.LogDay(this);
|
||||||
if (Day % 10 == 0)
|
if (Day % 10 == 0)
|
||||||
GD.Print($"[WorldSim] Day {Day} complete.");
|
GD.Print($"[WorldSim] Day {Day} complete (pop {Npcs.Count}).");
|
||||||
|
|
||||||
if (StopAfterDays > 0 && Day >= StopAfterDays)
|
if (StopAfterDays > 0 && Day >= StopAfterDays)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ public class Knowledge
|
|||||||
public static KnowledgeDomain DomainFor(MaterialKind kind) => kind switch
|
public static KnowledgeDomain DomainFor(MaterialKind kind) => kind switch
|
||||||
{
|
{
|
||||||
MaterialKind.Food => KnowledgeDomain.Forage,
|
MaterialKind.Food => KnowledgeDomain.Forage,
|
||||||
|
MaterialKind.Herb => KnowledgeDomain.Forage, // gathering the living land
|
||||||
MaterialKind.Wood => KnowledgeDomain.Woodcraft,
|
MaterialKind.Wood => KnowledgeDomain.Woodcraft,
|
||||||
_ => KnowledgeDomain.Masonry, // stone, clay — builder's craft
|
_ => KnowledgeDomain.Masonry, // stone, clay, ore — builder's craft
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+350
-37
@@ -40,6 +40,104 @@ public class Npc
|
|||||||
// --- Knowledge (SPEC §5) ----------------------------------------------
|
// --- Knowledge (SPEC §5) ----------------------------------------------
|
||||||
public Knowledge Know = new();
|
public Knowledge Know = new();
|
||||||
|
|
||||||
|
// --- Known nodes: the world is only what you've found (addendum §4) ----
|
||||||
|
// An NPC gathers only from resource nodes it has personally discovered
|
||||||
|
// (by coming within sensing range) or been told about. This is what
|
||||||
|
// makes towns insular echo chambers — no global map, so a town works its
|
||||||
|
// own known ground until scarcity pushes someone to explore. Distinct
|
||||||
|
// from the warmth-echo map (that's NPC-to-NPC trust); this is
|
||||||
|
// NPC-to-place memory, its own structure per the addendum's open Q.
|
||||||
|
public readonly HashSet<ResourceNode> KnownNodes = new();
|
||||||
|
|
||||||
|
// Known structures: same principle as known nodes — you can only use or
|
||||||
|
// return to a building you've discovered or raised yourself. This is what
|
||||||
|
// lets a lone builder finish their OWN home (they remember the foundation
|
||||||
|
// they laid) instead of re-founding a new one every time they wander off
|
||||||
|
// for wood, and it keeps towns insular: you don't beeline to a granary
|
||||||
|
// across the world you've never seen.
|
||||||
|
public readonly HashSet<Building> KnownStructures = new();
|
||||||
|
|
||||||
|
/// <summary>Discover buildings within sensing range this tick.</summary>
|
||||||
|
public void SenseStructures(GameManager gm)
|
||||||
|
{
|
||||||
|
foreach (var b in gm.Buildings)
|
||||||
|
if (Position.DistanceSquaredTo(b.Site) <= SensingRadius * SensingRadius)
|
||||||
|
KnownStructures.Add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public const float SensingRadius = 22f;
|
||||||
|
|
||||||
|
/// <summary>Discover any nodes within sensing range this tick.</summary>
|
||||||
|
public void SenseNodes(World world)
|
||||||
|
{
|
||||||
|
world.ForEachNodeNear(Position, SensingRadius, n => KnownNodes.Add(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Learn a node from someone who already knows it (social
|
||||||
|
/// diffusion — the same proximity rule as skills, per addendum §4).</summary>
|
||||||
|
public void ShareNodeKnowledge(Npc other)
|
||||||
|
{
|
||||||
|
// Tell them about a few of what we know they don't — word of a good
|
||||||
|
// grove travels through a town without a global broadcast.
|
||||||
|
int shared = 0;
|
||||||
|
foreach (var n in KnownNodes)
|
||||||
|
{
|
||||||
|
if (other.KnownNodes.Add(n)) shared++;
|
||||||
|
if (shared >= 3) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Venture toward unexplored ground and sense as you go (addendum §4
|
||||||
|
/// wander-when-starved). Bias outward from the town anchor so exploration
|
||||||
|
/// heads into new territory rather than re-treading known home ground.
|
||||||
|
/// Stage 1: a plain outward walk that discovers new nodes. Stage 2 will
|
||||||
|
/// make direction and eagerness soul-weighted.
|
||||||
|
/// </summary>
|
||||||
|
private void Explore(GameManager gm)
|
||||||
|
{
|
||||||
|
Activity = "exploring for new ground";
|
||||||
|
Vector2 anchor = gm.TownAnchor(HomeTown);
|
||||||
|
Vector2 outward = (Position - anchor);
|
||||||
|
if (outward.LengthSquared() < 1f)
|
||||||
|
outward = new Vector2(PersonalityModifier, 1f - Mathf.Abs(PersonalityModifier));
|
||||||
|
outward = outward.Normalized();
|
||||||
|
// A little personality-driven veer so explorers fan out, not conga-line.
|
||||||
|
outward = outward.Rotated(PersonalityModifier * 1.2f);
|
||||||
|
Position += outward * MoveSpeed;
|
||||||
|
SenseNodes(gm.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Nearest node of a kind this NPC knows about AND considers worth
|
||||||
|
/// taking (same regrowth-floor ethic as World.FindNearest). Returns null
|
||||||
|
/// if none of their known nodes qualify — the concrete signal to explore.
|
||||||
|
/// </summary>
|
||||||
|
private ResourceNode? FindNearestKnown(MaterialKind kind, float minFraction)
|
||||||
|
{
|
||||||
|
ResourceNode? best = null;
|
||||||
|
float bestDist = float.MaxValue;
|
||||||
|
foreach (var node in KnownNodes)
|
||||||
|
{
|
||||||
|
if (node.Kind != kind || node.IsDepleted) continue;
|
||||||
|
if (node.Kind != MaterialKind.Water && node.RegenPerDay > 0f &&
|
||||||
|
node.Amount <= node.MaxAmount * minFraction)
|
||||||
|
continue;
|
||||||
|
float d = Position.DistanceSquaredTo(node.Cell);
|
||||||
|
if (d < bestDist) { bestDist = d; best = node; }
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Bonds: the first social verb beyond work (relationships) ---------
|
||||||
|
// A pair-bond forms between two settled adults who keep warm company.
|
||||||
|
// Reproduction is deferred (bonds-first); for now a bond is a standing
|
||||||
|
// relationship — chosen companionship, warmth that compounds, someone
|
||||||
|
// whose grave you would tend.
|
||||||
|
public Npc? Partner;
|
||||||
|
public bool IsBonded => Partner != null;
|
||||||
|
public bool IsAdult => AgeDays >= 20f; // childhood is the first ~20 days
|
||||||
|
|
||||||
// --- State -----------------------------------------------------------
|
// --- State -----------------------------------------------------------
|
||||||
public NpcState State = NpcState.Gathering;
|
public NpcState State = NpcState.Gathering;
|
||||||
|
|
||||||
@@ -110,6 +208,7 @@ public class Npc
|
|||||||
{
|
{
|
||||||
if (_targetNpc == dead) _targetNpc = null;
|
if (_targetNpc == dead) _targetNpc = null;
|
||||||
if (_giftSource == dead) _giftSource = null;
|
if (_giftSource == dead) _giftSource = null;
|
||||||
|
if (Partner == dead) Partner = null; // a bond outlives nothing but memory
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Diagnostics (read-only views for the stats logger) ---------------
|
// --- Diagnostics (read-only views for the stats logger) ---------------
|
||||||
@@ -135,6 +234,7 @@ public class Npc
|
|||||||
private Building? _foodSource; // granary being visited for food
|
private Building? _foodSource; // granary being visited for food
|
||||||
private Npc? _giftSource; // neighbor being asked for food
|
private Npc? _giftSource; // neighbor being asked for food
|
||||||
private float _stateTimer;
|
private float _stateTimer;
|
||||||
|
private int _senseTimer = -1; // ticks until next node-sensing sweep; <0 = stagger on first tick
|
||||||
|
|
||||||
// Organic construction: nights spent sleeping outside. Three rough
|
// Organic construction: nights spent sleeping outside. Three rough
|
||||||
// nights and a person starts gathering stone for a roof of their own.
|
// nights and a person starts gathering stone for a roof of their own.
|
||||||
@@ -175,6 +275,19 @@ public class Npc
|
|||||||
_stateTimer += 1f;
|
_stateTimer += 1f;
|
||||||
StateTicksToday[(int)State]++;
|
StateTicksToday[(int)State]++;
|
||||||
|
|
||||||
|
// See what's around you as you live — discovery is passive (addendum
|
||||||
|
// §4). Sensed periodically, not every tick: you don't miss a grove by
|
||||||
|
// checking every ~30 ticks instead of every one, and a full-node scan
|
||||||
|
// per NPC per tick is the sim's heaviest cost otherwise.
|
||||||
|
if (_senseTimer < 0)
|
||||||
|
_senseTimer = (int)(Mathf.Abs(PersonalityModifier) * 150f) % 30; // stagger the herd
|
||||||
|
else if (--_senseTimer <= 0)
|
||||||
|
{
|
||||||
|
SenseNodes(world);
|
||||||
|
SenseStructures(gm);
|
||||||
|
_senseTimer = 30;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Vitals override everything
|
// 1. Vitals override everything
|
||||||
if (State != NpcState.Resting && (Fatigue > 80f || Health < 30f))
|
if (State != NpcState.Resting && (Fatigue > 80f || Health < 30f))
|
||||||
Enter(NpcState.Resting);
|
Enter(NpcState.Resting);
|
||||||
@@ -209,6 +322,16 @@ public class Npc
|
|||||||
Nourishment = Mathf.Min(1f, Nourishment + 0.25f * (1f - debris * 0.5f));
|
Nourishment = Mathf.Min(1f, Nourishment + 0.25f * (1f - debris * 0.5f));
|
||||||
}
|
}
|
||||||
if (Nourishment <= 0.05f) Health = Mathf.Max(0f, Health - 0.01f);
|
if (Nourishment <= 0.05f) Health = Mathf.Max(0f, Health - 0.01f);
|
||||||
|
|
||||||
|
// Herbs are medicine: the hurt who carry them mend faster, and a
|
||||||
|
// skilled forager gets more from the same leaf. Reason to gather
|
||||||
|
// herbs, and a trade good worth carrying between towns.
|
||||||
|
if (Health < 90f &&
|
||||||
|
Inventory.TryGetValue(MaterialKind.Herb, out float herb) && herb >= 1f)
|
||||||
|
{
|
||||||
|
Inventory[MaterialKind.Herb] = herb - 1f;
|
||||||
|
Health = Mathf.Min(100f, Health + 6f * (1f + Know[KnowledgeDomain.Forage]));
|
||||||
|
}
|
||||||
if (Nourishment < 0.3f) _hungerMemory = true; // real hunger is not forgotten
|
if (Nourishment < 0.3f) _hungerMemory = true; // real hunger is not forgotten
|
||||||
Nourishment = Mathf.Clamp(Nourishment, 0f, 1f);
|
Nourishment = Mathf.Clamp(Nourishment, 0f, 1f);
|
||||||
|
|
||||||
@@ -264,6 +387,18 @@ public class Npc
|
|||||||
if (foodCarried < reserveTarget && (Nourishment < 0.8f || Soul.Accumulation > 0.5f))
|
if (foodCarried < reserveTarget && (Nourishment < 0.8f || Soul.Accumulation > 0.5f))
|
||||||
return MaterialKind.Food;
|
return MaterialKind.Food;
|
||||||
|
|
||||||
|
// Homeless too long → build a roof, whatever your soul. Even the
|
||||||
|
// selfish build private shelter (just never for anyone else). If they
|
||||||
|
// already have one under construction, gather what its NEXT stage
|
||||||
|
// needs — a lone builder must supply their own build end to end, or
|
||||||
|
// it stalls at the walls (this is why East homes never finished).
|
||||||
|
if (!IsCommunal && _unshelteredRests >= 3)
|
||||||
|
{
|
||||||
|
var mine = MyUnfinishedShelter(gm);
|
||||||
|
if (mine?.NeededMaterial is MaterialKind need) return need;
|
||||||
|
return MaterialKind.Stone; // none yet — gather the foundation
|
||||||
|
}
|
||||||
|
|
||||||
if (IsCommunal)
|
if (IsCommunal)
|
||||||
{
|
{
|
||||||
// Communal duty is to your own settlement — you heat your own
|
// Communal duty is to your own settlement — you heat your own
|
||||||
@@ -402,8 +537,17 @@ public class Npc
|
|||||||
if (TotalCarried() >= EffectiveCapacity)
|
if (TotalCarried() >= EffectiveCapacity)
|
||||||
{
|
{
|
||||||
// A full pack means different things to different souls:
|
// A full pack means different things to different souls:
|
||||||
// communal souls take it to the village; hoarders sit on it.
|
// communal souls take it to the village; hoarders sit on it —
|
||||||
if (!IsCommunal) { Enter(NpcState.Socializing); return; }
|
// unless they're homeless and carrying stone, in which case even
|
||||||
|
// a selfish soul goes to raise their own roof.
|
||||||
|
if (!IsCommunal)
|
||||||
|
{
|
||||||
|
// Homeless and carrying what their roof needs next? Go build.
|
||||||
|
if (_unshelteredRests >= 3 && CarriesShelterMaterial(gm))
|
||||||
|
{ Enter(NpcState.Building); return; }
|
||||||
|
Enter(NpcState.Socializing);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Inventory.TryGetValue(demanded, out float haveDemanded);
|
Inventory.TryGetValue(demanded, out float haveDemanded);
|
||||||
if (haveDemanded >= EffectiveCapacity * 0.25f) { Enter(NpcState.Building); return; }
|
if (haveDemanded >= EffectiveCapacity * 0.25f) { Enter(NpcState.Building); return; }
|
||||||
@@ -413,10 +557,22 @@ public class Npc
|
|||||||
|
|
||||||
if (_targetNode == null || _targetNode.IsDepleted || _targetNode.Kind != demanded)
|
if (_targetNode == null || _targetNode.IsDepleted || _targetNode.Kind != demanded)
|
||||||
{
|
{
|
||||||
_targetNode = world.FindNearest(demanded, Position, HarvestSeekFloor);
|
// Only ever gather from nodes we personally know (addendum §4).
|
||||||
|
_targetNode = FindNearestKnown(demanded, HarvestSeekFloor);
|
||||||
|
|
||||||
// Hungry and the land has nothing: the granary, then a neighbor.
|
// Don't know a source for what's needed? Explore: move toward
|
||||||
// This is where winter turns scarcity into community.
|
// unexplored ground (away from town center) and sense as you go.
|
||||||
|
// This is the stage-1 discovery trigger — a minimal, non-random
|
||||||
|
// venture-out that keeps a hungry NPC from starving atop
|
||||||
|
// undiscovered abundance. (Stage 2 makes it soul-weighted.)
|
||||||
|
if (_targetNode == null && demanded != MaterialKind.Food)
|
||||||
|
{
|
||||||
|
Explore(gm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hungry and no known food: the granary, then a neighbor — and
|
||||||
|
// if all else fails, explore for new forage.
|
||||||
if (_targetNode == null && demanded == MaterialKind.Food)
|
if (_targetNode == null && demanded == MaterialKind.Food)
|
||||||
{
|
{
|
||||||
foreach (var b in gm.Buildings)
|
foreach (var b in gm.Buildings)
|
||||||
@@ -433,23 +589,28 @@ public class Npc
|
|||||||
// this keeps gifts meaningful instead of a food-swapping loop.
|
// this keeps gifts meaningful instead of a food-swapping loop.
|
||||||
if (Nourishment >= 0.55f) { Enter(NpcState.Socializing); return; }
|
if (Nourishment >= 0.55f) { Enter(NpcState.Socializing); return; }
|
||||||
float bestScore = float.MinValue;
|
float bestScore = float.MinValue;
|
||||||
foreach (var other in gm.Npcs)
|
Npc? giftFound = null;
|
||||||
|
gm.Grid.ForEachNear(Position, 60f, other =>
|
||||||
{
|
{
|
||||||
if (other == this) continue;
|
if (other == this) return;
|
||||||
float warmth = GetWarmth(other.Name);
|
float warmth = GetWarmth(other.Name);
|
||||||
if (warmth < -0.3f) continue;
|
if (warmth < -0.3f) return;
|
||||||
if (!other.Inventory.TryGetValue(MaterialKind.Food, out float f) || f <= 3f) continue;
|
if (!other.Inventory.TryGetValue(MaterialKind.Food, out float f) || f <= 3f) return;
|
||||||
float score = warmth * 40f - Position.DistanceTo(other.Position);
|
float score = warmth * 40f - Position.DistanceTo(other.Position);
|
||||||
if (score > bestScore) { bestScore = score; _giftSource = other; }
|
if (score > bestScore) { bestScore = score; giftFound = other; }
|
||||||
}
|
});
|
||||||
|
_giftSource = giftFound;
|
||||||
if (_giftSource != null) return;
|
if (_giftSource != null) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_targetNode ??= world.FindNearest(MaterialKind.Food, Position, HarvestSeekFloor)
|
// Known food anywhere we've been, at any amount when truly
|
||||||
?? world.FindNearest(MaterialKind.Wood, Position, HarvestSeekFloor)
|
// hungry (survival overrides the commons floor).
|
||||||
?? world.FindNearest(MaterialKind.Stone, Position, HarvestSeekFloor)
|
_targetNode ??= FindNearestKnown(MaterialKind.Food, 0f);
|
||||||
?? world.FindNearest(MaterialKind.Clay, Position, HarvestSeekFloor);
|
|
||||||
if (_targetNode == null) { Enter(NpcState.Socializing); return; }
|
// Still nothing known to eat: explore for new forage rather than
|
||||||
|
// starve. This is the safety valve that keeps a town alive while
|
||||||
|
// its known ground recovers — and the seed of first contact.
|
||||||
|
if (_targetNode == null) { Explore(gm); return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveToward(_targetNode.Cell);
|
MoveToward(_targetNode.Cell);
|
||||||
@@ -469,9 +630,13 @@ public class Npc
|
|||||||
Inventory.TryGetValue(_targetNode.Kind, out float have);
|
Inventory.TryGetValue(_targetNode.Kind, out float have);
|
||||||
Inventory[_targetNode.Kind] = have + taken;
|
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);
|
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 && CarriesShelterMaterial(gm))
|
||||||
|
Enter(NpcState.Building);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,13 +648,15 @@ public class Npc
|
|||||||
if (_targetNpc == null)
|
if (_targetNpc == null)
|
||||||
{
|
{
|
||||||
float bestDist = float.MaxValue;
|
float bestDist = float.MaxValue;
|
||||||
foreach (var other in gm.Npcs)
|
Npc? partner = null;
|
||||||
|
gm.Grid.ForEachNear(Position, 60f, other =>
|
||||||
{
|
{
|
||||||
if (other == this) continue;
|
if (other == this) return;
|
||||||
if (!TradeSystem.CanTrade(this, other, out _)) continue;
|
if (!TradeSystem.CanTrade(this, other, out _)) return;
|
||||||
float d = Position.DistanceSquaredTo(other.Position);
|
float d = Position.DistanceSquaredTo(other.Position);
|
||||||
if (d < bestDist) { bestDist = d; _targetNpc = other; }
|
if (d < bestDist) { bestDist = d; partner = other; }
|
||||||
}
|
});
|
||||||
|
_targetNpc = partner;
|
||||||
if (_targetNpc == null) { Enter(NpcState.Building); return; }
|
if (_targetNpc == null) { Enter(NpcState.Building); return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,11 +670,102 @@ public class Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>True if this homeless builder is carrying enough of the
|
||||||
|
/// material their private roof needs next (or enough stone to found one).</summary>
|
||||||
|
private bool CarriesShelterMaterial(GameManager gm)
|
||||||
|
{
|
||||||
|
var mine = MyUnfinishedShelter(gm);
|
||||||
|
var need = mine?.NeededMaterial ?? MaterialKind.Stone;
|
||||||
|
return Inventory.TryGetValue(need, out float have) && have >= 8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>This soul's own in-progress private shelter, if any — the
|
||||||
|
/// nearest unfinished shelter they KNOW about in their town. Because it
|
||||||
|
/// searches known structures (not all buildings by proximity), a builder
|
||||||
|
/// reliably returns to the foundation they laid instead of forgetting it
|
||||||
|
/// the moment they wander off and founding another.</summary>
|
||||||
|
private Building? MyUnfinishedShelter(GameManager gm)
|
||||||
|
{
|
||||||
|
Building? mine = null;
|
||||||
|
float best = float.MaxValue;
|
||||||
|
foreach (var b in KnownStructures)
|
||||||
|
{
|
||||||
|
if (b.Town != HomeTown || b.IsComplete || b.IsRuined ||
|
||||||
|
b.Kind != BuildingKind.Shelter) continue;
|
||||||
|
float d = Position.DistanceSquaredTo(b.Site);
|
||||||
|
if (d < best) { best = d; mine = b; }
|
||||||
|
}
|
||||||
|
return mine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
// My own unfinished home — found via known-structures memory, so I
|
||||||
|
// return to the foundation I laid however far I wandered for wood,
|
||||||
|
// rather than re-founding a new one each trip.
|
||||||
|
Building? mine = MyUnfinishedShelter(gm);
|
||||||
|
|
||||||
|
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);
|
||||||
|
KnownStructures.Add(mine); // you never forget the home you laid
|
||||||
|
// Don't clear the homeless drive yet — a foundation isn't a home.
|
||||||
|
// It resets only once the roof is on (below), so the builder keeps
|
||||||
|
// supplying walls and roof instead of stalling at the foundation.
|
||||||
|
Godot.GD.Print($"[Homestead] day {gm.Day}: {Name} ({HomeTown}) breaks ground on a private home.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity = "building my own home";
|
||||||
|
MoveToward(mine.Site);
|
||||||
|
if (Position.DistanceTo(mine.Site) < ArriveDist)
|
||||||
|
{
|
||||||
|
mine.Deliver(this);
|
||||||
|
if (mine.IsComplete)
|
||||||
|
{
|
||||||
|
_unshelteredRests = 0; // a home at last — drive satisfied
|
||||||
|
Enter(NpcState.Socializing);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Foundation down but walls/roof still needed — go fetch the
|
||||||
|
// next material and come back. A lone builder finishes their
|
||||||
|
// own house or it never gets finished.
|
||||||
|
Enter(NpcState.Gathering);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void TickBuilding(GameManager gm)
|
private void TickBuilding(GameManager gm)
|
||||||
{
|
{
|
||||||
// Communal work is for communal souls. The others still sleep in the
|
// Communal work is for communal souls — the others don't tend the
|
||||||
// shelters and eat from the granary — freeriding is the whole point.
|
// village's hearths or fill its granary. But even a selfish soul
|
||||||
if (!IsCommunal) { Enter(NpcState.Socializing); return; }
|
// 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:
|
// Serve your own settlement's buildings, nearest first:
|
||||||
// construction → firewood → granary deposits → expansion.
|
// construction → firewood → granary deposits → expansion.
|
||||||
@@ -574,6 +832,7 @@ public class Npc
|
|||||||
site = Building.NewShelter(home + jitter);
|
site = Building.NewShelter(home + jitter);
|
||||||
site.Town = HomeTown;
|
site.Town = HomeTown;
|
||||||
gm.Buildings.Add(site);
|
gm.Buildings.Add(site);
|
||||||
|
KnownStructures.Add(site);
|
||||||
_unshelteredRests = 0;
|
_unshelteredRests = 0;
|
||||||
GD.Print($"[Found] day {gm.Day}: {Name} founds shelter at {site.Site} " +
|
GD.Print($"[Found] day {gm.Day}: {Name} founds shelter at {site.Site} " +
|
||||||
$"(centroid dist {(site.Site - gm.TownCentroid(HomeTown)).Length():0})");
|
$"(centroid dist {(site.Site - gm.TownCentroid(HomeTown)).Length():0})");
|
||||||
@@ -588,6 +847,7 @@ public class Npc
|
|||||||
site = Building.NewGranary(Position + jitter);
|
site = Building.NewGranary(Position + jitter);
|
||||||
site.Town = HomeTown;
|
site.Town = HomeTown;
|
||||||
gm.Buildings.Add(site);
|
gm.Buildings.Add(site);
|
||||||
|
KnownStructures.Add(site);
|
||||||
}
|
}
|
||||||
// Nothing needs your stone: take it back to the quarry rather
|
// Nothing needs your stone: take it back to the quarry rather
|
||||||
// than carry a house on your back forever. Matter is conserved;
|
// than carry a house on your back forever. Matter is conserved;
|
||||||
@@ -636,7 +896,11 @@ public class Npc
|
|||||||
foreach (var b in gm.Buildings)
|
foreach (var b in gm.Buildings)
|
||||||
{
|
{
|
||||||
if (b.RestCapacity <= 0) continue;
|
if (b.RestCapacity <= 0) continue;
|
||||||
if (gm.RestingOccupancy(b, this) >= b.RestCapacity) continue;
|
// Read the cached per-tick occupancy; +1 to leave room for us if
|
||||||
|
// we're not already counted there.
|
||||||
|
bool alreadyHere = Position.DistanceSquaredTo(b.Site) < 6.25f;
|
||||||
|
int taken = alreadyHere ? b.Occupancy - 1 : b.Occupancy;
|
||||||
|
if (taken >= b.RestCapacity) continue;
|
||||||
float d = Position.DistanceSquaredTo(b.Site);
|
float d = Position.DistanceSquaredTo(b.Site);
|
||||||
if (d < bestDist) { bestDist = d; shelter = b; }
|
if (d < bestDist) { bestDist = d; shelter = b; }
|
||||||
}
|
}
|
||||||
@@ -647,7 +911,7 @@ public class Npc
|
|||||||
if (shelter != null)
|
if (shelter != null)
|
||||||
{
|
{
|
||||||
if (Position.DistanceTo(shelter.Site) > 2.5f) MoveToward(shelter.Site);
|
if (Position.DistanceTo(shelter.Site) > 2.5f) MoveToward(shelter.Site);
|
||||||
else sheltered = gm.RestingOccupancy(shelter, this) < shelter.RestCapacity;
|
else sheltered = true; // we selected a shelter with a free bed
|
||||||
}
|
}
|
||||||
Activity = sheltered ? "resting at shelter"
|
Activity = sheltered ? "resting at shelter"
|
||||||
: shelter != null ? "walking home to rest"
|
: shelter != null ? "walking home to rest"
|
||||||
@@ -688,18 +952,17 @@ public class Npc
|
|||||||
// than drifting to whoever's closest. This is the North's culture in
|
// than drifting to whoever's closest. This is the North's culture in
|
||||||
// motion: the young sitting at the feet of the old, on purpose.
|
// motion: the young sitting at the feet of the old, on purpose.
|
||||||
Npc? nearest = null;
|
Npc? nearest = null;
|
||||||
float bestDist = float.MaxValue;
|
|
||||||
|
|
||||||
if (Soul.Absorption > 1.2f && Know.Total < Know.Capacity * 0.6f)
|
if (Soul.Absorption > 1.2f && Know.Total < Know.Capacity * 0.6f)
|
||||||
{
|
{
|
||||||
Npc? teacher = null;
|
Npc? teacher = null;
|
||||||
float bestWorth = 0.15f; // must actually know more than us
|
float bestWorth = 0.15f; // must actually know more than us
|
||||||
foreach (var other in gm.Npcs)
|
gm.Grid.ForEachNear(Position, 40f, other =>
|
||||||
{
|
{
|
||||||
if (other == this || other.HomeTown != HomeTown) continue;
|
if (other == this || other.HomeTown != HomeTown) return;
|
||||||
float worth = (other.Know.Total - Know.Total) * (1f + other.Soul.TeachingDrive);
|
float worth = (other.Know.Total - Know.Total) * (1f + other.Soul.TeachingDrive);
|
||||||
if (worth > bestWorth) { bestWorth = worth; teacher = other; }
|
if (worth > bestWorth) { bestWorth = worth; teacher = other; }
|
||||||
}
|
});
|
||||||
if (teacher != null)
|
if (teacher != null)
|
||||||
{
|
{
|
||||||
if (Position.DistanceTo(teacher.Position) > 3f)
|
if (Position.DistanceTo(teacher.Position) > 3f)
|
||||||
@@ -717,13 +980,51 @@ public class Npc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise: drift toward the nearest neighbor — community forms
|
// A bonded soul keeps their partner's company by preference —
|
||||||
// where feet do.
|
// relationships are a pull the work queue doesn't override.
|
||||||
foreach (var other in gm.Npcs)
|
if (IsBonded && Partner!.Health > 0f)
|
||||||
{
|
{
|
||||||
if (other == this) continue;
|
if (Position.DistanceTo(Partner.Position) > 3f)
|
||||||
|
{
|
||||||
|
Activity = $"with {Partner.Name}";
|
||||||
|
MoveToward(Partner.Position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RecordEcho(Partner.Name, 0.02f);
|
||||||
|
Activity = $"beside {Partner.Name}";
|
||||||
|
}
|
||||||
|
if (!gm.IsNight && _stateTimer > 20f) Enter(NpcState.Gathering);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise: drift toward the nearest neighbor — community forms
|
||||||
|
// where feet do. Grid-scoped so it stays cheap at scale.
|
||||||
|
Npc? found = null;
|
||||||
|
float fBest = float.MaxValue;
|
||||||
|
gm.Grid.ForEachNear(Position, 30f, other =>
|
||||||
|
{
|
||||||
|
if (other == this) return;
|
||||||
float d = Position.DistanceSquaredTo(other.Position);
|
float d = Position.DistanceSquaredTo(other.Position);
|
||||||
if (d < bestDist) { bestDist = d; nearest = other; }
|
if (d < fBest) { fBest = d; found = other; }
|
||||||
|
});
|
||||||
|
nearest = found;
|
||||||
|
|
||||||
|
// Consider bonding: an unbonded adult who keeps warm company with a
|
||||||
|
// compatible, unbonded neighbor may pair with them — real warmth,
|
||||||
|
// both grown, companionship chosen not assigned. Town is NOT a
|
||||||
|
// requirement: usually you bond within your own people (that's who
|
||||||
|
// you're near), but a wanderer who warms to someone from another
|
||||||
|
// town can shack up across cultures — the first quiet thread of
|
||||||
|
// contact between two peoples.
|
||||||
|
if (!IsBonded && IsAdult && nearest is { IsBonded: false, IsAdult: true } n &&
|
||||||
|
Position.DistanceTo(n.Position) < 4f &&
|
||||||
|
GetWarmth(n.Name) > 0.4f && n.GetWarmth(Name) > 0.4f)
|
||||||
|
{
|
||||||
|
Partner = n;
|
||||||
|
n.Partner = this;
|
||||||
|
string kind = n.HomeTown == HomeTown ? HomeTown : $"{HomeTown}+{n.HomeTown}";
|
||||||
|
Godot.GD.Print($"[Bond] day {gm.Day}: {Name} and {n.Name} ({kind}) pair up.");
|
||||||
}
|
}
|
||||||
if (nearest != null && Position.DistanceTo(nearest.Position) > 3f)
|
if (nearest != null && Position.DistanceTo(nearest.Position) > 3f)
|
||||||
{
|
{
|
||||||
@@ -732,6 +1033,18 @@ public class Npc
|
|||||||
}
|
}
|
||||||
else if (nearest != null)
|
else if (nearest != null)
|
||||||
{
|
{
|
||||||
|
// Company that isn't teaching still warms — this is how bonds
|
||||||
|
// become possible: familiarity accrues just by spending time.
|
||||||
|
RecordEcho(nearest.Name, 0.01f);
|
||||||
|
// Word of good ground travels between neighbors — the same
|
||||||
|
// proximity diffusion as skills, applied to places (addendum §4).
|
||||||
|
// Gated to the sense cadence so it isn't re-run every tick (the
|
||||||
|
// set-iteration was a real per-tick cost at scale).
|
||||||
|
if (_senseTimer >= 29)
|
||||||
|
{
|
||||||
|
nearest.ShareNodeKnowledge(this);
|
||||||
|
ShareNodeKnowledge(nearest);
|
||||||
|
}
|
||||||
Activity = LearnFrom(nearest)
|
Activity = LearnFrom(nearest)
|
||||||
? $"learning from {nearest.Name}"
|
? $"learning from {nearest.Name}"
|
||||||
: $"chatting with {nearest.Name}";
|
: $"chatting with {nearest.Name}";
|
||||||
|
|||||||
@@ -89,6 +89,25 @@ public class SoulProfile
|
|||||||
TeachingDrive = 0.9f, // and to hand it down in turn — the whole culture
|
TeachingDrive = 0.9f, // and to hand it down in turn — the whole culture
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// West-weighted profile: worth measured in visible possessions
|
||||||
|
/// (DESIGN.md). They build — even communally — but for display, so they
|
||||||
|
/// expand shelters hard (status is size); moderate generosity, moderate
|
||||||
|
/// hoarding, little interest in learning or teaching. A functioning town
|
||||||
|
/// whose surplus goes to ostentation rather than resilience.
|
||||||
|
/// </summary>
|
||||||
|
public static SoulProfile MaterialistSoul() => new()
|
||||||
|
{
|
||||||
|
Type = SoulType.Materialist,
|
||||||
|
Generosity = 0.4f,
|
||||||
|
Sustainability = 0.6f,
|
||||||
|
CommunityBias = 0.6f,
|
||||||
|
StatusBias = 0.9f,
|
||||||
|
Accumulation = 0.6f,
|
||||||
|
Absorption = 0.9f,
|
||||||
|
TeachingDrive = 0.2f,
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// East-weighted profile — not part of MVP behavior, but defined now for
|
/// East-weighted profile — not part of MVP behavior, but defined now for
|
||||||
/// the end-of-MVP contrast test (SPEC §11 amendment): 3 selfish NPCs
|
/// the end-of-MVP contrast test (SPEC §11 amendment): 3 selfish NPCs
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace WorldSim;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A coarse spatial hash over NPC positions so proximity queries stop being
|
||||||
|
/// O(n²). Rebuilt once per tick from the live NPC list; queries return only
|
||||||
|
/// the buckets within range. At ~80 NPCs this turns every soul-pressure,
|
||||||
|
/// neighbor, and teacher scan from "look at everyone" into "look at the few
|
||||||
|
/// nearby" — the difference between a live view that stutters and one that
|
||||||
|
/// doesn't.
|
||||||
|
/// </summary>
|
||||||
|
public class SpatialGrid
|
||||||
|
{
|
||||||
|
private readonly float _cell;
|
||||||
|
private readonly Dictionary<(int, int), List<Npc>> _buckets = new();
|
||||||
|
|
||||||
|
public SpatialGrid(float cellSize) => _cell = cellSize;
|
||||||
|
|
||||||
|
private (int, int) Key(Vector2 p) =>
|
||||||
|
(Mathf.FloorToInt(p.X / _cell), Mathf.FloorToInt(p.Y / _cell));
|
||||||
|
|
||||||
|
public void Rebuild(IReadOnlyList<Npc> npcs)
|
||||||
|
{
|
||||||
|
foreach (var list in _buckets.Values) list.Clear();
|
||||||
|
foreach (var npc in npcs)
|
||||||
|
{
|
||||||
|
var key = Key(npc.Position);
|
||||||
|
if (!_buckets.TryGetValue(key, out var list))
|
||||||
|
_buckets[key] = list = new List<Npc>();
|
||||||
|
list.Add(npc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke <paramref name="action"/> for every NPC within <paramref
|
||||||
|
/// name="radius"/> of <paramref name="center"/> (excluding none — caller
|
||||||
|
/// filters). Scans only the buckets the radius touches.
|
||||||
|
/// </summary>
|
||||||
|
public void ForEachNear(Vector2 center, float radius, System.Action<Npc> action)
|
||||||
|
{
|
||||||
|
int reach = Mathf.CeilToInt(radius / _cell);
|
||||||
|
var (cx, cy) = Key(center);
|
||||||
|
for (int dx = -reach; dx <= reach; dx++)
|
||||||
|
for (int dy = -reach; dy <= reach; dy++)
|
||||||
|
{
|
||||||
|
if (_buckets.TryGetValue((cx + dx, cy + dy), out var list))
|
||||||
|
foreach (var npc in list) action(npc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://c25pljmkqmej
|
||||||
+10
-3
@@ -21,7 +21,7 @@ public static class StatsLogger
|
|||||||
"avg_fatigue,avg_nourish,avg_health,carried," +
|
"avg_fatigue,avg_nourish,avg_health,carried," +
|
||||||
"gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
|
"gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
|
||||||
"shelters_done,ruins,avg_cond,upkeep_stock,burn_per_day,modules,granary_food," +
|
"shelters_done,ruins,avg_cond,upkeep_stock,burn_per_day,modules,granary_food," +
|
||||||
"avg_debris,refusals,incomplete_sites,avg_knowledge,deaths";
|
"avg_debris,refusals,incomplete_sites,avg_knowledge,deaths,births,population";
|
||||||
|
|
||||||
private const string NpcHeader =
|
private const string NpcHeader =
|
||||||
"day,npc,name,soul,town,dominant,gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
|
"day,npc,name,soul,town,dominant,gather_ticks,build_ticks,trade_ticks,rest_ticks,social_ticks," +
|
||||||
@@ -35,7 +35,11 @@ public static class StatsLogger
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
string dir = ProjectSettings.GlobalizePath("res://");
|
// Write into soak/ — a plain folder Godot doesn't import as assets
|
||||||
|
// (a .gdignore there stops the editor from turning CSV columns into
|
||||||
|
// translation files). Keeps generated debug output out of the way.
|
||||||
|
string dir = Path.Combine(ProjectSettings.GlobalizePath("res://"), "soak");
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
_path = Path.Combine(dir, "soak_stats.csv");
|
_path = Path.Combine(dir, "soak_stats.csv");
|
||||||
_npcPath = Path.Combine(dir, "soak_npc_days.csv");
|
_npcPath = Path.Combine(dir, "soak_npc_days.csv");
|
||||||
_giftPath = Path.Combine(dir, "soak_gifts.csv");
|
_giftPath = Path.Combine(dir, "soak_gifts.csv");
|
||||||
@@ -149,7 +153,9 @@ public static class StatsLogger
|
|||||||
float knowSum = 0f;
|
float knowSum = 0f;
|
||||||
foreach (var npc in gm.Npcs) knowSum += npc.Know.Total;
|
foreach (var npc in gm.Npcs) knowSum += npc.Know.Total;
|
||||||
row.Append((knowSum / count).ToString("0.000", ci)).Append(',');
|
row.Append((knowSum / count).ToString("0.000", ci)).Append(',');
|
||||||
row.Append(gm.DeathsToday);
|
row.Append(gm.DeathsToday).Append(',');
|
||||||
|
row.Append(gm.BirthsToday).Append(',');
|
||||||
|
row.Append(gm.Npcs.Count);
|
||||||
|
|
||||||
File.AppendAllText(_path, row + "\n");
|
File.AppendAllText(_path, row + "\n");
|
||||||
|
|
||||||
@@ -190,5 +196,6 @@ public static class StatsLogger
|
|||||||
TradeSystem.TradesToday = 0;
|
TradeSystem.TradesToday = 0;
|
||||||
TradeSystem.RefusalsToday = 0;
|
TradeSystem.RefusalsToday = 0;
|
||||||
gm.DeathsToday = 0;
|
gm.DeathsToday = 0;
|
||||||
|
gm.BirthsToday = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+114
-54
@@ -63,6 +63,8 @@ public partial class Visualization : Node2D
|
|||||||
MaterialKind.Clay => new Color(0.75f, 0.45f, 0.25f),
|
MaterialKind.Clay => new Color(0.75f, 0.45f, 0.25f),
|
||||||
MaterialKind.Water => new Color(0.25f, 0.45f, 0.85f),
|
MaterialKind.Water => new Color(0.25f, 0.45f, 0.85f),
|
||||||
MaterialKind.Food => new Color(0.80f, 0.30f, 0.40f),
|
MaterialKind.Food => new Color(0.80f, 0.30f, 0.40f),
|
||||||
|
MaterialKind.Ore => new Color(0.65f, 0.55f, 0.75f),
|
||||||
|
MaterialKind.Herb => new Color(0.45f, 0.80f, 0.55f),
|
||||||
_ => Colors.Magenta,
|
_ => Colors.Magenta,
|
||||||
};
|
};
|
||||||
// Fade toward depletion so dying groves read at a glance
|
// Fade toward depletion so dying groves read at a glance
|
||||||
@@ -81,18 +83,52 @@ public partial class Visualization : Node2D
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Map: buildings ----------------------------------------------
|
// --- Map: buildings ----------------------------------------------
|
||||||
|
// Shelters wear their town's culture-color; granaries stay green;
|
||||||
|
// ruins go dark. A house shared by two towns (a mixed household) is
|
||||||
|
// split diagonally, half each culture — you can see across the map
|
||||||
|
// where someone shacked up with a neighbor from another people.
|
||||||
for (int i = 0; i < _gm.Buildings.Count; i++)
|
for (int i = 0; i < _gm.Buildings.Count; i++)
|
||||||
{
|
{
|
||||||
var b = _gm.Buildings[i];
|
var b = _gm.Buildings[i];
|
||||||
Color c = b.IsRuined ? new Color(0.25f, 0.23f, 0.20f)
|
|
||||||
: b.Kind == BuildingKind.Granary
|
|
||||||
? (b.IsComplete ? new Color(0.55f, 0.70f, 0.40f)
|
|
||||||
: new Color(0.45f, 0.52f, 0.32f))
|
|
||||||
: b.IsComplete ? new Color(0.9f, 0.85f, 0.6f).Darkened((1f - b.Condition) * 0.5f)
|
|
||||||
: new Color(0.6f, 0.5f, 0.3f);
|
|
||||||
float size = CellPixels + 3f + (b.CurrentStage + b.StageProgress) * 2f + b.Modules * 1.5f;
|
float size = CellPixels + 3f + (b.CurrentStage + b.StageProgress) * 2f + b.Modules * 1.5f;
|
||||||
var p = MapPos(b.Site);
|
var p = MapPos(b.Site);
|
||||||
DrawRect(new Rect2(p.X - size / 2f, p.Y - size / 2f, size, size), c);
|
var rect = new Rect2(p.X - size / 2f, p.Y - size / 2f, size, size);
|
||||||
|
|
||||||
|
if (b.IsRuined)
|
||||||
|
{
|
||||||
|
DrawRect(rect, new Color(0.25f, 0.23f, 0.20f));
|
||||||
|
}
|
||||||
|
else if (b.Kind == BuildingKind.Granary)
|
||||||
|
{
|
||||||
|
DrawRect(rect, b.IsComplete ? new Color(0.55f, 0.70f, 0.40f)
|
||||||
|
: new Color(0.45f, 0.52f, 0.32f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Base color = the house's own town culture, dimmed by wear.
|
||||||
|
float dim = b.IsComplete ? (1f - b.Condition) * 0.5f : 0.35f;
|
||||||
|
Color own = TownColor(_gm.TownSoul(b.Town)).Darkened(dim);
|
||||||
|
|
||||||
|
bool mixed = b.ResidentTownB != "" && b.ResidentTownB != b.ResidentTownA;
|
||||||
|
if (mixed)
|
||||||
|
{
|
||||||
|
// Split diagonally: town A on the upper-left triangle,
|
||||||
|
// town B on the lower-right.
|
||||||
|
Color ca = TownColor(_gm.TownSoul(b.ResidentTownA)).Darkened(dim);
|
||||||
|
Color cb = TownColor(_gm.TownSoul(b.ResidentTownB)).Darkened(dim);
|
||||||
|
var tl = new Vector2(rect.Position.X, rect.Position.Y);
|
||||||
|
var tr = new Vector2(rect.End.X, rect.Position.Y);
|
||||||
|
var br = new Vector2(rect.End.X, rect.End.Y);
|
||||||
|
var bl = new Vector2(rect.Position.X, rect.End.Y);
|
||||||
|
DrawColoredPolygon(new[] { tl, tr, bl }, ca); // upper-left ▲
|
||||||
|
DrawColoredPolygon(new[] { tr, br, bl }, cb); // lower-right ▼
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawRect(rect, own);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawString(font, p + new Vector2(size / 2f + 2f, 4f), $"{i + 1}",
|
DrawString(font, p + new Vector2(size / 2f + 2f, 4f), $"{i + 1}",
|
||||||
fontSize: 10, modulate: TextDim);
|
fontSize: 10, modulate: TextDim);
|
||||||
}
|
}
|
||||||
@@ -117,68 +153,92 @@ public partial class Visualization : Node2D
|
|||||||
$"{(_gm.IsNight ? "· night" : "· day")} {_gm.TicksPerRealSecond:0}x",
|
$"{(_gm.IsNight ? "· night" : "· day")} {_gm.TicksPerRealSecond:0}x",
|
||||||
fontSize: 18, modulate: TextMain);
|
fontSize: 18, modulate: TextMain);
|
||||||
|
|
||||||
// --- Panel: villager roster --------------------------------------
|
// --- Panel: per-town summary (scales to any population) ----------
|
||||||
float y = 66f;
|
float y = 74f;
|
||||||
DrawString(font, new Vector2(PanelX + 16, y), "VILLAGERS",
|
|
||||||
fontSize: 13, modulate: TextDim);
|
|
||||||
y += 10f;
|
|
||||||
|
|
||||||
for (int i = 0; i < _gm.Npcs.Count; i++)
|
foreach (var town in _gm.Towns)
|
||||||
{
|
{
|
||||||
var npc = _gm.Npcs[i];
|
// Aggregate this town's people.
|
||||||
y += 20f;
|
int pop = 0; float nour = 0f, know = 0f, debris = 0f;
|
||||||
|
int gathering = 0, building = 0, resting = 0, social = 0, other = 0;
|
||||||
|
foreach (var npc in _gm.Npcs)
|
||||||
|
{
|
||||||
|
if (npc.HomeTown != town.Name) continue;
|
||||||
|
pop++; nour += npc.Nourishment; know += npc.Know.Total; debris += npc.Imprint.Total;
|
||||||
|
switch (npc.State)
|
||||||
|
{
|
||||||
|
case NpcState.Gathering: gathering++; break;
|
||||||
|
case NpcState.Building: building++; break;
|
||||||
|
case NpcState.Resting: resting++; break;
|
||||||
|
case NpcState.Socializing: social++; break;
|
||||||
|
default: other++; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (npc.Soul.Type == SoulType.Selfish)
|
// Aggregate this town's buildings.
|
||||||
DrawCircle(new Vector2(PanelX + 24, y - 5f), 6f, new Color(0.75f, 0.15f, 0.15f));
|
int shelters = 0, ruins = 0; float granary = 0f;
|
||||||
DrawCircle(new Vector2(PanelX + 24, y - 5f), 4.5f,
|
foreach (var b in _gm.Buildings)
|
||||||
StateColor(npc.State).Darkened(npc.Imprint.Total * 0.7f));
|
{
|
||||||
DrawString(font, new Vector2(PanelX + 36, y),
|
if (b.Town != town.Name) continue;
|
||||||
$"{i + 1,2} {npc.State,-11} {npc.Activity}",
|
if (b.IsRuined) ruins++;
|
||||||
fontSize: 13, modulate: TextMain);
|
else if (b.Kind == BuildingKind.Granary) granary += b.FoodStock;
|
||||||
DrawString(font, new Vector2(PanelX + 390, y),
|
else if (b.IsComplete) shelters++;
|
||||||
$"N {npc.Nourishment * 100,3:0} D {npc.Imprint.Total * 100,2:0}" +
|
}
|
||||||
$" K {npc.Know.Total,4:0.00} A {npc.AgeDays,3:0}" +
|
|
||||||
$" {npc.DominantStateToday().ToString().ToLower()[..4]}",
|
var head = TownColor(town.Soul);
|
||||||
|
DrawString(font, new Vector2(PanelX + 16, y),
|
||||||
|
$"{town.Name.ToUpper()} · {town.Soul.ToString().ToLower()}",
|
||||||
|
fontSize: 15, modulate: pop > 0 ? head : TextDim);
|
||||||
|
DrawString(font, new Vector2(PanelX + 250, y),
|
||||||
|
pop > 0 ? $"pop {pop}" : "— extinct —",
|
||||||
|
fontSize: 15, modulate: pop > 0 ? TextMain : new Color(0.8f, 0.4f, 0.4f));
|
||||||
|
y += 22f;
|
||||||
|
|
||||||
|
if (pop > 0)
|
||||||
|
{
|
||||||
|
float inv = 1f / pop;
|
||||||
|
DrawString(font, new Vector2(PanelX + 28, y),
|
||||||
|
$"fed {nour * inv * 100,3:0}% know {know * inv,4:0.00} debris {debris * inv * 100,2:0}%",
|
||||||
|
fontSize: 13, modulate: TextDim);
|
||||||
|
DrawString(font, new Vector2(PanelX + 320, y),
|
||||||
|
$"⌂{shelters} ▦{granary:0}" + (ruins > 0 ? $" ✗{ruins}" : ""),
|
||||||
|
fontSize: 13, modulate: TextDim);
|
||||||
|
y += 19f;
|
||||||
|
DrawString(font, new Vector2(PanelX + 28, y),
|
||||||
|
$"gather {gathering} build {building} rest {resting} social {social}" +
|
||||||
|
(other > 0 ? $" other {other}" : ""),
|
||||||
fontSize: 12, modulate: TextDim);
|
fontSize: 12, modulate: TextDim);
|
||||||
|
y += 19f;
|
||||||
|
}
|
||||||
|
y += 12f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Panel: buildings --------------------------------------------
|
// --- Panel: world vitals (bottom) --------------------------------
|
||||||
y += 34f;
|
y += 8f;
|
||||||
DrawString(font, new Vector2(PanelX + 16, y), "BUILDINGS",
|
float wood = 0f, stone = 0f, food = 0f;
|
||||||
fontSize: 13, modulate: TextDim);
|
|
||||||
y += 10f;
|
|
||||||
|
|
||||||
for (int i = 0; i < _gm.Buildings.Count; i++)
|
|
||||||
{
|
|
||||||
var b = _gm.Buildings[i];
|
|
||||||
y += 18f;
|
|
||||||
string status = b.IsRuined ? "RUIN"
|
|
||||||
: !b.IsComplete
|
|
||||||
? $"building: {b.Stages[b.CurrentStage].Name} {b.StageProgress * 100,3:0}%"
|
|
||||||
: b.Kind == BuildingKind.Granary
|
|
||||||
? $"granary food {b.FoodStock,5:0.0}/{Building.FoodStockCap:0}"
|
|
||||||
: $"cond {b.Condition * 100,3:0}% wood {b.UpkeepStock,4:0.0}/{Building.UpkeepStockCap:0}" +
|
|
||||||
$" mods {b.Modules}/{Building.ModuleCap} burn {b.DailyBurn:0.0}/day";
|
|
||||||
DrawString(font, new Vector2(PanelX + 36, y),
|
|
||||||
$"{i + 1} {b.Town,-5} {status}", fontSize: 12,
|
|
||||||
modulate: b.IsRuined ? TextDim : TextMain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Panel: world totals -----------------------------------------
|
|
||||||
y += 34f;
|
|
||||||
float wood = 0f, stone = 0f, clay = 0f, foodTotal = 0f;
|
|
||||||
foreach (var n in _gm.World.Nodes)
|
foreach (var n in _gm.World.Nodes)
|
||||||
{
|
{
|
||||||
switch (n.Kind)
|
switch (n.Kind)
|
||||||
{
|
{
|
||||||
case MaterialKind.Wood: wood += n.Amount; break;
|
case MaterialKind.Wood: wood += n.Amount; break;
|
||||||
case MaterialKind.Stone: stone += n.Amount; break;
|
case MaterialKind.Stone: stone += n.Amount; break;
|
||||||
case MaterialKind.Clay: clay += n.Amount; break;
|
case MaterialKind.Food: food += n.Amount; break;
|
||||||
case MaterialKind.Food: foodTotal += n.Amount; break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DrawString(font, new Vector2(PanelX + 16, y),
|
DrawString(font, new Vector2(PanelX + 16, y),
|
||||||
$"WORLD wood {wood:0} stone {stone:0} clay {clay:0} food {foodTotal:0}",
|
$"WORLD pop {_gm.Npcs.Count} +{_gm.BirthsToday}/−{_gm.DeathsToday} today",
|
||||||
|
fontSize: 14, modulate: TextMain);
|
||||||
|
y += 20f;
|
||||||
|
DrawString(font, new Vector2(PanelX + 16, y),
|
||||||
|
$"land wood {wood:0} stone {stone:0} food {food:0}",
|
||||||
fontSize: 13, modulate: TextDim);
|
fontSize: 13, modulate: TextDim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Color TownColor(SoulType t) => t switch
|
||||||
|
{
|
||||||
|
SoulType.Generational => new Color(0.55f, 0.75f, 0.95f), // North — cool
|
||||||
|
SoulType.Nature => new Color(0.55f, 0.85f, 0.55f), // South — green
|
||||||
|
SoulType.Materialist => new Color(0.90f, 0.80f, 0.45f), // West — gold
|
||||||
|
_ => new Color(0.90f, 0.45f, 0.45f), // East — red
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-9
@@ -4,7 +4,7 @@ using Godot;
|
|||||||
|
|
||||||
namespace WorldSim;
|
namespace WorldSim;
|
||||||
|
|
||||||
public enum MaterialKind { Wood, Stone, Clay, Water, Food }
|
public enum MaterialKind { Wood, Stone, Clay, Water, Food, Ore, Herb }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A harvestable resource node on the grid (SPEC §6).
|
/// A harvestable resource node on the grid (SPEC §6).
|
||||||
@@ -28,7 +28,7 @@ public class ResourceNode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class World
|
public class World
|
||||||
{
|
{
|
||||||
public const int GridSize = 256;
|
public const int GridSize = 1152;
|
||||||
|
|
||||||
public List<ResourceNode> Nodes { get; } = new();
|
public List<ResourceNode> Nodes { get; } = new();
|
||||||
|
|
||||||
@@ -37,6 +37,20 @@ public class World
|
|||||||
|
|
||||||
private readonly Random _rng;
|
private readonly Random _rng;
|
||||||
|
|
||||||
|
// Node cell index (built once — nodes never move). Only the sensing sweep
|
||||||
|
// uses it, but that runs per-NPC constantly, so it's the one place a node
|
||||||
|
// index genuinely pays (unlike nearest-of-kind, which stays a linear scan).
|
||||||
|
private const int NodeCell = 32;
|
||||||
|
private readonly Dictionary<(int, int), List<ResourceNode>> _nodeCells = new();
|
||||||
|
|
||||||
|
private void IndexNode(ResourceNode n)
|
||||||
|
{
|
||||||
|
var key = ((int)(n.Cell.X / NodeCell), (int)(n.Cell.Y / NodeCell));
|
||||||
|
if (!_nodeCells.TryGetValue(key, out var list))
|
||||||
|
_nodeCells[key] = list = new List<ResourceNode>();
|
||||||
|
list.Add(n);
|
||||||
|
}
|
||||||
|
|
||||||
public World(int seed)
|
public World(int seed)
|
||||||
{
|
{
|
||||||
_rng = new Random(seed);
|
_rng = new Random(seed);
|
||||||
@@ -49,25 +63,31 @@ public class World
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Generate()
|
public void Generate()
|
||||||
{
|
{
|
||||||
PlaceMany(MaterialKind.Water, count: 6, amount: float.PositiveInfinity, regen: 0f);
|
// Resource counts scale with area (1152² ≈ 2.25× the 768² world) so
|
||||||
PlaceMany(MaterialKind.Clay, count: 10, amount: 40f, regen: 0.5f); // TODO: constrain near water
|
// density holds as the towns spread to wider cardinal points.
|
||||||
PlaceMany(MaterialKind.Wood, count: 60, amount: 30f, regen: 2f);
|
PlaceMany(MaterialKind.Water, count: 90, amount: float.PositiveInfinity, regen: 0f);
|
||||||
PlaceMany(MaterialKind.Stone, count: 12, amount: 80f, regen: 0f);
|
PlaceMany(MaterialKind.Clay, count: 180, amount: 40f, regen: 0.5f);
|
||||||
PlaceMany(MaterialKind.Food, count: 40, amount: 20f, regen: 4f); // South: flora most abundant
|
PlaceMany(MaterialKind.Wood, count: 1080, amount: 30f, regen: 2f);
|
||||||
|
PlaceMany(MaterialKind.Stone, count: 315, amount: 80f, regen: 0f);
|
||||||
|
PlaceMany(MaterialKind.Food, count: 810, amount: 20f, regen: 4f);
|
||||||
|
PlaceMany(MaterialKind.Ore, count: 90, amount: 60f, regen: 0f);
|
||||||
|
PlaceMany(MaterialKind.Herb, count: 270, amount: 15f, regen: 3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaceMany(MaterialKind kind, int count, float amount, float regen)
|
private void PlaceMany(MaterialKind kind, int count, float amount, float regen)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Nodes.Add(new ResourceNode
|
var node = new ResourceNode
|
||||||
{
|
{
|
||||||
Kind = kind,
|
Kind = kind,
|
||||||
Cell = new Vector2I(_rng.Next(GridSize), _rng.Next(GridSize)),
|
Cell = new Vector2I(_rng.Next(GridSize), _rng.Next(GridSize)),
|
||||||
Amount = amount,
|
Amount = amount,
|
||||||
MaxAmount = amount,
|
MaxAmount = amount,
|
||||||
RegenPerDay = regen,
|
RegenPerDay = regen,
|
||||||
});
|
};
|
||||||
|
Nodes.Add(node);
|
||||||
|
IndexNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +130,35 @@ public class World
|
|||||||
return taken;
|
return taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Invoke action for every node within radius — used by NPCs to
|
||||||
|
/// discover nearby nodes (addendum §4 sensing). Cell-indexed: scans only
|
||||||
|
/// the buckets the radius touches, not all ~1,260 nodes.</summary>
|
||||||
|
public void ForEachNodeNear(Vector2 position, float radius, System.Action<ResourceNode> action)
|
||||||
|
{
|
||||||
|
float r2 = radius * radius;
|
||||||
|
int reach = (int)(radius / NodeCell) + 1;
|
||||||
|
int cx = (int)(position.X / NodeCell);
|
||||||
|
int cy = (int)(position.Y / NodeCell);
|
||||||
|
for (int dx = -reach; dx <= reach; dx++)
|
||||||
|
for (int dy = -reach; dy <= reach; dy++)
|
||||||
|
{
|
||||||
|
if (!_nodeCells.TryGetValue((cx + dx, cy + dy), out var list)) continue;
|
||||||
|
foreach (var node in list)
|
||||||
|
if (position.DistanceSquaredTo(node.Cell) <= r2)
|
||||||
|
action(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Seed a town's founders with the resources around their home,
|
||||||
|
/// so they begin with a working local map instead of blind.</summary>
|
||||||
|
public IEnumerable<ResourceNode> NodesWithin(Vector2 center, float radius)
|
||||||
|
{
|
||||||
|
float r2 = radius * radius;
|
||||||
|
foreach (var node in Nodes)
|
||||||
|
if (center.DistanceSquaredTo(node.Cell) <= r2)
|
||||||
|
yield return node;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Nearest node of a kind regardless of amount — for returning
|
/// <summary>Nearest node of a kind regardless of amount — for returning
|
||||||
/// unneeded minerals to the quarry rather than carrying them forever.</summary>
|
/// unneeded minerals to the quarry rather than carrying them forever.</summary>
|
||||||
public ResourceNode? FindNearestAny(MaterialKind kind, Vector2 position)
|
public ResourceNode? FindNearestAny(MaterialKind kind, Vector2 position)
|
||||||
|
|||||||
-534
@@ -1,534 +0,0 @@
|
|||||||
day,giver,giver_soul,receiver,receiver_soul,material,amount
|
|
||||||
3,North_V,Generational,North_R,Generational,Stone,3.0
|
|
||||||
3,North_S,Generational,South_A,Nature,Stone,3.0
|
|
||||||
3,North_T,Generational,South_N,Selfish,Stone,3.0
|
|
||||||
4,North_W,Generational,South_H,Nature,Stone,3.0
|
|
||||||
4,North_P,Generational,South_M,Selfish,Stone,3.0
|
|
||||||
12,South_D,Nature,South_G,Nature,Stone,3.0
|
|
||||||
17,South_L,Nature,North_S,Generational,Stone,3.0
|
|
||||||
18,South_I,Nature,South_D,Nature,Stone,3.0
|
|
||||||
20,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
25,North_W,Generational,North_V,Generational,Stone,3.0
|
|
||||||
101,South_M,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
101,South_M,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
101,South_M,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
101,South_M,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
101,South_M,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
101,South_M,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
102,South_O,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_D,Nature,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_M,Selfish,North_V,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_N,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
102,South_O,Selfish,North_U,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_N,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_N,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_J,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
103,South_D,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_G,Nature,South_H,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_H,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_H,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_M,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_H,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_F,Nature,North_B26,Generational,Stone,3.0
|
|
||||||
103,North_S,Generational,South_A,Nature,Stone,3.0
|
|
||||||
103,North_V,Generational,South_F,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_N,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_N,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,North_Q,Generational,South_G,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_H,Nature,South_L,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_D,Nature,Stone,3.0
|
|
||||||
103,South_N,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,South_N,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
103,South_O,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
103,South_B,Nature,South_J,Nature,Stone,3.0
|
|
||||||
103,South_D,Nature,North_E29,Generational,Stone,3.0
|
|
||||||
103,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
103,South_I,Nature,South_A,Nature,Stone,3.0
|
|
||||||
103,North_Q,Generational,South_I,Nature,Stone,3.0
|
|
||||||
103,North_U,Generational,North_C27,Generational,Stone,3.0
|
|
||||||
103,South_M,Selfish,North_T,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,North_T,Generational,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,North_S,Generational,South_D,Nature,Stone,3.0
|
|
||||||
103,South_M,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_T,Generational,Refusal,0.0
|
|
||||||
103,South_M,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,North_T,Generational,Refusal,0.0
|
|
||||||
103,North_B26,Generational,South_O,Selfish,Stone,3.0
|
|
||||||
103,South_O,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
103,South_O,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
104,South_E,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_O,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_M,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_N,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
104,South_M,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_N,Selfish,South_D28,Nature,Refusal,0.0
|
|
||||||
104,South_O,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_N,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
104,South_N,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
104,South_N,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_N,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
104,South_F,Nature,North_F30,Generational,Stone,3.0
|
|
||||||
104,South_N,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_N,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_F,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_O,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_O,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_D28,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_M,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_M,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
104,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_E,Nature,Stone,3.0
|
|
||||||
104,South_F,Nature,South_D,Nature,Stone,3.0
|
|
||||||
104,South_J,Nature,South_I,Nature,Stone,3.0
|
|
||||||
104,South_G,Nature,South_F,Nature,Stone,3.0
|
|
||||||
104,South_K,Nature,South_G,Nature,Stone,3.0
|
|
||||||
104,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
104,South_A,Nature,South_H,Nature,Stone,3.0
|
|
||||||
104,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
104,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
104,South_E,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
104,South_I,Nature,South_B,Nature,Stone,3.0
|
|
||||||
104,South_D,Nature,South_E,Nature,Stone,3.0
|
|
||||||
105,South_F,Nature,South_I,Nature,Stone,3.0
|
|
||||||
105,South_N,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
105,South_N,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_F,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_A,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_B,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_E,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_G,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_H,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_I,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_K,Nature,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,South_L,Nature,Refusal,0.0
|
|
||||||
105,South_O,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_O,Selfish,North_F30,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_P,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_S,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_W,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_B26,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_C27,Generational,Refusal,0.0
|
|
||||||
105,South_G31,Selfish,North_E29,Generational,Refusal,0.0
|
|
||||||
106,South_H,Nature,South_G31,Selfish,Stone,3.0
|
|
||||||
107,South_A,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
108,North_Q,Generational,South_I33,Selfish,Stone,3.0
|
|
||||||
108,South_G31,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
108,South_G31,Selfish,North_Q,Generational,Refusal,0.0
|
|
||||||
109,South_G31,Selfish,South_I33,Selfish,Refusal,0.0
|
|
||||||
109,South_O,Selfish,South_I33,Selfish,Refusal,0.0
|
|
||||||
109,South_G31,Selfish,South_I33,Selfish,Refusal,0.0
|
|
||||||
109,South_O,Selfish,South_I33,Selfish,Refusal,0.0
|
|
||||||
117,South_J,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_J,Nature,Stone,3.0
|
|
||||||
117,South_I,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,South_K,Nature,South_H,Nature,Stone,3.0
|
|
||||||
117,South_L,Nature,South_I,Nature,Stone,3.0
|
|
||||||
117,South_B,Nature,South_K,Nature,Stone,3.0
|
|
||||||
117,South_A,Nature,South_B,Nature,Stone,3.0
|
|
||||||
117,South_D28,Nature,South_A,Nature,Stone,3.0
|
|
||||||
117,South_D,Nature,South_L,Nature,Stone,3.0
|
|
||||||
117,South_H32,Nature,South_D,Nature,Stone,3.0
|
|
||||||
117,South_G,Nature,South_D28,Nature,Stone,3.0
|
|
||||||
117,South_J,Nature,South_G,Nature,Stone,3.0
|
|
||||||
117,North_E29,Generational,South_J,Nature,Stone,3.0
|
|
||||||
117,South_F,Nature,South_H32,Nature,Stone,3.0
|
|
||||||
117,South_H,Nature,South_F,Nature,Stone,3.0
|
|
||||||
117,North_S,Generational,South_H,Nature,Stone,3.0
|
|
||||||
117,North_B26,Generational,South_I,Nature,Stone,3.0
|
|
||||||
118,North_V,Generational,South_J34,Nature,Stone,3.0
|
|
||||||
118,South_L,Nature,South_K,Nature,Stone,3.0
|
|
||||||
119,South_A,Nature,North_Q,Generational,Stone,3.0
|
|
||||||
121,South_D28,Nature,North_U,Generational,Stone,3.0
|
|
||||||
121,South_D28,Nature,North_C27,Generational,Stone,3.0
|
|
||||||
122,North_E29,Generational,North_P,Generational,Stone,3.0
|
|
||||||
122,South_A,Nature,South_K35,Nature,Stone,3.0
|
|
||||||
122,North_B26,Generational,North_F30,Generational,Stone,3.0
|
|
||||||
123,South_H32,Nature,North_W,Generational,Stone,3.0
|
|
||||||
123,South_L,Nature,North_L36,Generational,Stone,3.0
|
|
||||||
124,South_D,Nature,South_M37,Nature,Stone,3.0
|
|
||||||
125,South_L,Nature,North_U,Generational,Stone,3.0
|
|
||||||
127,South_G,Nature,South_N38,Nature,Food,3.0
|
|
||||||
148,South_J,Nature,North_U,Generational,Stone,3.0
|
|
||||||
152,South_H32,Nature,South_O39,Nature,Stone,3.0
|
|
||||||
155,South_A,Nature,North_Q41,Generational,Stone,3.0
|
|
||||||
157,South_J34,Nature,South_N38,Nature,Stone,3.0
|
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="csv_translation"
|
|
||||||
type="Translation"
|
|
||||||
uid="uid://dpef17p6lhdnb"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
files=["res://soak_gifts.giver.translation", "res://soak_gifts.giver.translation", "res://soak_gifts.receiver.translation", "res://soak_gifts.receiver.translation", "res://soak_gifts.material.translation", "res://soak_gifts.amount.translation"]
|
|
||||||
|
|
||||||
source_file="res://soak_gifts.csv"
|
|
||||||
dest_files=["res://soak_gifts.giver.translation", "res://soak_gifts.giver.translation", "res://soak_gifts.receiver.translation", "res://soak_gifts.receiver.translation", "res://soak_gifts.material.translation", "res://soak_gifts.amount.translation"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress=1
|
|
||||||
delimiter=0
|
|
||||||
unescape_keys=false
|
|
||||||
unescape_translations=true
|
|
||||||
-6001
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="csv_translation"
|
|
||||||
type="Translation"
|
|
||||||
uid="uid://b1b2os1svftw2"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
files=["res://soak_npc_days.npc.translation", "res://soak_npc_days.name.translation", "res://soak_npc_days.soul.translation", "res://soak_npc_days.town.translation", "res://soak_npc_days.dominant.translation", "res://soak_npc_days.gather.translation", "res://soak_npc_days.build.translation", "res://soak_npc_days.trade.translation", "res://soak_npc_days.rest.translation", "res://soak_npc_days.social.translation", "res://soak_npc_days.nourish.translation", "res://soak_npc_days.health.translation", "res://soak_npc_days.debris.translation", "res://soak_npc_days.demand.translation", "res://soak_npc_days.rough.translation", "res://soak_npc_days.hunger.translation", "res://soak_npc_days.age.translation", "res://soak_npc_days.know.translation", "res://soak_npc_days.know.translation", "res://soak_npc_days.know.translation"]
|
|
||||||
|
|
||||||
source_file="res://soak_npc_days.csv"
|
|
||||||
dest_files=["res://soak_npc_days.npc.translation", "res://soak_npc_days.name.translation", "res://soak_npc_days.soul.translation", "res://soak_npc_days.town.translation", "res://soak_npc_days.dominant.translation", "res://soak_npc_days.gather.translation", "res://soak_npc_days.build.translation", "res://soak_npc_days.trade.translation", "res://soak_npc_days.rest.translation", "res://soak_npc_days.social.translation", "res://soak_npc_days.nourish.translation", "res://soak_npc_days.health.translation", "res://soak_npc_days.debris.translation", "res://soak_npc_days.demand.translation", "res://soak_npc_days.rough.translation", "res://soak_npc_days.hunger.translation", "res://soak_npc_days.age.translation", "res://soak_npc_days.know.translation", "res://soak_npc_days.know.translation", "res://soak_npc_days.know.translation"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress=1
|
|
||||||
delimiter=0
|
|
||||||
unescape_keys=false
|
|
||||||
unescape_translations=true
|
|
||||||
-241
@@ -1,241 +0,0 @@
|
|||||||
day,season,wood,stone,clay,food,harvested,trades,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_knowledge,deaths
|
|
||||||
1,spring,1572.9,960.0,400.0,649.9,572.0,0,0.0,0.766,100.0,572.0,7926,654,0,3486,11934,0,0,0.000,0.0,0.0,0,0.0,0.0031,0,0,0.007,0
|
|
||||||
2,spring,1624.2,960.0,400.0,732.8,46.2,0,0.0,0.914,100.0,568.2,1557,1177,0,12000,21266,0,0,0.000,0.0,0.0,0,0.0,0.0031,0,0,0.008,0
|
|
||||||
3,spring,1667.4,960.0,400.0,784.9,38.1,0,0.0,0.813,100.0,581.3,1365,1188,0,12000,21447,0,0,0.000,0.0,0.0,0,0.0,0.0031,0,0,0.008,0
|
|
||||||
4,spring,1447.2,653.5,400.0,730.7,761.6,3,0.4,0.741,100.0,507.3,9396,5333,920,14434,5917,3,0,1.000,19.5,10.5,9,0.0,0.0031,0,0,0.019,0
|
|
||||||
5,spring,1173.7,750.5,400.0,592.5,763.4,2,3.9,0.859,100.0,507.9,13306,1508,796,14653,5737,3,0,1.000,18.0,12.0,12,0.0,0.0031,0,0,0.029,0
|
|
||||||
6,spring,1000.7,750.5,400.0,577.2,560.3,0,3.9,0.778,100.0,562.0,10070,728,0,13608,11594,3,0,1.000,18.0,12.0,12,0.0,0.0032,0,0,0.036,0
|
|
||||||
7,spring,1027.2,750.5,400.0,573.3,351.8,0,2.0,0.906,100.0,542.0,8876,644,0,13605,12875,3,0,1.000,18.0,12.0,12,0.0,0.0032,0,0,0.041,0
|
|
||||||
8,spring,1016.1,750.5,400.0,587.3,376.2,0,6.2,0.814,100.0,557.9,11121,509,0,13628,10742,3,0,1.000,18.0,12.0,12,0.0,0.0034,0,0,0.046,0
|
|
||||||
9,spring,989.3,750.5,400.0,588.6,399.0,0,7.1,0.732,100.0,562.1,9166,932,20,13592,12290,3,0,1.000,18.0,12.0,12,0.0,0.0036,0,0,0.052,0
|
|
||||||
10,spring,987.3,750.5,400.0,588.4,381.4,0,6.8,0.850,100.0,558.1,9941,666,0,13601,11792,3,0,1.000,18.0,12.0,12,0.0,0.0036,0,0,0.058,0
|
|
||||||
11,spring,962.5,750.5,400.0,580.1,412.4,0,5.6,0.778,100.0,567.2,9466,1216,0,13613,11705,3,0,1.000,18.0,12.0,12,0.0,0.0037,0,0,0.074,0
|
|
||||||
12,spring,1008.6,750.5,400.0,628.0,276.4,0,5.7,0.897,100.0,543.0,9298,704,0,13599,12399,3,0,1.000,18.0,12.0,12,0.0,0.0038,0,0,0.082,0
|
|
||||||
13,spring,1008.3,750.5,400.0,607.7,381.7,1,4.9,0.824,100.0,555.2,9456,1209,144,13427,11764,3,0,1.000,18.0,12.0,12,0.0,0.0039,0,0,0.091,0
|
|
||||||
14,spring,989.5,750.5,400.0,588.1,417.7,0,3.4,0.722,100.0,569.5,8338,694,0,13282,13686,3,0,1.000,18.0,12.0,12,0.0,0.0039,0,0,0.103,0
|
|
||||||
15,spring,979.8,750.5,400.0,614.4,357.9,0,5.7,0.860,100.0,564.6,8260,699,16,13296,13729,3,0,1.000,18.0,12.0,12,0.0,0.0040,0,0,0.112,0
|
|
||||||
16,spring,934.1,750.5,400.0,622.6,392.7,0,4.1,0.768,100.0,567.4,7997,717,0,13283,14003,3,0,1.000,18.0,12.0,12,0.0,0.0042,0,0,0.122,0
|
|
||||||
17,spring,991.5,750.5,400.0,585.3,363.9,0,1.2,0.906,100.0,542.7,7778,715,0,13292,14215,3,0,1.000,18.0,12.0,12,0.0,0.0043,0,0,0.130,0
|
|
||||||
18,spring,972.2,778.6,400.0,590.9,395.5,1,4.6,0.813,100.0,571.1,7761,963,86,12987,14203,3,0,1.000,18.0,12.0,12,0.0,0.0044,0,0,0.141,0
|
|
||||||
19,spring,964.1,778.6,400.0,637.9,331.4,1,2.9,0.731,100.0,578.9,5712,1078,28,12891,16291,3,0,1.000,18.0,12.0,12,0.0,0.0046,0,0,0.149,0
|
|
||||||
20,spring,975.5,778.6,400.0,620.7,367.7,0,1.7,0.859,100.0,575.4,5539,1166,0,12631,16664,3,0,1.000,18.0,12.0,12,0.0,0.0047,0,0,0.166,0
|
|
||||||
21,spring,1021.6,786.7,400.0,678.8,250.3,1,1.1,0.776,100.0,590.0,5046,1226,50,12405,17273,3,0,1.000,18.0,12.0,12,0.0,0.0048,0,0,0.184,0
|
|
||||||
22,spring,1098.2,786.7,400.0,704.0,194.3,0,1.5,0.903,100.0,567.6,3213,1140,0,12314,19333,3,0,1.000,18.0,12.0,12,0.0,0.0049,0,0,0.195,0
|
|
||||||
23,spring,1187.3,799.7,400.0,727.3,145.1,0,0.6,0.821,100.0,585.8,2762,1271,0,12160,19807,3,0,1.000,18.0,12.0,12,0.0,0.0050,0,0,0.213,0
|
|
||||||
24,spring,1240.1,799.7,400.0,736.8,179.0,0,0.7,0.728,100.0,582.9,2452,1324,0,12156,20068,3,0,1.000,18.0,12.0,12,0.0,0.0051,0,0,0.227,0
|
|
||||||
25,spring,1200.3,698.8,400.0,703.5,442.8,0,0.6,0.865,100.0,573.1,6812,2885,0,13490,12813,4,0,1.000,24.0,16.0,16,0.0,0.0052,0,0,0.236,0
|
|
||||||
26,spring,1138.4,729.1,400.0,601.4,501.6,1,2.6,0.772,100.0,578.8,6811,1211,74,12814,15090,4,0,1.000,24.0,16.0,16,0.0,0.0055,0,0,0.248,0
|
|
||||||
27,spring,1165.9,751.3,400.0,724.5,174.9,0,0.0,0.909,100.0,562.4,3251,1548,0,12155,19046,4,0,1.000,24.0,16.0,16,0.0,0.0055,0,0,0.251,0
|
|
||||||
28,spring,1245.9,751.3,400.0,759.6,86.4,0,0.0,0.816,100.0,585.9,2591,1520,0,12000,19889,4,0,1.000,24.0,16.0,16,0.0,0.0056,0,0,0.262,0
|
|
||||||
29,spring,1341.2,751.3,400.0,771.7,48.2,0,0.0,0.733,100.0,591.1,1890,1162,0,12000,20948,4,0,1.000,24.0,16.0,16,0.0,0.0058,0,0,0.276,0
|
|
||||||
30,summer,1406.2,751.3,400.0,769.1,56.2,0,0.0,0.850,100.0,584.4,1996,1218,0,12000,20786,4,0,1.000,24.0,16.0,16,0.0,0.0058,0,0,0.280,0
|
|
||||||
31,summer,1488.6,751.3,400.0,762.7,45.1,0,0.0,0.777,100.0,585.5,1811,1168,0,12000,21021,4,0,1.000,24.0,16.0,16,0.0,0.0060,0,0,0.289,0
|
|
||||||
32,summer,1564.9,751.3,400.0,764.1,45.6,0,0.0,0.894,100.0,568.1,1905,1284,0,12000,20811,4,0,1.000,24.0,16.0,16,0.0,0.0062,0,0,0.298,0
|
|
||||||
33,summer,1629.4,751.3,400.0,752.0,65.2,0,0.0,0.820,100.0,589.3,2087,1376,0,12000,20537,4,0,1.000,24.0,16.0,16,0.0,0.0064,0,0,0.302,0
|
|
||||||
34,summer,1673.4,751.3,400.0,758.0,40.3,0,0.0,0.727,100.0,587.6,1692,1169,0,12000,21139,4,0,1.000,24.0,16.0,16,0.0,0.0067,0,0,0.307,0
|
|
||||||
35,summer,1680.9,751.3,400.0,749.8,66.1,0,0.0,0.863,100.0,588.7,2238,1658,0,12000,20104,4,0,1.000,24.0,16.0,16,0.0,0.0069,0,0,0.311,0
|
|
||||||
36,summer,1688.6,751.3,400.0,752.4,42.3,0,0.0,0.769,100.0,589.0,1803,1166,0,12000,21031,4,0,1.000,24.0,16.0,16,0.0,0.0071,0,0,0.312,0
|
|
||||||
37,summer,1688.8,751.3,400.0,761.0,40.8,0,0.0,0.905,100.0,564.8,1924,1228,0,12000,20848,4,0,1.000,24.0,16.0,16,0.0,0.0072,0,0,0.313,0
|
|
||||||
38,summer,1694.4,751.3,400.0,745.6,66.9,0,0.0,0.811,100.0,589.8,2193,1137,0,12000,20670,4,0,1.000,24.0,16.0,16,0.0,0.0075,0,0,0.315,0
|
|
||||||
39,summer,1693.9,751.3,400.0,752.8,40.8,0,0.0,0.727,100.0,587.6,1897,1172,0,12000,20931,4,0,1.000,24.0,16.0,16,0.0,0.0077,0,0,0.320,0
|
|
||||||
40,summer,1692.6,751.3,400.0,748.8,63.9,0,0.0,0.853,100.0,587.5,2247,1455,0,12000,20298,4,0,1.000,24.0,16.0,16,0.0,0.0079,0,0,0.323,0
|
|
||||||
41,summer,1697.0,751.3,400.0,747.2,40.9,0,0.0,0.769,100.0,585.4,1688,1174,0,12000,21138,4,0,1.000,24.0,16.0,16,0.0,0.0082,0,0,0.326,0
|
|
||||||
42,summer,1692.7,751.3,400.0,755.9,44.4,0,0.0,0.904,100.0,564.7,1836,1221,0,12000,20943,4,0,1.000,24.0,16.0,16,0.0,0.0083,0,0,0.327,0
|
|
||||||
43,summer,1695.9,751.3,400.0,742.6,63.6,0,0.0,0.819,100.0,585.3,2007,1153,0,12000,20840,4,0,1.000,24.0,16.0,16,0.0,0.0086,0,0,0.329,0
|
|
||||||
44,summer,1695.8,751.3,400.0,748.1,43.5,0,0.0,0.735,100.0,585.8,1762,1166,0,12000,21072,4,0,1.000,24.0,16.0,16,0.0,0.0088,0,0,0.333,0
|
|
||||||
45,summer,1697.8,751.3,400.0,731.6,68.4,0,0.0,0.860,100.0,590.2,2193,1137,0,12000,20670,4,0,1.000,24.0,16.0,16,0.0,0.0092,0,0,0.337,0
|
|
||||||
46,summer,1699.2,751.3,400.0,740.6,42.0,0,0.0,0.775,100.0,589.1,1757,1165,0,12000,21078,4,0,1.000,24.0,16.0,16,0.0,0.0093,0,0,0.339,0
|
|
||||||
47,summer,1698.3,751.3,400.0,751.6,41.4,0,0.0,0.900,100.0,566.5,1940,1309,0,12000,20751,4,0,1.000,24.0,16.0,16,0.0,0.0095,0,0,0.342,0
|
|
||||||
48,summer,1693.5,751.3,400.0,739.7,79.9,0,0.0,0.824,100.0,594.6,2214,1218,0,12000,20568,4,0,1.000,24.0,16.0,16,0.0,0.0099,0,0,0.344,0
|
|
||||||
49,summer,1697.5,751.3,400.0,756.4,29.3,0,0.0,0.719,100.0,582.8,1623,1172,0,12000,21205,4,0,1.000,24.0,16.0,16,0.0,0.0099,0,0,0.345,0
|
|
||||||
50,summer,1697.0,751.3,400.0,737.5,80.1,0,0.0,0.863,100.0,590.8,2189,1143,0,12000,20668,4,0,1.000,24.0,16.0,16,0.0,0.0102,0,0,0.346,0
|
|
||||||
51,summer,1696.1,751.3,400.0,755.2,32.6,0,0.0,0.768,100.0,581.3,1670,1177,0,12000,21153,4,0,1.000,24.0,16.0,16,0.0,0.0103,0,0,0.347,0
|
|
||||||
52,summer,1699.2,751.3,400.0,752.2,51.2,0,0.0,0.902,100.0,567.5,1965,1150,0,12000,20885,4,0,1.000,24.0,16.0,16,0.0,0.0104,0,0,0.347,0
|
|
||||||
53,summer,1698.9,751.3,400.0,740.3,67.6,0,0.0,0.826,100.0,591.1,2164,1138,0,12000,20698,4,0,1.000,24.0,16.0,16,0.0,0.0105,0,0,0.348,0
|
|
||||||
54,summer,1704.4,751.3,400.0,750.9,40.9,0,0.0,0.721,100.0,591.0,1839,1665,0,12000,20496,4,0,1.000,24.0,16.0,16,0.0,0.0106,0,0,0.349,0
|
|
||||||
55,summer,1698.5,751.3,400.0,754.3,63.1,0,0.0,0.865,100.0,588.1,2060,1279,0,12000,20661,4,0,1.000,24.0,16.0,16,0.0,0.0106,0,0,0.351,0
|
|
||||||
56,summer,1700.5,751.3,400.0,760.0,38.8,0,0.0,0.769,100.0,584.9,1708,1169,0,12000,21123,4,0,1.000,24.0,16.0,16,0.0,0.0107,0,0,0.352,0
|
|
||||||
57,summer,1697.9,751.3,400.0,760.7,54.0,0,0.0,0.903,100.0,573.9,2010,1292,0,12000,20698,4,0,1.000,24.0,16.0,16,0.0,0.0109,0,0,0.353,0
|
|
||||||
58,summer,1699.9,751.3,400.0,756.0,54.5,0,0.0,0.817,100.0,585.4,2005,1159,0,12000,20836,4,0,1.000,24.0,16.0,16,0.0,0.0111,0,0,0.354,0
|
|
||||||
59,summer,1704.6,751.3,400.0,751.5,47.5,0,0.0,0.721,100.0,590.9,1885,1163,0,12000,20952,4,0,1.000,24.0,16.0,16,0.0,0.0114,0,0,0.355,0
|
|
||||||
60,autumn,1697.0,751.3,400.0,733.6,78.7,0,0.0,0.864,100.0,595.2,2304,1503,0,12000,20193,4,0,1.000,24.0,16.0,16,0.0,0.0116,0,0,0.356,0
|
|
||||||
61,autumn,1697.3,751.3,400.0,747.0,30.1,0,0.0,0.768,100.0,583.3,1609,1178,0,12000,21213,4,0,1.000,24.0,16.0,16,0.0,0.0117,0,0,0.356,0
|
|
||||||
62,autumn,1702.6,751.3,400.0,734.1,49.2,0,0.0,0.902,100.0,567.5,1911,1154,0,12000,20935,4,0,1.000,24.0,16.0,16,0.0,0.0119,0,0,0.357,0
|
|
||||||
63,autumn,1706.7,751.3,400.0,723.4,60.9,0,0.0,0.815,100.0,585.4,2193,1137,0,12000,20670,4,0,1.000,24.0,16.0,16,0.0,0.0120,0,0,0.358,0
|
|
||||||
64,autumn,1701.7,751.3,400.0,733.4,41.3,0,0.0,0.728,100.0,583.7,1713,1169,0,12000,21118,4,0,1.000,24.0,16.0,16,0.0,0.0121,0,0,0.359,0
|
|
||||||
65,autumn,1699.9,751.3,400.0,720.1,70.6,0,0.0,0.862,100.0,589.3,2372,1224,0,12000,20404,4,0,1.000,24.0,16.0,16,0.0,0.0122,0,0,0.361,0
|
|
||||||
66,autumn,1699.4,751.3,400.0,732.0,35.4,0,0.0,0.765,100.0,582.7,1660,1174,0,12000,21166,4,0,1.000,24.0,16.0,16,0.0,0.0123,0,0,0.363,0
|
|
||||||
67,autumn,1687.3,751.3,400.0,743.8,55.1,0,0.0,0.908,100.0,571.8,2150,1632,0,12000,20218,4,0,1.000,24.0,16.0,16,0.0,0.0124,0,0,0.365,0
|
|
||||||
68,autumn,1682.3,751.3,400.0,734.2,72.5,0,0.0,0.811,100.0,589.6,2440,1526,0,12000,20034,4,0,1.000,24.0,16.0,16,0.0,0.0125,0,0,0.366,0
|
|
||||||
69,autumn,1689.7,751.3,400.0,737.2,42.2,0,0.0,0.724,100.0,588.8,1940,1158,0,12000,20902,4,0,1.000,24.0,16.0,16,0.0,0.0127,0,0,0.366,0
|
|
||||||
70,autumn,1694.6,751.3,400.0,727.4,59.6,0,0.0,0.867,100.0,582.3,2053,1148,0,12000,20799,4,0,1.000,24.0,16.0,16,0.0,0.0129,0,0,0.367,0
|
|
||||||
71,autumn,1698.8,751.3,400.0,723.4,52.2,0,0.0,0.779,100.0,570.3,1903,1106,0,11520,20031,4,0,1.000,24.0,16.0,16,0.0,0.0131,0,0,0.353,1
|
|
||||||
72,autumn,1688.0,751.3,400.0,728.7,58.1,0,0.0,0.902,100.0,564.3,2113,1237,0,11999,20651,4,0,1.000,24.0,16.0,16,0.0,0.0132,0,0,0.366,0
|
|
||||||
73,autumn,1695.1,751.3,400.0,708.5,70.7,0,0.0,0.824,100.0,591.0,2393,1132,0,12000,20475,4,0,1.000,24.0,16.0,16,0.0,0.0133,0,0,0.367,0
|
|
||||||
74,autumn,1698.1,751.3,400.0,726.5,34.9,0,0.0,0.727,100.0,583.9,1731,1173,0,12000,21096,4,0,1.000,24.0,16.0,16,0.0,0.0135,0,0,0.367,0
|
|
||||||
75,autumn,1700.8,751.3,400.0,713.4,71.7,0,0.0,0.859,100.0,590.6,2247,1252,0,12000,20501,4,0,1.000,24.0,16.0,16,0.0,0.0136,0,0,0.368,0
|
|
||||||
76,autumn,1706.8,751.3,400.0,724.1,37.7,0,0.0,0.772,100.0,585.3,1750,1170,0,12000,21080,4,0,1.000,24.0,16.0,16,0.0,0.0137,0,0,0.368,0
|
|
||||||
77,autumn,1706.4,751.3,400.0,726.1,49.8,0,0.0,0.895,100.0,571.1,2060,1244,0,12000,20696,4,0,1.000,24.0,16.0,16,0.0,0.0139,0,0,0.369,0
|
|
||||||
78,autumn,1699.3,751.3,400.0,730.8,56.9,0,0.0,0.816,100.0,584.0,2050,1691,0,12000,20259,4,0,1.000,24.0,16.0,16,0.0,0.0141,0,0,0.371,0
|
|
||||||
79,autumn,1707.0,751.3,400.0,722.3,48.0,0,0.0,0.738,100.0,588.0,1960,1156,0,12000,20884,4,0,1.000,24.0,16.0,16,0.0,0.0144,0,0,0.372,0
|
|
||||||
80,autumn,1706.1,751.3,400.0,716.2,62.5,0,0.0,0.851,100.0,587.4,2246,1250,0,12000,20504,4,0,1.000,24.0,16.0,16,0.0,0.0146,0,0,0.372,0
|
|
||||||
81,autumn,1707.1,751.3,400.0,725.7,39.5,0,0.0,0.772,100.0,582.9,1692,1185,0,12000,21123,4,0,1.000,24.0,16.0,16,0.0,0.0148,0,0,0.373,0
|
|
||||||
82,autumn,1688.6,751.3,400.0,741.7,56.5,0,0.0,0.904,100.0,574.5,2085,1559,0,12000,20356,4,0,1.000,24.0,16.0,16,0.0,0.0151,0,0,0.373,0
|
|
||||||
83,autumn,1696.9,751.3,400.0,720.6,66.3,0,0.0,0.815,100.0,591.3,2303,1132,0,12000,20565,4,0,1.000,24.0,16.0,16,0.0,0.0153,0,0,0.374,0
|
|
||||||
84,autumn,1698.2,751.3,400.0,728.7,40.0,0,0.0,0.737,100.0,587.4,1876,1165,0,12000,20959,4,0,1.000,24.0,16.0,16,0.0,0.0155,0,0,0.375,0
|
|
||||||
85,autumn,1705.8,751.3,400.0,706.8,72.9,0,0.0,0.858,100.0,590.2,2347,1130,0,12000,20523,4,0,1.000,24.0,16.0,16,0.0,0.0158,0,0,0.376,0
|
|
||||||
86,autumn,1710.7,751.3,400.0,718.7,38.4,0,0.0,0.769,100.0,585.6,1785,1176,0,12000,21039,4,0,1.000,24.0,16.0,16,0.0,0.0161,0,0,0.376,0
|
|
||||||
87,autumn,1710.1,751.3,400.0,717.2,58.4,0,0.0,0.912,100.0,549.8,2020,1093,0,11520,19927,4,0,1.000,24.0,16.0,16,0.0,0.0164,0,0,0.362,1
|
|
||||||
88,autumn,1706.1,751.3,400.0,701.0,80.0,0,0.0,0.814,100.0,587.8,2565,1118,0,11999,20318,4,0,1.000,24.0,16.0,16,0.0,0.0166,0,0,0.377,0
|
|
||||||
89,autumn,1706.5,751.3,400.0,717.5,38.9,0,0.0,0.744,100.0,581.7,1825,1164,0,12000,21011,4,0,1.000,24.0,16.0,16,0.0,0.0167,0,0,0.378,0
|
|
||||||
90,winter,1692.5,751.3,400.0,626.8,66.6,0,0.0,0.864,100.0,584.2,2238,1172,0,12000,20590,4,0,1.000,24.0,16.0,16,0.0,0.0171,0,0,0.379,0
|
|
||||||
91,winter,1683.3,751.3,400.0,553.6,49.6,0,0.0,0.784,100.0,568.9,2144,1091,0,11520,19805,4,0,1.000,24.0,16.0,16,0.0,0.0173,0,0,0.366,1
|
|
||||||
92,winter,1660.2,751.3,400.0,484.4,65.9,0,0.0,0.895,100.0,563.6,2484,1542,0,11999,19975,4,0,1.000,24.0,16.0,16,0.0,0.0174,0,0,0.377,0
|
|
||||||
93,winter,1648.1,751.3,400.0,407.7,71.8,0,0.0,0.822,100.0,563.0,3193,1030,0,11520,18817,4,0,1.000,24.0,16.0,16,0.0,0.0177,0,0,0.364,1
|
|
||||||
94,winter,1637.4,751.3,400.0,341.7,65.6,0,0.0,0.761,100.0,582.7,5738,918,0,12306,17038,4,0,1.000,24.0,16.0,16,0.0,0.0180,0,0,0.368,0
|
|
||||||
95,winter,1632.8,751.3,400.0,274.5,64.8,0,0.0,0.861,100.0,585.4,5010,1102,0,12000,17888,4,0,1.000,24.0,16.0,16,0.0,0.0183,0,0,0.380,0
|
|
||||||
96,winter,1625.2,751.3,400.0,238.9,40.4,0,0.0,0.781,100.0,581.8,3064,1094,0,12000,19842,4,0,1.000,24.0,16.0,16,0.0,0.0185,0,0,0.381,0
|
|
||||||
97,winter,1638.0,751.3,400.0,219.8,6.8,0,0.0,0.890,100.0,525.7,3243,314,0,12000,20443,4,0,1.000,24.0,16.0,16,0.0,0.0188,0,0,0.381,0
|
|
||||||
98,winter,1631.0,751.3,400.0,202.8,24.6,0,0.0,0.819,100.0,505.2,2018,255,0,12000,21727,4,0,1.000,24.0,16.0,16,0.0,0.0190,0,0,0.382,0
|
|
||||||
99,winter,1609.5,751.3,400.0,185.6,42.1,0,0.0,0.758,100.0,494.9,2606,683,0,12000,20711,4,0,1.000,24.0,16.0,16,0.0,0.0194,0,0,0.382,0
|
|
||||||
100,winter,1601.7,751.3,400.0,174.2,23.0,0,0.0,0.867,100.0,454.9,2384,145,0,12000,21471,4,0,1.000,24.0,16.0,16,0.0,0.0196,0,0,0.383,0
|
|
||||||
101,winter,1606.0,751.3,400.0,162.4,12.7,0,0.0,0.746,100.0,427.6,2162,220,0,12000,21618,4,0,1.000,24.0,16.0,16,0.0,0.0198,0,0,0.383,0
|
|
||||||
102,winter,1603.0,751.3,400.0,151.1,21.9,0,2.1,0.714,100.0,400.5,5670,151,0,12523,17656,4,0,1.000,24.0,16.0,16,0.0,0.0218,6,0,0.383,0
|
|
||||||
103,winter,938.8,751.3,400.0,142.3,712.2,0,3.7,0.499,100.0,419.6,9415,280,0,13606,12699,4,0,1.000,24.0,16.0,16,0.0,0.0366,54,0,0.391,0
|
|
||||||
104,winter,795.7,430.1,400.0,135.4,1322.3,55,1.1,0.297,100.0,471.1,11581,1341,997,13608,7033,4,0,1.000,14.0,16.0,16,0.0,0.0400,54,0,0.392,1
|
|
||||||
105,winter,792.0,330.7,400.0,130.0,2045.3,101,1.4,0.171,100.0,359.0,9538,3315,3148,13544,5015,4,0,0.950,5.6,16.0,16,0.0,0.0267,16,0,0.404,1
|
|
||||||
106,winter,799.6,171.1,400.0,120.0,220.9,1,4.4,0.110,100.0,553.3,11281,2818,4824,15277,1800,4,0,0.875,0.1,16.0,16,0.0,0.0369,36,0,0.409,0
|
|
||||||
107,winter,771.5,150.9,400.0,120.0,96.3,1,3.5,0.133,100.0,536.8,6108,2453,1485,12721,11793,4,0,0.775,0.0,16.0,16,0.0,0.0369,0,0,0.407,1
|
|
||||||
108,winter,803.5,128.8,400.0,120.0,38.1,1,3.8,0.128,100.0,514.7,5837,2024,1764,12603,12332,4,0,0.675,0.0,16.0,16,0.0,0.0235,0,0,0.407,1
|
|
||||||
109,winter,772.8,128.8,400.0,120.0,78.8,1,3.9,0.106,100.0,514.9,6128,1703,1500,13087,13582,4,0,0.575,0.0,16.0,16,0.0,0.0241,2,0,0.426,0
|
|
||||||
110,winter,761.2,126.8,400.0,120.0,61.6,0,4.5,0.077,100.0,556.4,6292,1746,741,13069,14152,4,0,0.475,0.0,16.0,16,0.0,0.0265,4,0,0.426,0
|
|
||||||
111,winter,762.8,126.8,400.0,120.0,46.4,0,3.6,0.063,100.0,545.5,5424,1773,784,12951,15068,4,0,0.412,0.6,16.0,16,0.0,0.0265,0,0,0.428,0
|
|
||||||
112,winter,790.8,126.8,400.0,120.0,20.0,0,4.6,0.060,100.0,543.0,5777,1764,766,12920,14773,4,0,0.312,0.0,16.0,16,0.0,0.0265,0,0,0.428,0
|
|
||||||
113,winter,791.6,126.8,400.0,120.0,47.2,0,3.6,0.066,100.0,536.0,5334,2513,746,12951,14456,4,0,0.250,0.8,16.0,16,0.0,0.0265,0,0,0.429,0
|
|
||||||
114,winter,801.4,126.8,400.0,120.0,38.2,0,4.2,0.046,100.0,553.0,5819,2233,745,12926,14277,3,1,0.200,0.0,12.0,12,0.0,0.0265,0,0,0.430,0
|
|
||||||
115,winter,807.8,126.8,400.0,120.0,41.6,0,3.6,0.020,100.0,547.3,5539,2129,759,12926,14647,2,2,0.150,0.0,8.0,8,0.0,0.0265,0,0,0.430,0
|
|
||||||
116,winter,806.5,126.8,400.0,120.0,49.2,0,4.5,0.002,100.0,572.0,5585,2025,768,12918,14704,1,3,0.100,0.0,4.0,4,0.0,0.0275,0,0,0.439,0
|
|
||||||
117,winter,741.3,80.0,400.0,120.0,240.0,0,8.9,0.000,100.0,472.8,12976,2326,1681,15199,3818,1,3,0.150,1.5,4.0,4,0.0,0.0275,0,0,0.444,0
|
|
||||||
118,winter,761.3,0.0,333.7,120.0,3413.6,174,4.3,0.040,100.0,395.2,11399,2081,1548,13015,6517,1,3,0.050,0.0,4.0,4,0.0,0.0275,0,0,0.460,1
|
|
||||||
119,winter,760.9,0.0,192.6,120.0,194.6,2,3.7,0.026,100.0,506.0,12209,1684,709,14080,7318,0,4,0.000,0.0,0.0,0,0.0,0.0275,0,1,0.477,0
|
|
||||||
120,spring,863.0,0.0,181.3,360.0,174.6,1,5.2,0.012,100.0,463.1,11765,921,766,13863,8685,0,4,0.000,0.0,0.0,0,0.0,0.0275,0,1,0.489,0
|
|
||||||
121,spring,885.0,0.0,182.2,600.0,126.0,0,6.5,0.000,100.0,508.0,12640,202,242,13620,9296,0,4,0.000,0.0,0.0,0,0.0,0.0275,0,2,0.492,0
|
|
||||||
122,spring,961.5,0.0,187.2,614.0,286.5,6,6.9,0.664,100.0,492.4,12372,3235,786,14610,3557,2,4,1.000,15.5,4.5,1,0.0,0.0275,0,0,0.473,1
|
|
||||||
123,spring,1080.8,0.0,192.2,622.3,236.3,24,3.3,0.760,100.0,527.6,6563,3821,1354,12696,10126,2,4,1.000,14.5,5.5,3,0.0,0.0275,0,0,0.464,1
|
|
||||||
124,spring,1167.1,0.0,172.0,743.9,144.6,5,2.4,0.730,100.0,501.6,7346,2481,205,12680,11848,2,4,1.000,12.5,7.5,7,0.0,0.0275,0,1,0.456,1
|
|
||||||
125,spring,1188.1,0.0,168.5,570.5,544.8,2,6.4,0.702,100.0,482.0,14540,2699,403,15041,3317,3,4,1.000,16.0,10.0,8,0.0,0.0275,0,1,0.465,0
|
|
||||||
126,spring,1300.0,0.0,173.5,563.0,279.6,1,11.8,0.720,100.0,445.2,15127,906,61,14520,3946,3,4,0.967,13.0,11.0,10,0.0,0.0275,0,1,0.445,1
|
|
||||||
127,spring,1387.5,0.0,178.5,576.4,283.2,0,13.5,0.652,100.0,490.5,17236,585,0,15374,2805,3,4,0.933,12.0,12.0,12,0.0,0.0275,0,2,0.449,0
|
|
||||||
128,spring,1374.8,0.0,183.5,579.0,373.5,1,7.4,0.744,100.0,481.3,16469,0,0,14987,4544,3,4,0.900,4.0,12.0,12,0.0,0.0275,0,2,0.457,0
|
|
||||||
129,spring,1408.5,28.4,171.0,590.8,305.5,0,6.9,0.726,100.0,471.8,15917,860,121,15226,3876,3,4,0.850,6.0,12.0,12,0.0,0.0275,0,1,0.476,0
|
|
||||||
130,spring,1495.0,28.4,176.0,614.8,205.0,0,11.3,0.728,100.0,486.1,15488,1027,0,15069,4416,3,4,0.800,6.0,12.0,12,59.7,0.0275,0,1,0.481,0
|
|
||||||
131,spring,1575.2,28.4,181.0,637.3,169.3,0,12.3,0.740,100.0,482.4,15546,1454,0,15221,3779,3,4,0.750,6.0,12.0,12,136.6,0.0275,0,1,0.484,0
|
|
||||||
132,spring,1594.4,28.4,175.5,643.8,243.0,0,10.7,0.662,100.0,479.9,15750,1708,0,15381,3161,3,4,0.700,6.0,12.0,12,174.7,0.0275,0,1,0.489,0
|
|
||||||
133,spring,1669.9,28.4,180.5,632.0,197.8,0,12.4,0.684,100.0,493.5,15838,1468,0,15197,3497,3,4,0.650,6.0,12.0,12,264.1,0.0275,0,1,0.492,0
|
|
||||||
134,spring,1715.6,0.0,170.5,648.0,218.9,0,10.2,0.681,100.0,475.9,15895,1182,0,15030,3893,3,4,0.600,6.0,12.0,12,300.0,0.0275,0,2,0.496,0
|
|
||||||
135,spring,1743.3,0.0,172.5,586.9,292.0,0,15.7,0.713,100.0,451.0,17632,200,0,15443,2725,3,4,0.533,2.0,12.0,12,300.0,0.0275,0,2,0.500,0
|
|
||||||
136,spring,1721.7,0.0,177.5,584.1,287.3,0,15.9,0.755,100.0,476.2,17811,0,0,15480,2709,3,4,0.433,0.0,12.0,12,300.0,0.0275,0,2,0.503,0
|
|
||||||
137,spring,1743.3,0.0,175.0,599.6,230.1,0,15.5,0.697,100.0,479.7,17693,129,0,15453,2725,3,4,0.333,0.0,12.0,12,300.0,0.0275,0,2,0.506,0
|
|
||||||
138,spring,1764.9,0.0,180.0,643.5,175.4,0,15.9,0.739,100.0,464.2,17866,0,0,15425,2709,1,6,0.700,0.0,4.0,4,300.0,0.0275,0,2,0.509,0
|
|
||||||
139,spring,1780.8,0.0,170.0,623.6,272.1,0,16.3,0.721,100.0,484.4,17775,0,0,15516,2709,1,6,0.600,0.0,4.0,4,300.0,0.0275,0,2,0.512,0
|
|
||||||
140,spring,1718.9,18.0,172.5,649.6,286.5,0,12.3,0.733,100.0,513.0,15515,1429,0,15079,3977,1,6,0.650,6.0,4.0,4,305.2,0.0275,0,1,0.515,0
|
|
||||||
141,spring,1739.3,18.0,177.5,595.8,284.9,0,9.7,0.755,100.0,493.8,14493,1955,0,15164,4388,1,6,0.700,6.0,4.0,4,424.6,0.0275,0,1,0.519,0
|
|
||||||
142,spring,1737.6,25.0,182.5,636.7,217.1,0,8.7,0.697,100.0,547.1,14374,678,0,14592,6356,1,6,0.750,6.0,4.0,4,450.0,0.0275,0,1,0.522,0
|
|
||||||
143,spring,1631.8,16.8,187.5,645.8,371.2,0,8.7,0.739,100.0,533.8,12444,1794,0,14105,7657,2,6,0.900,12.0,8.0,8,450.0,0.0275,0,1,0.527,0
|
|
||||||
144,spring,1659.1,16.8,192.5,643.3,224.6,0,8.7,0.721,100.0,529.0,10605,521,0,13944,10930,2,6,0.925,12.0,8.0,8,450.0,0.0275,0,1,0.529,0
|
|
||||||
145,spring,1681.2,16.8,197.5,702.7,131.3,0,8.7,0.733,100.0,527.7,10521,526,0,13944,11009,2,6,0.950,12.0,8.0,8,450.0,0.0275,0,1,0.531,0
|
|
||||||
146,spring,1703.3,16.8,195.0,686.5,188.9,0,8.0,0.755,100.0,524.5,10505,525,0,13944,11026,2,6,0.975,12.0,8.0,8,450.0,0.0275,0,1,0.533,0
|
|
||||||
147,spring,1719.2,16.8,200.0,635.4,272.0,0,8.0,0.697,100.0,535.6,10446,531,0,13944,11079,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.537,0
|
|
||||||
148,spring,1735.7,16.8,190.0,702.1,165.3,0,6.8,0.739,100.0,533.3,9819,1085,121,13843,11132,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.540,0
|
|
||||||
149,spring,1746.9,16.8,192.5,629.3,307.2,1,6.6,0.721,100.0,537.8,10384,622,14,13874,11106,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.546,0
|
|
||||||
150,summer,1752.9,16.8,197.5,622.5,172.6,0,8.0,0.735,100.0,534.2,9757,523,0,13302,10978,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.521,1
|
|
||||||
151,summer,1755.9,16.8,195.0,555.1,236.4,0,4.8,0.757,100.0,527.3,10547,524,0,13900,11029,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.524,0
|
|
||||||
152,summer,1758.9,16.8,200.0,570.1,152.0,0,8.7,0.707,100.0,501.7,10635,462,0,13464,9999,2,6,1.000,12.0,8.0,8,450.0,0.0275,0,1,0.510,1
|
|
||||||
153,summer,1634.4,16.8,190.0,623.9,283.2,1,1.5,0.749,100.0,529.7,9168,2012,1,13707,11112,3,6,1.000,20.0,10.0,8,450.0,0.0275,0,0,0.546,0
|
|
||||||
154,summer,1661.3,16.8,195.0,624.5,133.3,0,4.4,0.727,100.0,531.1,7616,3011,0,12899,11034,3,6,1.000,20.0,10.0,8,505.4,0.0275,0,0,0.566,1
|
|
||||||
155,summer,1678.5,16.8,200.0,616.5,136.8,0,4.4,0.739,100.0,543.2,6880,3446,0,13517,12157,3,6,1.000,18.0,10.0,8,590.1,0.0275,0,0,0.598,0
|
|
||||||
156,summer,1630.0,0.0,194.0,632.3,199.4,1,4.3,0.751,100.0,526.3,8632,2329,43,13829,11167,3,6,1.000,18.0,12.0,12,600.0,0.0275,0,1,0.630,0
|
|
||||||
157,summer,1650.0,0.0,199.0,531.2,264.2,0,8.4,0.703,100.0,526.4,10493,586,0,13944,10977,3,6,1.000,14.0,12.0,12,600.0,0.0275,0,1,0.635,0
|
|
||||||
158,summer,1671.0,0.0,189.0,574.2,131.0,1,6.2,0.764,100.0,505.3,9522,798,15,12759,10026,3,6,0.967,12.0,12.0,12,600.0,0.0275,0,1,0.582,2
|
|
||||||
159,summer,1684.6,0.0,194.0,570.1,170.2,0,8.6,0.726,100.0,526.3,10897,502,0,13942,10659,3,6,0.933,12.0,12.0,12,600.0,0.0275,0,1,0.610,0
|
|
||||||
160,summer,1704.3,0.0,199.0,606.1,110.5,0,8.7,0.718,100.0,512.7,10458,529,0,13944,11069,3,6,0.900,12.0,12.0,12,600.0,0.0275,0,1,0.612,0
|
|
||||||
161,summer,1707.8,0.0,194.0,652.3,105.0,0,0.8,0.760,100.0,518.7,10270,1363,0,13859,10508,3,6,0.867,12.0,12.0,12,600.0,0.0275,0,1,0.614,0
|
|
||||||
162,summer,1716.8,0.0,199.0,552.1,261.2,0,8.0,0.721,100.0,514.8,9871,799,0,13302,10588,3,6,0.833,12.0,12.0,12,600.0,0.0275,0,1,0.584,1
|
|
||||||
163,summer,1648.8,57.6,191.5,607.7,204.9,0,1.9,0.743,100.0,505.2,8751,1928,0,13585,11736,3,6,0.850,18.0,12.0,12,629.9,0.0275,0,0,0.600,0
|
|
||||||
164,summer,1671.7,57.6,196.5,613.6,144.8,0,2.8,0.725,100.0,535.6,7460,3418,0,13801,11321,3,6,0.867,18.0,12.0,12,703.3,0.0275,0,0,0.608,0
|
|
||||||
165,summer,1690.1,0.0,198.0,568.7,255.0,0,5.4,0.737,100.0,516.1,8382,2499,0,13731,11388,3,6,0.883,18.0,12.0,12,750.0,0.0275,0,1,0.620,0
|
|
||||||
166,summer,1708.0,0.0,193.0,611.4,116.8,0,8.7,0.765,100.0,492.9,10430,473,0,13458,10199,3,6,0.900,14.0,12.0,12,750.0,0.0275,0,1,0.591,1
|
|
||||||
167,summer,1718.0,0.0,198.0,591.8,188.3,0,8.7,0.717,100.0,521.1,11242,480,0,14105,10173,3,6,0.867,12.0,12.0,12,750.0,0.0275,0,1,0.593,0
|
|
||||||
168,summer,1732.7,0.0,190.5,604.1,135.3,0,8.7,0.739,100.0,519.3,10433,633,0,13901,11033,3,6,0.833,12.0,12.0,12,750.0,0.0275,0,1,0.622,0
|
|
||||||
169,summer,1746.2,0.0,195.5,626.8,105.5,0,8.7,0.737,100.0,491.7,10437,475,0,13464,10184,3,6,0.800,12.0,12.0,12,750.0,0.0275,0,1,0.592,1
|
|
||||||
170,summer,1753.2,0.0,198.0,562.1,240.9,0,0.7,0.739,100.0,530.9,10611,729,0,13873,10787,3,6,0.767,12.0,12.0,12,750.0,0.0275,0,1,0.622,0
|
|
||||||
171,summer,1652.5,18.8,193.0,648.1,210.7,0,1.4,0.751,100.0,537.5,8552,2641,0,13944,10863,3,6,0.783,17.8,12.0,12,750.0,0.0275,0,0,0.627,0
|
|
||||||
172,summer,1675.4,47.4,198.0,601.3,201.7,0,1.5,0.723,100.0,550.2,7124,3129,0,13620,12127,3,6,0.800,18.0,12.0,12,862.4,0.0275,0,0,0.637,0
|
|
||||||
173,summer,1694.1,19.8,190.8,631.3,145.2,0,4.0,0.747,100.0,481.1,7999,2212,0,13175,11174,3,6,0.817,18.0,12.0,12,900.0,0.0275,0,1,0.625,1
|
|
||||||
174,summer,1710.2,19.8,195.8,523.7,275.2,0,8.7,0.729,100.0,517.3,10585,523,0,13943,10949,3,6,0.833,14.0,12.0,12,900.0,0.0275,0,1,0.628,0
|
|
||||||
175,summer,1725.7,19.8,198.3,568.4,124.8,0,4.8,0.741,100.0,503.0,10453,737,0,13852,10958,3,6,0.800,12.0,12.0,12,900.0,0.0275,0,1,0.630,0
|
|
||||||
176,summer,1738.2,19.8,193.3,604.2,140.7,0,8.4,0.753,100.0,509.0,10308,661,0,13944,11087,3,6,0.767,12.0,12.0,12,900.0,0.0275,0,1,0.632,0
|
|
||||||
177,summer,1752.3,19.8,196.0,586.5,178.2,0,8.3,0.725,100.0,514.2,10534,528,0,13933,11005,3,6,0.733,12.0,12.0,12,900.0,0.0275,0,1,0.637,0
|
|
||||||
178,summer,1766.4,19.8,191.0,589.7,148.8,0,7.6,0.737,100.0,513.0,10692,526,0,13881,10901,3,6,0.700,12.0,12.0,12,900.0,0.0275,0,1,0.638,0
|
|
||||||
179,summer,1768.8,19.8,196.0,567.9,169.1,0,8.7,0.729,100.0,499.4,10636,518,0,13944,10902,2,7,1.000,12.0,8.0,8,900.0,0.0275,0,1,0.640,0
|
|
||||||
180,autumn,1767.3,19.8,198.5,595.6,98.9,0,8.8,0.741,100.0,508.1,10468,534,0,13902,11096,2,7,1.000,12.0,8.0,8,900.0,0.0275,0,1,0.642,0
|
|
||||||
181,autumn,1766.3,19.8,193.5,642.8,87.0,0,8.7,0.753,100.0,521.4,10509,525,0,13944,11022,2,7,1.000,12.0,8.0,8,900.0,0.0275,0,1,0.643,0
|
|
||||||
182,autumn,1682.4,16.0,196.0,633.2,213.4,0,3.6,0.725,100.0,581.6,8867,2027,0,13741,11365,2,7,1.000,12.0,8.0,8,917.4,0.0275,0,0,0.647,0
|
|
||||||
183,autumn,1695.4,16.0,191.0,570.4,190.3,0,2.5,0.737,100.0,510.4,7305,3437,0,13601,11657,2,7,1.000,12.0,8.0,8,1050.0,0.0275,0,1,0.656,0
|
|
||||||
184,autumn,1708.4,16.0,196.0,574.1,113.1,0,8.6,0.769,100.0,458.1,10449,532,0,13464,10115,2,7,1.000,12.0,8.0,8,1050.0,0.0142,0,1,0.629,1
|
|
||||||
185,autumn,1705.0,16.0,198.5,533.8,197.7,0,8.0,0.777,100.0,502.9,10426,702,0,13935,10937,2,7,1.000,12.0,8.0,8,1050.0,0.0156,0,1,0.661,0
|
|
||||||
186,autumn,1718.0,16.0,193.5,570.6,110.9,0,8.5,0.784,100.0,511.1,10585,592,0,13940,10883,2,7,1.000,12.0,8.0,8,1050.0,0.0157,0,1,0.663,0
|
|
||||||
187,autumn,1729.0,16.0,196.0,562.2,148.4,0,8.7,0.761,100.0,526.7,10574,633,0,13944,10849,2,7,1.000,12.0,8.0,8,1050.0,0.0159,0,1,0.667,0
|
|
||||||
188,autumn,1618.1,0.0,196.0,580.2,259.6,0,3.1,0.768,100.0,522.9,8842,2003,0,13873,11282,3,7,1.000,18.5,11.5,11,1065.8,0.0159,0,0,0.676,0
|
|
||||||
189,autumn,1645.0,0.0,201.0,512.7,192.6,0,5.3,0.765,100.0,514.6,9284,1900,0,13922,10894,3,7,1.000,18.5,11.5,11,1142.7,0.0160,0,0,0.683,0
|
|
||||||
190,autumn,1663.5,0.0,206.0,528.2,108.1,0,6.4,0.772,100.0,481.6,9849,1217,0,13921,11013,3,7,1.000,18.5,11.5,11,1185.3,0.0160,0,0,0.689,0
|
|
||||||
191,autumn,1587.3,0.0,211.0,542.4,224.4,0,0.7,0.789,100.0,572.1,6745,1447,0,12951,14857,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.722,0
|
|
||||||
192,autumn,1603.3,0.0,216.0,568.0,120.8,0,0.0,0.756,100.0,586.4,2514,1111,0,12158,20217,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.825,0
|
|
||||||
193,autumn,1621.6,0.0,221.0,663.1,44.7,0,0.0,0.773,100.0,585.1,1840,1936,0,12000,20224,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.847,0
|
|
||||||
194,autumn,1647.7,0.0,226.0,708.1,52.0,0,0.0,0.760,100.0,594.1,2019,1150,0,12000,20831,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.863,0
|
|
||||||
195,autumn,1664.1,0.0,231.0,728.3,41.8,0,0.0,0.777,100.0,589.9,1696,1170,0,12000,21134,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.876,0
|
|
||||||
196,autumn,1685.6,0.0,236.0,722.5,45.1,0,0.0,0.784,100.0,589.9,2019,1151,0,12000,20830,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.880,0
|
|
||||||
197,autumn,1696.4,0.0,241.0,726.9,46.8,0,0.0,0.761,100.0,594.7,2059,1155,0,12000,20786,3,7,1.000,18.0,12.0,12,1200.0,0.0160,0,0,0.882,0
|
|
||||||
198,autumn,1707.4,0.0,246.0,726.6,42.6,0,0.0,0.768,100.0,592.3,1774,1168,0,12000,21058,3,7,1.000,18.0,12.0,12,1200.0,0.0161,0,0,0.889,0
|
|
||||||
199,autumn,1710.2,0.0,251.0,727.9,45.4,0,0.0,0.765,100.0,593.6,1957,1156,0,12000,20887,3,7,1.000,18.0,12.0,12,1200.0,0.0161,0,0,0.894,0
|
|
||||||
200,autumn,1718.8,0.0,256.0,731.8,34.4,0,0.0,0.772,100.0,583.0,1643,1195,0,12000,21162,3,7,1.000,18.0,12.0,12,1200.0,0.0162,0,0,0.896,0
|
|
||||||
201,autumn,1721.8,0.0,261.0,727.3,45.3,0,0.0,0.789,100.0,582.4,2007,1151,0,12000,20842,3,7,1.000,18.0,12.0,12,1200.0,0.0162,0,0,0.897,0
|
|
||||||
202,autumn,1723.3,0.0,266.0,592.8,233.4,0,0.7,0.756,100.0,599.5,3281,1063,0,12243,19413,3,7,1.000,18.0,12.0,12,1200.0,0.0163,0,0,0.910,0
|
|
||||||
203,autumn,1721.8,0.0,271.0,599.0,98.1,0,0.7,0.773,100.0,586.6,2647,1110,0,12162,20081,3,7,1.000,18.0,12.0,12,1200.0,0.0163,0,0,0.911,0
|
|
||||||
204,autumn,1714.4,0.0,276.0,617.7,91.1,0,0.0,0.760,100.0,592.8,2213,1252,0,12061,20474,3,7,1.000,18.0,12.0,12,1200.0,0.0165,0,0,0.916,0
|
|
||||||
205,autumn,1721.9,0.0,281.0,670.8,41.8,0,0.0,0.776,100.0,588.6,1932,1163,0,12000,20905,3,7,1.000,18.0,12.0,12,1200.0,0.0165,0,0,0.921,0
|
|
||||||
206,autumn,1723.9,0.0,286.0,709.5,46.5,0,0.0,0.783,100.0,590.2,1878,1156,0,12000,20966,3,7,1.000,18.0,12.0,12,1200.0,0.0166,0,0,0.924,0
|
|
||||||
207,autumn,1725.4,0.0,291.0,724.7,43.6,0,0.0,0.760,100.0,591.8,1805,1161,0,12000,21034,3,7,1.000,18.0,12.0,12,1200.0,0.0166,0,0,0.928,0
|
|
||||||
208,autumn,1721.9,0.0,296.0,728.2,46.1,0,0.0,0.767,100.0,584.7,1824,1160,0,12000,21016,3,7,1.000,18.0,12.0,12,1200.0,0.0167,0,0,0.931,0
|
|
||||||
209,autumn,1722.8,0.0,301.0,727.8,46.3,0,0.0,0.763,100.0,586.9,1912,1253,0,12000,20835,3,7,1.000,18.0,12.0,12,1200.0,0.0167,0,0,0.933,0
|
|
||||||
210,winter,1715.8,0.0,306.0,648.5,43.1,0,0.0,0.770,100.0,585.1,1855,1155,0,12000,20990,3,7,1.000,18.0,12.0,12,1200.0,0.0168,0,0,0.933,0
|
|
||||||
211,winter,1706.1,0.0,311.0,564.3,59.8,0,0.0,0.786,100.0,591.0,2454,1126,0,12000,20420,3,7,1.000,18.0,12.0,12,1200.0,0.0169,0,0,0.936,0
|
|
||||||
212,winter,1704.7,0.0,316.0,380.3,165.8,0,0.7,0.753,100.0,592.7,3433,1054,0,12162,19351,3,7,1.000,18.0,12.0,12,1200.0,0.0169,0,0,0.939,0
|
|
||||||
213,winter,1691.1,0.0,321.0,286.9,95.9,0,0.0,0.769,100.0,588.0,4607,962,0,12552,17879,3,7,1.000,18.0,12.0,12,1200.0,0.0171,0,0,0.944,0
|
|
||||||
214,winter,1690.2,0.0,326.0,260.6,16.8,0,0.0,0.773,100.0,558.8,4237,1469,0,11780,17074,3,7,1.000,18.0,12.0,12,1174.7,0.0171,0,0,0.908,1
|
|
||||||
215,winter,1682.2,0.0,331.0,242.7,18.0,0,0.0,0.780,100.0,579.7,3214,1134,0,11999,19653,3,7,1.000,18.0,12.0,12,1126.7,0.0172,0,0,0.944,0
|
|
||||||
216,winter,1664.7,0.0,336.0,224.3,28.6,0,0.0,0.786,100.0,586.8,2972,1470,0,12000,19558,3,7,1.000,18.0,12.0,12,1095.7,0.0173,0,0,0.948,0
|
|
||||||
217,winter,1663.8,0.0,341.0,209.2,8.8,0,0.0,0.762,100.0,574.7,2961,1112,0,12000,19927,3,7,1.000,18.0,12.0,12,1074.7,0.0173,0,0,0.949,0
|
|
||||||
218,winter,1642.9,0.0,346.0,193.4,33.4,0,0.0,0.776,100.0,535.4,4171,4159,0,11520,14710,3,7,1.000,18.0,12.0,12,1069.0,0.0175,0,0,0.911,1
|
|
||||||
219,winter,1644.8,0.0,351.0,180.7,7.7,0,3.3,0.763,100.0,527.5,8689,5180,0,12936,9195,3,7,1.000,18.0,12.0,12,1034.8,0.0175,0,0,0.925,0
|
|
||||||
220,winter,1651.2,0.0,356.0,167.8,5.6,0,1.4,0.779,100.0,547.5,9597,5162,0,13216,8025,3,7,1.000,18.0,12.0,12,963.3,0.0176,0,0,0.931,0
|
|
||||||
221,winter,1644.6,0.0,361.0,156.7,17.3,0,3.1,0.795,100.0,548.5,9749,5542,0,13281,7428,3,7,1.000,18.0,12.0,12,914.3,0.0177,0,0,0.939,0
|
|
||||||
222,winter,1649.2,0.0,366.0,146.6,5.7,0,1.4,0.761,100.0,524.3,8976,4270,0,13056,9698,3,7,1.000,18.0,12.0,12,903.3,0.0178,0,0,0.943,0
|
|
||||||
223,winter,1654.8,0.0,371.0,137.8,4.5,0,1.1,0.767,100.0,510.8,9610,5167,0,13194,8029,3,7,1.000,18.0,12.0,12,876.3,0.0178,0,0,0.947,0
|
|
||||||
224,winter,1635.7,0.0,376.0,130.0,29.3,0,0.7,0.763,100.0,503.2,9057,5016,0,12991,8936,3,7,1.000,18.0,12.0,12,863.3,0.0179,0,0,0.949,0
|
|
||||||
225,winter,1615.4,0.0,381.0,123.3,31.3,0,2.2,0.779,100.0,548.5,10192,5061,0,13267,7480,3,7,1.000,18.0,12.0,12,803.3,0.0180,0,0,0.951,0
|
|
||||||
226,winter,1615.0,0.0,386.0,120.4,11.9,0,0.6,0.794,100.0,529.3,9917,5295,0,13446,7342,3,7,1.000,18.0,12.0,12,781.0,0.0180,0,0,0.952,0
|
|
||||||
227,winter,1619.0,0.0,390.0,120.0,8.8,0,0.1,0.761,100.0,625.0,9592,5657,0,13395,7356,3,7,1.000,18.0,12.0,12,653.0,0.0182,0,0,0.952,0
|
|
||||||
228,winter,1629.4,0.0,394.0,120.0,0.0,0,1.8,0.766,100.0,593.2,8296,6042,0,12717,8945,3,7,1.000,18.0,12.0,12,619.3,0.0182,0,0,0.953,0
|
|
||||||
229,winter,1639.2,0.0,397.5,120.0,0.0,0,3.8,0.762,100.0,542.7,8680,6070,0,12765,8485,3,7,1.000,18.0,12.0,12,615.3,0.0182,0,0,0.954,0
|
|
||||||
230,winter,1606.4,0.0,399.0,120.0,43.2,0,1.1,0.778,100.0,523.8,10154,5319,0,13166,7361,3,7,1.000,18.0,12.0,12,612.3,0.0182,0,0,0.955,0
|
|
||||||
231,winter,1592.5,0.0,400.0,120.0,25.1,0,1.6,0.793,100.0,511.1,10480,4396,0,13246,7878,3,7,1.000,18.0,12.0,12,586.8,0.0182,0,0,0.955,0
|
|
||||||
232,winter,1550.9,0.0,400.0,120.0,55.2,0,2.9,0.760,100.0,557.3,8925,4309,0,12737,10029,3,7,1.000,18.0,12.0,12,539.8,0.0182,0,0,0.956,0
|
|
||||||
233,winter,1551.0,0.0,400.0,120.0,13.5,0,0.9,0.765,100.0,598.9,8166,5788,0,12892,9154,3,7,1.000,18.0,12.0,12,458.0,0.0182,0,0,0.957,0
|
|
||||||
234,winter,1563.9,0.0,400.0,120.0,0.0,0,1.8,0.771,100.0,553.9,9720,4123,0,13192,8965,3,7,1.000,18.0,12.0,12,458.0,0.0182,0,0,0.957,0
|
|
||||||
235,winter,1563.0,0.0,400.0,120.0,14.5,0,0.5,0.777,100.0,500.4,10355,3474,0,13391,8780,3,7,1.000,18.0,12.0,12,473.0,0.0182,0,0,0.958,0
|
|
||||||
236,winter,1544.6,0.0,400.0,120.0,32.0,0,6.0,0.792,100.0,500.3,12884,2372,0,14131,6613,3,7,1.000,18.0,12.0,12,433.0,0.0182,0,0,0.958,0
|
|
||||||
237,winter,1519.4,0.0,400.0,120.0,39.7,0,3.0,0.759,100.0,508.3,11578,3413,0,14097,6912,3,7,1.000,18.0,12.0,12,393.4,0.0182,0,0,0.959,0
|
|
||||||
238,winter,1527.4,0.0,400.0,120.0,6.4,0,1.1,0.764,100.0,522.7,12352,3010,0,13908,6730,3,7,1.000,18.0,12.0,12,340.4,0.0182,0,0,0.959,0
|
|
||||||
239,winter,1541.8,0.0,400.0,120.0,0.0,0,1.7,0.770,100.0,486.7,13633,2290,0,14422,5655,3,7,1.000,18.0,12.0,12,331.4,0.0182,0,0,0.959,0
|
|
||||||
240,spring,1555.6,0.0,400.0,360.0,29.3,0,2.1,0.776,100.0,495.4,13944,1918,0,14428,5710,3,7,1.000,18.0,12.0,12,300.0,0.0182,0,0,0.960,0
|
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="csv_translation"
|
|
||||||
type="Translation"
|
|
||||||
uid="uid://da6vou2v16yvt"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
files=["res://soak_stats.season.translation", "res://soak_stats.wood.translation", "res://soak_stats.stone.translation", "res://soak_stats.clay.translation", "res://soak_stats.food.translation", "res://soak_stats.harvested.translation", "res://soak_stats.trades.translation", "res://soak_stats.avg.translation", "res://soak_stats.avg.translation", "res://soak_stats.avg.translation", "res://soak_stats.carried.translation", "res://soak_stats.gather.translation", "res://soak_stats.build.translation", "res://soak_stats.trade.translation", "res://soak_stats.rest.translation", "res://soak_stats.social.translation", "res://soak_stats.shelters.translation", "res://soak_stats.ruins.translation", "res://soak_stats.avg.translation", "res://soak_stats.upkeep.translation", "res://soak_stats.burn.translation", "res://soak_stats.modules.translation", "res://soak_stats.granary.translation", "res://soak_stats.avg.translation", "res://soak_stats.refusals.translation", "res://soak_stats.incomplete.translation", "res://soak_stats.avg.translation", "res://soak_stats.deaths.translation"]
|
|
||||||
|
|
||||||
source_file="res://soak_stats.csv"
|
|
||||||
dest_files=["res://soak_stats.season.translation", "res://soak_stats.wood.translation", "res://soak_stats.stone.translation", "res://soak_stats.clay.translation", "res://soak_stats.food.translation", "res://soak_stats.harvested.translation", "res://soak_stats.trades.translation", "res://soak_stats.avg.translation", "res://soak_stats.avg.translation", "res://soak_stats.avg.translation", "res://soak_stats.carried.translation", "res://soak_stats.gather.translation", "res://soak_stats.build.translation", "res://soak_stats.trade.translation", "res://soak_stats.rest.translation", "res://soak_stats.social.translation", "res://soak_stats.shelters.translation", "res://soak_stats.ruins.translation", "res://soak_stats.avg.translation", "res://soak_stats.upkeep.translation", "res://soak_stats.burn.translation", "res://soak_stats.modules.translation", "res://soak_stats.granary.translation", "res://soak_stats.avg.translation", "res://soak_stats.refusals.translation", "res://soak_stats.incomplete.translation", "res://soak_stats.avg.translation", "res://soak_stats.deaths.translation"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress=1
|
|
||||||
delimiter=0
|
|
||||||
unescape_keys=false
|
|
||||||
unescape_translations=true
|
|
||||||
Reference in New Issue
Block a user