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
- 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 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.
- 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
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:
- 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.