Full 4X Systems: Resource Screen, New Game Plus, Emergent Story
Status: DESIGN APPROVED 2026-06-15 (finding gd-04) — Implemented this session.
Last updated: August 30, 2026
Lineage — Full 4X Systems: Resource Screen, New Game Plus, Emergent Story
Status: DESIGN APPROVED 2026-06-15 (finding gd-04) — Implemented this session.
This doc is the design home for the three 4X "build-out" pillars that finding gd-04 (process-reports
report 3) called out as missing or hollow in Blood Lineage: a real resource management screen, a
meaningful New Game Plus the player can actually see and feel, and an emergent-story event
system that reacts to the player's accumulated history. It is a sibling of kingdom.md
(the per-turn economy), prestige.md (the prestige/ascension service layer), and
progression.md (turn pipeline, random events).
Origin (finding gd-04)
"BL's 7-resource 4X has no screen, hollow NG+, no emergent story."
The owner chose the ambitious path: build out the full 4X, not pare it down. The three sub-systems below were sequenced screen → NG+ → emergent events, each landing with its own hermetic scenario_tests.
Pillar 1 — Resource Management Screen
The gap
Blood Lineage has 7 resources (Gold, Food, Wood, Stone, Iron, Mana, Gems) but no single consolidated
screen that shows, per resource: how much you HAVE, what you NET per turn, and whether that stockpile
is rising or falling. view status (the compact scan) lists the seven amounts on one line with no
per-turn flow; view income is a gold-and-food-centric steward ledger. Neither is the 4X "economy
dashboard" a strategy player reaches for.
The screen
Command: resource screen / manage resources / economy screen / resource report /
treasury report. Routes through the Tier-4 →
LINEAGE_VIEW with matched key RESOURCE_SCREEN, handled by
. Also surfaced as a tap option on the kingdom status
menu and from the income/scan views.
The screen renders all seven resources, one line each, in the fixed order Gold, Food, Wood, Stone, Iron, Mana, Gems. Each line states the current stockpile, the net per-turn flow, and a one-word trend:
Treasury screen.
Gold: 1000, plus 45 per turn, rising.
Food: 500, plus 29 per turn, rising.
Wood: 300, steady.
Stone: 250, steady.
Iron: 200, steady.
Mana: 75, plus 5 per turn, rising.
Gems: 0, steady.
Royal Seals: 12. (premium currency line, shown only when balance > 0)
Trend word is derived purely from the computed net: net > 0 → "rising", net < 0 → "falling",
net == 0 → "steady". A resource with zero stockpile and zero net is still listed (the screen is a
complete seven-resource ledger, never a filtered subset — the per-item-coverage rule).
Net-per-turn computation (single source of truth)
Net = production − consumption, computed per resource from the SAME primitives the turn pipeline uses,
so the screen never contradicts what actually happens on end turn:
| Resource | Production | Consumption |
|---|---|---|
| Gold | territory base (capital +50, others +25) + MARKET (MARKET_GOLD×level) + worker gold |
army upkeep + empire maintenance |
| Food | territory base (+5 each) + FARM (FARM_FOOD×level) + worker food |
population ÷ FOOD_CONSUMPTION_DIVISOR + army units ÷ 4 |
| Wood | LUMBER_MILL (LUMBER_MILL_WOOD×level) + worker wood |
— |
| Stone | MINE (MINE_STONE×level) + worker stone |
— |
| Iron | MINE (MINE_IRON×level) + worker iron |
— |
| Mana | MANA_WELL + TEMPLE (*_MANA×level) + worker mana + 5 base regen |
— |
| Gems | — (premium, not produced per turn) | — |
All building/territory/worker numbers come from ,
, , and
— the exact calls viewIncome already uses, so
the two views agree. Seasonal modifiers are intentionally NOT folded into the headline net (they vary
by turn and would make the trend word flicker); the screen notes the active season's bias in one
sentence instead.
Management hub
The screen ends with the management options a player needs to act on what they just read: assign workers, build, royal seals shop, view income (the detailed steward ledger), and end turn. The screen is never a text-only dead end (the no-dead-end invariant).
Pillar 2 — Meaningful New Game Plus (the Legacy screen + carryover payoff)
The gap
The Prestige & Ascension service layer (prestige.md) already records victories
(lineage.user_lineage_ascension), carries traits + prestige + a starting-generation bonus to the
next kingdom, and computes a cross-game Ancient Bloodline tier. But it was hollow to the player:
there was no screen to SEE your NG+ standing, and the carryover bonuses were silent — a returning
victor never felt their legacy. This pillar makes NG+ visible and adds a felt, scaling payoff.
The Legacy screen
Command: legacy / view legacy / ascension / prestige / bloodline / new game plus /
dynasty legacy. Routes through → LINEAGE_VIEW matched
key LEGACY, handled by the new . Surfaced as a tap option on the
dynasty and kingdom-status screens.
It reads the player's account ref (chatUser.getChatRef()) and renders two tracks:
- Ancient Bloodline (cross-game prestige) — current tier name (
PrestigeTier.getDisplayName) and, when below Mythic, a one-line nudge toward the next tier. Sourced from (read-only; falls back to Commoner when no row exists). - New Game Plus (dynasty ascension) — victory count (the NG+ level), highest generation reached, carried prestige, and carried trait names. Sourced from .
A fresh player with no victories sees the call to action, never a blank: "Your legacy is yet unwritten. Win your first kingdom to begin your dynasty's ascension — each victory carries traits, prestige, and a richer founding into your next realm." This deterministic empty-state is what the hermetic scenario_test pins (a brand-new account has no ascension row → the call-to-action renders).
The carryover payoff (felt headstart)
On top of the existing trait/prestige/generation carryover, a victorious dynasty now founds its next kingdom with a scaling resource headstart — the visible, felt payoff that makes NG+ matter:
headstart_gold = min(victoryCount, 5) × 250 (cap +1250)
headstart_food = min(victoryCount, 5) × 100 (cap +500)
Applied in .applyKingdomCarryover(kingdom, accountRef), called from
immediately after the founding-ruler trait/prestige carryover
(so it runs exactly once, at dynasty founding, for genuinely new kingdoms — the method is gated by
!kingdom.hasDynasty()). The grant lands on kingdom.resources via modifyResource, mode-agnostic.
When the player explicitly founds the dynasty, announces the
payoff in voice-first copy via — e.g. "Your
bloodline remembers. Three past victories enrich your founding with 750 gold and 300 food." The
describe call is read-only and recomputes the same deterministic numbers; the grant itself is applied
by applyKingdomCarryover.
Caps compose with the existing Track A + Track B caps in prestige.md (5 traits, +20
per stat, 2500 prestige, +5 generation). The resource headstart is bounded independently at NG+ 5.
Pillar 3 — Emergent Story System (Dynasty Chronicle)
The gap
Random events (progression.md § Random Events) fire on a flat 10% roll and are
stateless — they never reference what the player has actually done. There was no narrative that emerged
from the player's own history: a long-reigning monarch, a fortune amassed, an empire spread wide, a
people who survived famine. Those are the beats that make a 4X campaign feel like a story.
The system
is a deterministic, state-triggered story layer evaluated at the end
of every turn (in , after random events, before the turn summary). It is
NOT RNG-based — each beat has a predicate over current kingdom/world state and fires once per
kingdom (tracked on LineageKingdom.firedStoryBeats, mirroring awardedMilestones). Determinism is
deliberate: it makes the system hermetically testable (seed the trigger state, end turn, assert the
beat) and makes the narrative feel earned rather than random.
When a beat fires, the service:
- Announces a voice-first chronicle line inline in the end-turn text: "A new chapter is added to
your dynasty's chronicle:
. <one-line narration referencing the ruler/dynasty by name>." - Optionally adds a pending
LineageEvent(built like any other event, with 2-3 choices) so the player can respond through the existing event-response NLU and get a lasting effect.
The beats (ship with four; the system is extensible)
| Beat id | Deterministic trigger | Title | Theme |
|---|---|---|---|
THE_GILDED_THRONE |
gold ≥ 5000 | The Gilded Throne | Amassed fortune — choice: commission a monument (morale/stability) vs invest in trade (gold) |
THE_HUNGRY_YEARS |
consecutiveZeroFoodTurns ≥ 3 (famine) |
The Hungry Years | A people who endured starvation — a somber chronicle beat |
THE_WIDE_REALM |
owned territories ≥ 8 | The Wide Realm | An empire spread across the land |
THE_ENDURING_DYNASTY |
dynasty.generationNumber ≥ 3 |
The Enduring Dynasty | A bloodline that has outlived three rulers |
Each narration interpolates the ruler's name / dynasty name so the beat reads as the player's own story, not boilerplate. Beats are evaluated in declaration order; multiple may fire in one turn.
SE-3 extended this system with a revisitable Dynasty Chronicle pull surface
(chronicle / my chronicle, ) that reads the fired beats back
on demand, plus four new beats that reference the Empire tier and New Game Plus state. See
empire-4x-layer.md Pillar 3 for the canonical design and implementation.
The required scenario_test seeds setGold: 5000, ends a turn, and asserts the chronicle line appears
(contains_text "chronicle", a short stable token) — deterministic regardless of the separate 10%
random-event roll.
Why deterministic, not random
A famine or a fortune is already the product of dozens of player decisions; surfacing a story beat the moment that state is reached IS the emergence. Adding an RNG gate on top would (a) make the beat feel arbitrary and (b) make it untestable hermetically (the hermetic-scenario-tests rule bans RNG-dependent assertions). The trigger state is the emergence; the beat is its narration.
Regression Coverage
| scenario_test | Guards |
|---|---|
resource screen renders all 7 resources with per-turn flow |
Pillar 1 |
legacy renders the NG+ / Ancient Bloodline standing (empty-state call to action for a fresh account) |
Pillar 2 |
setGold 5000; end turn surfaces a dynasty chronicle beat |
Pillar 3 |
The NG+ carryover-grant transform (resource headstart math + caps) is covered by a JUnit test on
because seeding a user_lineage_ascension victory row is outside the
scenario harness's hermetic seed surface.