Files

50 KiB

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, death, replacement, and causal diagnosis.

Revision: recruit-line-design-r2 / 2026-08-10

Product intent is defined in GAME_PRODUCT_CONTRACT.md. Prices, rewards, progression rates, capacity selection, and pacing are defined in ECONOMY_AND_BALANCE.md. Durable commit and recovery semantics are defined in SAVE_AND_FAILURE_CONTRACT.md.

1. System Invariants

  1. Each side occupies one ordered horizontal line. Position zero is front; a larger position is farther rearward. There is no second spatial axis.
  2. Allied simultaneous footprint begins at four and reaches ten. Reserve and cumulative hires are separate and never redefine this limit.
  3. Battle is automatic. The player may start, pause, change speed, inspect, or retreat, but cannot activate attacks/skills, reorder, equip, or promote while resolving.
  4. 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.
  5. Zero HP means Fallen. The Recruit leaves the resolving line immediately, never respawns in that battle, and is never replaced by Reserve during that battle. At outcome commit, that Recruit is permanently removed from the run and its equipment returns to run inventory.
  6. The same start state, ruleset, content revision, seed, and retreat timestamp produces the same state hashes and result.
  7. Display frame rate and pause/1x/2x/4x do not change simulation time or draws.
  8. Every targeting exception, failed action, movement conflict, retarget, immunity, proc suppression, and outcome has one inspectable reason.
  9. All damage has a declared type, power source, defense, rounding boundary, critical rule, modifier groups, and floor/nullification behavior.
  10. 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

run
  run_id, contract_id, difficulty_id, ruleset_version, content_revision
  generation_seed, Market index, cleared Rounds, Line capacity
  Coin, Replacement Credit, refresh/lock counters
  living Recruits, Reserve, inventory, Artifacts
  hired/fallen/dismissed totals, boss state, run 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, survived battles, 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

run_created
-> Market_open
-> battle_offer_committed
-> countdown
-> resolving
-> outcome_locked
-> diagnosis
-> reward_or_failure_applied
-> next_Market | boss_Muster | run_closed

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 run records battles entered, victories, retreats survived, allies ahead at commit, first Fallen ally witnessed, promotion, and final disposition. History may unlock a run-local title or catalog fact but cannot grant a hidden stat. After run close, only the immutable summary Record remains; the Recruit is no longer playable.

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:

  1. accept lifecycle control stamped for this tick, including retreat start;
  2. expire statuses and barriers whose end tick equals this tick;
  3. resolve periodic status events due this tick;
  4. complete casts, channels, projectile arrivals, and summon expiries;
  5. select actions for actors already ready and legal;
  6. resolve voluntary and forced movement intents;
  7. apply simultaneous damage, healing, barrier, and resource deltas by batch;
  8. finalize action-outcome records, mark zero-HP actors Fallen, and run declared outcome/death triggers once;
  9. compact lines, insert legal summons, and evaluate objective/retreat/phase;
  10. 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:

  1. required side and living/Fallen/summon state;
  2. cross-line or same-line reach;
  3. protection mode;
  4. required status, cast, HP band, or tag;
  5. exclusion, immunity, and maximum targets;
  6. 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:

  1. If a committed interrupt already cancelled the action, emit one AO_INTERRUPTED action record and stop.
  2. 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.
  3. Apply the skill's declared invalid-target policy. A successful retarget_same_policy reserves a new target and continues without refund; ground_resolve snapshots eligible current occupants at the stored depth; otherwise emit AO_FIZZLED and stop that action.
  4. Resolve current projectile/protection paths. Emit AO_INTERCEPTED for each redirected intended target, then create component records for the actual interceptor. Interception itself never counts as an applied component.
  5. 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.
  6. 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_BLOCKED for each allocation.
  7. Check declared immunity before consuming a resistance or critical draw. Emit AO_IMMUNE on rejection.
  8. For remaining resistible status components, consume and record exactly one status_apply draw. Emit AO_RESISTED when the roll fails the threshold.
  9. Queue remaining numeric/status/movement deltas for priority 7. After the simultaneous batch, emit AO_APPLIED when primary state changed or AO_NO_CHANGE when it did not.
  10. 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 to N adjacent block swaps;
  • pull N: move the target toward front through up to N swaps;
  • 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:

  1. committed allied and enemy order;
  2. predicted and actual first targets;
  3. first divergence from predicted action/target/timing;
  4. first protection change, projectile interception, or reach failure;
  5. first decisive major action and available pre-battle counter categories;
  6. every Fallen Recruit with the preceding five simulation seconds;
  7. collapse, displacement, summon-space, retarget, and proc-suppression events;
  8. effective damage, prevention, healing, control, and resource totals;
  9. 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.