Skip to main content

Quick Start

Say to your Alexa device:

"Alexa, open Lineage Game"

  1. 1Found your kingdom and choose your ruling dynasty
  2. 2Manage resources, build armies, and forge alliances
  3. 3Wage wars or negotiate diplomacy with neighboring realms
  4. 4Guide your lineage through generations of rulers

Overview

Status: COMPLETE — Full design documented

Last updated: October 7, 2026

Lineage — Game Design Overview

Status: COMPLETE — Full design documented

Doc coverage:: COMPLETE — Full code extraction done. All mechanics verified against Java source.

Lineage is a turn-based kingdom management strategy game where players build dynasties across generations. Players manage resources, construct buildings, train armies, conduct diplomacy, research technologies, cast spells, and navigate dynastic succession — all across three distinct game modes (Local, Multiplayer, Global) with different action economies.

Game Identity

Property Value
play_game ID lineage
skill_identifier BLOOD_LINEAGE
Genre Turn-based strategy kingdom management
Engine Multi-mode (Local/Multiplayer/Global) with action economy
DB Schema lineage

North-Star Vision

vision.md is the locked-in three-mode north star (VISION LOCKED 2026-07-17): the bounded, decision-resolved Campaign (~100 turns, 3 acts), the Clash-of-Clans "Eternal Realm" (build-grow-compare, Realm Power ranking), and the Total-War "War of the Realms" scenarios (faction pick, clear objective, difficulty) — plus living named factions and a steward/advisor layer for the two on-ramps (drive the story yourself, or take recommended actions). Read it for WHERE the game is going and WHY; this index stays authoritative for WHAT exists today. The gap between them is the build backlog.

Design Pillars

  1. Dynastic Legacy — The ruler dies, the kingdom persists. Traits, prestige, and choices carry across generations
  2. Strategic Depth Over Complexity — 12 unit types, 6 terrain types, 7 resources, but each decision matters
  3. Three-Mode Flexibility — Solo vs friends vs competitive global, same mechanics but different pacing
  4. Subscriber Value — Doubled daily actions (10 vs 5) for subscribers, Royal Seals as the premium currency

Core Loop

Manage kingdom each turn (or action):
  → Build/upgrade buildings (5 categories)
  → Assign workers to resource production
  → Train and move military units (12 types)
  → Conduct diplomacy (treaties, war)
  → Research technologies (3 eras)
  → Cast spells (mana-based)
  → Handle events (random with choices)
  → Manage dynasty (heirs, marriage, education)
  → End turn → economy resolves, research progresses
    → Ruler ages, heirs grow, succession may trigger

Game Modes

Mode Turn Mechanic Action Limit World
Local Explicit "end turn" Unlimited Solo vs AI kingdoms
Multiplayer Simultaneous resolution Unlimited Shared world via ChatFriend
Global Immediate actions, daily allowance 5/day (free), 10/day (sub) spoken on entry 1000x1000+ persistent world

Action Economy (Global Mode)

  • Daily limit: 5 actions (free) / 10 actions (subscriber), tracked by and spoken on Global entry. Royal Seals refill resets the day's counter.
  • Processed: immediately by the same handlers as Local. There is no hourly ROUND queue.
  • Subscriber check: (per-skill resolver). only applies the 5/10 daily cap; it does not look up a product of its own.

Resource Routing by Mode

Mode Resource Storage
Global
Local/Multiplayer LineageKingdom.resources map
Gems (all modes) CurrencyLedger (premium currency)

Kingdom Model

Resources (7 types)

Resource Purpose
Gold Primary currency — building, recruiting, research
Food Population support
Wood Building material
Stone Fortifications
Iron Military equipment
Mana Magic resource (75 base, 100 max, +5/turn regen)
Gems Secondary premium currency — LINEAGE_GEMS on the cross-game CurrencyLedger (ledger key lineage_gems), used ONLY for the ghost-save apology grant. The PLAYER-VISIBLE premium currency — the balance the panel UI shows, the only currency the Royal Seals Shop debits, and what every login / daily / monthly / holiday reward grants — is Royal Seals (ROYAL_SEAL, ledger key royal_seals). The collect generator credits Royal Seals through (audited); a PREMIUM_CURRENCY reward never lands in mana. Both currencies are registry-handled and operator-grantable/clawable via — see § Admin Grant (EC04-02) and § Game-Specific Currencies.

Kingdom State

Key fields on LineageKingdom:

  • resources: Map<String, Integer> — 7 resource types
  • population, morale (0-100), stability (0-100)
  • workerAssignments: Map<String, Integer> — workers per resource
  • currentResearchId, researchPoints, discoveredTechnologies
  • dynasty, ruler, heirs — dynasty system (JSON)
  • religionId, religiousPolicy (TOLERANCE/ENFORCEMENT/NEUTRAL)
  • isEliminated, hasAchievedVictory, victoryType

Buildings

Categories

Economy, Military, Magic, Defense, Research

Building Costs & Times

Building Gold Wood Stone Iron Turns
Farm 100 50 — — 2
Mine 150 50 50 — 3
Lumber Mill 100 25 — — 2
Barracks 200 100 50 — 3
Market 250 100 — — 3

Buildings are placed on territories. Each territory has maxBuildingSlots limiting total buildings.


Military

12 Unit Types

Unit Cost Upkeep/Turn Strength
Militia 50 1 5
Warrior 75 2 8
Infantry 100 3 10
Archer 150 4 12
Scout 75 2 6
Cavalry 200 6 18
Pikeman 125 4 12
Crossbowman 175 5 15
Knight 450 9 25
Battle Mage 400 10 30
Siege 500 12 20
Elite 800 16 40

Army Model

  • units: Map<String, Integer> — unit type → quantity
  • stance: DEFENSIVE, OFFENSIVE, RAIDING, FORTIFYING
  • morale, movementPointsRemaining, maxMovementPoints
  • movementPath: List<String> — ordered territory IDs for pathing

Combat Resolution

Total Strength = sum(unit_strength × quantity) for each unit type
  + Fortification Bonus: +20 per fortification level
  + Terrain Defense Bonus (defender only)
  × Morale Modifier: 50% (morale 0) → 120% (morale 100)
  ± Combat Variance: ±10%

Base Territory Defense: 50

Terrain Defense Bonuses (defender):

Terrain Bonus
Mountains +25
Hills +15
Forest +10
Plains 0
Swamp -5
Desert -3

Casualty Rates:

Outcome Casualties
Winner 10%
Loser 25%
Pyrrhic Victory 40%

Territory System

Territory Model

Each territory is a tile on the world grid:

  • terrainType: MOUNTAINS, HILLS, FOREST, PLAINS, SWAMP, DESERT
  • naturalResources: Map<String, Integer> — per-terrain yields
  • buildings: List<TerritoryBuilding> — up to maxBuildingSlots
  • fortificationLevel — defense bonus (+20 per level)
  • enhancementLevel (0-5) — terrain improvement
  • unrestLevel (0-100) — rebellion risk (85+ triggers rebellion)
  • securityLevel (0-3) — police/security presence
  • territoryClassification: BASE (protected) or EXPANSION (conquerable)
  • distanceFromCapital — affects maintenance costs
  • powerLevel (1-10) — strategic value

Territory Enhancement

Enhancement Level Production Bonus
0 (base) 0%
1 +20%
2 +40%
3 +60%
4 +80%
5 (max) +100%

Enhancement Cost: base_cost × (level + 1) × (1 + distance × 0.2) Maintenance Cost: enhancement_level × 10 × (1 + distance × 0.2)

Root Kingdom Protection

In Global mode, the player's BASE territory cannot be attacked or conquered. Only EXPANSION territories are conquerable.


Diplomacy

Treaty Types

Type Effect
NON_AGGRESSION Cannot attack each other
ALLIANCE Military support obligation
TRADE_AGREEMENT Resource exchange benefits
VASSAL Subordinate relationship

Treaty lifecycle: PENDING → ACTIVE → BROKEN/EXPIRED

AI Personalities (7 types)

AGGRESSIVE, PEACEFUL, DIPLOMATIC, SCHOLAR, MERCHANT, MYSTIC, BALANCED

Each AI has trait weights (aggression, diplomacy, greed, ambition, caution, loyalty, pragmatism, mysticism) and priority weights (military, economy, technology, magic, expansion, defense) that determine behavior.

Research & Technology

Three Eras (Cost-Gated, Not Prerequisite-Gated)

Era Research Cost Notes
Ancient 100 gold Available immediately
Classical 200 gold No prerequisite
Medieval 400 gold No prerequisite
  • Progress: 10 research points per turn
  • Concurrent blocking: Only one research at a time
  • No era prerequisites: Can research Medieval tech immediately (intentional design)

Advancement System (3 Categories)

Category Purpose
TECHNOLOGY Tech research tree — unlocks abilities
MAGIC Magic advancement — unlocks spells
CIVILIZATION Population/culture/infrastructure

Nodes have tiers (1-5), resource costs, and required progress points.


Magic System

Source:

Mana

  • Base pool: 75 current / 100 max
  • Regeneration: 5 mana per turn
  • Ruler magic stat affects regeneration and spell power

16 Spells (5 Categories)

Combat Spells (Target: ARMY)

Spell Mana Duration Effect
Fireball 20 Instant 50 damage (1 damage = kills 1/10 of a unit)
Healing Light 15 Instant 30 heal (restores morale by heal/3, units by heal/3%)
Arcane Shield 25 3 turns +25 defense bonus
Haste 20 2 turns +2 movement bonus

Territory Spells (Target: TERRITORY)

Spell Mana Duration Effect
Bless the Land 30 5 turns +25% production bonus
Protective Ward 35 10 turns +30 defense bonus
Reveal Secrets 15 Instant Reveals hidden resources

Kingdom Spells (Target: SELF/KINGDOM)

Spell Mana Duration Effect
Mana Surge 10 Instant +20 mana regen
Prosperity 40 5 turns +50 gold per turn
Inspiration 25 3 turns +15 morale bonus

Advanced Spells

Spell Mana Target Duration Effect
Meteor Strike 60 TERRITORY Instant 100 damage + building damage
Resurrection 50 ARMY Instant Resurrect 25% of fallen units
Earthquake 45 TERRITORY Instant +50 siege bonus

Legendary Spells (Require LEGENDARY_MAGIC tech)

Spell Mana Target Effect Extra Req
Time Stop 200 GLOBAL Victory spell — casting wins the game LEGENDARY_MAGIC
Apocalypse 150 GLOBAL 200 global damage LEGENDARY_MAGIC + LEGENDARY_WARFARE
Divine Intervention 100 KINGDOM +10% all bonuses, 10 turns LEGENDARY_MAGIC

Spell Requirements

  • Spells costing ≥ 40 mana require BASIC_MAGIC technology
  • Stacking prevention: cannot cast same spell on same target if already active

Enchantments

Spells with duration > 0 create LineageEnchantment effects:

  • turnsRemaining countdown, auto-removed at 0
  • effectData: Map<String, Object> — bonuses/penalties
  • Target types: TERRITORY, ARMY, KINGDOM, GLOBAL

Dynasty System

Dynasty Model

  • dynastyName, dynastyMotto, dynastySigil
  • prestigePoints — accumulated across generations
  • generationNumber — starts at 1, increments on succession
  • dynastyTraits: List<DynastyTrait> — inheritable traits
  • rulerHistory: List<LineageRulerHistory> — past rulers

Ruler

  • Stats: leadership, warfare, diplomacy, magic
  • healthStatus: HEALTHY → ILL → DYING → DECEASED
  • personalTraits: List<DynastyTrait> — traits affecting rule
  • spouse: LineageSpouse — provides bonuses and heirs

Ruler Aging & Death

Source: LineageRuler.ageOneYear, LineageRuler.shouldDieNaturally

Condition Mechanic
Age 60+ (HEALTHY) 0.05 × (age − 60) chance/year to become ILL (e.g., age 62 = 10%)
Age 70+ (ILL) 0.10 × (age − 70) chance/year to become DYING (e.g., age 73 = 30%)
Age 80+ 0.05 × (age − 80) chance/year to die naturally (escalating)
DYING 25% chance per turn to die

Heirs

  • successionOrder — position in line (1 = first)
  • claimStrength (0-100) — affects succession disputes
  • educationFocus: LEADERSHIP, WARFARE, DIPLOMACY, MAGIC
  • educationProgress (0-100) — toward education completion
  • relationToRuler: SON, DAUGHTER, BROTHER, SISTER, NEPHEW, NIECE, GRANDSON, GRANDDAUGHTER, GREAT_GRANDSON, GREAT_GRANDDAUGHTER, COUSIN
    • On succession the remaining heirs are relabeled relative to the NEW monarch (LineageKingdom.processSuccession -> reclassifyHeirsRelativeToNewRuler): the old ruler's other children become BROTHER/SISTER, nieces/nephews become COUSIN, grandchildren via a sibling become NEPHEW/NIECE. A new monarch's own children (matched by parentRulerId) are promoted to SON/DAUGHTER. Cadet accession (nephew, niece, cousin, grandchild) maps the old ruler's children and other nephews to COUSIN; blood siblings sharing parentRulerId become BROTHER/SISTER. A former monarch's child relabelled COUSIN still weds and bears children (; progression.md § Cadet Branches). LineageHeir.toRuler carries the heir's living consort onto the new ruler. Designate heir-apparent lists the current ruler's own children only; the full house stays on view heirs and view family. viewFamily names the ruler's own parents: LineageKingdom.processSuccession records them on the new ruler (LineageRuler.fatherName and motherName) from the heir's parentRulerId and motherName, the father being the other partner of the parent the heir was born to, the reigning ruler or a sibling heir of a cadet branch. A regent has no parents in the house and gets no Parents line. A ruler with no recorded parents reads the previous rulerHistory entry as its parents. Each of the ruler's own children is read with both parents: the ruler and the other parent, the mother under a king and the father under a queen. A child's recorded mother is the female partner at birth, the queen herself under a queen. viewRuler's child count is living SON/DAUGHTER, not the consort birth counter. Educate pickers speak existing calculatePotential the same way view heirs does.
  • A child of a SON/DAUGHTER is a GRANDSON/GRANDDAUGHTER; a child of a grandchild is a GREAT_GRANDSON/GREAT_GRANDDAUGHTER. Sibling lines still produce NEPHEW/NIECE.
  • Every living heir is on the old-age curve (LineageHeir.shouldDieOfOldAge, 75+ escalating, certain at age 100), including SON/DAUGHTER — otherwise the direct-heir cap never opens for a new generation.
  • Must be 16+ years to rule

Marriage

4 marriage types: LOVE, ARRANGED, DIPLOMATIC, CONQUEST

  • Female fertility: Until age 45
  • Male fertility: Until age 60
  • Spouse traits may pass to children via inheritanceChance

Traits (10 Predefined)

BRILLIANT, WARLIKE, DIPLOMATIC (Silver Tongue), MAGICAL_AFFINITY, SICKLY, CRUEL, AMBITIOUS, PATIENT, DRAGONBLOOD, LEGITIMIZED

Categories: PERSONALITY, PHYSICAL, MENTAL, BLOODLINE

  • Bloodline traits always inherit
  • Others have inheritanceChance (0.0-1.0)
  • Stat bonuses and kingdom effects per trait

Religion System

  • religionId — current religion (e.g., "REL_001")
  • religiousPolicy: TOLERANCE, ENFORCEMENT, NEUTRAL
  • Conversion has a penalty period (conversionPenaltyEnds)
  • Events can involve religious expansion

Victory Conditions

Source:

5 victory types. Checked each turn. If only 1 kingdom remains, automatic DOMINATION victory.

Victory Condition Threshold
DOMINATION Control territories ≥ 75% of all territories
ECONOMIC Accumulate gold ≥ 100,000 gold
DIPLOMATIC Form alliances Allied with ≥ 50% of non-eliminated kingdoms
TECHNOLOGICAL Research all 5 legendary techs LEGENDARY_WARFARE, MAGIC, ECONOMY, DIPLOMACY, CONSTRUCTION
MAGICAL Cast TIME_STOP spell Spell status = COMPLETED

Tie resolution (multiple simultaneous victories): Most territories → Most gold → Highest morale → Alphabetical kingdom ID.

Game completion: Sets world.victorKingdomId, world.victoryType, world.victoryTurn, world.isCompleted = true, world.isActive = false.


Events

Source:

Event Mechanics

  • Chance per turn: 10% (0.10 probability)
  • Disabled by: worldSettings["randomEvents"] = false
  • Eliminated kingdoms do not receive events
  • Lifecycle: PENDING → RESOLVED (player chooses) or EXPIRED (auto-penalized)
  • History: Last 50 events kept in log

13 Events (10 Generic + 3 Seasonal)

The 10 generic events are rows in lineage.rule_lineage_common (rule_type EVENT); the 3 seasonal events (BLIZZARD, DROUGHT, HARVEST_FESTIVAL) are code-driven constants in , not DB rows. A live EVENT rule count of 10 is correct. See progression.md § Event Definitions.

Source:

Generic Events (any season)

Event Weight Expiry Key Choice Best Outcome
Bountiful Harvest 15 3 turns Store/distribute/trade Distribute: +morale 10, +50% food
Gold Discovery 10 5 turns Extract/mine carefully/share Mine carefully: +150% gold
Trade Caravan 15 3 turns Trade/hospitality/tax Trade: +resource, -50% gold
Hero Emerges 8 5 turns Commander/advisor/quest Commander: +20% army strength
Divine Blessing 12 5 turns Festival/shrine/spread word Festival: +25 morale, -50 gold
Magical Storm 10 1 turn Harvest mana/shield/research Harvest: +30-69 mana (risky)
Plague 8 2 turns Quarantine/let run/magic cure Magic cure: -25% pop, -30 mana
Rebellion 8 2 turns Address/parade/ignore Address: +10 stability, -100 gold
Natural Disaster 6 1 turn Repair/evacuate/magic protect Magic: -40 mana, full protection
Bandit Raiders 8 2 turns Troops/pay off/fortify Troops: +5 army morale, no gold loss

Seasonal Events (season-locked, high weight when in season)

Event Season Weight Effect
Blizzard WINTER only 25 Food stockpile loss, movement penalty, -5 stability
Drought SUMMER only 20 Severe food/morale penalty (crop loss %)
Harvest Festival AUTUMN only 25 Food bonus, morale boost, choice of celebration type

Expiration Penalties (auto-applied if ignored)

Event Penalty
Plague Full population loss
Rebellion -25 stability, -15 morale
Natural Disaster -50 population, -30 wood
Bandit Raiders Full gold at risk lost
Others -5 morale

Global World

Map Structure

  • Size: 1000x1000+ tiles
  • Chunk loading: 20x20 nearby chunk per request
  • Spiral coordinates: ringNumber + ringPosition for territory placement

Territory Contestation

  • isAttackable — whether territory can be attacked
  • contestedByUserId, contestedProgress (0-100)
  • Contest progresses over time; at 100%, territory changes ownership
  • Player BASE territories are protected (not attackable)

Save-State Persistence (2026-04-23)

Column constraint: lineage.lineage_game_map.map_ref must hold sp_{userId} for every player. Alexa account identifiers can reach 254 chars, so the column is sized at VARCHAR(400) to fit a sp_ prefix + a maxed-out Alexa id.

Historical bug: Prior to 2026-04-23 the column was VARCHAR(255). Inserts for users with userId length >= 253 chars produced silently-truncated/rejected writes (DB strict mode dependent). 24 / 76 single-player accounts (31.6%) accumulated accountCache state claiming hasSinglePlayerGame=true with a singlePlayerKingdomId but zero corresponding lineage_game_map rows. On relaunch, LineageGameLoader.loadSinglePlayerGame detected the ghost save, logged CRITICAL, and silently created a fresh game — the players experienced losing their kingdom.

Ghost-save recovery path (LineageGameLoader.loadSinglePlayerGame): when expectedExisting is true but neither Redis nor DB returns a map:

  1. Log a CRITICAL error + force an ErrorEmailSender alert (#8262).
  2. Grant 15 lineage_gems as a one-time apology through (or for gems, which calls it).
  3. Stamp so repeated relaunches do not re-award gems.
  4. Proceed with the usual getOrCreateSinglePlayerGame flow.

Save path contract: Single-player writes go through LineageGameSaver.saveGameMap → which writes Redis AND upserts to lineage.lineage_game_map in the same call. Redis TTL is 7 days; the DB row is the source of truth.

Multiplayer and global-world paths are unaffected by the column-size bug (they key on partyRef and (xCoord, yCoord) respectively, neither of which contains the Alexa userId).

Action queues by mode

RETIRED. The Global hourly ROUND queue is retired. Wiring it would have delayed every Global build, recruit, research, spell, move, attack, claim, treaty, war, and trade by up to an hour into a drain that skipped whole batches via OFFSET-while-mutate, charged BUILD/RECRUIT/RESEARCH costs that diverged from the live handlers, and logged treaty/war/trade as success without changing state. The live Global world (Eternal Realm) stays: launch still offers "global world", handlers still resolve immediately, and the daily 5/10 allowance remains the spoken budget plus Royal Seals refill. , the lineage_action_queue insert, , , , and are gone. cancel action / view-actions reads the live JSON queue, not a hardcoded empty sentence.

Local and Multiplayer games queue pending BUILD, RESEARCH, and RECRUIT work on LineageGameMapData.actionQueue, persisted as JSON inside lineage.lineage_game_map.map_data. is the owner: it appends on queue, completes on end-turn, and removes finished rows. That list is live game state. It is kept, and it is bounded. Global has no second table beside it.

The JSON queue must not be collapsed into a database ROUND table. Deleting it would drop Local and Multiplayer pending work.

Combat resolutions

Lineage has three combat resolutions after this change, one per mode. A fourth unused stub (processRegionalCombat) is deleted.

Mode Owner Casualties Variance
Local Attacker 10% if they win, 25% if they lose. Defenders 40% if the attacker wins, 15% if they hold. Matches WINNER 10 / LOSER 25 / PYRRHIC 40. +/-5% (STANDARD_COMBAT_VARIANCE_*)
Global Loser 20–40% of the weaker side's strength, winner 10–20% of the weaker side. Territory enters CONTESTED. +/-10% (COMBAT_VARIANCE_*)
Multiplayer Loser 50%, winner 25%, applied through . Simultaneous resolution; no extra roll here

Three is correct: Local is a turn-map fight against stationed defenders, Global is a persistent-world conquest against territory defense plus garrison, Multiplayer is a simultaneous pair of armies. They do not share a loop. Global attacks go through when the player attacks, not through a weekly regional sweep.

Serializer invariant

LineageGameMapData must not expose a second Jackson property for the same live collection. An alias getter that returns actionQueue is a writable actionsQueue property under Jackson's default MapperFeature.USE_GETTERS_AS_SETTERS (the shared JsonWriterUtility mapper leaves that default on). Deserialize then replaces the list from actionQueue and appends actionsQueue into the same list, doubling the queue on every load. Derived getters that return a live mutable collection (LineageGlobalKingdom.getTerritories, getArmies) or a second copy of a persisted collection (getPlayerKingdoms, getAIOnlyKingdoms, LineageReligion.getBonusTypes) are @JsonIgnore. Persistence uses the Lombok field accessors only.

map_data size ceiling

The write path refuses any serialized map_data larger than 8 MiB (8,388,608 characters). A healthy map is under 1 MB. 8 MiB is eight times a large healthy game and 1/64 of prod max_allowed_packet (512 MB), so a serializer bug cannot silently grow a row past the dump ceiling in one doubling. and both refuse; the last-good database row is left in place. Constant: LineageMapDataSizeGuard.MAX_MAP_DATA_CHARS.

Meta-Command Bypass During Kingdom-Name Prompt (2026-04-28)

Bug: A fresh player whose kingdom needed naming had every utterance consumed as a candidate kingdom name. "help", "options", "what can I say", "stats", and any other meta-command silently re-rendered the same kingdom-name prompt forever, with no accessibility escape valve. Discovered via scripts/alexa/console_playtest.py --skill blood-lineage — 6/7 turns returned the same prompt regardless of utterance.

Root cause: returns false for KINGDOM_NAME so REPEAT, LINEAGE_RECRUIT, etc. can't strand the player with zero options. But that gate is too coarse — it also blocked legitimate accessibility commands (HELP, LIST_COMMANDS, MAIN_MENU, EXIT) that the player needs to escape the prompt cleanly.

Fix: Added — a universal allowlist of meta-commands (HELP, HELP_DETAILS, LIST_COMMANDS, LIST_COMMAND_DETAILS, REPEAT, MAIN_MENU, EXIT, BASELINE_REPORT_BUG, BASELINE_SUBMIT_FEEDBACK, BASELINE_WHATS_NEW, SUBSCRIBE) that ALWAYS escape forced-interaction prompts. NOTE 2026-06-17: REPEAT is in this allowlist so it escapes the gate, but Lineage's REPEAT handler currently returns an empty response, so the bypass yields silence at the gate, see Known Issues . The pending interaction is preserved across the bypass, so the next turn re-prompts via the still-stored pending. Applied at all three entry points: handleValueEntryInteraction, handleYesNoInteraction, and handleNewInteraction (first-turn path). Universal fix — applies to Lineage kingdom naming, Darkness Falls character creation, Dark Tower, etc.

Affected callers: every game with a forced-interaction provider that returns false from allowsCommandPassThroughDuringValueEntry or allowsCommandPassThroughDuringYesNo. Lineage KINGDOM_NAME is the canonical case; DF/DT character setup providers are similar.

Coverage: scenario_tests rows 351 (launch; help) and 352 (launch; stormhold; yes; status) regression-protect the bypass and the post-fix kingdom-name flow.

Stale Pending Forced Interaction (2026-04-27)

Bug: A KINGDOM_NAME / VALUE_ENTRY pending stored on user_profile.profile_data.pendingForcedInteraction was preserved across sessions even after the kingdom was successfully renamed. always re-prompted from the stored pending without revalidating against current state, so every relaunch repeated "What would you like to name your kingdom" forever despite the kingdom already having a name. Reported by player zoos (24 feedback rows: id 1504-1523) who counted at least 55 launches showing the prompt and asked for the kingdom to be named "Apex Legends Empire".

Fix: Added .isPendingStillRequired(props, pending) (default true). overrides it to return false when the pending is KINGDOM_NAME and the kingdom already has a non-default name. calls this method before processing any stored pending and clears the pending if the underlying state has resolved the prompt out from under it. Same gate (isKingdomUnnamed) is now used by checkForForcedInteraction and the new method so the new-prompt and resume-prompt paths agree.

Affected players: any account whose kingdom was named while a stale pendingForcedInteraction was on user_profile would have hit this. Detection query: SELECT amazon_skill_id FROM game_user.user_profile WHERE JSON_EXTRACT(profile_data, '$.pendingForcedInteraction.interactionType') = 'KINGDOM_NAME' AND JSON_EXTRACT(profile_data, '$.pendingForcedInteraction.category') = 'VALUE_ENTRY' joined against lineage.lineage_game_map rows where kingdoms[*].kingdomName != 'New Kingdom'. Report covers 1 confirmed player; the fix is general and clears any future stale pendings on next launch.

Admin REST API

Source: — base path /api/lineage/admin Auth: Admin JWT Bearer token required for all endpoints.

Method Path Description
GET /worlds List all game world summaries (metadata only, no full state)
GET /world/{mapRef} Get full LineageGameMapData for a world (sp_{userId} or mp_{partyRef})
PUT /territory Update a territory in a world (query param mapRef, body LineageTerritory)
PUT /kingdom Update a kingdom in a world (query param mapRef, body LineageKingdom)

All endpoints call parseAndValidateAdminFromToken(token) for auth, then delegate to .


Subsystem Design Docs

Subsystem Design Doc Covers
Military military.md 12 unit types, combat formula, movement, conquest
Kingdom kingdom.md 15 buildings, workers, territory, production rates
Diplomacy diplomacy.md Relations, treaties, AI personalities, war/alliance formulas
Living Factions factions.md Named-faction roster (Phase 3, IMPLEMENTED) — identity, agenda, archetype mapping, and the shared-infra wiring across Campaign, Eternal Realm, and (future) War of the Realms
Magic magic.md 16 spells, mana system, tech gating, enchantments
Progression progression.md Turn pipeline, 5 victory conditions, dynasty, events, research
Endgame endgame.md + empire-4x-layer.md Building upgrades, legendary units, endgame threat events (endgame.md Pillars A/B/C), Empire tier + Edicts (SHIPPED via empire-4x-layer.md SE-1, -- endgame.md Pillar D is the origin design, not the current spec)
4X Systems four-x-systems.md Resource management screen (all 7 resources, net per turn), meaningful New Game Plus (Legacy screen + scaling founding headstart), emergent-story Dynasty Chronicle
Return Briefing return-briefing.md Spoken state-of-the-realm briefing delivered on session entry (snapshot + what-changed-since-last-session); the gd-04 voice-memory-load fix. IMPLEMENTED 2026-06-17 via on the welcomeReturningPlayer launch path; snapshot reconciled with the design 2026-06-21 — realm line names the lowest critically-low material, threats line surfaces a running food deficit projected to starve within ten turns.
Empire / 4X Build-Out empire-4x-layer.md MASTER design for the gd-04 "Invest in the 4X layer" build-out (decision 285): the post-victory Empire Tier (empire screen + Edicts), NG+ depth (chosen ascension), and emergent-story depth (revisitable Dynasty Chronicle) — all governed by an explicit seven-rule voice-memory-load budget. SE-1 (Empire Tier core, Empire Screen, Edicts) IMPLEMENTED; SE-2 (NG+ depth — chosen ascension trait + founding legacy) IMPLEMENTED; SE-3 (emergent-story depth — revisitable Dynasty Chronicle + four new beats) IMPLEMENTED.
War of the Realms Scenarios scenarios.md Phase 5, IMPLEMENTED 2026-07-18 — the scenario schema (chosen faction, fixed starting board, stated + re-readable objective, difficulty knobs) and the initial four scenarios (Unite the Broken Coast, Break the Iron Compact, Hold the Ashen Gate, The Merchant's Gambit), wired single-player first then multiplayer via the shared-map service.

Round-2 Playtest Fixes (2026-05-28)

Seven Playtest-BL findings (25716-25722) root-caused and fixed. scenario_tests 1632-1638.

  • Recruit into army 2+ (25716, feedback 7571) — normalized spaces to underscores before stripping the "to army N" suffix, so the suffix leaked into the unit token ("Warrior To Army 2"). Strip is now [\s_]- and INTO-aware; recruit/bare-unit patterns accept the "into army N" connector. Army targeting itself was already re-parsed from raw input.
  • Propose treaty/alliance (25717, feedback 7573) — handler blindly targeted aiKingdoms.get(0) — the same kingdom "declare war" hits — so once at war the proposal returned a contentless "Cannot propose treaty at this time." It now walks the AI roster for the first kingdom not at war and without an existing treaty of that type, and gives a specific reason when none qualify.
  • Event response NLU (25718, feedback 7755) — only the verbose "respond to event N option M" worked. Displayed event options now carry an EVENT_<n>_OPTION_<m> matchedKey plus "option N"/"choice N"/"choose N" synonyms; handleEventResponse accepts the structured key, the verbose form, an option-only form, and a bare number; adds EVENT_RESPONSE_PATTERN so "respond option N" / "option N" route instead of FALLBACK.
  • Territory claim frontier (25719, feedback 7756) — the seed world used a sparse (step-3) unclaimed grid, so claimed cells never exposed adjacent neighbors and expansion dead-ended at ~12 territories. now lazily materializes an unclaimed tile at every in-bounds frontier coordinate; the existing per-held-territory recompute then keeps offering new land outward. NOTE: domination victory (>=50% of all territories) may warrant world-size/threshold tuning now that the denominator grows with exploration — flagged as a balance follow-up, not a blocker.
  • "recruit knight" default-5 / "recruit a knight" (25720, feedback 7757) — a bare "recruit knight" defaults to 5 (2250 gold) and looked un-recruitable; "recruit a knight" failed to parse the article. Leading "a"/"an" now means quantity 1, and a gold-shortfall on a defaulted count adds a hint pointing at the single-unit form. The default of 5 is unchanged (balance decision left to design).
  • Building upgrade L5 message (25721, feedback 7574) — level 5 is the intended cap. The success line now states the building is maxed and no longer offers a dead "upgrade more" option at the cap.
  • Attack/move-army sub-prompt phrasings (25722) — the army picker and move/attack territory pickers suggested phrasings ("army 1", "march north") that misrouted. Each picker option gained short synonyms (index, "army N", army name, "march ", "", terrain) so the suggested phrasing advances the flow.

Round-3 Playtest Fixes (2026-07-02)

RVF fixes for report group 165 (Blood Lineage building, upgrade, recruit, worker NLU plus spells). scenario_tests 2551-2560.

  • Research era names (finding 815) — the research menu prints era HEADERS ("Ancient era", "Classical era") for orientation, but they are not techs, so "research ancient era" hit "Unknown technology: Ancient Era". now treats an era name (Ancient/Classical/Medieval/Advanced/Legendary) as "research the next available tech in that era" (Ancient to Agriculture), or a graceful "no era technologies available" when none qualify.
  • Build/upgrade "... in territory N" (finding 845) — the NUMBER_KEY one-shot () does not strip the word "territory" from the extracted key, so "build wall in territory 1" arrived as building "WALL_TERRITORY" ("no building called Wall Territory"). handleBuild now strips a trailing TERRITORY/CAPITAL/LAND location word (the territory index is already carried in possibleNumbers).
  • Upgrade a 2nd same-type building (finding 902) — the capital starts with 2 farms; bare "upgrade farm" only ever leveled the first, and "upgrade second farm" failed ("Unknown building type: Second Farm"). handleUpgradeBuilding now parses an ordinal ("first/second/2nd") or "level N" selector to pick the instance, and with no selector upgrades the LOWEST-level copy so repeated "upgrade farm" reaches every instance; a hint names the "upgrade second farm" form.
  • Worker assignment robustness (finding 904) — the game's most-used first move silently failed for a dropped verb ("30 workers to food"), synonym/misheard verbs ("sign/hire/gather workers to X"), the "two"-to-"to" homophone, and a missing count. A shared now tolerates all of these; routes verbless and synonym-verb forms; recovers a garbled or missing resource+count from the raw utterance and assigns ALL idle workers when no count is spoken; handleRecruit delegates a "hire/sign workers to " utterance (the FREE_FORM "hire" one-shot otherwise stole it) to the worker handler. Every path echoes the concrete result.
  • Spell cast + list (finding 910) — "cast " ("cast healing light") and a bare "spells" dead-ended in FALLBACK. adds cast and spell-menu patterns; fuzzy-resolves displayed names and partials to the canonical spell key; a "more spells" option pages the spell menu to the full catalog (a working "more" where "repeat" only replays).
  • Recruit mishearings (findings 911, 846) — "pipemen"/"pipe men"/"bike men" (pikeman), "night"/"nights" (knight), "malaria"/"malaysia" (militia), and "crossbow men/man" plus bare "crossbow" (crossbowman) were rejected as unknown units. Added to ; LineageSynonymResolver.normalizeUnit now falls back to that map so BOTH the recruit-handler one-shot path and the Tier-4 bare-unit path resolve them.

Known residual (pre-existing shared NLU, out of scope): "assign two workers to X" (explicit word "two") can be intercepted by the Tier-2 OPTIONS fuzzy matcher depending on which options are active, routing to a view instead of the worker handler. The homophone "assign to workers to X" and all four documented finding-904 phrasings work.

Sub-Docs In This Directory

Design docs that live alongside this index and were not previously linked from it. Wired in for index-to-sub-doc discoverability by design-audit follow-up (2026-06-15). Read the one matching your task.

Doc Covers
pacing.md Win-condition pacing & earnability audit (2026-07-17) — the ~100-turn target bands, the per-victory earnability analysis (MAGICAL currently UNEARNABLE: TIME_STOP 200 mana vs maxMana 100; TECH too slow; DOMINATION moving denominator; DIPLOMATIC risk-too-fast), and the empirical audit method.
campaign.md The Campaign shape (Phase 2, IMPLEMENTED 2026-07-17) — the bounded ~100-turn 3-act campaign (Founding 1-25 / Ascendance 26-70 / Reckoning 71+), the soft Century target, the turn-~100 Twilight-of-the-Age reckoning + decision-authored epilogue (Conqueror/Diplomat/Steward/Archmage/Dynast), and the Phase-2 win-condition earnability fixes (MAGICAL mana cap, TECH rate, DIPLOMATIC hold gate).
vision.md North-star vision (LOCKED 2026-07-17) — the three modes (Campaign / Eternal Realm / War of the Realms), bounded ~100-turn decision-resolved campaign, living factions, advisor layer, and the loop-fix backlog (war/army/diplomacy/onboarding/dynasty). Grounded in live player data + firsthand play.
advisor.md The Steward/advisor (Phase 1, IMPLEMENTED 2026-07-17) — the pull-on-demand recommended-actions layer: state signals read, the ranked candidate list, Act-aware framing, the safe-but-less-optimal on-ramp framing, and the onboarding-hint wiring that fixed the turn-1-5 churn cliff.
factions.md Living factions (Phase 3, IMPLEMENTED 2026-07-17) — the named-faction roster (six factions, one per AIPersonality archetype: identity, sigil, motto, homeland, lore, agenda, signature bias, stance-to-player) and its wiring across Campaign rivals, Eternal Realm AI realms, and the future War of the Realms scenario sides.
four-x-systems.md Lineage — Full 4X Systems: Resource Screen, New Game Plus, Emergent Story
prestige.md Lineage — Prestige & Ascension System Design
player-request-backlog.md Owner-dispositioned player requests + Design Fit Gate (standing idea 25326); L9 one-type-per-territory confirmed
eternal-realm.md The Eternal Realm (Phase 4, IMPLEMENTED 2026-07-18) — the Clash-of-Clans build-grow-compare loop on Global mode: the Realm Power formula (territory+buildings+army+prestige), the speakable Realm Ledger (rank, throne-holder, weekly trend), growth narration on the return briefing, and named-faction board population via .

Kingdom guard contract (handler precondition)

Every Lineage handler method opens with the kingdom guard:

Boolean guard = lineageKingdomGuard.requireKingdom(gbp);
if (guard != null) return guard;

Contract: requireKingdom returns null when a kingdom is present (proceed), and returns (which is false = CONTINUE_GAME) when absent — so a no-kingdom call launches the kingdom-creation flow inline. handleView with no kingdom therefore returns HandlerResult.HANDLED_FAILURE (the guard already ran launch), not a fallback.

Testing note: Mockito's default answer for an unstubbed Boolean-returning mock is false, NOT null. A with-kingdom unit test that does not stub the guard gets false → guard != null is true → the handler returns early with the wrong result. Stub it explicitly: when(guard.requireKingdom(any())).thenReturn(null) for the with-kingdom path; thenReturn(false) (the propagated launch result) for the no-kingdom path (assertFalse, not assertNull).

Onboarding scenario-test setup (kingdom naming)

Kingdom naming is a forced-interaction VALUE_ENTRY: a fresh character's first input establishes the pending interaction and shows the prompt; the value is processed on the SECOND input. A single-input naming test re-prompts and fails — author it as a chain that establishes the prompt first, e.g. name my kingdom X; yes (the runner's bypass leaves the kingdom unnamed with the pending interaction live). Same mechanism as DT character naming — see dark-tower/index.md § Onboarding scenario-test setup traps.

Books by Lincoln Cole

Read the worlds behind the games

All books at llitd.com ↗