Kingdom
Status: COMPLETE — All systems documented; see Known Issues section for any deferred follow-ups
Last updated: September 23, 2026
Lineage -- Kingdom Management Design
Status: COMPLETE — All systems documented; see Known Issues section for any deferred follow-ups
Kingdom management covers buildings, workers, resources, territory production, population, and the core economic loop. The economy flows through two channels: worker-based production (direct assignment) and territory/building-based production (passive per-turn income).
Kingdom Naming and Rename
Initial Naming (Forced Interaction)
Source:
When a kingdom is unnamed (kingdomName is null, blank, or "New Kingdom"), turn 1 launches a forced VALUE_ENTRY prompt: "What would you like to name your kingdom on the global world map?". The player provides a name; the provider validates it and switches to a YES_NO confirmation. On YES, the name persists to LineageKingdom.kingdomName. After turn 1 the prompt no longer fires (prevents the alternating-block loop).
Explicit Rename (Always Available)
Source: ->
Players can rename a kingdom that already has a name. Recognized utterances:
| Utterance | Routes to |
|---|---|
name my kingdom X |
LINEAGE_RENAME_KINGDOM with proposed=X |
rename my kingdom to X |
LINEAGE_RENAME_KINGDOM |
rename kingdom X |
LINEAGE_RENAME_KINGDOM |
change kingdom name to X |
LINEAGE_RENAME_KINGDOM |
set kingdom name to X |
LINEAGE_RENAME_KINGDOM |
call my kingdom X |
LINEAGE_RENAME_KINGDOM |
The handler reuses the same YES_NO confirmation infrastructure as the initial-naming flow. isPendingStillRequired keeps YES_NO pendings alive even when the kingdom already has a name (the stale-pending sweep only auto-clears VALUE_ENTRY pendings — clearing YES_NO would break the rename flow).
Regression coverage: game_test.scenario_tests rows 338 (initial-naming variant) and 345 (rename-synonym variant).
Kingdom Model
Source: LineageKingdom
Starting Resources
Source:
| Resource | Starting Amount |
|---|---|
| Gold | 1,000 |
| Food | 500 |
| Wood | 300 |
| Stone | 250 |
| Iron | 200 |
| Mana | 75 |
| Gems | Tracked via CurrencyLedger (separate) |
Starting Stats
| Stat | Value |
|---|---|
| Population | 50 |
| Morale | 50 (0-100) |
| Stability | 50 (0-100) |
| Ruler Leadership | 50 |
| Ruler Warfare | 50 |
| Ruler Diplomacy | 50 |
| Ruler Magic | 50 |
Resource Storage by Mode
| Mode | Storage |
|---|---|
| SINGLE_PLAYER / MULTIPLAYER | LineageKingdom.resources (Map<String, Integer>) |
| GLOBAL | (SeasonalCurrencyCounts) |
| Gems (all modes) | CurrencyLedger (transaction-tracked) |
Source: handles mode-aware routing for all resource operations.
Buildings
Source:
Building Types & Costs (16 live)
| Building | Gold Cost | Category |
|---|---|---|
| FARM | 100 | Economy |
| GRANARY | 200 | Economy — LIVE (see the status note under Food Storage Cap); +1,500 food storage cap |
| MINE | 150 | Economy |
| LUMBER_MILL | 120 | Economy |
| MARKET | 200 | Economy |
| BARRACKS | 250 | Military |
| ARCHERY_RANGE | 300 | Military |
| STABLE | 400 | Military |
| ARMORY | 350 | Military |
| MAGE_TOWER | 500 | Magic |
| TEMPLE | 400 | Magic |
| MANA_WELL | 450 | Magic |
| CITY_WALLS | 300 | Defense |
| WATCHTOWER | 150 | Defense |
| ACADEMY | 400 | Research |
| LIBRARY | 350 | Research |
Buildings cost only gold. There are no wood/stone/iron building costs despite those resources existing.
Spoken build menu is DERIVED from BUILDING_COSTS and BUILDING_PREREQUISITES (L7).
reads both maps, so every buildable type is spoken with its cost
and its prerequisite, for example "Granary, 200 gold, needs a farm". The previous menu was a
hand-written list that named only 11 of the 16 buildings — granary, armory, mana well, academy and
library were unreachable for any player who went by the menu. The menu also states the L9 rule aloud
("One of each building type per territory, so spread new types across your lands"), and the capital
line names what is already standing ("...building slots used, already standing, 2 farms") so a new
ruler learns what filled their slots. Never re-type these costs as literals in copy.
Building Construction Flow
Player says "build farm" or "build mine in territory 2"
-> Parse building type and optional territory specifier
-> Normalize: strip BUILDING_ prefix, handle synonyms, spaces to underscores
-> Validate building type exists in BUILDING_COSTS
-> Determine target territory:
- Extracted "in territory N" pattern -> stable holding number (assigned at claim, never reused)
- Two numbers from possibleNumbers -> coordinates (X, Y)
- One number from possibleNumbers -> stable holding number (1-based)
- Default -> capital territory
-> Check: territory not at building capacity
-> Check: building type not already present in territory
(INTENTIONAL — one of each building *type* per territory; multiple *different* types allowed until terrain slot cap. Confirmed owner 2026-08-01 / player-request-backlog L9. Not unlimited same-type stacks.)
-> Check: sufficient gold
-> Create TerritoryBuilding(type, level=1, isActive=true)
-> Deduct gold AFTER successful building creation
-> Display atmospheric flavor text per building type
Building Prerequisites
Source:
Some buildings require another building to exist in any owned territory before they can be constructed:
| Building | Requires |
|---|---|
| ARCHERY_RANGE | BARRACKS |
| STABLE | BARRACKS |
| ARMORY | BARRACKS |
| MAGE_TOWER | TEMPLE |
| All others | No prerequisite |
If the prerequisite is not met, the handler returns an error: "You need a {prerequisite} before you can build a {building}."
Building Synonyms
| Input | Resolves To |
|---|---|
| lumbermill, lumber, sawmill | LUMBER_MILL |
| magetower, mage, wizard_tower | MAGE_TOWER |
| archeryrange, archery, range | ARCHERY_RANGE |
| citywalls, walls, wall | CITY_WALLS |
| manawell, well, mana | MANA_WELL |
| tower, watch | WATCHTOWER |
Bare Building Names (No Verb Required)
Players can also say a building name by itself and skip the build verb: academy, library, farm, lumber mill, etc. This is handled in (Tier 4 NLU) and routes to LINEAGE_BUILD with the building name as the matched key. Common command words (build, status, help, menu, research, shop, etc.) are rejected to prevent hijacking menu navigation.
The BUILD_PATTERN article group uses word boundaries (\b(?:a|an|the)\b) so phrases like build academy do not incorrectly strip the leading a from academy as an article. Database one-shot patterns (game_process.process_one_shot_values) with opening_text='build a' were updated to 'build a ' (trailing space) for the same reason — prefix-match stripping must require a word boundary after the article.
Building Capacity Per Terrain
Source:
| Terrain | Max Slots |
|---|---|
| PLAINS | 6 |
| HILLS | 4 |
| FOREST | 4 |
| DESERT | 4 |
| MOUNTAINS | 3 |
| SWAMP | 3 |
| Default | 5 |
Design decision (intentional strategic constraint). The per-terrain slot caps are a deliberate endgame tradeoff, not a balance defect. At endgame the binding constraint intentionally shifts from gold scarcity to infrastructure scarcity: a player cannot build every economic AND military building in one territory, so terrain choice (PLAINS gives the most slots at 6) and build prioritization become meaningful strategic decisions. Reviewed against finding BL-2026-0307-016 (playtest_findings 17770), which flagged the 5-slot default as severe: resolved working-as-designed — the cap is the mechanic, not a bug. Expand capacity by selecting better terrain, not by raising the cap. Revisit only if telemetry shows it collapses build diversity to a single dominant order.
Building Production (Per Level Per Turn)
Source (canonical): — single source of truth.
| Building | Resource | Amount/Level |
|---|---|---|
| FARM | food | 25 |
| MINE | stone | 10 |
| MINE | iron | 8 |
| LUMBER_MILL | wood | 12 |
| MARKET | gold | 50 |
| MANA_WELL | mana | 10 |
| TEMPLE | mana | 5 |
Consolidated in epic #7528 — both and delegate to . Canonical value: FARM_FOOD = 25 (2 farms × 25 = 50 food/turn). MARKET_GOLD raised 20 -> 50 (2026-07-18, pacing.md ECONOMIC finding) so markets are a real income driver for a committed economic build instead of a rounding error next to worker/territory gold.
Workers
Source: , LineageKingdom
Worker Pool
totalWorkers = kingdom.population
idleWorkers = population - totalAssignedWorkers
assignedWorkers = SUM(workerAssignments.values())
Workers are drawn from the population pool. There is no separate "worker" resource -- population IS the worker pool.
Worker Assignment
Valid resources for worker assignment: wood, stone, iron, food, gold, mana
assignWorkers(resource, count):
increase = count - currentAssignment[resource]
if assigned would exceed population:
FAIL: "Not enough idle workers"
workerAssignments[resource] = count
Note: assignWorkers sets the TOTAL count for a resource, not adds to it. Assigning 5 workers to wood when 3 are already there only consumes 2 additional idle workers. Assigning past the full-pace share (75% of population) is allowed up to the whole population; those extra people produce at half pace instead of being refused.
Worker Production Rate
Source: via
fullPaceShare = population * WORKER_ASSIGNMENT_CAP_PCT (0.75)
fullRate = 8 units per turn
overCapRate = 4 units per turn (WORKER_OVERCAP_PRODUCTION_PCT = 0.5)
production[resource] = blended full-pace plus half-pace yield across the kingdom assignment
Workers within the full-pace share produce 8 per turn. Workers assigned above that share still produce, at half pace, rather than yielding zero. The blend is summed in long space and saturates at RESOURCE_MAX when the product would overflow, so a kingdom whose worker total is near the integer ceiling still produces a positive rate. Raised from 5 (2026-07-18, pacing.md ECONOMIC finding) so a committed economic build's income compounds fast enough to land near the target.
Worker Commands
| Command | Action |
|---|---|
assign 5 workers to wood |
Sets wood workers to 5 |
unassign workers from wood |
Removes all workers from wood |
unassign all workers |
Clears all assignments |
Worker Cap (RESOLVED 2026-05-22, RAISED 2026-07-18, DIMINISHING 2026-08-27)
LineageKingdom.getMaxAssignableWorkers is the full-pace share: WORKER_ASSIGNMENT_CAP_PCT (75%) of population. getHardWorkerCap is the whole population. assignWorkers refuses only past population. Workers above the full-pace share produce at WORKER_OVERCAP_PRODUCTION_PCT (half). releaseExcessWorkers only trims when assigned exceeds population. Voice copy names both the full-pace count and the half-pace remainder so over-assignment never reads as zero output.
Territory System
Source: LineageTerritory,
Territory Model
| Field | Type | Purpose |
|---|---|---|
territoryId |
String | Unique ID |
xCoord / yCoord |
Integer | Grid position |
terrainType |
String | MOUNTAINS, HILLS, FOREST, PLAINS, SWAMP, DESERT |
ownerKingdomId |
String | Owner (null if unclaimed) |
naturalResources |
Map | Base yields per terrain |
buildings |
List |
Constructed buildings |
fortificationLevel |
Integer | Defense bonus (+20/level) |
enhancementLevel |
Integer | 0-5, production bonus |
distanceFromCapital |
Integer | Affects maintenance |
powerLevel |
Integer | 1-10, strategic value |
maxBuildingSlots |
Integer | Building capacity |
unrestLevel |
Integer | 0-100, rebellion at 85+ |
securityLevel |
Integer | 0-3, police presence |
territoryClassification |
String | BASE (protected) or EXPANSION (conquerable) |
holdingNumber |
Integer | Stable 1-based spoken number for this kingdom; assigned once at claim, capital is 1 |
Terrain Power Levels
Source:
| Terrain | Power | Rationale |
|---|---|---|
| PLAINS | 6 | Fertile farmland |
| FOREST | 6 | Abundant wood, hunting |
| MOUNTAINS | 5 | Defensible, mineral-rich |
| HILLS | 5 | Good vantage, minerals |
| SWAMP | 4 | Mystical but harsh |
| DESERT | 3 | Barren, limited resources |
Terrain Resource Bonuses (% bonus to base production)
Source:
| Terrain | Bonus |
|---|---|
| FOREST | +25% wood |
| MOUNTAINS | +25% stone, +25% iron |
| PLAINS | +25% food |
| HILLS | +15% gold, +15% stone |
| SWAMP | +50% mana |
| DESERT | (none) |
Territory Base Income (Per Turn)
Source:
| Source | Resource | Amount |
|---|---|---|
| Any territory | gold | +25 |
| Capital territory | gold | +50 |
| FOREST terrain | wood | +10 |
| MOUNTAINS terrain | stone | +8, iron |
| PLAINS terrain | food | +12 |
| RIVER/LAKE terrain | food | +8 |
| Other terrain | food | +5 |
Territory Enhancement System
Source: LineageTerritory.calculateEnhancementCost, LineageTerritory.getProductionMultiplier
| Enhancement Level | Production Bonus | Cost Formula |
|---|---|---|
| 0 (base) | +0% | N/A |
| 1 | +20% | baseCost * 1 * (1 + distance * 0.2) |
| 2 | +40% | baseCost * 2 * (1 + distance * 0.2) |
| 3 | +60% | baseCost * 3 * (1 + distance * 0.2) |
| 4 | +80% | baseCost * 4 * (1 + distance * 0.2) |
| 5 (max) | +100% | baseCost * 5 * (1 + distance * 0.2) |
Enhancement cost returns: {gold: totalCost, wood: totalCost/2, stone: totalCost/2}
Territory Maintenance Cost
goldCost = enhancementLevel * 10 * (1 + distanceFromCapital * 0.2)
Only applies when enhancement level > 0. Higher distance = higher maintenance.
Territory Claiming
Source: (the model-layer claim, used by AI expansion); (the player-facing voice command, which owns the gold cost and per-turn gate below).
Requirements:
- Territory must be unclaimed (no owner)
- Territory must be adjacent to at least one territory owned by the claiming kingdom
- The claiming kingdom has not already claimed a territory this turn (see Claim Pacing below)
- The claiming kingdom can afford the current claim cost (see Claim Pacing below)
Claim Pacing (2026-07-18, pacing.md DOMINATION finding)
Claiming was gated only by a flat 100 gold with no per-turn limit, so a treasury-rich kingdom could spam-claim the ever-expanding frontier (unclaimed tiles are lazily materialized at every in-bounds frontier coordinate — see ) straight to the Domination victory threshold (30 territories) in ~10-15 turns instead of the ~60-110 turn target band. Two throttles now apply, both owned by :
- One claim per turn.
LineageKingdom.lastTerritoryClaimTurn/hasClaimedTerritoryThisTurnblock a second claim on the same turn; the player is told to end the turn first. - Rising claim cost. returns
TERRITORY_CLAIM_BASE_COST (100) + (ownedTerritoryCount - 1) * TERRITORY_CLAIM_COST_PER_OWNED (40)— the first claim (capital only owned) still costs 100 gold, unchanged; each additional owned territory raises the NEXT claim's cost by 40 gold, so expansion gets meaningfully more expensive as the kingdom grows instead of a flat rate forever.
Territory Numbering (stable holdings)
Source: LineageTerritoryHoldings, LineageTerritory.holdingNumber
Spoken "territory N" is a stable holding number, not the current index in the world tile list. World-list order shifts when frontier tiles materialize or a newly claimed tile sorts between existing holdings, which made "territory 2" resolve to a different land after claim or build. Each owned territory is stamped a holding number once (capital = 1, each later claim = max + 1) and never reused. A claim, transfer, or capture stamps the next free number in the new realm instead of keeping the previous owner's number. If a save already has two holdings with the same number, the first in holding-number then territory-id order keeps it and the other is renumbered, so the spoken numbers and the enhance path name the same lands and the held count matches. LineageTerritoryHoldings.ownedInHoldingOrder is the one list every view, build, upgrade, and enhance path reads. Older saves with null holding numbers are backfilled on first view, capital first.
Starting Territory
New kingdoms get a PLAINS capital territory with 2 FARM buildings (level 1, active). Starting food production: 12 (PLAINS terrain income) + 50 (2 farms × 25) = 62 food/turn. Starting consumption: 50 pop ÷ 3 (FOOD_CONSUMPTION_DIVISOR) ≈ 17 food/turn, giving a ~+45 food surplus per turn.
Food Consumption (RESOLVED)
Food consumption is fully implemented in and . See Food Consumption System section below.
Food Storage Cap, Overflow Allowance, and Granaries (SHIPPED — status note below)
Status: SHIPPED, and this heading was stale until 2026-08-24. The section still read "DESIGN
ONLY — do not implement until the owner greenlights this" while the code had already implemented it.
Verified live in : :303 caps free GRANARY buildings kingdom-wide so the free
path stays meaningful, :382 raises the soft food cap on build and immediately drains temporary
overflow into the stockpile, and LineageFoodStorage.BUILDING_GRANARY plus the GRANARY_EXPANSION
shop entry both exist. GRANARY is in the live BUILDING_COSTS and BUILDING_PREREQUISITES maps, so a
player could already say "build granary" and have it work.
The owner approval on record is player-request-backlog.md (owner 2026-08-01, "all recommended KEEP"),
whose L6 row asks specifically for "free GRANARY discoverability" — which is why added
granary to the spoken build menu and gave it a direct build granary option. If the formal greenlight
for was never separately recorded, that is a bookkeeping gap, not a reason to un-ship the
code — flag it to the owner rather than reverting. Epic 25099 is the original implementation tracker.
Sources of truth for this design:
- Player feedback fb 10640 ("if I get too much golden food I wont lose it will I a friend said they lost theirs")
- Report 265 (BL-01) — closed as NEEDS_HUMAN, then owner-directed
- human_question 24961 owner decision (2026-07-28): keep a storage cap; overflow is held in a temporary allowance (not destroyed); that state triggers an ISP / shop offer to raise the cap; never silent loss or silent expiry
- fairness mandate: free buildable Granary so the mechanic is not pure pay-to-avoid-loss
Terminology: "Golden food" is player slang for kingdom food (golden-fields flavor copy). There is no separate GOLDEN_FOOD resource in code or design.
Current live behavior (confirmed 2026-07-30 against code)
| Layer | Behavior today |
|---|---|
| Intentional food storage cap | None. Design and code do not define a soft food stockpile ceiling. |
| Hard safety ceiling | LineageKingdom.RESOURCE_MAX = 2_000_000_000 on SP/MP resources map — all resources (including food) silently saturate at this int safety cap (addResources / modifyResource long-sum then cap). Practically unreachable for food in normal play. |
| GLOBAL mode food | SeasonalCurrencyCounts.food is a long with no soft cap. |
| Seasonal food loss | Blizzard / Drought can reduce stockpile; Royal Granary (shop, 40 Royal Seals) is a one-shot shield that cancels the next Blizzard/Drought food loss only. It does not raise storage capacity. |
| Free Granary building | Does not exist. Building list has FARM but no GRANARY. |
Conclusion for fb 10640: there is no intentional mid-game food cap that silently discards surplus today. Player-reported "loss" is most likely seasonal event loss, famine consumption, or second-hand confusion. The owner still wants a fair, telegraphed, monetizable food-storage mechanic as a designed system (not a silent bug fix).
Design goals
- Never silent food loss — any overflow or expiry is spoken in voice-first language.
- Cap stays — food stockpile has a real soft ceiling that creates a decision (spend food / expand storage / let surplus sit in allowance).
- Overflow is held, not destroyed — temporary allowance per owner decision 24961 (supersedes pure "instant spoilage at the cap").
- Telegraphed countdown — allowance expiry is warned several turns in advance ( spoilage countdown, adapted to the allowance model so a quiet expiry cannot become a dark pattern).
- Monetizable without paywall — paid Granary Expansion raises the cap; free Granary building also raises the cap.
- Distinct products — Royal Granary (seasonal shield) stays separate from Granary Expansion (permanent capacity).
Soft food storage cap
Applies to kingdom food only (not gold/wood/stone/iron/mana). Modes: SP, MP, and GLOBAL (route through so both storage backends honor the same effective cap).
effectiveFoodCap =
BASE_FOOD_STORAGE_CAP
+ (count of GRANARY buildings owned * GRANARY_BUILDING_CAP_BONUS)
+ (granaryExpansionPurchases * GRANARY_EXPANSION_CAP_BONUS)
| Constant | Value | Rationale |
|---|---|---|
BASE_FOOD_STORAGE_CAP |
3,000 | Starting food is 500 with ~+45 surplus/turn early; cap creates mid-campaign pressure without punishing the first ~50 turns of a normal surplus. |
GRANARY_BUILDING_CAP_BONUS |
+1,500 per free Granary building | Free path: one capital granary → 4,500 cap; two → 6,000. |
GRANARY_EXPANSION_CAP_BONUS |
+3,000 per paid expansion | Permanent paid raise; stackable up to MAX_GRANARY_EXPANSIONS. |
MAX_GRANARY_EXPANSIONS |
3 | Soft ceiling on paid stacking (max +9,000 from shop). |
MAX_FREE_GRANARIES |
2 (one building type per territory, max two territories) | Free path remains meaningful without trivializing the paid product. |
RESOURCE_MAX remains the hard int safety floor above all soft caps.
Temporary overflow allowance (not silent discard)
When any food credit (turn production, pack grant, tribute, event) would push stockpile above effectiveFoodCap:
- Fill stockpile to the cap.
- Put the remainder into
foodOverflowAllowance(kingdom field; GLOBAL: same field on the kingdom model / parallel seasonal field as needed). - Cap the allowance itself at
ALLOWANCE_MAX = max(1_000, effectiveFoodCap / 2)so runaway production cannot bank infinite free food outside the cap. - Refresh the spoilage timer on every new overflow deposit:
foodAllowanceExpiresOnTurn = currentTurn + ALLOWANCE_TURNS(ALLOWANCE_TURNS = 5). - Speak on first deposit (and on every new deposit that increases the pile):
"Your granaries are full. {N} surplus food is held in temporary stores and will spoil in {T} turns unless you expand storage or spend it. Say build granary, or buy granary expansion for more capacity."
Drain order for food spends / consumption: stockpile first, then allowance (so allowance is the fragile overflow, not a second free stockpile that shields famine forever).
On cap raise (free Granary completes or Granary Expansion purchases): immediately move as much allowance as fits into the stockpile under the new cap; speak the amount recovered; clear timer if allowance hits 0.
Telegraphed spoilage countdown
| Turn relative to expiry | Player-facing requirement |
|---|---|
| Deposit turn | Always announce hold + turns remaining + levers (build / shop). |
| 3 turns remaining | End-of-turn warning: "Temporary food stores will spoil in 3 turns." |
| 2 turns remaining | Same, count = 2. |
| 1 turn remaining | Same, count = 1; offer Granary Expansion shop option if not at max expansions. |
| Expiry turn | Explicit loss: "{N} surplus food spoiled and was lost." Never silent. Then clear allowance + timer. |
Anti-dark-pattern rule (owner flag on 24961): a quietly-expiring allowance is forbidden. If the player never hears the countdown, the design is wrong. Warnings ride end-of-turn summary + return briefing food-threat fragment when allowance > 0.
ISP / shop suggestion while allowance > 0: once per session (or at most once every 3 turns) surface a soft option "buy granary expansion" / route into LINEAGE_SHOP with matchedKey GRANARY_EXPANSION, using the premium-shop shortfall→resume path when seals are insufficient. Do not hard-force Upsell every turn (respects the 7-day Upsell cooldown for proactive pitches; player-initiated shop buy is always allowed).
Free buildable Granary
Add GRANARY to the economy building list.
| Property | Value |
|---|---|
| Gold cost | 200 (aligned with MARKET) |
| Category | Economy |
| Prerequisite | At least one FARM exists in any owned territory |
| Placement | One GRANARY per territory; kingdom total capped at MAX_FREE_GRANARIES (2) |
| Production | None (storage only — not a farm substitute) |
| Cap effect | +GRANARY_BUILDING_CAP_BONUS (+1,500) while the building stands |
| Synonyms | granary, grain store, food store, storehouse |
| Voice on complete | "Granary complete. Food storage capacity is now {effectiveFoodCap}." + drain allowance if any |
Fairness: a free player who invests gold and a building slot can raise capacity without spending Royal Seals. Paid expansion remains the faster / higher jump.
Granary Expansion (in-skill purchase)
| Property | Value |
|---|---|
| Shop name | Granary Expansion |
| Matched key | GRANARY_EXPANSION |
| Cost | 80 Royal Seals |
| Category | functional (permanent) |
| Effect | Permanent +3,000 to effectiveFoodCap; increment granaryExpansionPurchases (max 3) |
| At max | Refuse with "Your granaries are already fully expanded." |
| On purchase | Drain allowance into stockpile; speak new cap and recovered food |
| Shortfall | Existing spendThenApply + minimum-pack resume (premium-shop-framework) |
Pricing rationale vs live catalog ( costs): Mana Potion 30, Royal Granary (shield) 40, Instant Building 60, Instant Recruit 75, Alliance Banner tier ~80, Large Resource Pack 100. Permanent capacity is worth more than a one-shot seasonal shield (40) and sits at the permanent-cosmetic tier (80) so a shortfall is covered by a single $1 pack (100 seals, or 200 with first-purchase bonus) without needing a mid pack.
Product separation (critical):
| Product | What it does | What it is NOT |
|---|---|---|
| Royal Granary (existing, 40 seals) | One-shot shield vs next Blizzard/Drought stockpile hit | Not a storage-cap raise |
| Granary Expansion (new, 80 seals) | Permanent food storage cap raise | Not a seasonal shield |
| Granary building (new, 200 gold) | Free permanent cap raise | Not a premium product |
State fields (implementation sketch — post-greenlight)
On LineageKingdom (and GLOBAL equivalent):
foodOverflowAllowance(int, default 0)foodAllowanceExpiresOnTurn(Integer, nullable)granaryExpansionPurchases(int, 0–3)
Constants in (or a small food-storage constants block). Cap math centralized so status, end-turn, shop, and build all read the same number.
Status / economy readout
When stockpile is at ≥90% of cap, or allowance > 0, status and economy screens speak capacity:
"Food: {stockpile} of {cap} stored" and if allowance > 0: ", plus {allowance} in temporary stores spoiling in {T} turns".
Scenario tests required at implement time (epic 25099 — not this task)
- Overflow lands in allowance, stockpile equals cap, not silently dropped.
- Allowance deposit speaks hold + turns + levers.
- Countdown warnings at T-3 / T-2 / T-1; expiry speaks explicit loss.
- Free GRANARY raises cap and drains allowance into stockpile.
- Granary Expansion purchase raises cap, drains allowance, refuses at max expansions.
- Shortfall on Granary Expansion offers minimum pack resume (framework path).
- Food consumption drains stockpile before allowance.
Out of scope for this design
- Soft caps on gold/wood/stone/iron (owner decision is food-only).
- Changing Royal Granary seasonal-shield behavior.
- New SMAPI SKUs (uses existing Royal Seal packs only).
Greenlight checklist for owner
- Approve BASE 3,000 / free +1,500 / paid +3,000 ×3 numbers, or name replacements
- Approve 5-turn allowance timer + T-3/T-2/T-1 warnings
- Approve 80-seal Granary Expansion price
- Approve free GRANARY building (200 gold, Farm prereq, max 2)
- Confirm Royal Granary remains seasonal-shield-only (no rename collision)
Food Consumption System
Source: ,
Food consumption runs during turn processing after resource production. Two implementations exist:
| Implementation | Used By | Source |
|---|---|---|
| Global/MP turn processing | line 346 | |
Inline in endTurn() |
Single Player turn processing |
Consumption Formula
populationConsumption = population / FOOD_CONSUMPTION_DIVISOR
armyConsumption = SUM(army.totalUnitCount / 4) for each army ( only)
totalConsumption = populationConsumption + armyConsumption
FOOD_CONSUMPTION_DIVISOR = 3 is defined in . The SP endTurn() implementation does not include army food consumption -- only population.
Three States
| State | Condition | Effects |
|---|---|---|
| Surplus | food >= consumption | Reset famine counter, +5% pop growth (min 1), +10% worker productivity bonus on this turn's production, +2 stability toward the natural equilibrium of 50 (the recovery lever the low-stability advisory promises) |
| Deficit | food < consumption AND food > 0 | -5% pop (min 1), -5 morale, -20% worker productivity, releases excess workers, deducts from reserves |
| Famine | food = 0 (reserves exhausted) | All deficit penalties PLUS: tracks consecutiveZeroFoodTurns, -5 stability per turn |
Famine Escalation (3+ consecutive zero-food turns)
When consecutiveZeroFoodTurns >= 3:
| Effect | Amount |
|---|---|
| Additional population loss | -10% (min 1), on top of the -5% deficit loss |
| Stability penalty | -10 (on top of the -5 per turn) |
| Army desertion | 10% of each unit type per army (min 1 per type) |
SP Turn Warnings (endTurn only)
The SP endTurn() handler provides player-facing text warnings:
| Condition | Message |
|---|---|
| Surplus but thin margin (netFood < consumption) | "Note: Food production is close to consumption levels..." |
| Deficit with reserves | "Warning: Food production below consumption. Reserves depleted by {N} food." + estimated turns remaining |
| Reserves exhausted | "Warning: Food shortage! Your people are starving." |
| Famine (3+ turns) | "FAMINE! {N} people have perished from starvation. Rebellion threatens." + "10% of your troops have deserted due to famine." |
Stability Recovery (recovery half of the stability system)
Stability decrements come from famine (-5/turn starving, -10 catastrophic) and rebellion. The recovery lever is a food surplus: while the realm is well-fed the kingdom regains STABILITY_SURPLUS_REGEN = 2 stability per turn, capped at STABILITY_NATURAL_EQUILIBRIUM = 50 (the founding value). Rising above 50 still requires the positive levers (a rebellion event's "address grievances" choice, a DIVINE_INTERVENTION spell). Applied in both food-consumption paths: (single-player, surplus branch) and (global/multiplayer, surplus branch); constants in . This makes the low-stability advisory's "ease the food shortage to steady the realm" a real, always-available action — before it, stability could only fall and no player action recovered it.
Territory Loyalty and Rebellion System
Source: LineageTerritory.unrestLevel (existing field, repurposed as the inverse of loyalty) + (new) + LineageRebellion model (existing).
Loyalty is tracked per territory as the inverse of unrestLevel: loyalty = 100 - unrestLevel. A fresh peaceful territory sits at unrestLevel 0 (loyalty 100). Edge cases (newly conquered territory, distant frontier, food famine) push unrestLevel up; garrisons, temples, and good economy push it down. When unrestLevel reaches the rebellion threshold, the territory revolts.
Stability legibility (finding 914). When kingdom stability is low (below 40), no longer speaks a bare number — it names the likely driver (a food shortage, frontier unrest at unrestLevel >= 50 on an owned territory, or morale below 30) and the lever ("Garrison a restless province, build a Temple, or ease the food shortage to steady the realm"). Guard: .
Per-Turn Loyalty Drift
Computed in between AI turns and victory check.
| Source | Unrest Delta per Turn |
|---|---|
| Distance from capital | +1 per 4 tiles distance (rounded down). Capital is +0. |
| Newly conquered (within last 5 turns of capture) | +3 |
| Garrisoned by friendly army at this territory | -3 |
| TEMPLE on this territory | -2 (per temple) |
| CITY_WALLS on this territory | -1 |
| Famine state on owning kingdom (consecutiveZeroFoodTurns >= 1) | +2 |
| Kingdom morale below 30 | +1 |
| Kingdom morale above 70 | -1 |
| Default decay toward 0 when no other modifiers fired | -1 |
Bounds: clamped to [0, 100] after every turn.
Rebellion Threshold and Trigger
| State | unrestLevel | Effect |
|---|---|---|
| Stable | 0-49 | No special effects |
| Restless | 50-69 | -10% production this turn |
| Brewing | 70-84 | -25% production, spawns a BREWING LineageRebellion row if none exists |
| Open Rebellion | 85+ | BREWING -> ACTIVE, production drops to zero, territory becomes attackable by any kingdom. After 3 turns ACTIVE with no garrison, territory ownership transfers to NULL (independent rebel state) |
Suppressing a Rebellion
The owning kingdom must move a friendly army onto the territory. Each turn the army is present, rebellionStrength drops by min(50, army.totalUnitCount * 2). Once rebellionStrength reaches 0 the rebellion is marked SUPPRESSED, unrestLevel resets to 40, and territory production resumes next turn.
Voice-First Notifications
End-of-turn copy added to endTurn summary when transitions occur:
| Transition | Player-facing text |
|---|---|
| unrest crosses 70 | "Restlessness spreads in {terrain name}. The people grow weary, my liege. " |
| unrest crosses 85 | "Rebellion breaks out in {terrain name}. Banners of revolt fly. " |
| rebellion SUPPRESSED | "Order has been restored in {terrain name}. " |
| ownership transfers to NULL | "{terrain name} has slipped from our grasp. The rebels have driven your banner from the field. " |
Out of Scope (this iteration)
- Player-issued "send envoy" diplomatic suppression (deferred to a later cycle)
- Rebellion demands integration with religious / taxation policy (model exists, no UI yet)
Inter-Kingdom Tribute System
Source: LineageTreaty.terms (existing JSON map) extended with tribute keys + (new) called from after AI turns.
Tribute lets a stronger kingdom extract regular gold (and optionally food) from a weaker kingdom without permanent conquest. It rides on the existing VASSAL treaty type and on a new TRIBUTE treaty type, so the diplomacy menu can offer it as a peace-treaty term during war negotiation. Tied into diplomacy.md treaty system.
Treaty Term Keys
When a treaty has a tribute_amount_gold (or tribute_amount_food) value in its terms, automated tribute settlement applies it each turn.
| Treaty Term Key | Type | Meaning |
|---|---|---|
tribute_payer_kingdom_id |
String | Kingdom ID that pays tribute each turn |
tribute_recipient_kingdom_id |
String | Kingdom ID that receives tribute each turn |
tribute_amount_gold |
Integer | Gold transferred per turn (default 0) |
tribute_amount_food |
Integer | Food transferred per turn (default 0) |
tribute_duration_turns |
Integer | Number of turns tribute lasts (NULL = until treaty broken) |
Default Tribute Amounts (by Treaty Type)
For convenience, when the diplomacy handler proposes a treaty, default tribute amounts are set per treaty type:
| Treaty Type | Default tribute_amount_gold | Default tribute_amount_food |
|---|---|---|
| VASSAL | 25 | 5 |
| TRIBUTE (new) | 50 | 0 |
| ALLIANCE | 0 (no tribute) | 0 |
| TRADE_AGREEMENT | 0 (tribute lives separately from trade) | 0 |
| NON_AGGRESSION | 0 | 0 |
Per-Turn Settlement
In (called from endTurn after AI turns, before victory check):
- Enumerate all ACTIVE treaties on the world.
- For each treaty with
tribute_amount_gold > 0ortribute_amount_food > 0: a. Find payer and recipient kingdoms. b. Compute actual transfer:min(tribute_amount, payer.gold). If payer cannot cover, transfer what they have and apply -2 morale on payer (tribute default penalty). c. Deduct from payer, credit to recipient via so mode-aware routing applies. d. Decrementtribute_duration_turnsif set; treaty auto-expires when it hits 0. - Voice-friendly summary on the receiving player's turn: "Tribute of {N} gold has arrived from {kingdom}. "
- Voice-friendly summary on the paying player's turn: "You sent {N} gold in tribute to {kingdom}. "
Diplomacy Hook
runs each turn applying ACTIVE tribute terms (settlement shipped). The player-facing PROPOSE_TRIBUTE matched key exists in , but no NLU entry point (option synonym or game_process.process_one_shot_values pattern) routes a spoken utterance to it yet — a player cannot currently say "propose tribute" and reach this branch. See diplomacy.md § PROPOSE_TRIBUTE and index.md Known Issues.
Resource Production Pipeline (Turn Processing)
Source: ,
Each turn processes resources in this order:
1. Worker-based production
For each resource in workerAssignments:
kingdom.resources[resource] += workers * 8
2. Territory-based production (Global mode)
For each owned territory:
territoryProduction = calculateResourceProduction(territory)
= naturalResources / 2 (base)
+ buildingProduction (per building type and level)
+ terrainBonus (% bonus on existing production)
kingdom.addResources(territoryProduction)
3. Kingdom bonus production
For each KingdomBonus with *_production keys:
kingdom.resources[resource] += bonusAmount
Base Production Rates (Stub)
Source: LineageKingdom.getResourceProductionRate
These are stub values used for display when actual territory data is unavailable:
| Resource | Rate/Turn |
|---|---|
| Gold | 100 |
| Food | 50 |
| Wood | 30 |
| Stone | 30 |
| Iron | 20 |
| Mana | 5 |
Premium Shop (Royal Seals)
Source: (extracted from )
| Item | Matched Key | Cost (Royal Seals) | Effect |
|---|---|---|---|
| Resource Bonus (spoken) / Instant Action (key) | INSTANT_ACTION | 25 | +100 gold, +50 food |
| Small Resource Pack | RESOURCES | 50 | +500 gold, +200 food |
| Large Resource Pack | RESOURCE_PACK_LARGE | 100 | +1500 gold, +500 food, +200 wood, +100 stone |
| Instant Recruit | BOOST | 75 | +10 Militia to first army |
| Instant Building | BUILDING | 60 | Completes current construction instantly |
| Mana Potion | MANA | 30 | +50 mana |
| Royal Granary | ROYAL_GRANARY | 40 | One-shot shield vs next Blizzard/Drought food loss (LIVE; not a storage-cap raise) |
| Granary Expansion | GRANARY_EXPANSION | 80 | Permanent +3,000 food storage cap — LIVE (handleGranaryExpansion, max 3 purchases); see Food Storage Cap section |
| Dynasty Expansion | DYNASTY_EXPANSION | 80 | Permanent +4 living-heir roster room so cadet branches resume bearing children — LIVE, max 2 purchases (12 then 16 then 20). Never raises DIRECT_HEIR_CAP. See progression.md § Dynasty Expansion |
| Master Builders Writ | MASTER_BUILDERS_WRIT | 50 | +1 building slot on the capital territory |
| Fertile Season | FERTILE_SEASON | 35 | +50 food per turn for 5 turns |
| War Chest | WAR_CHEST | 60 | Reinforce armies with 15 militia |
| Peace Envoy | PEACE_ENVOY | 45 | End a war and force a truce |
| Rush Claim | RUSH_CLAIM | 30 | Claim a territory even if you already claimed this turn |
| Actions Refill | ACTIONS_REFILL | 20 | Refill daily global actions |
| Alliance Banner | ALLIANCE_BANNER | 80 | Rotating dynasty sigil shown in diplomacy |
Table completed 2026-08-25. It had drifted: Granary Expansion was still marked
"awaiting greenlight" though handleGranaryExpansion is implemented and scenario-tested, and the
seven items below it were live in but absent here. Costs read from
, effects from the shop listing copy.
Every advertised item has a matching purchasable option. The Large Resource Pack was previously spoken in the menu copy but had no option or switch case, so a player was told about an item they could not buy; RESOURCE_PACK_LARGE now wires the option, switch case, and handleResourcePackLarge grant. scenario_tests cover the large-pack purchase.
Premium Shop Naming (RESOLVED)
"Instant Action" stays as-is in the current copy. Renaming is deferred — the shop label is voice-spoken to subscribers daily and rebranding mid-cycle would invalidate the muscle-memory of established players. Track via the Instant Action stub Known Issue entry.