135 KiB
Aetherbound Guild - Gameplay, Battle, Economy And Save
Complete gameplay rules, deterministic battle, progression, economy, pacing, failure, persistence and recovery.
Owner Review / Owner 审核
重点确认招募、自动排阵、战斗、击倒与下关恢复、装备、持续成长、经济、难度、失败与存档规则。这里回答“每一步怎么玩、怎么算、输赢后发生什么”。
本文件是当前六份审核文档之一。历史拆分文件仅保留在 Git 历史中;文内规则、表格和 ID 仍是完整开发依据。
P0 Consolidation Role
This document is the systems authority inside the consolidated project
contract. It defines what each recurring decision changes, which state owns
the result, how Coin/XP/Equipment/Company/Contract values persist, and how
failure, recovery and Save receipts behave. It does not define page layout or
art treatment; those belong to 03_PAGES_AND_UX.md and
04_ART_ANIMATION_AUDIO.md.
2026-08-17 Continuous-Growth Owner Override
This override is the current authority everywhere this file conflicts with the older FG-4 implementation model below:
- one Guild save owns one persistent Expedition Company across Contract runs;
- New Game creates exactly four stable provisional offers and commits exactly two of them once as the initial persistent roster;
- a zero-HP Recruit is knocked out for the current battle, remains owned and is battle-ready again for the next stage with the same identity and growth;
- Contract clear or withdrawal closes only Contract-local progress, formation, encounter and temporary-effect state, then returns to the Guild; and
- death-funded Replacement Credit, Company-collapse roster deletion, Recruit archiving and loss of levels/XP/equipment at Contract close are superseded.
The exact next-stage HP amount is intentionally frozen for the later balance conversion. DEV-2 guarantees persistent ownership and next-stage availability; it must not invent a full-heal rule or permanent casualty.
The older sections that still name Fallen, Replacement Credit,
run_creation_draft, short-lived current_run Recruits, Company collapse or
roster archiving are FROZEN_LEGACY_FG4 evidence. Their deterministic battle,
economy and Save-v11 details remain preserved until the named later player-order
conversion, but those conflicting lifecycle effects are not current product
authority. Battle-local Fallen event/code identifiers may temporarily remain
as implementation names only; product-facing meaning is Knocked Out and never
permanent roster removal.
For DEV-2, the current persistence boundary is:
Guild_slot
initial_company_draft or null
expedition_company or null
initial_company_draft
draft_id, seed, status, source_revision
offers[0..3], offer_set_hash
selected_offer_ids[0..2], selection_revision
expedition_company
company_id, created_from_draft_id
owned_recruits[2..], reserve_recruit_ids[]
persistent inventory, Coin, levels, XP, Professions, Traits and history
active_contract or null
An uncommitted draft and a committed initial Company are mutually exclusive. The same saved seed always produces the same four IDs in the same positions. Selection may contain zero, one or two distinct offer IDs; only exactly two can enter review. Commit atomically removes the draft, writes one Company containing only the selected two Recruit records and stores an idempotent receipt. A retry returns that receipt and never creates a second Company or rerolls the offers.
Aetherbound Guild: Systems And Battle Authority
Authority: generated-Recruit state, Profession grammar, Market/run handoffs, ordered Party-line geometry, deterministic auto-battle, equipment and Artifact hooks, targeting, movement, knockout, recovery, and causal diagnosis.
Revision: recruit-line-design-r2 / 2026-08-10
Product intent is defined in 01_GAME_DESIGN.md. Prices, rewards, progression rates, capacity selection, and pacing are defined in 02_GAMEPLAY_AND_BALANCE.md. Durable commit and recovery semantics are defined in 02_GAMEPLAY_AND_BALANCE.md.
1. System Invariants
- Each side occupies one ordered horizontal line. Position zero is front; a larger position is farther rearward. There is no second spatial axis.
- Allied simultaneous footprint begins at four and reaches ten. Reserve and cumulative hires are separate and never redefine this limit.
- Battle is automatic. The player may start, pause, change speed, inspect, or retreat, but cannot activate attacks/skills, reorder, equip, or promote while resolving.
- A Recruit has one generated identity, one current fixed Profession, five rolled attributes from an equal level budget, exactly one Trait, equipment, level, and survival history.
- Zero HP means Knocked Out. The Recruit leaves the resolving line immediately, never respawns in that battle, and is never replaced by Reserve during that battle. The Recruit remains in the persistent Expedition Company and is battle-ready again for the next stage with equipment and growth unchanged.
- The same start state, ruleset, content revision, seed, and retreat timestamp produces the same state hashes and result.
- Display frame rate and pause/1x/2x/4x do not change simulation time or draws.
- Every targeting exception, failed action, movement conflict, retarget, immunity, proc suppression, and outcome has one inspectable reason.
- All damage has a declared type, power source, defense, rounding boundary, critical rule, modifier groups, and floor/nullification behavior.
- No standard battle exceeds 150 simulation seconds.
2. Authoritative State Model
profile
settings, accessibility, language, input mappings
Renown, unlock breadth, Region/Contract progress, Records, collection facts
persistent Expedition Company, inventory, Coin and Recruit growth
Contract expedition
contract_run_id, contract_id, difficulty_id, ruleset_version, content_revision
generation_seed, Market index, cleared Rounds, Line capacity
route, refresh/lock counters, deployed formation, temporary Artifacts
knockout events, boss state, Contract result
Recruit
recruit_id, generated_name_parts, rendered_name_snapshot, appearance_seed
origin_profession_id, current_profession_id, promotion_state
level, xp, five base attributes, Trait id
equipped_item_id or null, effective stats, battles entered, victories,
hire receipt
encounter
encounter_id, battle_offer_id, root_seed, phase, tick
ordered allied/enemy actor sequences and footprints
HP, resources, readiness, cooldowns, casts, statuses, barriers
event queue, draw counters, retreat state, objective, outcome, event journal
presentation only
camera, interpolation, animation frame, particles, selected inspector,
expanded tooltip, pointer, audio playback cursor
Presentation never authors state. Battle arithmetic uses signed 64-bit integer
fixed point with 100 units per displayed point. Percentages use basis points
(10,000 = 100%). A formula rounds only where this document says floor,
ceil, or round_half_up.
3. Run And Market State Machine
Contract_created
-> Market_open
-> battle_offer_committed
-> countdown
-> resolving
-> outcome_locked
-> diagnosis
-> reward_or_failure_applied
-> next_Market | boss_Muster | Contract_return_to_Guild
The Market snapshot contains three Recruit offers, four equipment offers, and three battle offers. Offer generation, prices, locks, and refreshes are owned by the economy authority. This document owns these system rules:
- leaving and reopening a Market preserves all offer IDs and generated values;
- buying removes exactly that offer and never silently fills the empty slot;
- locked unbought offers persist to the next Market as declared;
- equipment, order, promotion, and dismissal are legal only while Market is open or during boss Muster;
- battle commit stores an immutable deployed lineup, inventory ownership, effective-stat snapshot, enemy lineup, seed, risk, and result rules;
- no Market edit after commit can affect that encounter;
- result inspection never applies or skips a reward operation.
4. Generated Recruit Contract
4.1 Generation
Recruit generation uses labeled deterministic streams so a name draw cannot change attributes or Trait:
recruit_name, recruit_appearance, recruit_profession,
recruit_attributes, recruit_trait
For offer level L from 1 through 10:
attribute_budget(L) = 30 + 5*L
attribute_floor(L) = 3 + L
attribute_cap(L) = 12 + 3*L
Might + Finesse + Insight + Vigor + Resolve equals the exact budget. Every
attribute stays within floor/cap. The generator first assigns the floor to all
five, then distributes the remaining points one at a time by the labeled stream
without exceeding cap. Because totals are equal at a level, no Recruit is
strictly superior only because its random total is larger.
Every Recruit row stores its inputs and output hash. Generated name components and modular visual parts create identity and readable variation but no hidden mechanical modifier.
4.2 Trait
Each Recruit receives exactly one of 36 authored Traits. A Trait row has one visible benefit and one visible cost, both mechanical. It cannot be removed, stacked, upgraded, rerolled, or suppressed by changing language or appearance.
A Trait is invalid if its cost never changes a decision in either of its two fixed fixtures, or if its benefit is only a larger unconditional value. Trait tags may participate in hidden-hybrid eligibility only when that condition is shown after discovery.
4.3 Survival History
The persistent Recruit records battles entered, victories, retreats survived, allies ahead at commit, first knocked-out ally witnessed, promotion, knockout events and final dismissal if any. History may unlock a title or catalog fact but cannot grant a hidden stat. Contract close adds an immutable summary Record without making that Recruit unplayable or replacing its stable ID.
5. Profession Catalog And Promotion
The fixed catalog contains 12 base, 24 regular advanced, and 6 hidden hybrid Professions. Content owns identities and instances; this document owns schema and topology.
5.1 Topology
- Every base Profession has exactly two regular advanced descendants.
- Every regular advanced Profession has exactly one parent base.
- Every hidden hybrid declares exactly two compatible base-family IDs and an original battlefield responsibility distinct from both parents.
- A Recruit has exactly one current Profession. Equipment never changes the stored Profession ID.
- A Recruit's origin base is immutable even after promotion.
5.2 Promotion
A base Recruit becomes eligible after reaching level 4 and surviving three completed battles. Promotion is one-way and can happen once. The Market review shows new action rules, lost rules, target/reach changes, resource loop, price or opportunity cost, and the two validation fixtures before confirm.
The two regular descendants are always deterministic choices once eligible. A hidden hybrid appears as an additional choice only when its revealed catalog predicate is satisfied. Allowed predicate inputs are origin base, Trait tags, equipped behavior tags, current Artifact tags, adjacent deployed Profession families, and cleared Contract facts. A predicate cannot read generated name, appearance, playtime, wall clock, or social state.
Promotion preserves that Recruit's individual level and XP, HP percentage outside battle, Trait, equipped item, survival history, and recruit ID. It replaces current Profession, action table, resource meter, and derived Profession bases atomically. It is not a free job switch or reversible respec.
5.3 Automatic Action Unlocks
A Profession action kit unlocks by that Recruit's individual level. Levels are
bounded to 1..10; there is no Company level and another Recruit's XP cannot
unlock these rules:
| Recruit level | Available automatic rules |
|---|---|
| 1 | basic action, resource rule, identity passive |
| 2 | first technique and its priority row |
| 3 | second technique and its priority row |
| 4 | signature and its priority row; promotion becomes possible after the survival requirement |
Promoting replaces the action kit with the promoted Profession's level-valid kit. A direct regular-advanced hire uses the same level schedule. Falling below an unlock level is impossible, and equipment cannot unlock a later action early. Every unlocked action is automatic; the player prepares through hire, equipment, deployment, and order rather than selecting it during battle.
5.4 Profession Row
profession_id, tier (base | regular_advanced | hidden_hybrid)
parent_base_ids, unlock/promotion predicate
battlefield responsibility, preferred depth, failure mode, counter tags
base HP, base Tempo, base defenses, resource schema
basic action, two techniques, signature, passives
automatic priority table and target policies
movement/reach/protection/projectile/healing rules
two decision-opposed validation fixtures
presentation and accessibility event requirements
An advanced or hidden Profession must transform target, timing, position, resource flow, protection, or risk ownership. A stronger scalar copy fails.
6. Party-Line Geometry
6.1 Ordered Footprint
Each actor declares footprint 1 or 2. Standard Recruits use footprint 1. An actor with footprint 2 is one unit ID, one HP pool, and one action state occupying a contiguous block.
The authoritative line is an ordered actor sequence with no interior empty
space after normalization. For actor A:
depth(A) = sum(footprint(X) for every living actor X ahead of A)
front_cell(A) = depth(A)
rear_cell(A) = depth(A) + footprint(A) - 1
Allied deployed footprint cannot exceed current Line capacity. Recruits left out of the sequence are Reserve. Order ties and simultaneous insertion use stable actor ID only after all player-visible rules are equal.
6.2 Cross-Line Distance And Same-Line Distance
For opposing source S and target T:
cross_line_distance(S,T) = 1 + depth(S) + depth(T)
For allied actors:
same_line_distance(S,T) =
max(0, max(front_cell(S), front_cell(T)) -
min(rear_cell(S), rear_cell(T)) - 1)
Adjacent footprints therefore have same-line distance zero. Every action declares a maximum cross-line or same-line reach. No visual closeness overrides the integer distance.
6.3 Protection
protection_stacks(T) = min(2, depth(T))
Each occupied footprint ahead contributes one stack up to two. Protection is not a generic defense stat; actions use one declared mode:
| Mode | Rule |
|---|---|
frontbound |
Only targets with depth=0 are candidates |
screened |
Deeper targets may be candidates, but resolved damage is multiplied by max(0.70, 1 - 0.15*protection_stacks) |
intercepted_projectile |
Projectile collides with the first eligible footprint in its current path |
lobbed |
Ignores collision but uses screened damage |
bypass_protection |
Ignores stacks; must be declared in preview and telegraph |
Healing and boons do not gain a hidden bonus from protection. The inspect view shows stacks, contributing actors, target legality, and expected multiplier.
7. Encounter Lifecycle
| Phase | Legal player actions | Commit behavior |
|---|---|---|
| Preview | Inspect enemy order, actions, risk, reward, timeout, retreat | Offer is stable; no spend |
| Prepare | Equip, promote, dismiss, deploy, reorder | Changes remain reversible until battle confirm |
| Countdown | Pause, speed, inspect | Three simulation seconds; lineup locked |
| Resolve | Pause, speed, inspect, retreat | Automatic action events and retreat timestamp journaled |
| Outcome locked | Inspect | Victory, defeat, timeout, or retreat cannot change |
| Diagnose | Inspect causal timeline | No reward applied by viewing/skipping |
| Settle | Choose fixed reward if eligible | One atomic result operation |
| Finalized | Continue to Market/run result | Casualties, equipment return, Coin/Credit, and reward agree |
8. Deterministic Time, Events, And Draws
8.1 Fixed Tick And Priority
One simulation tick is exactly 100 milliseconds. At each tick:
- accept lifecycle control stamped for this tick, including retreat start;
- expire statuses and barriers whose end tick equals this tick;
- resolve periodic status events due this tick;
- complete casts, channels, projectile arrivals, and summon expiries;
- select actions for actors already ready and legal;
- resolve voluntary and forced movement intents;
- apply simultaneous damage, healing, barrier, and resource deltas by batch;
- finalize action-outcome records, mark zero-HP actors Fallen, and run declared outcome/death triggers once;
- compact lines, insert legal summons, and evaluate objective/retreat/phase;
- advance readiness, cooldown, cast, status, timeout, and retreat clocks.
Events in the same numeric batch read one pre-batch state and apply together. An actor alive at batch start completes its already-scheduled event even if the same batch makes it Fallen. A death trigger cannot restore the source above zero HP and cannot recursively produce another death trigger in the same tick. An outcome-triggered derived action is queued no earlier than priority 4 of the next tick; it cannot join or reopen the batch that produced its outcome.
8.2 Labeled Determinism
The encounter root seed supplies independent labels:
target_tie, critical, status_apply, proc_choice,
summon_variant, reward
For a draw:
roll_bp = hash64(root_seed, label, actor_id, action_sequence,
target_id, draw_index) mod 10,000
The event journal records label and draw index. Adding an equipment proc cannot shift target, critical, status, or reward results in another stream. There is no random damage variance or hidden miss chance.
9. Attributes And Derived Statistics
| Attribute | Primary responsibility |
|---|---|
| Might | physical power and Guard contribution |
| Finesse | Tempo, physical precision, and critical pressure |
| Insight | arcane power and status Potency |
| Vigor | maximum HP, Guard, and movement stability |
| Resolve | healing power, Ward, and status Tenacity |
At level L:
PhysicalPower = WeaponPower + 2.00*Might + 0.50*Finesse
ArcanePower = FocusPower + 2.00*Insight + 0.50*Resolve
HealingPower = FocusPower + 1.20*Insight + 1.20*Resolve
MaxHP = ProfessionBaseHP + 8*L + 10*Vigor
Guard = ArmorGuard + 1.20*Vigor + 0.60*Might
Ward = ArmorWard + 1.20*Resolve + 0.60*Insight
Potency = Insight + 0.50*Finesse + FlatPotency
Tenacity = Resolve + 0.50*Vigor + FlatTenacity
Tempo = clamp(ProfessionBaseTempo + 0.40*Finesse + FlatTempo, 20, 100)
Initiative = clamp(ProfessionBaseInitiative + 0.25*Finesse + FlatInitiative,
0, 95)
Derived values round down to 1/100 after the full expression. Profession bases
must stay within BaseHP 140-420, BaseTempo 24-55, and BaseInitiative 0-45
unless a fixed exception fixture is approved. A MaxHP change outside battle
preserves current HP percentage and does not heal.
10. Readiness And Automatic Action Selection
At battle start, Readiness = Initiative. Each tick while an actor can act:
Readiness = min(150, Readiness + Tempo*0.1)
At Readiness >= 100, the actor scans its Profession priority rows from top to
bottom. The first row with a legal action, true visible condition, and legal
target starts. It subtracts 100 Readiness and retains overflow. If none is
legal, readiness remains capped and the actor checks again next tick.
Priority conditions may read only current HP bands, resource, status, casts,
depth, protection, ally/enemy counts, summon space, cooldown, phase, and preview
tags. They cannot read future draws. Every Profession has a legal fallback or
an explicit NO_REACHABLE_TARGET idle result.
| Timing field | Boundary |
|---|---|
| Wind-up | 0.1-1.5 s |
| Major telegraph | at least 1.5 s; first boss use at least 2.5 s |
| Channel/cast | 0.3-4.0 s |
| Recovery | 0-2.0 s |
| Cooldown | 0-30 s |
The automatic table is part of Profession identity. Players compare it but do not script arbitrary condition programs.
11. Target Selection, Reach, And Retarget
An action constructs candidates in this order:
- required side and living/Fallen/summon state;
- cross-line or same-line reach;
- protection mode;
- required status, cast, HP band, or tag;
- exclusion, immunity, and maximum targets;
- target policy.
Core target policies are frontmost, rearmost, lowest_hp_ratio,
highest_power, active_cast, marked, and self. Numeric ties use depth in
the policy's natural direction, then target_tie. The default hostile policy is
frontmost. Enemy-specific score tables must be shown in preview when they can
select something other than the declared policy result.
At action start the target unit ID is reserved. At completion, the action uses one declared invalid-target policy:
retarget_same_policy: rebuild candidates and choose again;fizzle: apply no primary effect and use the stated cooldown refund;ground_resolve: resolve at the stored depth and affect current occupants.
A target moving to another depth remains the same target if still legal. Every retarget or fizzle logs the first rejecting filter.
11.1 Forecast Is Not Resolution
A forecast is a diagnostic prediction made from the committed preview or the state at automatic action selection. It stores predicted target IDs, depth, timing, and the rules that could change them. It never reserves a target and never fires a battle trigger.
At action start, target selection creates the authoritative reservation. If its
target differs from forecast because an earlier action, movement, collapse, or
status changed state, the journal records FORECAST_DIVERGED with the first
changed input. That is not a hit, miss, dodge, resistance, or action outcome.
The reserved action then resolves normally.
Likewise, if a reserved target moves before completion but remains targetable
and inside all declared reach/protection filters, the action follows the same
unit ID. Its terminal component outcome can be AO_APPLIED; the detail reason
is TARGET_MOVED_STILL_LEGAL. Movement alone never creates an avoidance roll.
11.2 Terminal Outcome IDs
Every started action produces one or more terminal outcome records. Records are per effect component and actual recipient; routing/invalidity records can name the intended target, and action-level cancellation records have no recipient. An area or multi-component action can therefore produce mixed outcomes without collapsing them into an invented accuracy value.
| Outcome ID | Exact precondition | Ordering point | Player-visible causal label |
|---|---|---|---|
AO_APPLIED |
Legal component changes HP, barrier, status, resource, order, or another declared authoritative field on its actual recipient | Finalized after priority-7 deltas | Applied; use Followed target detail for TARGET_MOVED_STILL_LEGAL |
AO_NO_CHANGE |
Component reaches a legal recipient but caps/current state yield zero primary change | Finalized after priority-7 deltas | No change plus cap/current-state reason |
AO_INVALID_REACH |
Reserved target is living/targetable but current reach or protection filter is illegal | Completion validation at priority 4 | Out of reach plus old/current depth and required reach |
AO_INVALID_UNTARGETABLE |
Reserved target is living but a declared Untargetable rule excludes it | Completion validation at priority 4 | Untargetable plus rule ID and remaining duration |
AO_INVALID_FALLEN |
Reserved target is absent from the living line because it became Fallen before completion | Completion validation at priority 4 | Target already Fallen plus death event ID |
AO_INVALID_FILTER |
Reserved target fails another declared side/state/tag candidate filter after the three specific invalid checks | Completion validation at priority 4 | Target no longer eligible plus filter ID |
AO_INTERCEPTED |
Current projectile/protection path deterministically redirects the intended target's component to an eligible interceptor | Routing after target validation at priority 4 | Intercepted by {actor} plus path/protection rule ID |
AO_BLOCKED |
An explicit Block charge or named deterministic component blocker nullifies the component before its primary delta | Defense allocation at priority 4; charge/delta commits in priority 7 | Blocked plus blocker actor/rule ID |
AO_IMMUNE |
A declared immunity tag fully rejects the component before any resistance draw | Component defense at priority 4 | Immune plus immunity tag/source ID |
AO_RESISTED |
A resistible status component is not immune and its stored status_apply roll is at/above ApplyChanceBp |
Component defense at priority 4 | Resisted plus roll, threshold, Potency, and Tenacity |
AO_FIZZLED |
Invalid-target policy is fizzle, retarget finds no legal candidate, or ground resolution has no eligible occupant |
After invalid-target policy at priority 4 | Action fizzled plus invalid outcome/filter and refund |
AO_INTERRUPTED |
A started wind-up/channel is cancelled by a declared interrupt before completion | When interrupt commits at priority 4 | Interrupted plus interrupter/rule and refund |
AO_BLOCKED is not generic zero damage: barrier absorption is AO_APPLIED
because barrier state changes. AO_IMMUNE requires a named immunity. A legal
heal into full HP is AO_NO_CHANGE, not resistance. AO_RESISTED is limited to
the existing deterministic status-application check and never implies an
accuracy/evasion stat or a general attack miss.
An action summary is derived only for display:
APPLIED_ALL = every primary component record is AO_APPLIED
APPLIED_PARTIAL = at least one primary component is AO_APPLIED and at least one is not
APPLIED_NONE = no primary component is AO_APPLIED
Summary values are not trigger IDs. The terminal records remain authoritative.
11.3 Resolution And Routing Order
At priority 4, each completing action uses this order:
- If a committed interrupt already cancelled the action, emit one
AO_INTERRUPTEDaction record and stop. - Revalidate each reserved target against current state in this first-failure
order: Fallen/absent, Untargetable, other declared candidate filter, then
reach/protection. Emit the corresponding
AO_INVALID_*reservation record. - Apply the skill's declared invalid-target policy. A successful
retarget_same_policyreserves a new target and continues without refund;ground_resolvesnapshots eligible current occupants at the stored depth; otherwise emitAO_FIZZLEDand stop that action. - Resolve current projectile/protection paths. Emit
AO_INTERCEPTEDfor each redirected intended target, then create component records for the actual interceptor. Interception itself never counts as an applied component. - Expand components and area recipients in current depth then stable-ID order. A footprint-2 actor is expanded once unless the skill explicitly says once per footprint.
- Allocate finite Block charges and deterministic blockers. Same-tick claims
use completion tick, target depth, source stable ID, then action sequence; one
charge cannot block two components. Emit
AO_BLOCKEDfor each allocation. - Check declared immunity before consuming a resistance or critical draw. Emit
AO_IMMUNEon rejection. - For remaining resistible status components, consume and record exactly one
status_applydraw. EmitAO_RESISTEDwhen the roll fails the threshold. - Queue remaining numeric/status/movement deltas for priority 7. After the
simultaneous batch, emit
AO_APPLIEDwhen primary state changed orAO_NO_CHANGEwhen it did not. - At priority 8, derive the action summary, apply at most one declared refund, claim outcome triggers, log suppressed duplicates, and queue derived actions for the next tick.
An invalid reservation record remains terminal evidence even when retarget or ground resolution continues. The redirected/new recipient receives its own terminal component record, so diagnosis can say both why the original target was not affected and what actually happened.
11.4 Journal, Refund, And Proc Contract
Every outcome record stores:
root_action_id, action_instance_id, action_sequence, skill_id, source_id
selection_tick, completion_tick, effect_component_id, component_tags
forecast_target_ids, reserved_target_id, reserved_depth
actual_recipient_id, current_depth, outcome_id, reason_id
retarget_policy, resolution_disposition, redirected_action_or_component_id
interceptor_id, blocker_id, immunity_tag as applicable
roll_label, draw_index, roll_bp, threshold_bp as applicable
raw_delta, effective_delta, barrier_delta, status_or_movement_delta
resource_spent, cooldown_committed, refund_resource, refund_cooldown_ticks
trigger_claim_keys, fired_trigger_ids, suppressed_trigger_ids
parent_action_id, derived_depth
Resource cost, Readiness, and cooldown are committed when the action starts. Default refund/proc behavior is:
| Outcome/disposition | Default refund | Primary effect procs |
|---|---|---|
| Invalid record followed by successful retarget/ground resolution | none | evaluate only the new actual recipient's component outcomes |
AO_FIZZLED |
skill's declared fizzle_resource_refund_bp and fizzle_cooldown_refund_bp |
no on-hit/on-damage/on-heal/on-status proc |
AO_INTERRUPTED |
skill's declared interrupt refund fields | on_interrupt and matching on_outcome only |
AO_INTERCEPTED |
none | intended target can observe AO_INTERCEPTED; primary procs evaluate on actual recipient only |
AO_BLOCKED, AO_IMMUNE, AO_RESISTED |
none unless exact ID appears in refund_on_outcome_ids |
matching defensive hook and on_outcome only; no primary effect proc |
AO_NO_CHANGE |
none | on_outcome only; no effective-delta proc |
AO_APPLIED |
none | only hooks whose required effective delta/status/movement actually occurred |
An outcome refund is evaluated once per root action after every component record
is final. The skill declares refund_match = all_primary | any_primary; default
is all_primary. Refund totals clamp to the originally committed cost/cooldown
and never multiply by targets, components, or repeated outcome records.
Outcome triggers use:
trigger_id, observed_role (source | intended_target | actual_recipient)
outcome_ids[], component_tags[], once_scope (action | recipient | component)
allow_derived (default false), resulting_action_or_hook
Default once_scope is action. Before firing, create:
trigger_claim_key = hash(root_action_id, trigger_id,
scope_recipient_or_component)
The first claim fires in outcome-record order; later identical claims log
DUPLICATE_TRIGGER_CLAIM and do nothing. Derived actions keep the same
root_action_id, increment derived_depth, and cannot trigger a row with
allow_derived=false. No derived chain can exceed depth 4 or the hook's declared
per-action cap.
12. Projectile And Area Resolution
A projectile declares speed in footprints per second, collision mode, pierce count, and damage retention. At launch:
arrival_ticks = max(1, ceil(cross_line_distance / projectile_speed / 0.1))
At arrival, an intercepted projectile traverses the current opposing order
from front to its reserved target and collides with the first eligible actor.
After each pierced actor, remaining damage is multiplied by the declared
retention in 0.50-0.90. A reserved target that moved behind a new protector
can therefore be intercepted. Lobbed and bypassing projectiles follow their
declared protection mode instead.
Areas are contiguous footprint intervals, not visual circles. An area row declares start policy, length, falloff, and whether a footprint-2 actor is hit once or once per footprint; default is once per actor.
13. Healing, Support, And Protection Access
Support actions use same-line distance. Default heal selection is lowest HP
ratio among legal allies; exact ratio ties choose the frontmost, then
target_tie. A heal cannot pass its declared same-line reach because the
animation appears to span the line.
Barrier applies after healing in the same batch and is capped at 40% of target
MaxHP across all generic barriers. Excess is logged as waste. Block is an
explicit charge that nullifies one eligible hit after interception and before
barrier. Area, true, or unblockable events must declare ineligibility.
Protection stacks do not redirect heals. A support Profession may explicitly
target nearest_ally_ahead, nearest_ally_behind, or a contiguous interval;
the predicted support path updates when order changes.
14. Movement, Push, Pull, And Summons
14.1 Reordering Actions
Battle movement is an automatic action, never free dragging:
advance: swap the actor block with the adjacent actor block ahead;withdraw: swap with the adjacent actor block behind;push N: move the target toward rear through up toNadjacent block swaps;pull N: move the target toward front through up toNswaps;insert: add a legal summon before/after its source;return: remove a temporary summon or restore an explicitly stored order.
Footprint-2 actors move as indivisible blocks. Simultaneous conflicting intents
resolve larger declared movement priority first, then higher source Potency,
then stable source ID. Losing intents fail with DESTINATION_RESERVED.
Forced movement stops before an Immovable actor. Each unresolved forced step
at a line boundary or blocker deals:
collision_damage = max(1, floor(0.08 * source_PhysicalPower))
once per action, not once per blocked step. Rooted blocks voluntary movement;
Immovable blocks forced movement. Rejections name ROOTED, IMMOVABLE,
NO_ADJACENT_ACTOR, DESTINATION_RESERVED, or CAST_LOCKED.
14.2 Summon Footprint
Each side has temporary summon allowance of two footprint beyond its committed deployment. A summon declares footprint 1 or 2 and insertion side relative to its source. It is legal only when:
current_living_footprint + summon_footprint
<= committed_deployment_footprint + 2
A failed insertion spends no summon resource and returns NO_SUMMON_SPACE.
Summons never enter Reserve, hold equipment, create Replacement Credit, count
as cumulative hires, or persist after battle.
14.3 Death Collapse
After every death batch, Fallen actors are removed and both lines compact while
preserving the relative order of survivors. New depths become authoritative
before summon insertion and objective checks at priority 9. A scheduled action
that reserved a Fallen target follows its retarget policy; it does not target
the actor that happened to collapse into the old depth unless it uses
ground_resolve.
Reserve Recruits never fill a collapsed position during battle. At the next Market the player explicitly chooses any replacement and new order.
15. Damage, Critical, Healing, And Floors
15.1 Damage
Skills declare Base, Coefficient, PowerSource, type, pierce, protection
mode, and whether critical is legal.
RawDamage = max(0, Base + Coefficient * selected_power)
EffectiveDefense = clamp(relevant_defense - pierce, -75, 500)
if EffectiveDefense >= 0:
DefenseMultiplier = 100 / (100 + EffectiveDefense)
else:
DefenseMultiplier = 2 - 100 / (100 - EffectiveDefense)
CritChanceBp = clamp(skill_base_crit_bp
+ 20*(source_Finesse - target_Resolve)
+ explicit_crit_bp,
0, 5000)
crit = can_crit and critical_roll_bp < CritChanceBp
CritMultiplier = clamp(declared_crit_multiplier, 1.25, 2.00) if crit else 1.00
OutgoingGroup = clamp(1 + sum(outgoing_modifiers), 0.25, 3.00)
IncomingGroup = clamp(1 + sum(incoming_modifiers), 0.25, 3.00)
EncounterGroup = clamp(1 + sum(encounter_modifiers), 0.25, 3.00)
GroupProduct = clamp(OutgoingGroup * IncomingGroup * EncounterGroup, 0.10, 4.00)
Mitigated = RawDamage * DefenseMultiplier * CritMultiplier * GroupProduct
Screened = Mitigated * max(0.70, 1 - 0.15*protection_stacks)
DamageFloor = ceil(0.04 * RawDamage)
FinalDamage = 0 if explicit_nullification else
max(1, DamageFloor, floor(Screened))
HPDamage = max(0, FinalDamage - barrier_absorbed)
Use Screened=Mitigated for non-screened modes. Guard defends physical, Ward
defends arcane, and true damage uses zero defense, cannot critical, ignores
screening, and is capped at 25% target MaxHP per non-boss event. Barrier absorbs
after the floor; an explicit nullification can produce zero. No other ordinary
reduction bypasses the four-percent floor.
Fixed boundary: RawDamage=125, defense 500, GroupProduct 0.10, no critical,
and no screening yields 2.083... before the floor. DamageFloor=5, so the
resolved damage is 5 before barrier. Explicit nullification yields zero.
15.2 Healing
RawHeal = max(0, Base + Coefficient * HealingPower)
FinalHeal = floor(RawHeal * OutgoingHealGroup * ReceivedHealGroup)
EffectiveHeal = min(FinalHeal, MaxHP - current_HP)
Healing does not critical unless the skill declares a visible healing-critical rule. Overheal has no effect unless one named hook converts it; conversion is capped at 50% of overheal and still respects the barrier cap.
16. Status Effects And Resolution Order
Each status declares:
status_id, category, source_id, target_id
base_chance_bp, potency_source, resist_stat
duration_ticks, interval_ticks, max_stacks
stack_rule (add | refresh | replace | independent)
dispel/immunity tags, on_apply, on_tick, on_expire
presentation and causal-report events
For a resistible status:
ApplyChanceBp = clamp(BaseChanceBp + 25*(Potency - Tenacity), 500, 9500)
applies = status_apply_roll_bp < ApplyChanceBp
Guaranteed effects bypass the roll but not declared immunity. If simultaneous
effects apply the same status, resolve replace, then add, then refresh,
then independent instances by source ID. Expiry occurs before periodic ticks,
so a status with end_tick == current_tick does not tick again.
Hard control effective duration is:
duration = clamp(BaseDuration * 100/(100 + Tenacity), 0.2, 3.0)
After hard control ends, the actor gains four seconds of Control Guard, reducing new hard-control duration by 75%. No actor may be unable to act for more than 50% of any rolling ten-second window. Boss caps and immunities are previewed.
17. Equipment, Artifacts, And Hooks
Each Recruit has exactly one universal active equipment slot. An item may be
presented as armament, guard, garb, charm, or kit, but those forms describe
eligibility, attachment and visual language rather than simultaneous body
slots. A Recruit therefore owns zero or one equipped_item_id.
Equipping a candidate is one atomic replacement: the candidate leaves run inventory, the previous item returns to inventory if present, and the Recruit's single slot points to the candidate. An Artifact is a shared run rule and never occupies this slot. An item may react to an allied Recruit's item event, but no effect may require its wearer to hold a second item.
All 320 equipment rows must alter a decision and declare one named hook. Scalar budget may support the hook but cannot be the row's only identity. One item ID cannot be owned by two Recruits. Company-unique effects declare a unique group; later copies retain local behavior but show the shared portion dormant.
Artifacts are shared run rules. A run holds at most three active Artifacts. A fourth acquisition requires replacing one or declining the new row after an exact before/after preview. All 60 must change formation, targeting, market, risk, resource, promotion, summon, or reward valuation and must name a conflict.
Legal battle hooks are:
before_target, after_target, before_cast, on_cast_complete, on_interrupt,
before_damage, after_damage, on_critical, before_heal, after_heal,
on_barrier_break, on_status_apply, on_status_expire,
on_advance, on_withdraw, on_push, on_pull, on_protection_change,
on_resource_gain, on_signature, on_summon, on_fallen, after_collapse
Each hook has a trigger limit, minimum 0.5-second cooldown unless a fixed loop proof allows otherwise, and recursion declaration. Derived events cannot retrigger their source by default.
18. Death, Dismissal, And Replacement
18.1 Battle Death
At zero HP, a non-summon Recruit becomes Fallen:
- it cannot act, target, protect, receive healing, or be promoted;
- its death trigger resolves once at priority 8;
- it is removed for line collapse;
- no timer, item, Profession, Artifact, difficulty rule, or Reserve state can respawn, resurrect, or substitute for it during the encounter;
- its recruit ID and optional equipped item ID enter the pending outcome casualty set;
- it remains visible in diagnosis with the preceding five seconds of causes.
At outcome application, each casualty and all returned equipment commit with Replacement Credit as one transaction. Victory, defeat, timeout, and retreat do not change the permanence of already Fallen Recruits.
18.2 Dismissal
Dismissal is a Market-only operation. It is illegal for a deployed Recruit in a committed battle, a Fallen Recruit awaiting outcome, or a Recruit referenced by a pending promotion. It also uses the product authority's canonical count:
live_recruit_count = count(unique Recruit IDs owned by the current run
whose state is living,
across deployed party and Reserve)
dismissal_legal = Market_open and target_is_living and
live_recruit_count >= 2
The preview and commit independently evaluate dismissal_legal. Review shows
equipment return, rebate, lost level/history, and resulting deployable
footprint. A legal confirm removes the Recruit once and asserts the post-state
has live_recruit_count >= 1.
If the count is one, or a once-valid preview becomes stale after another
serialized operation leaves one living Recruit, reject FINAL_LIVE_RECRUIT.
The rejection removes no Recruit or equipment, grants no Coin or Replacement
Credit, changes no counters, and creates no protected recovery offer. Repeated
confirm returns the same rejection. An interrupted pending dismissal must
revalidate the active count before it can apply and is rejected without mutation
when that count is one.
Dismissal never creates Replacement Credit or a Meta reward. Explicit run abandonment is a distinct Market/result transaction, and casualty-driven replacement/Company collapse remains exclusive to casualty settlement.
18.3 Replacement
Replacement is an ordinary hire using Coin and eligible Replacement Credit. After a casualty, the next Market protects one base-Profession recovery offer from refresh until bought or explicitly declined. Reserve never fills the line automatically. A run closes only when the player cannot legally deploy one living Recruit after all available recovery purchases or explicitly abandons. A blocked final dismissal never creates or refreshes this offer and never invokes the casualty recovery predicate.
19. Battle Control, Retreat, Timeout, And Outcome
Pause, 1x, 2x, and 4x affect presentation only. Inspection while paused can open actor state, target reasoning, current action, queued major event, line depths, protection, status order, and causal log.
Retreat becomes legal at tick 50 (5.0 seconds). Confirm begins a 20-tick global withdrawal. Automatic actions continue and Recruits can fall during it. At the end of the 20th tick, living allied non-summon actors escape and outcome becomes retreat. Repeating retreat confirm returns the same command receipt.
At 120 seconds, Overtime begins:
for each completed 10-second Overtime band:
all damage dealt multiplier += 0.25
all healing and new barrier multiplier -= 0.20
damage bonus caps at +0.75; healing/barrier penalty caps at -0.60
At tick 1500, if the objective is not satisfied, the result is timeout defeat. Living Recruits survive; Fallen Recruits remain lost. Timeout grants no battle reward and applies the failure transaction in the save authority.
Victory is evaluated after simultaneous damage, death, collapse, and summon events. If both victory and all-allied-Fallen predicates become true in the same batch, the declared objective decides: elimination objectives are a mutual defeat; survival/objective-complete battles are victory with zero living deployed Recruits and can close the run if no Reserve remains.
20. Enemy And Battle-Offer Contract
Every ordinary/elite enemy and boss row declares:
enemy_id, ordinary | elite | boss, Region/Contract placement
footprint, preferred depth, movement rules
basic/technique/signature actions and automatic priority
target/protection/reach/projectile/heal/summon rules
first-major-action window and telegraph
phase predicates, immunities, counter tags, two rational responses
interaction with at least two older mechanics
first-failure contribution and fixed fixtures
Before commitment, a battle offer shows exact enemy order and footprint, target policies, protection bypass, earliest major windows, movement, summon allowance, resistances, objective, timeout, retreat consequence, Coin reward, and reward family. A hidden visual identity may remain concealed for discovery; a mechanic needed for a fair choice may not.
The complete envelope is 100 ordinary/elite identities plus 16 bosses across 8 Regions. Presentation variants do not count toward those totals.
21. Causal Diagnosis
The result report presents, in order:
- committed allied and enemy order;
- predicted and actual first targets;
- first divergence from predicted action/target/timing;
- first protection change, projectile interception, or reach failure;
- first decisive major action and available pre-battle counter categories;
- every Fallen Recruit with the preceding five simulation seconds;
- collapse, displacement, summon-space, retarget, and proc-suppression events;
- effective damage, prevention, healing, control, and resource totals;
- reward/failure/casualty operation IDs in technical details.
The report can compare one alternate order or equipment removal against the same seed in a no-reward rehearsal. It may explain categories but cannot auto-equip a supposed universal answer.
22. Content Schemas
22.1 Skill Row
skill_id, owner_profession_id, tags, timing
candidate filters, target policy, protection mode, retarget policy
invalid-target outcome mapping, fizzle/interrupt refund fields
reach, projectile/area/movement/summon fields
Base, Coefficient, PowerSource, type, pierce, critical rule
resource cost/gain, cooldown, status rows, proc hooks
refund_on_outcome_ids, refund_match
outcome triggers (trigger_id, observed_role, AO_* outcome_ids,
component_tags, once_scope, allow_derived, resulting action/hook)
automatic priority condition, illegal reasons, causal labels
animation/VFX/SFX/caption/reduced-motion requirements
fixed input and expected event output
22.2 Equipment Row
equipment_id, form, acquisition band, list-price inputs
eligible Profession/action tags
changed decision and named behavior hook
stat support budget, trigger, cooldown, recursion
order/target/timing/resource/risk tradeoff
two interaction fixtures and one loss/comparison fixture
presentation/accessibility/localization needs
22.3 Artifact Row
artifact_id, unlock/offer placement, shared hook
run rule changed, conflict group, replacement comparison
Market/battle/risk inputs and outputs
two builds whose valuation changes in opposite directions
fixed seed fixture and causal event
22.4 Battle Offer Row
battle_offer_id, Region, Contract, Round, risk tier
enemy lineup/order/levels, seed labels, objective
preview fields, Coin reward, reward family, retreat/failure receipt
expected duration, profile assertion, causal-report requirements
23. Static Validation Gates
- all Profession topology counts and parent links reconcile to 42;
- all 36 Traits have one benefit, one cost, and two decision fixtures;
- all 320 equipment and 60 Artifact rows name a behavior change;
- all 100 ordinary/elite and 16 boss rows create a distinct counter question;
- no deployed footprint exceeds current Line capacity;
- target preview equals the first simulated target for fixed fixtures;
- identical state/seed/retreat inputs yield identical hashes at every tick;
- all actions stay inside reach, critical, defense, barrier, control, proc, and timeout bounds;
- every projectile and movement conflict produces the declared collision/order;
- every death returns the exact owned equipment once and never introduces a Reserve automatically;
- invalid actions spend no resource and return one enumerated reason;
- every started action/component has a declared terminal
AO_*record and every outcome trigger references only IDs in Section 11.2; - duplicate trigger claims are journaled and cannot fire twice;
- all standard fixtures resolve or timeout at/before tick 1500.
24. Required Fixed Test Vectors
| Vector | Setup | Expected result |
|---|---|---|
| Frontbound | Three enemies; target policy frontmost | Only depth-zero enemy is a candidate |
| Screened rear | Target has two footprint ahead | Legal screened hit uses 0.70 multiplier |
| Cross-line reach | source depth 1, target depth 2, reach 4 | distance 1+1+2=4, legal; reach 3 is illegal |
| Heal tie | Two allies at equal HP ratio in reach | Frontmost wins, then deterministic tie draw |
| Projectile intercept | Reserved rear target gains a new front summon before arrival | Current front summon is hit unless bypass/lobbed |
| Push footprint | Push a footprint-2 target one step | Whole block swaps; it never splits |
| Blocked push | Forced move has two remaining steps at boundary | One collision event, not two |
| Summon full | committed footprint 10 plus temporary footprint 2 | another footprint-1 summon fails NO_SUMMON_SPACE |
| Simultaneous lethal | Two actors complete lethal actions in one batch | Both events apply, both actors become Fallen |
| Death collapse | Front actor falls before a reserved cast completes | Survivors compact; cast follows its declared retarget rule |
| Reserve behavior | Deployed actor falls while living Reserve exists | Reserve does not enter until next Market preparation |
| Damage floor | Raw 125, defense 500, group product 0.10 | damage 5 before barrier; explicit nullification 0 |
| Critical boundary | roll 2499 with chance 2500 bp | critical; roll 2500 is not |
| Status expiry | periodic tick equals end tick | expiry occurs; no final periodic tick |
| Retreat | confirm at tick 50, no terminal predicate | outcome retreat after tick 70 batch; later duplicate has no effect |
| Speed parity | identical battle at 1x and 4x | all authoritative hashes equal |
| Timeout | objective incomplete at tick 1200/1500 | Overtime applies, then timeout defeat at tick 1500 |
| Casualty equipment | Fallen Recruit owns one item | Recruit removed and that item ID returned exactly once; null slot returns nothing |
| Final dismissal | one living Recruit across deployed plus Reserve | preview/commit reject FINAL_LIVE_RECRUIT; no state or recovery-offer change |
| Moved target remains legal | Reserved target changes depth but remains targetable and in reach | same ID receives AO_APPLIED; detail TARGET_MOVED_STILL_LEGAL; no refund |
| Moved target leaves reach | Reserved target moves from distance 2 to 3 against reach 2; policy fizzle |
AO_INVALID_REACH then AO_FIZZLED; declared fizzle refund once |
| Target becomes Untargetable | Living reserved target gains declared Untargetable before completion | AO_INVALID_UNTARGETABLE; row retarget/fizzle policy applies; no resistance draw |
| Target falls first | Reserved target becomes Fallen in an earlier tick | AO_INVALID_FALLEN names death event; collapsed-depth actor is not substituted |
| Interception | New front protector intercepts projectile aimed at legal rear target | intended target AO_INTERCEPTED; protector gets its own component outcome |
| Explicit Block | Actual recipient owns one eligible Block charge | AO_BLOCKED; one charge consumed; no primary proc or default refund |
| Immunity | Status target has matching immunity tag | AO_IMMUNE; no status_apply draw and no status proc |
| Resistance | No immunity; stored roll 7000, threshold 6500 | AO_RESISTED with roll/threshold; no general attack miss |
| Mixed area | Three recipients: one changed, one immune, one already capped | AO_APPLIED, AO_IMMUNE, AO_NO_CHANGE; summary APPLIED_PARTIAL |
| Duplicate trigger suppression | Mixed area yields three matching records for one once-per-action trigger | first claim fires; later claims log DUPLICATE_TRIGGER_CLAIM; one derived action next tick |
25. Acceptance Checklist
- One ordered line owns protection, reach, projectiles, healing, movement, summon footprint, death collapse, and replacement behavior.
- Battle formulas define tick order, random labels, damage floor, critical, status order, timeout, and fixed vectors.
- Deterministic outcomes distinguish forecast divergence, target invalidation, interception, Block, immunity, resistance, application, and duplicate trigger suppression without accuracy/evasion.
- Generated Recruit and fixed Profession schemas are complete without requiring authored individual narrative content.
- Fully automatic combat exposes only the approved diagnostic controls and retreat.
- Content counts and no-filler tests match the product authority.
- Save/failure owns durable death and operation recovery; economy owns all purchase, reward, capacity, and pacing numbers.
Aetherbound Guild: Economy And Balance Authority
Authority: Market offers, prices, locks, refreshes, Coin and Replacement Credit, rewards, progression rates, Line-capacity selection, difficulty parameters, first-clear pacing, solvency, recovery, and anti-dominance tests.
Revision: anti-dominance-fixture-r1 / 2026-08-11
01_GAME_DESIGN.md owns the player promise and content envelope. 02_GAMEPLAY_AND_BALANCE.md owns battle and content schemas. 02_GAMEPLAY_AND_BALANCE.md owns exactly-once application, run failure, interruption, and recovery.
1. Economy Invariants
- All gameplay value is earned in play. There is no paid currency, paid reroll, ad reward, energy, streak, offline income, or real-time wait.
- Coin and Replacement Credit exist only in the current run. Renown and progression facts persist, but cannot buy raw combat stats, starting Coin, or starting Line capacity.
- Every Market contains one steady battle offer. A random offer or refresh is never required to obtain a baseline counter for a mandatory boss.
- Death is costly through lost level, Profession, Trait, history, and order, but returned equipment and Credit make ordinary replacement recoverable.
- Dismissal, selling, refresh, lock, reward, and purchase formulas cannot create Coin-positive loops.
- All 320 equipment and 60 Artifact rows change a decision. Economy tiers and prices may not turn a scalar variant into a gameplay identity.
- Reward, Market, Recruit-generation, and combat random streams are separated. Reload, speed, input repeat, and unrelated draws do not change offers.
- The Standard first clear is solvent on deterministic steady offers without Meta power, random high-tier equipment, or repeated failed-run farming.
2. Resource Ledger
| ID | Player name | Persistence/cap | Sources | Sinks or closure |
|---|---|---|---|---|
coin |
Coin | Current run; nonnegative; no hard cap | Run start, battle rewards, reward cards, equipment sales, dismissal rebate | Recruit/equipment purchase, refresh, lock; cleared when run closes |
replacement_credit |
Replacement Credit | Current run; cap 54 | Fallen non-summon Recruits | Optional reduction on a later Recruit hire; cleared when run closes |
xp |
Experience | Current Recruit; level cap 10 | Completed battles entered by that Recruit | Level thresholds; disappears with Recruit/run close |
renown |
Renown | Guild; cap 9,999 | first Contract clears, first discoveries, mastery goals, limited repeat objective | Catalog breadth, previews, challenge laws, hidden-hybrid discovery clues |
clear_fact |
Region/Contract clear | Guild fact, not spendable | first valid boss result | Region order, ending, postgame access |
discovery_fact |
Catalog discovery | Guild fact, not spendable | first valid inspection/acquisition/encounter | Collection, deterministic future pool access, completion |
There is no material or crafting currency in the base contract. Equipment is bought, rewarded, equipped, returned after death, sold, or closed with the run. Adding a persistent resource requires an Owner-approved contract revision.
3. Run Opening And Capacity Economy
A run begins with:
- two of four provisional generated Recruits selected at zero Coin price;
52 Coin;- zero Replacement Credit;
- Line capacity four;
- exactly one starting item on each provisional Recruit and no extra equipped slots;
- no active Artifact.
The first Market contains at least two base-Profession Recruit offers at level
- The two together cost 28 Coin, leaving 24 for an equipment, lock, refresh, or reserve decision.
For C cleared ordinary Rounds in 0..12:
line_capacity(C) = min(10, 4 + floor(C/2))
Capacity therefore becomes 4,5,6,7,8,9,10 at clear counts
0,2,4,6,8,10,12. It is granted automatically after result settlement, is
not sold, and resets next run. Purchases and cumulative hires do not change it.
4. Market Board And Offer Generation
Every ordinary Market contains:
| Row | Slots | Generation constraint |
|---|---|---|
| Recruit | 3 | At least one base Profession; after a casualty, one protected recovery offer |
| Equipment | 4 | At least three different behavior tags and two legal current users unless Company is empty |
| Battle | 3 | Exactly one steady offer and two distinct higher-risk or different-counter offers |
Boss Muster uses the same Recruit/equipment counts but one fixed boss offer. It cannot refresh or replace the boss.
Each Market is generated from:
hash(run_seed, contract_id, Market_index, row_id, slot_index, refresh_index)
Labeled substreams are recruit, equipment, battle, and reward. An offer
stores its complete generated fields and hash before presentation. Reopening,
changing language, inspecting another screen, or closing the application does
not redraw it.
4.1 Offer Level And Pool
For ordinary Round R in 1..12:
offer_level(R) = min(10, 1 + floor((R-1)/3))
Boss Muster uses the Round-12 offer level. Base Professions remain in every pool. Regular advanced direct hires may appear from Round 7 after their catalog unlock. Hidden hybrids are promotion outcomes and cannot be bought directly.
Equipment uses Region band B in 0..7 and item tier T in 0..3. At least
one tier-0/1 legal item remains possible in every ordinary Market. A boss
counter has one deterministic Region objective or fixed Muster offer; it is
never refresh-gated.
4.2 Lock
The player may lock at most three unbought Recruit/equipment offers. Each newly
locked offer costs 2 Coin once and persists through the next Market or until
bought/declined. Unlocking does not refund Coin. Battle offers can be locked
only within the current Market so the player can refresh other rows; they never
carry beyond a committed battle.
The protected recovery offer needs no paid lock, survives refresh, and expires only when bought, explicitly declined, or the run closes.
4.3 Refresh
Refreshing replaces every unlocked, unbought offer except a fixed boss and a
protected recovery offer. Let N be prior refreshes in the current Market and
L the number of paid locked offers:
refresh_cost(N,L) = min(24, 6 + 3*N + 2*L)
N starts at zero each Market and increments atomically with the new board.
The first no-lock refresh costs 6, the second 9, and the seventh and later cost
24. Insufficient Coin rejects the operation without changing offers or N.
5. Prices, Sales, And Dismissal
5.1 Recruit Price
For offer level L and Profession tier P (0 base, 1 regular advanced):
hire_list_price(L,P) = 10 + 4*L + 10*P
Trait and rolled distribution do not add a hidden price because level totals are equal-budget and every Trait has a cost. A Recruit's generated offer stores the list price.
Replacement Credit is optional at confirm. If use_credit is true:
credit_used = min(replacement_credit_balance, hire_list_price)
coin_cost = hire_list_price - credit_used
If false, credit_used=0. Coin cost, Credit spend, Recruit creation, and offer
removal apply atomically. Credit cannot buy equipment, refreshes, locks, or
Meta progression.
5.2 Equipment Price And Sale
For Region band B in 0..7 and item tier T in 0..3:
equipment_list_price(B,T) = 12 + 3*B + 6*T
sale_value = floor(0.30 * coin_price_paid)
An equipment reward stores coin_price_paid=0 and therefore sells for zero;
its value is the behavior it enables. Purchased copies never sell above 30%.
Locked, equipped, or battle-committed items must be released before sale.
5.3 Dismissal Rebate
The product authority's canonical count and precondition apply before rebate calculation:
live_recruit_count = count(unique Recruit IDs owned by the current run
whose state is living,
across deployed party and Reserve)
dismissal_legal = Market_open and target_is_living and
live_recruit_count >= 2
Only for a legal dismissal:
if survived_battles >= 2:
dismissal_rebate = min(10, floor(0.25 * coin_price_paid))
else:
dismissal_rebate = 0
coin_price_paid excludes Credit. Equipment returns before the Recruit is
removed, all in one operation. Dismissal creates no Credit, Renown, XP transfer,
offer reroll, or reward. A same-level replacement always costs more Coin than
the rebate unless Credit came from an unrelated death.
When live_recruit_count == 1, preview and commit reject
FINAL_LIVE_RECRUIT before the rebate formula. The blocked action grants zero
Coin, zero Credit, no protected recovery offer, and no economic or roster
mutation. Abandon Run remains a separately confirmed run-close operation and
does not pay a dismissal rebate.
Counterexample trace:
state: Market open; one living Recruit; Coin=3; Credit=0;
no protected recovery offer; Recruit paid 32 Coin and survived 3 battles
attempt: preview dismissal, then submit the same confirm after interruption
result: FINAL_LIVE_RECRUIT at preview and commit
after: one living Recruit; Coin=3; Credit=0; no protected offer;
dismissed_total unchanged; calculated dismissal rebate is not applied
next legal terminal choice: continue Market play or confirm Abandon Run
The hypothetical eight-Coin rebate cannot make the final dismissal legal. Casualty settlement may later create Credit or a protected offer if the Recruit falls; it is not simulated by dismissal.
6. Battle Income And Reward Drafts
Battle risk Q is 0 steady, 1 pressured, or 2 elite. For Region band
B in 0..7 and ordinary Round R:
battle_coin(B,R,Q) =
floor((18 + 2*R + 2*B + 7*Q) * difficulty_reward_multiplier)
reward_budget(B,R,Q) = 12 + 2*R + 3*B + 6*Q
Coin pays once on victory before the reward choice. Defeat, timeout, and retreat pay no battle Coin. Economic consequences after those outcomes are owned only by the save/failure authority.
The victory reward draft is stable:
| Risk | Cards | Required composition |
|---|---|---|
| Steady | 2 choose 1 | one legal equipment/tag card; one floor(0.50*reward_budget) Coin card |
| Pressured | 3 choose 1 | two distinct legal equipment/tag cards; one Coin or Recruit-discount card |
| Elite | 3 choose 1 | one Artifact-eligible card, one equipment/tag card, one Coin/recovery card |
An Artifact card offers three fixed Artifact IDs and the player chooses one. If three Artifacts are already active, comparison/replacement is part of the same operation. Declining a reward is legal and grants nothing. A reward card cannot be rerolled by leaving the result.
The boss awards no spendable Coin because the run closes. A first boss clear grants the persistent values in Section 9 and one fixed discovery choice.
7. Death Credit And Recovery Solvency
When a hired or provisional Recruit becomes Fallen, use its original list price and actual Coin paid:
credit_grant = min(original_list_price,
10 + floor(coin_price_paid/2))
new_credit_balance = min(54, old_credit_balance + credit_grant)
Credit, permanent Recruit removal, and equipment return apply in one casualty
operation. A provisional Recruit has coin_price_paid=0 and an implicit level-1
base list price of 14, so it grants 10 Credit. Summons grant none.
After one or more casualties, the next Market reserves one base-Profession recovery offer with all of these properties:
- its level is
max(1, offer_level-1); - its Profession supplies at least one missing primary responsibility among protection, damage, reach, or sustain when such a catalog row is unlocked;
- it is not replaced by refresh and needs no lock fee;
- its list price uses the normal formula and Credit can reduce it to zero;
- buying or explicitly declining it clears protection, not remaining Credit.
The guarantee makes a replacement visible, not automatically optimal. A lost advanced or promoted Recruit returns as a cheaper base Recruit unless the player chooses to spend more on another offer.
7.1 Three-Death Fixture
At Round 7, three base Recruits originally bought for 18 Coin each fall. The current base list price is 22, the player has 12 Coin, and Credit cap is 54:
grant per Recruit = min(22, 10 + floor(18/2)) = 19
balance after three grants = min(54, 57) = 54
replacement Coin costs = 0, 0, 12
ending Coin = 0; ending Credit = 0
Three legal replacements are therefore purchasable in the next Market. The player has lost their levels, Traits, promotion progress, history, and all liquid flexibility, so the loss is recoverable but not profitable.
8. XP, Levels, And Promotion Pace
For Recruit level L from 1 through 9:
xp_to_next(L) = 20 + 10*L
battle_xp(R,Q) = 10 + 2*R + 4*Q
Living deployed Recruits receive 100% on victory, 50% on defeat/timeout when at least one deployed Recruit survives, and 50% on completed retreat. Reserve and Fallen Recruits receive zero. Difficulty and display speed do not multiply XP.
XP is applied after casualty determination. A Recruit can gain multiple levels from one award, checking the formula at each new level, but cannot exceed 10. At cap, excess is discarded and shown. Promotion eligibility at level 4 plus three survived battles is owned by the systems authority.
There is no permanent Recruit level, inheritance, XP item, or Meta stat. New hires catch up through offer level and price rather than receiving another Recruit's progress.
8.1 Enemy Rank And Within-Run Scaling
Regions add mechanics, not a permanent vertical stat ladder. Within a run, enemy stat pressure follows the current offer level and risk:
encounter_rank(R,Q,boss) =
min(6, offer_level(R) + Q + (1 if boss else 0))
rank_multiplier = 1 + 0.08*(encounter_rank - 1)
Apply rank_multiplier once to an enemy row's base MaxHP, power, Guard, Ward,
Potency, and Tenacity, rounding half up. Tempo, Initiative, reach, target rules,
cooldowns, footprint, and status durations do not scale. Difficulty then applies
its declared HP and damage/healing multipliers once.
Identity base budgets are content-authored within the systems ranges and must pass fixed same-rank comparisons. A later Region cannot substitute a larger base budget for a new mechanic, and no mandatory battle assumes a prior run's Recruit or equipment.
9. Renown And Meta Progression
For Region number G in 1..8 and Contract rank K in {1,2}:
first_clear_renown(G,K) = 8 + 2*G + 4*K
repeat_objective_renown = min(2, unclaimed_repeat_goals_for_contract)
First discovery of a Profession, Trait, equipment behavior family, Artifact, ordinary/elite enemy, or boss grants one Renown once. A row's presentation variants grant none. Repeat objectives are finite checklist entries; replaying an unchanged clear after they are claimed grants zero Renown.
Renown purchases only breadth:
| Unlock | Cost range | Allowed effect |
|---|---|---|
| Catalog pool packet | 4-8 | Add sidegrade equipment/Trait/Artifact rows to future eligible pools |
| Advanced Profession clue/trial | 8-12 | Reveal requirements and enable a deterministic trial |
| Hidden-hybrid clue/trial | 14-18 | Reveal one predicate and enable its mastery trial |
| Threat archive upgrade | 6-10 | Expose additional exact preview fields for encountered families |
| Oath law | 12-20 | Add a postgame optional run modifier and its completion Record |
Forbidden effects include percentage power, HP, defense, Coin gain, cheaper shops, free refreshes, starting equipment, starting Recruits, extra reward cards, larger starting Line capacity, or casualty reversal.
All mandatory Standard counters are in the default or deterministic Contract pool. A player never needs a Renown purchase to finish the first clear.
9.1 Guild Charter Transaction
PRO-002 presents the existing Renown authority as the Guild Charter. It is
not a new economy, currency, progression tree, or permanent-stat layer. The
board contains exactly eight horizontal Region seals in campaign order. A seal
opens only its authored packet cards and prerequisite tracks; no radial layout
or copied node graph is permitted.
Each claim uses one stable charter_claim_id and the existing cost range above:
preview = (charter_claim_id, region_id, prerequisite_ids[], renown_cost,
effect_family, future_run_effect, balance_revision)
commit = verify preview + debit Renown + append one claim receipt atomically
retry = return the original receipt; never debit or grant twice
The preview must show current Renown, remaining Renown, every prerequisite,
whether each prerequisite is satisfied, the exact future-run breadth change,
and the statement No permanent combat power. A failed prerequisite, stale
balance revision, insufficient balance, duplicate claim, or interrupted write
cannot partially reveal a packet or consume Renown. Respec and refund are not
part of the contracted board; claims are permanent breadth unlocks.
The first-clear choice after the sixteenth boss creates no new currency and grants no choice-specific combat value. Both branches settle the same earned Renown and first-clear Records exactly once, archive the surviving Company, and close Coin/Credit with the run. Complete the First Chronicle changes only the next destination to Final Ledger/Title. Open the Oath Season additionally sets postgame eligibility and enters rule review; its first playable state is a new generated run after that review. Ordinary New Run remains available and uses the same persistent breadth already owned.
10. Equipment And Artifact Distribution
The 320 equipment entries are divided into eight Region bands of 40. Every band contains all five item forms (armament, guard, garb, charm, and kit), all primary responsibilities, and at least three opposed order/reach/protection plans. Every Recruit has one universal active slot, so form controls eligibility and presentation rather than granting simultaneous slots. Tier describes price and availability, not strict power. A lower tier must lead one fixed comparison in which it is the rational choice.
Each item has a numeric support budget separate from its required behavior:
item_stat_budget(T) = 30 + 8*T
The behavior hook reserves 12-24 budget points. At most 50% of the total budget may be generic HP, power, Guard, or Ward. Remaining numeric support uses:
| Stat | Cost |
|---|---|
| +1 Might, Finesse, Insight, Vigor, or Resolve | 2 |
| +1 WeaponPower, FocusPower, ArmorGuard, or ArmorWard | 1 |
| +6 MaxHP | 1 |
| +1 Potency or Tenacity | 1 |
| +0.20 Tempo or Initiative | 1 |
The one equipped item's numeric support is added before derived-stat rounding. Region band does not increase this budget; later bands introduce new interactions rather than automatic vertical power.
All 320 entries pass the systems behavior fixture. No scalar-only allowance or minimum subset exists.
The 60 Artifacts are distributed across first-clear, elite, boss, mastery, and postgame pools. Every run sees at least one deterministic Artifact choice by the end of Round 6 and at least one additional choice by boss Muster. No Artifact is required for a mandatory boss. Duplicate active Artifact IDs are illegal.
Bad-luck protection uses behavior tags:
if two consecutive eligible equipment drafts omit the selected behavior tag:
the third eligible draft contains that tag
The counter resets when offered, not accepted. The selected tag may be changed at any Market for zero Coin before a draft is generated. It cannot name an undiscovered exact item.
11. Capacity Selection Simulation
The 10-12 target range was evaluated with an explicit analytical workload
model. It is a design simulation, not human readability evidence.
For profile P and candidate capacity C:
prep_seconds(P,C) = ceil(base_P + inspect_P*C +
reorder_P*C*(C-1)/2)
battle_p95_seconds(C) = ceil(52 + 5.4*C)
causal_events_per_second(C) = 1.2 + 0.24*C
The pair term models order comparisons, not every permutation. The gate is
prep <= 150 s for every profile, battle p95 <=120 s, causal events <=4.0/s,
and the three-death fixture recoverable in at most one Market.
| Profile | base |
inspect |
reorder |
C=10 prep | C=11 prep | C=12 prep |
|---|---|---|---|---|---|---|
| Normal | 20 | 4.0 | 0.8 | 96 s | 108 s | 121 s |
| Active | 25 | 5.0 | 1.4 | 138 s | 157 s | 178 s |
| Efficient | 15 | 3.0 | 0.5 | 68 s | 76 s | 84 s |
| Adversarial | 20 | 4.5 | 1.3 | 124 s | 141 s | 160 s |
| Returning | 30 | 5.5 | 1.3 | 144 s | 162 s | 182 s |
| Candidate | Profiles passing prep | Battle p95 | Causal events/s | Three-death recovery | Result |
|---|---|---|---|---|---|
| 10 | 5/5 | 106 s | 3.60 | 1 Market | Pass |
| 11 | 3/5 | 112 s | 3.84 | 1 Market | Fail profile gate |
| 12 | 2/5 | 117 s | 4.08 | 1 Market | Fail profile and event gates |
Ten is the largest candidate passing every declared gate. Human testing still owns whether ten simultaneous allies plus enemies remain visually legible.
12. Contract And First-Clear Pacing
Each Region contains two Contracts. Every Contract is twelve ordinary Rounds, boss Muster, and one boss. The Normal authored means are:
| Region | Contract 1 | Contract 2 | Region total | Content pressure |
|---|---|---|---|---|
| 1 | 50 min | 54 min | 104 min | recruit valuation, front/rear, reach |
| 2 | 54 min | 58 min | 112 min | protection bypass and healing access |
| 3 | 56 min | 60 min | 116 min | projectiles and interception |
| 4 | 58 min | 62 min | 120 min | movement, push, and pull |
| 5 | 60 min | 64 min | 124 min | summons and footprint pressure |
| 6 | 62 min | 66 min | 128 min | status ordering and control |
| 7 | 64 min | 68 min | 132 min | promotion and Artifact conflicts |
| 8 | 66 min | 70 min | 136 min | full-system synthesis |
Successful Contract time sums to 972 minutes. This time is active Market,
battle, result, and boss play; it excludes loading and forced waiting.
12.1 Five Full-Clear Profiles
| Profile | Successful Contract minutes | Failed/abandoned-run minutes | Guild/onboarding/recap minutes | Total | First-clear hours |
|---|---|---|---|---|---|
| Efficient | 768 | 120 | 90 | 978 | 16.30 h |
| Normal | 972 | 120 | 78 | 1,170 | 19.50 h |
| Active | 1,152 | 150 | 90 | 1,392 | 23.20 h |
| Adversarial | 928 | 300 | 92 | 1,320 | 22.00 h |
| Returning | 1,024 | 120 | 161 | 1,305 | 21.75 h |
Every profile is inside 15-25 hours. The efficient profile cannot skip required bosses or decisions; it saves time through faster comparison and presentation speed. Adversarial includes more elite offers and recoverable losses. Returning includes recap/segmentation overhead, not forced repetition.
Mastery targets 60+ cumulative hours. At least 70% of post-ending time must use a previously unclear Profession, Trait, equipment behavior, Artifact conflict, enemy/boss fixture, or Oath law. An unchanged clear may contribute at most 20% of any mastery milestone.
13. Exact Twenty-Minute Pacing Traces
All timestamps are simulation-independent wall time spent actively playing a
representative 1,200-second session. M lists Market openings. B lists battle
start-end intervals. D lists meaningful decisions; confirmation, inspection,
speed changes, and reward animation do not count.
| Profile | M Market opens (s) |
B battle intervals (s) |
D decision timestamps (s) |
Maximum decision gap |
|---|---|---|---|---|
| Normal | [0,300,600,900] |
[(180,270),(480,570),(780,870),(1080,1170)] |
[25,90,175,280,325,390,475,580,625,690,775,880,925,990,1075,1180] |
105 s |
| Active | [0,330,660,990] |
[(210,300),(540,630),(870,960),(1140,1200)] |
[20,75,135,205,310,350,410,475,535,640,680,740,805,865,970,1015,1070,1135] |
105 s |
| Efficient | [0,260,520,780,1040] |
[(130,230),(390,490),(650,750),(910,1010),(1170,1200)] |
[35,125,240,295,385,500,555,645,760,815,905,1020,1075,1165] |
115 s |
| Adversarial | [0,290,610,940] |
[(150,260),(440,580),(760,910),(1100,1200)] |
[30,80,145,270,320,375,435,590,640,700,755,920,970,1030,1095] |
165 s |
| Returning | [0,270,590,930] |
[(140,240),(420,550),(760,890),(1090,1180)] |
[25,85,135,250,300,355,415,560,620,680,755,900,950,1015,1085,1190] |
145 s |
The gap includes time zero to the first decision and the last decision to 1,200. Every battle that completes before the trace boundary is followed by its next decision within 15 seconds. Decision kinds across each trace must include Recruit/equipment valuation, order or deployment, battle-risk commitment, reward/recovery, and next-Market budget. Adversarial's 165-second gap is a long elite battle and remains below the product veto because the battle itself is capped at 150 simulation seconds and the result decision appears immediately afterward.
14. Standard Solvency Trace
A lowest-reward run takes only steady offers. In Region band B, ordinary
battle income is:
sum(battle_coin(B,R,0), R=1..12)
= sum(18 + 2*R + 2*B)
= 372 + 24*B Coin
With starting Coin, total pre-boss resources are 424 + 24*B Coin. The
baseline plan spends:
| Required purchase | Cost |
|---|---|
| Eight base hires needed to grow from two provisional Recruits to capacity ten | 156 |
Two tier-0/1/2/3 items in Region band B |
168 + 24*B |
| Two refreshes in one no-lock Market | 15 |
| Three locks | 6 |
| Total | 345 + 24*B |
The Region-band income and equipment-price terms cancel exactly, so the run
reaches boss Muster with 79 Coin before optional sales, risky-offer
bonuses, reward Coin cards, or Credit. The deterministic boss-counter objective
costs no more than one omitted baseline equipment purchase. Standard solvency
passes when every Region seed can follow an equivalent plan with at least 40
Coin or one complete three-casualty recovery set entering boss Muster.
15. Anti-Dominance And Balance Gates
15.1 Required Strategy Tests
| Candidate policy | Why it might dominate | Rejection fixture |
|---|---|---|
| Always refresh twice | More chances at desired synergies | Costs at least 15 Coin per Market before locks; 12-Market use costs 180, exceeds the 79-Coin baseline reserve and must lose one fixed low-variance seed |
| Never refresh | Preserves all Coin | Must lose value in at least two of five seeds where one refresh exposes a counter tag worth more than 6 Coin |
| Buy every Recruit | Reserve breadth and death insurance | Reserve earns no XP/Coin; dismissal returns at most 25% paid Coin; fixed plan must lose equipment/refresh flexibility and fail one boss comparison |
| Dismiss after every battle | Attempt to cycle Traits/offers | No Credit, zero rebate before two survivals, maximum 10 later; cycle is strictly Coin-negative and loses history/level |
| Never dismiss | Avoid sunk-cost loss | Must lose one fixture where releasing an obsolete low-level Reserve funds a reachable counter without weakening deployed footprint |
| Never replace | Preserve Coin after death | Must lose one post-casualty fixture because lower footprint changes reach/protection and leaves Coin unused |
| Always take steady | Minimize death | Must trail pressured/elite in at least one build-breadth objective and one Artifact timing fixture |
| Always take elite | Maximize rewards | Expected casualties and missed steady recovery must reduce clear rate or terminal Coin in at least two profiles |
No policy needs to be bad everywhere. A policy is dominant if it weakly beats all alternatives in every fixed state and strictly beats one; any such result blocks the design.
15.2 Executable Fixed-Seed Comparator
The Gate 6 build-policy proof is
ANTI_DOMINANCE_FIXED_SEEDS.json,
recalculated by python3 tools/simulate_anti_dominance.py. It is a prebattle
feasibility comparator, not a second combat model: the fixture declares the
locked route's ordered enemy inputs, required counter tags, minimum deployed
footprint, and casualty counts. The script replays the Market transactions,
tests that the resulting deployed build covers those route requirements, and
then applies the Section 6 battle-Coin formula only on a clear. It introduces
no accuracy, evasion, random draw, hidden generator state, or formula override.
Every seed declares all of the following rather than asking a generator for them at test time:
| Fixture field | Required declared input or recalculation |
|---|---|
| State | Round, cleared Rounds, Region band, difficulty, Coin, Credit before casualties, prior refresh count, paid locks, and expected capacity/offer-level/refresh-cost values |
| Company | Every living Recruit ID, deployed/Reserve assignment, counter tags, Coin paid, and survived-battle count |
| Recovery | Every casualty's original list price, Coin paid, expected Credit grant, post-casualty Credit, and the protected offer ID or explicit null |
| Boards | All three Recruit, four equipment, and three battle offers on both the opening and first-refresh board, including exact price inputs and stored prices |
| Route | The paid-locked route preserved through refresh, ordered enemy inputs, risk, required tags, deployed footprint, outcome casualties, and stored battle Coin |
| Oracle | Exact action trace and outcome metrics for every policy plus the expected winner |
Each fixture's opening Coin is the post-lock balance; the declared paid lock is already sunk. Its count still enters the first-refresh formula, and the locked route is byte-identical on the refresh board so every policy faces the same combat contract.
The script rejects a missing row or field, a sixth or duplicate seed, a changed
locked route or protected offer, a noncanonical price/reward/Credit value, an
illegal deployment, or an expected-result mismatch. A casualty state must have
exactly one protected Recruit on both boards. The protected offer remains
unchanged through refresh. Dismissal checks the canonical living count before
target selection; with one living Recruit it records FINAL_LIVE_RECRUIT, pays
no rebate, and may still perform a separate legal equipment purchase. Casualty
Credit and protected recovery are inputs to later hire transactions, never a
dismissal side effect.
The four fixed policy families are intentionally narrow and deterministic:
| Policy | Exact algorithm |
|---|---|
refresh_first |
Pay exactly the declared first refresh when affordable, then buy at most one affordable refreshed equipment offer that maximizes missing route-tag coverage; ties use lower price then offer ID |
hire_first |
Buy at most one affordable opening-board Recruit, preferring the protected offer, then missing route-tag coverage, lower Coin cost after optional Credit, lower list price, and offer ID; deploy it only when capacity has a vacancy |
dismiss_first |
If legal, dismiss one Reserve with least route relevance, then highest rebate and offer ID tie-breaks; otherwise record the rejection; buy at most one affordable opening-board equipment counter |
no_replace |
Never refresh, hire, or dismiss; buy at most one affordable opening-board equipment counter using the same coverage/price/ID ordering |
The comparison is lexicographic and all higher values are better:
route_cleared, ending Coin, ending Credit, ending living Recruit count, then
counter-tag coverage. The JSON also records deployed/required footprint,
battle Coin, Market Coin spent, dismissal rebate, Credit used, Line capacity,
and exact actions. This ordering does not convert Credit into Coin and does not
claim that the fixture policies are exhaustive play. It makes one declared
prebattle choice comparable without hiding a utility weight.
For two policies A and B, A weakly dominates B only when A's complete
comparison tuple is at least B's on all five seeds and strictly greater on at
least one. The run fails if either policy has no win, has no loss, or any
ordered policy pair meets that definition. --self-test first accepts the
canonical matrix, then creates an in-memory matrix in which refresh_first
beats every peer on every seed and proves that the dominance check rejects it.
| Stable seed | Fixed state counterfactual | Expected winner |
|---|---|---|
AD-FS-001-REFRESH-COUNTER |
First refresh exposes the locked pressured route's only affordable wardbreak counter | refresh_first |
AD-FS-002-PROTECTED-HIRE |
One casualty leaves both a protection and fourth-deployed-Recruit gap | hire_first |
AD-FS-003-DISMISSAL-REBATE |
A legal four-Coin obsolete-Reserve rebate makes the current reach counter affordable | dismiss_first |
AD-FS-004-PRESERVE-COIN |
The current line already clears; extra transactions lose Coin or living roster value | no_replace |
AD-FS-005-CREDIT-CROSSOVER |
Final-Recruit dismissal is illegal and a zero-Coin protected hire beats two equipment paths | hire_first |
Canonical verification is:
python3 tools/simulate_anti_dominance.py --self-test
python3 tools/simulate_anti_dominance.py
python3 tools/simulate_anti_dominance.py | shasum -a 256
Two default runs must be byte-identical. The summary prints every policy's
clear, ending Coin, ending Credit, ending living count, and counter coverage
for every seed, the win counts, a canonical result SHA-256, and
ABG_ANTI_DOMINANCE_OK no_weak_dominance=1.
15.3 Complete Gates
- Solvency: all eight Region bands have a steady Standard plan reaching boss Muster with 40 Coin or the full declared recovery set.
- Recovery: the Section 7.1 three-death state fields three legal base replacements in one Market and does not increase total Coin-equivalent value.
- Capacity: candidate ten is the only candidate passing all profile, battle-duration, event-rate, and recovery gates.
- Profession diversity: each base branch pair and hidden hybrid has opposed fixtures; no identity leads both without a different Company/order cost.
- Equipment/Artifact diversity: every row changes two observable events; no price/tier creates strict catalog-wide superiority.
- Market diversity: across five fixed run seeds and five profiles, at least three different first purchases, battle risks, and final orders are optimal.
- Failure pressure: one death is consequential; three are recoverable; a full-company loss can close a run without making next-run Meta power required.
- Decision density: exact traces reproduce their maximum gaps, and no battle/result handoff exceeds 15 real seconds after resolution at 1x.
- Campaign: all profiles finish within 15-25 hours and mastery has new decision content through 60+ hours.
16. Difficulty Contracts
Difficulty is chosen before run creation and stored for the entire run:
| Difficulty | Enemy HP | Enemy damage/healing | Reward multiplier | Audience |
|---|---|---|---|---|
| Wayfinder | 0.90x | 0.90x | 1.00x | learning and accessibility-forward play |
| Standard | 1.00x | 1.00x | 1.00x | authored first-clear baseline |
| Oathbound | 1.10x | 1.12x | 1.15x | prepared high-risk play |
Multipliers apply once after enemy derived stats and once to battle Coin where declared. They do not change offer access, Recruit attribute budgets, XP, Renown, target rules, telegraph length, Replacement Credit, Line capacity, or save behavior. Fallen Recruits remain permanent on every difficulty.
Postgame Oath laws are opt-in rule changes, not hidden difficulty multipliers. Each declares Market/formation/enemy/reward changes and its Record. Laws may not alter transaction integrity or reintroduce permanent Meta stats.
17. Fixed Economy Test Vectors
| Vector | Inputs | Expected result |
|---|---|---|
| Capacity | cleared Rounds 0,2,4,6,8,10,12 | 4,5,6,7,8,9,10 |
| Base hire | L=3, P=0 | 22 Coin list price |
| Advanced hire | L=3, P=1 | 32 Coin list price |
| Credit hire | list 22, Credit 19, use=true | 3 Coin, Credit becomes zero |
| Item price | B=4, T=2 | 12+12+12=36 Coin |
| Item sale | 36 Coin paid | 10 Coin |
| Refresh | N=0/L=0; N=1/L=0; N=7/L=0 | 6, 9, 24 Coin |
| Steady income | B=0, R=5, Standard | 28 Coin |
| Region steady income | B=7, R=5, Standard | 42 Coin |
| Elite income | B=0, R=5, Oathbound | floor((18+10+14)*1.15)=48 Coin |
| Level XP | L=4 | 60 XP to level 5 |
| Battle XP | R=5, Q=2 | 28 XP to living deployed winner |
| Death Credit | original list 22, paid 18 | 19 Credit |
| Dismissal | paid 32, survived 3 | 8 Coin; no Credit |
| Final dismissal | one living Recruit, paid 32, survived 3, Coin 3 | reject FINAL_LIVE_RECRUIT; Coin remains 3, no rebate/offer/roster change |
| Solvency | any B; start plus 12 steady wins minus baseline | 79 Coin |
| Decision gaps | five Section 13 traces | 105, 105, 115, 165, 145 seconds |
| Capacity candidate | C=10 | 5/5 prep, 106 s p95, 3.60 events/s, one-Market recovery |
18. Acceptance Checklist
- Market board, offer levels, prices, refresh, lock, purchase, sale, and reward formulas are complete.
- Coin, Credit, XP, Renown, and progression facts have explicit persistence, sources, sinks, caps, and non-power boundaries.
- Guild Charter preview/claim/retry uses existing Renown, the declared cost ranges, exactly-once receipts, and no permanent raw power.
- Death recovery is affordable without making dismissal/death profitable.
- The dismissal rebate is unreachable when the target is the final living Recruit; abandonment and casualty recovery remain separate.
- Capacity ten follows a declared five-profile analytical selection.
- Five exact Market/battle/decision traces and campaign budgets meet 15-25 first-clear and 60+ mastery targets.
- Solvency and anti-dominance gates cover refresh, hire, dismiss, replace, and risk policies.
- All fixed content counts and no-filler requirements match the other authorities.
- Both final-campaign choices settle identical earned economy receipts, archive the Company, and differ only in destination/postgame eligibility.
Aetherbound Guild: Save And Failure Contract
Authority: versioned persistence, pending/applied operations, exactly-once commit, retry, duplicate protection, deterministic battle resume, Recruit death, dismissal, run failure, backup, corruption, migration, rollback, cloud conflict, clock behavior, bounded offline work, delete, and recovery UX.
Revision: recruit-line-design-r3 / 2026-08-11
01_GAME_DESIGN.md owns the player promise. 02_GAMEPLAY_AND_BALANCE.md owns battle state and casualty predicates. 02_GAMEPLAY_AND_BALANCE.md owns normal prices, rewards, pacing, and difficulty multipliers. This document is final authority for operation and gameplay-failure application.
1. Persistence Invariants
- A confirmed operation applies exactly once or not at all. Cost, result, receipt, and final status are one committed state.
- A durable
pendingrow contains immutable intent and zero gameplay deltas. It can be safely finalized or rejected; it can never contain a spent cost. - Suspend, crash, power loss, retry, duplicate input, device change, or cloud transport cannot redraw a Market/reward, duplicate an item/Renown grant, reverse a valid casualty, or change a deterministic battle.
- The newest valid local commit remains fully playable offline. Platform and cloud copies never become gameplay authority silently.
- A Fallen Recruit never respawns in the same battle and never returns to the same run through Reserve substitution, reload, backup choice, rehearsal, migration, reward, promotion, difficulty, or clock manipulation.
- Death removes the Recruit but returns exactly the Recruit's optional
equipped_item_idto run inventory. Neither half of that result can commit alone; an empty slot returns nothing. - Offline gameplay advances by zero simulation ticks and grants zero Coin, XP, Renown, offers, healing, or progress.
- Migration is copy-first, deterministic, sequential, and reversible until a later verified boundary. It never rerolls generated Recruit fields.
- Corruption recovery identifies the exact verified boundary. If later irreversible run operations cannot be reconstructed, the run is sealed rather than resumed from a state that could reverse death or duplicate value.
- Save, conflict, recovery, overwrite, abandon, dismissal, and delete flows support touch, mouse, keyboard, controller, localization, and accessibility.
- A Run seed is reserved in a durable
run_creation_draftbefore any opening Recruit is generated. At most one draft orcurrent_runexists, and a draft can only become thecurrent_runthat carries that same seed.
2. Save Topology And Envelope
The product supports three independent Guild slots. Each slot holds one active commit, four rotating verified backups, one run-start checkpoint, one latest Market checkpoint, one optional pre-migration copy, and redundant closure receipt ledgers.
profile_save
profile_schema_version
settings_revision, language, accessibility, input mappings
Guild_slot_index[]
platform_service_outbox (non-authoritative, bounded)
Guild_slot
Guild_id, lineage_id, slot_id
save_schema_version, ruleset_version, content_revision
commit_id, parent_commit_id, commit_sequence
generation_root_seed, next_run_ordinal
Region/Contract progress, Renown, unlocks, Records, discoveries
run_creation_draft or null
current_run or null
operation_journal, compact_applied_ids
closure_receipt_head, run_creation_receipt_head
payload_sha256, envelope_crc32
run_creation_draft
draft_id, run_id, Contract, difficulty, status
seed_ordinal, run_seed, source_commit_id
ruleset_version, content_revision, opening_role_weight_snapshot
opening_offers[0..3] or empty, opening_offer_set_hash or null
selected_offer_ids[2] or empty, selection_revision
draft_hash, run_creation_receipt_head
current_run
run_id, Contract, difficulty, run_seed, status
Market/cleared-Round/boss state
Coin, Replacement Credit, capacity, offers, locks, refresh counters
living Recruits, Reserve, inventory, Artifacts
encounter or null, pending outcome/reward or null
hired/fallen/dismissed totals
IDs and seeds are 128-bit values rendered as lowercase hexadecimal. Commit sequence is a local monotonic unsigned integer. CRC32 catches incomplete media writes; SHA-256 covers canonical payload bytes. Checksums are integrity tools, not online signatures or anti-cheat requirements.
run_creation_draft and current_run are mutually exclusive. A draft with
status seed_reserved has an empty offer array and selection. offers_ready
has exactly four complete offers and no accepted pair; selection_ready has the
same four offers and exactly two distinct selected IDs. No state may serialize a
partial offer array, one selected ID, or a draft whose seed ordinal is not less
than next_run_ordinal.
Wall-clock fields may be stored for display and diagnostics only. They cannot select conflict winners or calculate gameplay.
3. Versioning And Compatibility
| Field | Changes when | Compatibility rule |
|---|---|---|
profile_schema_version |
settings/slot index layout changes | profile-only ordered migration |
save_schema_version |
Guild/run/operation serialization changes | sequential copy migration required |
ruleset_version |
combat, target, price, failure, or progression formula changes | committed battle finishes under stored version |
content_revision |
stable catalog row or localization data changes | stable-ID mapping or explicit legacy handling |
The current schema and previous three shipped schemas must have tested adjacent migrations. Older schemas may have a longer supported chain; absence of a chain blocks that slot with export/recovery options and never authorizes reset.
A run-creation draft, battle, reward draft, Market board, or outcome already committed stays on its stored ruleset/content snapshot. A new ruleset becomes active only before seed reservation or a new Market is generated, after all prior result operations are finalized. It cannot rematerialize an existing opening four.
No shipped gameplay save exists during this design-only stage. These rules bind all later prototype and production schemas and do not imply a current runtime migration obligation.
4. Operation Identity And Status
Every state-changing action has:
operation_id = hash(Guild_id, lineage_id, commit_sequence_at_intent,
operation_kind, source_stable_id, local_nonce)
intent_hash = sha256(canonical_operation_inputs)
status: pending | applied | rejected
The journal row stores:
operation_id, operation_kind, intent_hash, status
pre_commit_id, result_commit_id
cost_delta, result_delta, rejection_reason
run_id, Market_index, encounter_id, simulation_tick as applicable
receipt_hash, previous_closure_receipt_hash as applicable
Rules for duplicate IDs:
- same
operation_idand sameintent_hash: return stored pending status, applied receipt, or rejection without creating a new operation; - same ID and different hash: reject
OPERATION_ID_CONFLICT, applying nothing; - new ID: validate and enter the transaction procedure below.
Applied IDs remain in the full journal through run close. They then compact into an immutable membership set retained for the Guild lineage. Receipt-bearing casualty, reward, boss-clear, Renown, run-close, migration, and delete operations remain in the redundant closure ledger until the Guild slot is deleted.
The detailed journal is bounded to 4,096 rows. At a Market with no pending operation, reaching 3,584 rows compacts the oldest finalized non-closure rows into sorted exact-ID segments containing operation ID, intent hash, final status, and receipt hash. The newest 512 detailed rows and every closure receipt remain expanded. Lookup checks exact segments before accepting a new ID; probabilistic membership is forbidden because a false match could reject a valid purchase or hide a duplicate.
5. Pending-To-Applied Transaction Procedure
Every durable transaction uses these steps:
- Look up ID/hash before current-state validation and return any existing row.
- Validate the active commit, legal phase, referenced IDs, target, and intent.
- Build a candidate child commit containing a
pendingrow with the complete immutable intent and zerocost_delta/result_delta. - Validate, write, flush, atomically point to, and read back that pending child.
- From the pending intent and unchanged parent facts, compute the complete cost and result. No new random draw is allowed; generated outputs were fixed in intent or derive from stored labeled seeds.
- Build one child that replaces
pendingwithapplied, includes all cost and result deltas, receipt, and closure link when required. - Validate schema, nonnegative resources, unique ownership, Recruit/equipment consistency, Market lineage, battle hashes, and operation transition.
- Serialize to a new file, write integrity values, flush file and directory, atomically replace the active pointer, then read back.
- Rotate backups only after the applied child reads back and validates.
A precondition failure after step 3 produces a rejected child with zero deltas
and one reason. It cannot return to pending. Presentation, sound, achievement,
cloud upload, and screen transition occur only after step 9.
5.1 Crash And Retry Boundaries
| Crash point | Reachable active state | Recovery/retry |
|---|---|---|
| Before pending pointer switch | Parent only | retry creates same intent; no cost exists |
| After pending switch | Pending intent, zero deltas | deterministic finalize or reject once |
| During applied pointer switch | Pending or complete applied child | validate selected pointer; finalize or return receipt |
| After applied switch, before backup rotation | Complete applied child | return stored receipt; never reapply |
| During backup/closure replication | Applied active plus older replicas | repair replicas from active receipt; no gameplay replay |
Recovery may finalize a pending buy, casualty, reward, or run-close operation only from its fixed intent. It never asks the player to redraw or reconfirm a result whose confirm was already durably recorded. A pending destructive action that lacks a valid target after recovery becomes rejected with no deltas.
6. Transaction Boundaries
| Action | Pending intent contains | Applied child contains |
|---|---|---|
| Begin run creation | Contract, difficulty, expected next_run_ordinal, derived draft/run IDs and seed, version/role-weight snapshot |
one seed_reserved draft and ordinal increment; no offers or current_run |
| Materialize opening offers | draft ID/hash, run seed hash, versions, expected empty offer set | all four indexed offer records/IDs/output hashes and one offer-set hash |
| Set opening selection | draft ID/hash, offer-set hash, expected selection revision, exactly two distinct offer IDs | same four offers, canonical selected pair, revision increment, receipt |
| Commit run creation | draft ID/hash, offer-set hash, selection revision, exact pair and output hashes | draft removed; same run ID/seed and selected Recruit records in one new current_run; opening Coin/capacity and run-start receipt |
| Buy Recruit | offer ID, recruit output hash, Credit choice, expected price | Coin/Credit cost, offer removal, Recruit ownership |
| Buy/sell equipment | offer/item ID and expected receipt | Coin delta and exactly one ownership change |
| Lock/refresh | Market hash, selected locks, expected cost | Coin cost, counters, complete fixed offer board |
| Equip/reorder | Recruit, candidate item, expected prior item or null, and/or order IDs | one-slot replacement receipt, complete legal inventory and Party-line state |
| Promote | Recruit, old/new Profession, eligibility proof | one Profession replacement and derived-state refresh |
| Dismiss | Recruit, optional equipped item ID, rebate preview, expected live_recruit_count |
Recruit removal, optional item return, Coin rebate, post-count at least one |
| Commit battle | battle offer, lineup, stats, seed, risk | immutable encounter start snapshot |
| Start retreat | encounter, accepted tick | one retreat timestamp; no duplicate start |
| Lock outcome | objective and final state hashes | immutable victory/defeat/timeout/retreat result |
| Apply casualties | exact Recruit/optional-item/Credit set | all Recruit removals, all present item returns, all Credit grants |
| Claim reward | fixed draft/card/disposition | one reward and draft removal |
| Close run | terminal cause and persistent grants | Coin/Credit clear, run result, Records/Renown once |
| Change difficulty/law | Guild-only selected rule set | next-run configuration only |
An operation cannot use a presentation animation as a commit boundary. A double-tap, key repeat, controller repeat, OS lifecycle retry, or cloud retry returns the same status/receipt.
7. Run Creation, Market, And Round Save Points
7.1 Seed-First Run Creation
Begin run creation derives values without an ambient RNG or wall clock:
seed_ordinal = next_run_ordinal
run_seed = low128(sha256(generation_root_seed || lineage_id ||
"run-seed" || u64(seed_ordinal)))
draft_id = low128(sha256(run_seed || "run-creation-draft"))
run_id = low128(sha256(run_seed || "run-id"))
Its pending intent fixes the chosen Contract/difficulty and generation snapshot
but generates no Recruit. Its applied child creates the seed_reserved draft,
increments next_run_ordinal once, mirrors a seed-reservation receipt into both
closure ledgers, and is flushed, pointed to, and read back before the opening
generator may run. A retry from the unchanged parent derives the same ordinal
and seed. Once a draft exists, a new begin request returns
RUN_CREATION_DRAFT_ACTIVE and that draft; it cannot consume another ordinal.
If current_run exists, begin returns RUN_ALREADY_ACTIVE and applies nothing.
Materialize opening offers uses only the read-back draft and the content
authority's fixed mappings for indices 0..3. One applied child stores all four
complete Recruit records, offer IDs, output hashes, and their canonical
offer-set hash. A missing index, duplicate ID, output-hash mismatch, changed
generation snapshot, or any fifth offer rejects with zero deltas and leaves the
same reserved seed. The materialization receipt is mirrored redundantly and is
sufficient to regenerate and verify the same four records.
The UI may hold a zero- or one-card highlight transiently, but the durable
Set opening selection operation accepts only a canonical unordered pair of two
distinct IDs from the saved four. A different legal pair replaces the prior
pair and increments selection_revision; repeating the same operation ID/hash
returns its original receipt. A new operation requesting the already accepted
pair returns SELECTION_UNCHANGED and that receipt without a commit. The player
may revise the pair until Run commit without regenerating an offer.
Back or Cancel exits the view only; it does not discard the draft, change its Contract/difficulty, consume an ordinal, or expose a refresh action. Save and Quit, suspension, process restart, locale/timezone change, and wall-clock rollback reopen the same four offers and latest durable pair. No player-facing action allocates a replacement draft while one exists.
Commit run creation revalidates the draft ID/hash, offer-set hash, exact
selection revision, pair, and both selected output hashes. Its applied child is
one atomic state: it removes the draft, creates current_run with the same
run_id and run_seed, transfers the two unchanged Recruit records, establishes
52 Coin and Line capacity four, and writes the run-start checkpoint and receipt.
There is no intermediate state with both objects or neither object. A request
for a stale draft/revision returns STALE_RUN_CREATION_DRAFT plus the current
draft summary and applies nothing. A retry naming an already promoted draft and
matching its commit receipt returns RUN_CREATION_ALREADY_APPLIED plus the
original receipt; a conflicting pair/hash is rejected. Neither path generates
offers or creates a second Run.
The Run-creation commit receipt is indexed by both operation_id and
draft_id. Therefore a duplicate confirm with the original ID and a recovery
retry that acquired a new operation ID both resolve to the one applied receipt
when their draft/pair/hash intent matches. A reused draft_id with different
intent returns RUN_CREATION_COMMIT_CONFLICT and cannot reach the generic
new-ID path.
Run-Creation Crash And Retry Matrix
| Durable boundary | Reachable state after recovery | Exact retry result |
|---|---|---|
| Before begin-pending pointer | parent, no draft, unchanged ordinal | derive the same ordinal/seed and retry |
| After begin-pending pointer | fixed seed intent, zero deltas | finalize the same seed_reserved draft once |
| After seed-reservation pointer/read-back | seed_reserved, no offers |
materialize indices 0..3 from that seed |
| Before/during materialization pointer | seed-only or one complete four-offer child | validate pointer; regenerate same four or return receipt |
| After materialization pointer | offers_ready, complete saved four |
reopen exact four; no generator call on normal load |
| Before/during selection pointer | prior pair or one complete revised pair | validate pointer; finalize pair or return its receipt |
| After selection pointer | selection_ready with exact pair/revision |
reopen same pair; later revision remains legal |
| Before/during Run-commit pointer | complete draft or complete current_run |
finalize from pending intent or return original commit receipt |
| After Run-commit pointer, before replica rotation | current_run, no draft |
repair replicas; never recreate draft or transfer twice |
Every row uses the generic pending-to-applied procedure in Section 5. A corrupt candidate is never partially merged with its parent.
7.2 Market, Round, And Run Save Points
Safe commits occur after:
- run-seed reservation, complete opening-offer materialization, each accepted two-Recruit selection revision, and atomic Run creation;
- Market generation, lock, refresh, buy, sell, equip, reorder, promote, and dismissal;
- battle offer commit and countdown start;
- accepted retreat start;
- encounter outcome lock;
- casualty application;
- reward claim or failure application;
- capacity increase, boss Muster, boss result, and run close.
Save and Quit completes the current tick/transaction and points to the same
active commit. It does not create a selectable branch or reroll point. Loading a
Market returns the exact offers, locks, refresh counter, Coin, Credit, Company,
Reserve, inventory, and order.
Failed attempts increment Market_index but not cleared_rounds. The next
Market still prepares the same required Round number with a new precommitted
board from the run seed. A boss failure reopens boss Muster with the same fixed
boss and newly derived Recruit/equipment offers. This progression cannot be
reset by closing or restoring a player-selectable save.
8. Battle Interruption And Deterministic Resume
An encounter snapshot stores:
encounter_id, ruleset_version, content_revision, root_seed
simulation_tick and per-label draw counters
ordered actor IDs/footprints, fixed-point HP/stats/resources/readiness
casts, projectiles, movement intents, summons, statuses, barriers, cooldowns
objective/phase/Overtime/retreat state
automatic event journal and accepted lifecycle commands
snapshot_hash, previous_snapshot_hash
The game writes a resumable snapshot every ten ticks, at every accepted retreat command, after every Fallen/collapse batch, and at outcome lock. On normal suspend it completes the current priority batch before acknowledging suspend.
If killed earlier, recovery:
- loads the newest valid encounter snapshot;
- replays deterministic automatic events and accepted lifecycle commands from the previous valid hash to the last journaled tick;
- verifies all labeled draw counters and state hashes;
- resumes at the first unprocessed priority of the next tick.
No wall time is substituted. A week-long suspend resumes the same tick. Camera, animation, particles, and audio may restart; authoritative events may not.
If all encounter snapshots are corrupt but the committed battle start and event
journal validate, replay from countdown using the same seed and retreat tick.
If replay hash diverges, seal the run as recovery_incomplete under Section 12;
never offer a fresh seed or pre-battle edit after observed casualties.
9. Recruit Death, Equipment Return, And Dismissal
9.1 Casualty Settlement
Fallen state exists in battle snapshots as soon as the death batch resolves. Run ownership changes only in the casualty settlement after outcome lock. The pending intent lists, for every casualty:
recruit_id, final Profession/level/XP/Trait/history hash
equipped_item_id or null
original list price, Coin paid, computed Credit grant
death tick and causal event ID
Applied settlement must satisfy:
all casualty Recruit IDs absent from living Company and Reserve
every non-null casualty equipped_item_id present exactly once in run inventory
Replacement Credit equals the capped sum
fallen total increases by exact casualty count
no non-casualty Recruit or item changes ownership
If any condition fails, the candidate is rejected and the outcome remains locked pending recovery. The game cannot enter the next Market with a partial casualty result.
Casualties apply on victory, defeat, timeout, and retreat. A same-batch mutual defeat does not preserve either Fallen Recruit. Rehearsal simulations create no operation and cannot affect ownership.
9.2 Dismissal
Dismissal is an explicit destructive operation from a Market. The pending review shows generated name, Profession, Trait, level, survival history, returned equipment, Coin rebate, resulting deployable footprint, and no Credit grant. Default focus is cancel. Both preview and commit use the product authority's canonical count:
live_recruit_count = count(unique Recruit IDs owned by the current run
whose state is living,
across deployed party and Reserve)
dismissal_legal = Market_open and target_is_living and
live_recruit_count >= 2
Dismissal is rejected for a Recruit referenced by a committed battle, pending
promotion, pending casualty settlement, or another dismissal. It is also
rejected as FINAL_LIVE_RECRUIT when the canonical count is one.
Preview rejection creates no operation ID, pending row, or save mutation. A
crafted or stale confirm is revalidated before a pending gameplay operation can
apply. Its FINAL_LIVE_RECRUIT response has zero cost/result deltas: no Recruit
or equipment moves, no Coin rebate, no Credit, no protected recovery offer, no
dismissed-total change, and no commit-sequence advance. The implementation may
retain only the rejected intent response keyed by operation ID and intent hash
so duplicate confirms return the same response; this is not an applied/pending
gameplay receipt and cannot later become legal after the Company changes.
A pending dismissal recovered after interruption stores its parent commit and expected count. Before transition to applied, it must prove the active parent is unchanged, pre-count is at least two, and post-count is exactly pre-count minus one and at least one. Otherwise it becomes the same zero-mutation rejected intent response. A successfully applied dismissal returns its original receipt on duplicate confirm and cannot remove another Recruit or pay a second rebate.
Explicit Abandon Run is a separate run-close operation; it does not reuse a
dismissal ID or pay a rebate. Casualty settlement is also separate and remains
the only path by which a final Recruit's death can create Credit, a protected
offer, recovery viability evaluation, or Company collapse.
9.3 No Resurrection Boundary
Applied casualty receipts are closure receipts. An older backup that predates a casualty can become active only after the receipt chain deterministically replays through that casualty or after the affected run is sealed. A recovery UI must never present "continue run" from an older state containing a Recruit whose later valid casualty receipt is known.
10. Duplicate Purchase, Reward, And Persistent Grant Protection
UI debounce is optional convenience; operation IDs are authority.
For purchase:
if operation applied: return stored Recruit/item and receipt
if pending: finalize same fixed offer and price
if offer absent under a new operation ID: reject OFFER_ALREADY_CONSUMED
For reward:
verify card ID belongs to stored draft
pending contains exact selected card and replacement choice if required
applied removes draft and adds one item/Artifact/Coin result
For Renown, clear, and discovery facts, the stable grant ID is derived from Guild ID plus objective/content ID. A repeated boss outcome or platform retry finds the existing applied ID and grants nothing again.
Optional platform achievements derive from applied Records. The outbox holds at most 100 idempotent events. When full, older events are regenerated from Records rather than blocking play or changing gameplay resources.
11. Backup, Corruption, And Closure Receipts
11.1 Backup Set
Each Guild slot stores:
active: newest validated commit;backup_1..4: distinct prior verified transaction boundaries;run_creation: latest verified seed/offers/selection draft boundary until atomic Run commit;run_start: current run creation commit until run close;Market_checkpoint: latest Market-open commit;pre_migration: source bytes before the latest migration;closure_Aandclosure_B: alternating append-only closure receipt ledgers;quarantine: corrupt bytes and diagnostics, never auto-deleted.
Backups rotate only after active read-back. Storage pressure removes diagnostic
logs before any active, closure, run-creation, run-start, Market, or
pre-migration copy. Seed reservation, offer materialization, selection revision,
and Run commit receipts are mirrored into both closure ledgers under
run_creation_receipt_head. Older selection receipts may compact only after an
exact-ID segment and the latest complete pair/revision snapshot are retained.
11.2 Validation Order
- envelope parse and size bounds;
- CRC32 and SHA-256;
- schema and required fields;
- Guild/lineage/parent/sequence links;
- operation status transitions and receipt chain;
- nonnegative Coin/Credit/Renown and cap checks;
- Recruit uniqueness, generated output hashes, and Profession topology;
- equipment ownership uniqueness and equip references;
- run-creation seed ordinal, draft/current-run exclusivity, indexed opening offer hashes, and selection revision;
- Market seed ancestry, offers, locks, and counters;
- encounter snapshot, event journal, draw counters, and outcome;
- persistent clear/discovery IDs and run-close consistency.
A settings error falls back to defaults without touching gameplay. Optional cloud/platform failure never labels a local save corrupt.
11.3 Recovery Algorithm
- Validate active, then backups newest to oldest.
- Validate both closure ledgers and choose the longest common valid chain.
- Select the newest valid gameplay commit whose ancestry matches the slot.
- Before Run commit, reconstruct a draft only from a valid seed-reservation receipt plus a complete matching receipt chain. Regenerate the four offers and verify their saved hashes, then restore the latest complete pair/revision.
- After a Run-commit receipt exists, never reconstruct its former draft. Recover
the matching
current_run, or seal it if the full transferred state cannot be verified. - Replay later closure receipts only when parent/result hashes form a complete chain and each result validates.
- If the chain reconstructs the newer state, write a recovered child and continue normally.
- If a missing/corrupt gap crosses a Run commit, casualty, reward, boss clear,
Renown grant,
or run close, restore persistent Guild state only through the verified
boundary and seal the current run as
recovery_incomplete. - If no active, backup, draft checkpoint, or redundant receipt proves the
reserved seed, mark the slot
creation_recovery_blocked; do not advance the ordinal, allocate another seed, or offer a playable branch. Export and the existing explicit Guild-slot delete/reset recovery remain available. - Preserve all rejected bytes in quarantine and write a diagnostic manifest.
Sealing clears run-only Coin/Credit and prevents reward or casualty farming. Recovered persistent facts are never guessed beyond the last verified receipt. The UI states the boundary and any unverifiable operations; it never claims full preservation without matching hashes.
12. Failure State Model And Consequences
Failure is classified before one operation calculates consequences:
| Kind | Predicate | Casualties | Coin fee | Run transition |
|---|---|---|---|---|
| Victory with losses | objective succeeds with one or more Fallen Recruits | Apply all | 0 | pay reward, next Market/boss/clear |
| Encounter defeat | all deployed non-summons Fallen or objective failure before timeout | Apply all | difficulty table | no reward; recovery Market if viable |
| Timeout defeat | objective incomplete at tick 1500 | Apply prior Fallen only | difficulty table | no reward; recovery Market if viable |
| Voluntary retreat | withdrawal completes | Apply all Fallen before completion | difficulty table | no reward; recovery Market if viable |
| Run abandonment | player confirms from Market/result | No new casualties | clear all run Coin/Credit | close run, no unearned boss grant |
| Company collapse | no living Recruit and no affordable protected recovery hire | already applied | 0 additional | close run |
| Process interruption | suspend/crash/power loss | none beyond deterministic replay | 0 | resume/reconstruct; not gameplay failure |
| Save corruption | active data fails validation | none invented | 0 | recover or seal; not gameplay failure |
Difficulty fees are the sole numeric failure-fee authority:
| Difficulty | Encounter defeat | Timeout | Retreat |
|---|---|---|---|
| Wayfinder | 0 Coin | min(2,current Coin) |
min(4,current Coin) |
| Standard | min(2,current Coin) |
min(4,current Coin) |
min(6,current Coin) |
| Oathbound | min(4,current Coin) |
min(6,current Coin) |
min(8,current Coin) |
Fee, casualty settlement, failure totals, consumed battle offer, and next-Market seed advance are one result transaction. Fees never make Coin negative and do not alter Credit. Retreat is therefore a controlled loss rather than a free way to cycle battle/Market offers.
12.1 Recovery Viability And Run Close
After failure settlement:
can_continue = living_recruit_count > 0
or coin + replacement_credit >= protected_offer_list_price
If true, open a recovery Market using the same required cleared-Round number. If false, show Company collapse and close the run after confirmation/automatic receipt. Explicitly declining the only affordable protected offer recomputes the predicate and previews run close before confirm.
This predicate runs only after casualty/failure settlement or protected-offer
decline. Dismissal cannot reduce the canonical live count below one and cannot
invoke this recovery/closure path. A player who wants to end a run while one or
more Recruits live must use the separate Abandon Run transaction.
Boss defeat follows the same rule. Cleared-Round count remains 12; boss Muster reopens if viable. No failure restores a consumed reward, dead Recruit, prior Market, or refresh counter.
12.2 Run Close
Run close stores terminal cause, Company history, all casualties/dismissals, boss/clear facts, discoveries, and eligible Renown. It then clears run-only Coin, Credit, Recruits, inventory, Artifacts, Market, and encounter state. Survivors become nonplayable history Records. One operation applies closure and persistent grants; retry returns the same run result.
13. Migration Contract
Migration runs only at startup or a Market with no pending operation. It never runs during countdown, battle, outcome, casualty settlement, reward selection, or run close.
- Validate and copy source bytes to
pre_migration. - Build an adjacent-version plan; skipping a required step is illegal.
- Resolve stable content IDs and list legacy/missing rows.
- Apply each pure deterministic migration to a copy.
- Preserve generated name parts, rendered-name snapshot, appearance seed, attributes, Trait, Profession, level, and survival history for living Recruits; do not draw replacements.
- Recompute derived stats from preserved source fields under the boundary rule.
- Validate operation, ownership, Market, battle, and closure chains.
- Write/read a new lineage child, then switch active pointer.
- Preserve pre-migration bytes until two later valid Market commits and run close or 30 launches, whichever is later.
A removed equipment/Artifact ID becomes a sealed legacy record with its stable ID and original ownership. At the next safe Market, the player chooses one of two deterministic same-band behavior replacements or leaves it sealed. A removed Profession keeps its stored ruleset for the current committed battle; afterward a deterministic parent-compatible replacement review is required.
If migration fails, discard the candidate and leave the source active under its
last supported ruleset where possible. Mark only that slot migration_blocked
and offer details/export. Never reset, auto-sell, reroll, or auto-equip.
14. Local, Cloud, Multi-Device, And Rollback
Cloud transports complete validated commits plus closure ledgers. It does not merge Coin, Recruits, equipment, offers, casualties, rewards, or operation rows.
| Commit topology | Resolution |
|---|---|
| Identical commit | no action |
| Local ancestor of cloud | offer verified cloud descendant; retain local backup |
| Cloud ancestor of local | keep local; queue upload |
| Different Guild/lineage | import only into an empty slot after validation |
| Same lineage, divergent descendants | never merge; choose one active branch, archive the other read-only |
Conflict comparison shows commit boundary, Region/Contract, Market/encounter, cleared Rounds, living/fallen counts, Renown, and closure receipt head. Wall clock is context only. Default is cancel/inspect.
The unchosen divergent branch cannot be duplicated into a second playable slot, because that would duplicate generated offers and allow alternate casualty or reward outcomes. It remains exportable/read-only until explicitly deleted.
A developer/support rollback follows the same recovery algorithm as corruption. It may activate an older commit only after replaying later valid closure receipts or sealing the affected run. No debug, platform, or user-facing path may resume an older branch that reverses a known applied casualty or reopens a known claimed reward.
15. Clock Rollback And Bounded Offline Behavior
All gameplay time uses simulation ticks or monotonic in-session duration. Wall clock is display/diagnostic data.
wall_delta = current_wall_clock - last_seen_wall_clock
if wall_delta < -300 seconds or wall_delta > 180 days:
record CLOCK_ANOMALY
change no gameplay state
While closed, the game advances exactly zero ticks and generates no Market, offer, Coin, Credit, XP, Renown, healing, promotion, unlock, enemy outcome, or reward. Return opens the saved state plus a compact recap.
Background work is bounded:
- at most one local save flush at a time;
- at most three complete cloud payloads queued per Guild slot;
- at most 100 idempotent platform events;
- at most 30 seconds of best-effort upload after an explicit foreground save, cancellable without affecting the local commit;
- no retry loop blocks exit, local play, or a new local commit.
Changing clock, timezone, locale, sleep duration, or network availability cannot change generated names, offers, difficulty, results, or Records.
16. Confirmation, Overwrite, Delete, And Reset
These actions require an effect review and a separate confirm: dismissal with history, promotion, Artifact replacement, protected recovery-offer decline that would close a run, run abandonment, difficulty/Oath-law change, cloud branch choice, migration fallback, Guild-slot overwrite, and Guild-slot delete.
Delete moves the complete Guild slot and closure ledgers to recoverable local trash for seven successful launches or until explicit empty-trash confirmation. A profile-wide reset additionally requires selecting a displayed localized phrase in a second dialog; typing is not required. Default focus is cancel, and destructive actions cannot share a single repeated input with the opener.
Every accepted confirm receives an operation ID. Repeating it returns the first receipt and cannot dismiss, grant, overwrite, close, or delete twice.
17. Accessibility, Localization, And Input Requirements
Saving,Saved,Pending,Recovered,Sealed,Conflict, andBlockeduse text plus distinct icons, never color/spinner alone.- Closing during
Pendingis legal; recovery finalizes/rejects from intent. - Recovery and conflict dialogs support 130% UI scale, screen-reader order, complete touch path, keyboard/controller focus, and reduced motion.
- Casualty review lists generated name, Profession, equipment returned, Credit, death tick, and first cause; it does not rely on animation or sound.
- Technical IDs/hashes are hidden by default but available in details and an exportable diagnostic manifest.
- Localized messages use semantic IDs and typed values, never string fragments.
- Controller disconnect or focus loss pauses presentation and commits nothing until a new explicit confirm is accepted.
- Haptic/audio feedback may acknowledge a save or casualty but cannot be the only state indication.
18. Required Recovery And Failure Matrix
| Test | Fault/input | Expected invariant |
|---|---|---|
| Seed reservation crash | crash after begin-pending or applied pointer | same ordinal/seed; zero offers before applied draft read-back; one draft after retry |
| Offer materialization crash | crash around four-offer pointer | seed-only draft or complete indices 0..3; retry yields identical IDs/output hashes |
| Selection revision crash | revise accepted pair and crash around pointer | prior complete pair or new complete pair with one revision/receipt; never one selected ID |
| Run creation duplicate | repeat original ID or use a new ID naming the applied draft/pair | same original receipt, same seed/two Recruit records, no draft and no second Run |
| Run creation stale draft | submit old draft hash or selection revision | STALE_RUN_CREATION_DRAFT, current summary returned, zero mutation |
| Run creation cancel/restart | Cancel, Save and Quit, or process restart before commit | same draft, four offer IDs/hashes and latest durable pair; no new ordinal/seed |
| Run draft clock rollback | wall clock moves back 24 hours before Run commit | diagnostic only; same draft/offers/pair and zero gameplay delta |
| Run draft active corruption | invalid active checksum, intact draft checkpoint/backup | recover newest valid draft boundary and exact four/pair; no replacement seed |
| Run draft replica corruption | active/backups invalid, redundant creation receipts intact | rebuild same seed/four/pair, or same committed Run if commit receipt exists |
| Run draft total corruption | no valid primary, backup, checkpoint, or creation receipt | creation_recovery_blocked; quarantine/export, no new draft or free reroll |
| Pending purchase | crash after pending pointer | zero cost until deterministic applied child; one Recruit after retry |
| Applied purchase | duplicate same operation ID | one cost, one Recruit, same receipt |
| Refresh crash | crash after Coin validation | old complete board or new complete board and cost; never mixed |
| Legal dismiss duplicate | start with two live Recruits; repeat confirm | one Recruit removal, zero-or-one item return, one rebate; final live Recruit remains |
| Final dismiss preview | one live Recruit, low Coin, no protected offer | FINAL_LIVE_RECRUIT; no operation ID or mutation; Abandon Run remains separate |
| Stale final dismiss | preview at two, another serialized dismissal leaves one, submit old confirm | zero-delta FINAL_LIVE_RECRUIT; no rebate, protected offer, or count change |
| Interrupted final dismiss | recover pending intent against active count one | reject without apply/receipt beyond rejected intent response; one Recruit remains |
| Battle suspend | suspend during projectile at tick 417 | identical next event/draw counters/final hash |
| Death snapshot | crash one tick after front Recruit falls | replay contains same death and collapse |
| Outcome crash | crash before casualty settlement | locked result reopens; settlement applies exact set once |
| Casualty partial candidate | omit the non-null equipped item in candidate | validation rejects; no Recruit removal/Credit commits |
| Reward duplicate | double-tap selected card | one item/Artifact/Coin result and draft removal |
| Boss grant duplicate | replay same boss-clear result | one clear fact and Renown grant |
| Three deaths | fixed economy fixture | Recruits removed, all equipment returned, 54 Credit capped |
| Standard retreat | 10 Coin at/after tick 70 | 6 Coin fee, all earlier casualties apply, no reward |
| Wayfinder timeout | 1 Coin at tick 1500 | 1 Coin fee, living Recruits survive, no reward |
| Company collapse | zero living, 9 Coin+Credit, protected price 14 | run closes; no free Recruit invented |
| Recoverable company | zero living, 14 Coin+Credit, protected price 14 | recovery Market opens; purchase still requires confirm |
| Clock rollback | wall clock moves back 24 hours | diagnostic only; zero gameplay delta |
| Thirty-day offline | close mid-run and return | zero tick/resource/offer progress; exact recap |
| Active corruption | invalid active checksum, intact receipts/backups | reconstruct newest valid chain or seal run at stated boundary |
| Casualty receipt beyond backup | selected backup contains later-Fallen Recruit | replay casualty or seal run; never resume with Recruit |
| All battle snapshots corrupt | valid start/journal remains | replay same seed/retreat tick or seal on hash divergence |
| Migration failure | stable-ID mapping invalid | source stays active; candidate discarded; export offered |
| Cloud divergence | same lineage, different descendants | one chosen active, other read-only; no merge/duplicate slot |
| Run-close retry | crash after persistent grants before screen transition | same result, Coin/Credit remain cleared, no duplicate Renown |
19. Acceptance Checklist
- Schema, ruleset, content, lineage, commit, and operation versions are separate and migration is copy-first.
- Pending/applied/rejected operations preserve zero-delta pending and atomic cost/result receipts.
- Run creation durably reserves one seed before offer generation, stores an
all-or-nothing indexed four, receipts revisable exact-pair selection, and
promotes that same seed and pair into
current_runexactly once. - Market, battle, casualty, reward, and run-close retries are idempotent.
- Battle suspend/crash reproduces deterministic state or seals the run on an unverifiable divergence.
- Death, equipment return, Credit, dismissal, replacement, defeat, timeout, retreat, and Company collapse are explicit and testable.
- Preview, stale confirm, duplicate confirm, and interruption cannot dismiss the final living Recruit or route dismissal through casualty recovery.
- Backups, closure receipts, corruption, migration, rollback, and cloud conflicts cannot knowingly reverse casualties or duplicate rewards.
- Clock rollback and bounded offline behavior produce zero gameplay progress.
- Confirmation, delete, accessibility, localization, and input rules cover every destructive and recovery state.