← ALL DOCUMENTS

Ω 15 — Endless Mode Generation Algorithm

15 — Endless Mode Generation Algorithm

Purpose

This document specifies the procedural generation system for Tao Baryon's endless mode. It covers the wave generation algorithm, depth-based scaling functions, enemy pool construction, formation logic, environmental hazard injection, boss insertion, reward curve, and the lore framing that ties infinite difficulty to the game's narrative.

Endless mode unlocks after Stage 30 is cleared. It is a prestige mode — not a progression shortcut. Full specification in 00_amendments.md §Amendment 4 and 03_difficulty_curve.md §Endless Mode Scaling.


Design Intent

Endless mode answers one question: how far can you go?

Every system in endless mode serves that question. The generation algorithm must feel fair at depth 5 and still be generating novel, readable, survivable-but-barely content at depth 500. It must never feel random in a frustrating way — patterns must be learnable even as they scale. And it must be narratively coherent: the deeper the player goes, the more the Apparatus's bleed-through has corrupted the physics of the region.

Three tensions the algorithm must hold:

  1. Readable vs. dense — bullets must be dodge-able up to the skill ceiling of the best possible player, even at depth 1000+
  2. Procedural vs. authored — waves must feel designed, not like random enemy soup
  3. Escalating vs. fair — difficulty must increase, but never feel arbitrary or cheap

The Depth Counter

Depth is the core variable driving all endless generation. It is an integer that increments by 1 each time a wave is fully cleared.

  • Depth 1 = first wave of endless mode
  • Depth has no cap
  • Depth persists within a single endless run; resets to 1 on run end (death or quit)
  • Depth is the only variable used for leaderboard ranking (ties broken by score)

Depth is not wave number. Every wave cleared = +1 depth, including sub-waves and continuation waves within a stage generation event. This means a player who clears a complex multi-wave sequence advances depth faster than one grinding simple singles — rewarding aggression.


Architecture Overview

The generation system runs a pipeline each time a new wave is needed:

[Depth counter]
      │
      ▼
[Difficulty Budget Calculator]
      │ produces: budget_points, density_cap, heat_level
      ▼
[Enemy Pool Selector]
      │ produces: weighted enemy_pool[]
      ▼
[Formation Template Picker]
      │ produces: formation_template
      ▼
[Wave Assembler]
      │ produces: wave_spec (enemy list, positions, timings, bullet patterns)
      ▼
[Hazard Injector]
      │ produces: hazard_list (active during this wave)
      ▼
[Event Checker]
      │ checks: boss_due? | ace_spawn? | boltzmann_event? | bleed_event?
      ▼
[Wave Executor]
      │ runs the wave, collects results
      ▼
[Reward Calculator]
      │ produces: credits, mastery_xp, shard_chance
      ▼
[Depth++, loop]

Each stage of this pipeline is defined below.


Stage 1 — Difficulty Budget Calculator

Every wave is assigned a budget expressed in abstract "threat points." Enemy units cost threat points; the assembler fills a wave with enemies until the budget is spent.

Budget Formula

base_budget = 20 + (depth × 2.5)
scaling_multiplier = 1.0 + (depth / 200)          // asymptotic, softcaps near depth 200
budget = base_budget × scaling_multiplier
budget = clamp(budget, 20, 2400)                   // hard floor and ceiling
Depth Approximate budget
1 22
10 47
25 87
50 152
100 278
200 540
500 970 (soft plateau)
1000 1380
2000 1980
5000 2390

The budget ceiling means depth 5000 is not infinitely harder than depth 1000 — the difficulty ceiling is reached through pattern complexity and hazard density, not purely through budget inflation. A wave at depth 5000 has roughly the same enemy count as depth 1000, but the pattern vocabulary is maximally complex.

Density Cap

Simultaneously, a density cap limits how many enemies can be on screen simultaneously (regardless of budget):

density_cap = clamp(8 + floor(depth / 8), 8, 65)
Depth Max simultaneous enemies
1 9
25 11
50 14
100 20
200 33
500 65 (cap)
1000+ 65 (cap holds)

The density cap prevents the screen from becoming unreadable. At the density ceiling, the algorithm must spawn enemies in waves — clearing previous enemies before introducing new ones — maintaining visual legibility.

Heat Level

Heat level is a categorical variable that drives bullet pattern selection:

heat_level = clamp(floor(depth / 25), 0, 10)
Depth range Heat level Pattern tier
0–24 0 Sector 1–2 patterns only
25–49 1 Sector 2–3 patterns
50–74 2 Sector 3 patterns
75–99 3 Sector 3–4 patterns
100–124 4 Sector 4 patterns
125–149 5 Sector 4–5 patterns
150–174 6 Sector 5 patterns
175–199 7 Sector 5 + early bullet hell
200–224 8 Bullet hell tier 1
225–249 9 Bullet hell tier 2
250+ 10 Maximum: Touhou-tier +

Stage 2 — Enemy Pool Selector

At each depth, a weighted pool of valid enemy types is constructed. The pool determines which enemies the assembler may select from.

Enemy Tier Gates

Enemy types unlock progressively by depth:

Depth gate Enemies unlocked
0 G1, G2, S1, K1 (Sector 1 basics)
10 G3, G4, S2, K2, B1, B2
20 G5, K3, B3, Sn1
30 Sn2, K4, B4
50 B5, Sn3, E1 (Choral Knight elite)
75 E2 (Inquisitor Hunter elite)
100 E3 (Geometer Saint elite) — +Boltzmann event trigger
150 E4 (Apparatus Guardian elite)
200 Ace-tier variants (all enemy types gain +30% HP, +20% speed)
350 Ace-tier variants gain second bullet pattern (simultaneous)
500 Ultra-tier variants (all enemy types gain +60% HP, +40% speed vs. base)

Weight Distribution Algorithm

Once the pool is constructed from unlocked enemy types, each enemy type is assigned a weight based on:

weight[e] = base_weight[e]
           × recency_bias(e, last_10_waves)   // reduce weight if overused recently
           × heat_preference(e, heat_level)    // snipers prefer high heat; grunts are flat
           × depth_bias(e, depth)              // elites increase in weight with depth

Recency bias ensures the player does not fight the same enemy type for 10 consecutive waves. If an enemy appeared in the last 3 waves, its weight is multiplied by 0.4. If in the last 6 waves, 0.7. Otherwise 1.0.

Heat preference maps enemy types to their ideal heat levels:

Enemy class Ideal heat Weight outside ideal
Grunts (G1–G5) 0–4 0.5× at heat 7+
Strafers (S1–S2) 2–6 0.6× at heat 0, 0.7× at heat 9+
Bombers (B1–B5) 3–7 0.5× at heat 0–1, 0.8× at heat 9+
Snipers (Sn1–Sn3) 5–9 0.4× at heat 0–2
Kamikaze (K1–K4) 0–5 0.5× at heat 8+
Elites (E1–E4) 4–10 0.6× below heat 4

Depth bias increases elite weight linearly:

elite_depth_weight = 1.0 + (depth / 100)  // E1 at depth 100 has 2× base weight vs depth 0

Stage 3 — Formation Template Picker

Enemies do not spawn randomly distributed. They spawn in formations — structured spatial arrangements that create intentional bullet geometry. A formation template defines:

  • Number of enemies
  • Spatial arrangement (line, V, diamond, arc, cluster, asymmetric)
  • Entry direction (top, side, diagonal)
  • Inter-enemy timing (simultaneous, staggered, cascading)
  • Collective firing behavior (synchronized, independent, alternating)

Formation Library

The system maintains a library of templates indexed by enemy count and heat level.

Single-enemy formations (heat 0–3):

  • Solo approach — straight down, fires independently
  • Flanker — enters from side, crosses playfield
  • Diver — enters from top, dives toward player position, pulls up

Pair formations (heat 0–5):

  • Mirror pair — symmetric left/right, synchronized fire
  • Staggered pair — one enters, second follows 0.8s later
  • Pincer — one from each side, converge on center

Trio formations (heat 1–6):

  • Triangle — nose forward, two flanking
  • Line abreast — three parallel, simultaneous entry
  • Cascading line — sequential entry left-to-right

Quad formations (heat 3–8):

  • Diamond — point lead, two mid, one trail
  • Box — two-by-two grid formation
  • Asymmetric cross — center + three off-axis

Large formations (heat 5–10):

  • Swarm cluster (6–12 light enemies) — tight, overlapping entry
  • Cross formation (5 enemies) — cardinal directions from a center anchor
  • Liturgical mandala (8 enemies) — circular, synchronized mandala fire
  • Inquisitor line (4–6 snipers) — precision-spaced, alternating fire
  • Apparatus array (6–10 mixed) — irregular grid, multi-pattern simultaneous

Formation Selection

At each wave generation step:

// pick formation size based on budget and density_cap
available_budget = wave_budget_remaining
max_formation_size = min(density_cap - current_on_screen, floor(available_budget / cheapest_enemy_cost))
formation_size = random_from_distribution(1..max_formation_size, biased toward mid-range)

// pick template from heat-appropriate formations of that size
candidates = formation_library.filter(size == formation_size AND min_heat <= heat_level)
template = weighted_random(candidates, prefer: templates not used in last 5 waves)

Stage 4 — Wave Assembler

The assembler takes a formation template and fills it with specific enemies from the weighted pool.

Fill Algorithm

procedure fill_formation(template, enemy_pool, budget_remaining):
  slots = template.slot_count
  result = []
  for slot in slots:
    candidates = enemy_pool.filter(cost <= budget_remaining / slots_remaining)
    chosen = weighted_random(candidates)
    result.append(chosen)
    budget_remaining -= chosen.cost
    slots_remaining -= 1
  return result

Slot cost table (threat points per enemy unit):

Enemy class Base cost
Grunt G1 2
Grunt G2 3
Grunt G3 4
Grunt G4 5
Grunt G5 6
Strafer S1 5
Strafer S2 8
Bomber B1 4
Bomber B2 6
Bomber B3 8
Bomber B4 11
Bomber B5 14
Sniper Sn1 9
Sniper Sn2 13
Sniper Sn3 18
Kamikaze K1 3
Kamikaze K2 4
Kamikaze K3 6
Kamikaze K4 9
Elite E1 30
Elite E2 38
Elite E3 45
Elite E4 55

Elite enemies consume a large portion of the budget. At low depths, a single elite may nearly exhaust the budget, making it the centerpiece of the wave. At high depths, the budget supports multiple elites simultaneously.

Pattern Assignment

After enemy selection, each enemy's bullet pattern is assigned from the heat-level-appropriate vocabulary:

pattern_pool = bullet_patterns.filter(min_heat_level <= heat_level)
pattern = weighted_random(pattern_pool, prefer: formation_coherence)

Formation coherence preference: when multiple enemies share a formation, the assembler prefers patterns that create complementary geometry — e.g., two snipers with alternating predictive shots create a rhythmic dodge window; two snipers both firing simultaneous waves create visual noise. The assembler enforces a coherence score and re-rolls pattern combinations below threshold 0.4.

Bullet pattern vocabulary by heat level:

Heat level Available patterns
0 Pulse, Spread
1 + Wave
2 + Predictive
3 + Spread-wide (5-shot)
4 + Spiral (slow)
5 + Spiral (medium), Mandala (small)
6 + Mandala (medium), Lensed (single curve)
7 + Cascading, Lensed (dual)
8 + Threading, Mandala (large)
9 + Spiral (fast), Threading (dense)
10 + Simultaneous multi-pattern (one enemy fires two patterns at once)

Stage 5 — Hazard Injector

Hazards are environmental obstacles injected independently of the enemy wave. They persist for a duration, then clear.

Hazard Gate Schedule

Depth Hazards available
0–24 None
25–49 Exotic Matter Clouds (visual, mild projectile curves)
50–99 + Gravitational Lensing Zones (visual warning of lensed bullets)
100–149 + Moving Lensing Zones (drift slowly across screen)
150–199 + Time-Dilated Zones (player and enemies slow inside)
200–299 + Erupting Exotic Clouds (expand then collapse, 8s cycle)
300–499 + Cosmic Strings (thin instant-kill lines, slow drift)
500+ + Spacetime Collapse Zones (region with increasing damage over time)

Hazard Injection Probability

hazard_chance = clamp((depth - 20) / 300, 0.0, 0.75)
// at depth 20: 0%, depth 50: 10%, depth 100: 26%, depth 200: 60%, depth 320+: 75%

When a hazard is injected, exactly one hazard type is selected (weighted toward recently-unused types). Multiple hazards can be active simultaneously only at depth 200+, with probability:

double_hazard_chance = clamp((depth - 200) / 400, 0.0, 0.4)
// at depth 200: 0%, depth 400: 50% of hazard-waves have two hazards, depth 600+: 40% cap

Cosmic strings at depth 300+ have a mandatory telegraph: a thin visual indicator appears 2 seconds before the string materializes, giving the player time to clear the zone. The string drifts at a predictable speed. This is lore-justified — the strings are real physics tears, not attacks; they move according to physics, not toward the player.


Stage 6 — Event Checker

After the wave is assembled but before it executes, the event checker runs special event triggers.

Boss Events

Every 50 depths, a boss event triggers, replacing the normal wave entirely:

Depth Boss event
50 Reverent Maelin (rematch, S1 boss) — 50% HP vs. campaign version
100 Final Chorus (rematch, S2 boss) — 70% HP
150 Inquisitor Cohort (rematch, S3 boss) — 85% HP
200 Mathematician-Saint Voren (rematch, S4 boss) — 100% HP + Endless Adaptation
250 Architect-Saint Halen Fragment — a sub-instance of Halen's consciousness, 800 HP (vs 2500 campaign), single-phase, uses Phase 2 patterns
300 Maelin rematch v2 — 120% HP, new pattern additions
350+ Boss cycle restarts with +20% HP scaling per 50-depth cycle

Endless Adaptation (depth 200+ bosses): Bosses in endless mode gain a new passive — each time they lose a phase (70% / 40% threshold), they temporarily gain +25% fire rate and +15% movement speed for 10 seconds. This is the "Endless Corruption" mechanic, narratively explained as the Apparatus bleed-through affecting even the Telos commanders' control systems.

Halen Fragment (depth 250): Not a full boss fight. Lore framing: "A shard of the uploaded consciousness, adrift in the bleed-through field. It fights without purpose — but it still knows how." Uses Phase 2's Integrated Mind patterns. No dialogue. Silent. Its death animation is different from the campaign version — it doesn't implode cleanly; it scatters, like a shattered mirror.

Boltzmann Events (depth 100+)

At depth 100+, with probability:

boltzmann_chance = clamp((depth - 100) / 500, 0.0, 0.25)

A Boltzmann Construct spawns mid-wave alongside normal enemies. It is not a standard enemy — it is a rare anomaly. Stats:

  • HP: 250 (depth 100) scaling to 800 (depth 500+)
  • Behavior: Erratic. Moves with pseudo-random direction changes every 0.8–1.5s. Fires Boltzmann Cascade patterns (matches the W8 weapon identity). Does not pursue player.
  • On death: Drops a guaranteed rare reward (see Reward Calculator)
  • Visual: Flickering silhouette — the sprite is unstable, shifting between 3–4 frames of a partially-realized form. Warm orange-purple color scheme. No clean outline.
  • Lore: "Statistical mechanics predicts that in a sufficiently high-entropy field, coherent structure can spontaneously emerge. Usually, it lasts microseconds. In the bleed-through zone, it lasts longer."

Bleed-Through Events (depth 200+)

At depth 200+, with probability:

bleed_chance = clamp((depth - 200) / 600, 0.0, 0.35)

A Bleed-Through Event triggers. This is a brief environmental disruption (5–8 seconds) where:

  • All bullet patterns on screen shift by one heat tier upward temporarily
  • Enemy HP does not change
  • The screen briefly desaturates at the edges
  • Sira-Vel's voice (pre-recorded fragment, not generated): "Physics integrity degrading. Hold position."

The event ends cleanly. It is a skill check — survive the brief escalation.


Stage 7 — Reward Calculator

Endless mode rewards are calculated per wave cleared, not per stage.

Per-Wave Rewards

base_credits = 15 + (depth × 0.8)
combo_multiplier = current_score_multiplier  // same 1×–10× system as campaign
wave_credits = floor(base_credits × combo_multiplier × 0.80)  // 80% of equivalent campaign rate

The 0.80 factor is the endless mode credit discount (see 00_amendments.md §Amendment 6, 09_economy.md). This ensures campaign remains the efficient path for credit grinding.

Pilot XP: 0. Endless mode does not contribute to Pilot Rank. This is a hard design decision — endless is mastery territory, not progression territory.

Ship Mastery XP: 100% rate. Endless is the best place to master a ship because run duration is limited only by skill, not by content volume.

Depth Milestone Rewards

At specific depth milestones, one-time rewards trigger (per endless run):

Depth Reward
10 200 bonus credits
25 1 Blueprint Shard
50 500 bonus credits + boss clear bonus
75 2 Blueprint Shards
100 800 bonus credits + Boltzmann unlocks
125 3 Blueprint Shards
150 1,200 bonus credits
200 2,000 bonus credits + 5 Blueprint Shards + Voren encounter bonus
250 3,000 bonus credits + Halen Fragment bonus + 1 Veiled Token
300 4,000 bonus credits + 8 Blueprint Shards + 1 Veiled Token
500 6,000 bonus credits + 12 Blueprint Shards + 2 Veiled Tokens
1000 12,000 bonus credits + 20 Blueprint Shards + 3 Veiled Tokens + cosmetic title

Cosmetic title at depth 1000: "Beyond Physics" — displayed on the pilot profile and leaderboard entry.

Boltzmann Construct Rare Drops

When a Boltzmann Construct is killed, it drops one of:

Reward Weight
2 Blueprint Shards 40%
4 Blueprint Shards 25%
1 Veiled Token 20%
500 bonus credits 10%
Exclusive cosmetic shard 5%

Exclusive cosmetic shards are only obtainable from Boltzmann Constructs — they unlock cosmetics unavailable in the shop (engine trail colors, hull decal patterns). This makes hunting Boltzmann Constructs a meaningful secondary objective within endless runs.


The Lore Escalation Curve

The depth counter drives not only mechanical difficulty but a narrative escalation. The deeper the player goes, the more the Apparatus's bleed-through has eroded the physics of the engagement zone. This is reflected in:

Visual Progression

Depth range Visual state
1–50 Normal deep-space background, stable colors
50–100 Subtle edge distortion, occasional lensing shimmer
100–200 Background color temperature shifts warmer, particle density increases
200–300 Screen edges show physics-tear artifacts (brief pixel displacement)
300–500 Background geometry becomes partially abstract — star fields warp and stretch
500–1000 Near-full abstraction. The "background" is now patterns of light and distortion. Enemy sprite edges flicker.
1000+ The playfield is barely recognizable as space. Light bends in real-time. Enemy colors shift toward Apparatus-gold. The game's UI elements flicker at the edges.

Design constraint: The HUD (HP bar, heat bar, score, depth counter) remains fully readable at all depths. The visual degradation affects only background and enemy sprites — never the player ship or UI chrome.

Audio Progression

Depth range Audio state
1–50 Sector 5 music theme (ambient, cosmological)
50–150 Music layers drop out one by one
150–300 Only bass drone and percussion remain
300–500 Irregular choral fragments (Telos liturgical, distorted)
500–1000 Near-silence; occasional sub-bass impact sounds
1000+ Sub-bass only; the sound of gravity

NPC Transmission Fragments

At specific depths, Sira-Vel and Veth transmit brief pre-recorded fragments. These are not generated — they are authored lines:

Depth Speaker Transmission
25 Sira-Vel "You're going deeper than our telemetry suggested. Keep moving."
50 Sira-Vel "Signal strength degrading. Whatever you're finding out there — come back."
100 Veth "The constructs at this depth aren't Telos. They're not anything. Thermal noise given momentum. Fascinating and deeply unsettling."
150 Sira-Vel "We're losing your position on our scans. I'm keeping the channel open."
200 Veth "Voren's calculations did not include this. I suspect he would have been disturbed. Perhaps that is something."
250 Sira-Vel "That was a piece of Halen. A fragment of the uploaded mind, scattered in the bleed-through field. He is already breaking apart. Whatever he was, Commander — it did not survive the machine."
300 Veth "I cannot calculate what you are flying through. That is the first time I have said those words."
500 Sira-Vel "[long static] ...still here. Keep flying."
1000 No transmission. Silence. Then a single tone — the same tone that played in Stage 30 when Halen died.

Pseudo-Code Summary

// Core endless loop — called when previous wave is cleared
EndlessWave generate_wave(int depth) {
  // 1. Budget
  double budget = clamp(20 + depth * 2.5 * (1.0 + depth / 200.0), 20, 2400);
  int density_cap = clamp(8 + depth ~/ 8, 8, 65);
  int heat_level = clamp(depth ~/ 25, 0, 10);

  // 2. Check special events
  if (depth % 50 == 0) return generate_boss_event(depth);
  if (roll(boltzmann_chance(depth))) inject_boltzmann_construct();
  if (roll(bleed_chance(depth))) schedule_bleed_event();

  // 3. Enemy pool
  List<EnemyType> pool = build_pool(depth, heat_level, recent_history);

  // 4. Formation
  FormationTemplate template = pick_formation(budget, density_cap, heat_level);

  // 5. Fill
  List<Enemy> enemies = fill_formation(template, pool, budget);

  // 6. Patterns
  for (Enemy e in enemies) {
    e.pattern = pick_pattern(heat_level, template, e.type);
  }

  // 7. Hazards
  List<Hazard> hazards = inject_hazards(depth, heat_level);

  // 8. Milestone reward
  if (depth in MILESTONE_DEPTHS) grant_milestone_reward(depth);

  return EndlessWave(enemies, template, hazards);
}

double boltzmann_chance(int depth) =>
    depth < 100 ? 0.0 : clamp((depth - 100) / 500.0, 0.0, 0.25);

double bleed_chance(int depth) =>
    depth < 200 ? 0.0 : clamp((depth - 200) / 600.0, 0.0, 0.35);

Leaderboard Integration

Endless mode submits scores to the platform leaderboard (Google Play Games / Apple Game Center) on run end (death or quit).

Score submitted:

score = depth × 1000 + total_credits_earned_this_run

Depth is the primary component (1000 points per depth) and credits secondary. This means reaching depth 100 with modest play (100,000 + credits) ranks above someone who reached depth 99 with exceptional play. Depth first, score second.

Leaderboard types:

  • Global all-time
  • Friends (platform friends list)
  • Monthly seasonal (resets first of each month; seasonal-exclusive cosmetic for top 100)

Score sanity filter: Scores with depth > (Pilot Rank × 20 + 200) are flagged as implausible and excluded from leaderboard submission locally. This is a heuristic, not anti-cheat — it simply avoids contributing clearly-modified saves to the public leaderboard.


Summary — Locked Decisions

  1. Depth counter increments per wave cleared, no cap, is the only leaderboard metric
  2. Budget formula: clamp(20 + depth × 2.5 × (1 + depth/200), 20, 2400)
  3. Density cap: clamp(8 + depth/8, 8, 65) — hard max 65 enemies on screen
  4. Heat level: clamp(depth/25, 0, 10) — drives bullet pattern vocabulary
  5. Enemy pool: weighted selection with recency bias, heat preference, depth bias
  6. Formations: template library, formation coherence scoring, anti-repeat weighting
  7. Boss events every 50 depths — rematch cycle with HP scaling
  8. Boltzmann Constructs depth 100+ — rare anomaly, exclusive cosmetic drop source
  9. Bleed-Through Events depth 200+ — brief bullet pattern escalation, authored NPC lines
  10. Cosmic strings gate: depth 300 — mandatory 2s telegraph before materialization
  11. Rewards: 80% credit rate vs. campaign, 0 Pilot XP, 100% Ship Mastery XP
  12. Depth milestones — one-time bonus rewards per run
  13. Visual/audio degradation — full abstraction at depth 1000+, HUD always readable
  14. NPC transmissions — 10 authored fragments at depth milestones, silence at 1000
  15. Leaderboard score: depth × 1000 + run_credits, platform-submitted, monthly seasonal

Document version: 1.0 (locked) Part of: Tao Baryon GDD — Tier 3 Meta Systems