Skip to main content

Kingdom

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:

  1. Territory must be unclaimed (no owner)
  2. Territory must be adjacent to at least one territory owned by the claiming kingdom
  3. The claiming kingdom has not already claimed a territory this turn (see Claim Pacing below)
  4. 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 / hasClaimedTerritoryThisTurn block 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

  1. Never silent food loss — any overflow or expiry is spoken in voice-first language.
  2. Cap stays — food stockpile has a real soft ceiling that creates a decision (spend food / expand storage / let surplus sit in allowance).
  3. Overflow is held, not destroyed — temporary allowance per owner decision 24961 (supersedes pure "instant spoilage at the cap").
  4. 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).
  5. Monetizable without paywall — paid Granary Expansion raises the cap; free Granary building also raises the cap.
  6. 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:

  1. Fill stockpile to the cap.
  2. Put the remainder into foodOverflowAllowance (kingdom field; GLOBAL: same field on the kingdom model / parallel seasonal field as needed).
  3. Cap the allowance itself at ALLOWANCE_MAX = max(1_000, effectiveFoodCap / 2) so runaway production cannot bank infinite free food outside the cap.
  4. Refresh the spoilage timer on every new overflow deposit: foodAllowanceExpiresOnTurn = currentTurn + ALLOWANCE_TURNS (ALLOWANCE_TURNS = 5).
  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)

  1. Overflow lands in allowance, stockpile equals cap, not silently dropped.
  2. Allowance deposit speaks hold + turns + levers.
  3. Countdown warnings at T-3 / T-2 / T-1; expiry speaks explicit loss.
  4. Free GRANARY raises cap and drains allowance into stockpile.
  5. Granary Expansion purchase raises cap, drains allowance, refuses at max expansions.
  6. Shortfall on Granary Expansion offers minimum pack resume (framework path).
  7. 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):

  1. Enumerate all ACTIVE treaties on the world.
  2. For each treaty with tribute_amount_gold > 0 or tribute_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. Decrement tribute_duration_turns if set; treaty auto-expires when it hits 0.
  3. Voice-friendly summary on the receiving player's turn: "Tribute of {N} gold has arrived from {kingdom}. "
  4. 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.