# Epic Survivors — Code Inventory & Line Counts

> Snapshot of every source file in the repository with line counts, grouped by what actually ships in the retail game vs. what's compiled-but-stripped (dev tools / autotest) vs. what never leaves the dev machine (unit tests, editor, build-time analyzers).

Generated from `wc -l` over each tracked file. "Lines" means raw line count including blanks, comments, and braces (not SLOC). Excludes `bin/`, `obj/`, `Backup/`, `Downloads/`, vendored content (`MonoGame.ImGuiNet/`, `ThirdParty/`).

---

## 📊 At A Glance

**804 first-party files • 133,126 lines of code + data • ~108K actually running in retail**

```mermaid
pie showData title Language breakdown (first-party code + data)
    "C# (.cs) — 116,800 lines" : 116800
    "YAML (.yaml) — 16,326 lines" : 16326
```

```mermaid
pie showData title Where does the C# go? (116,800 lines total)
    "SHIPPED — active in retail builds" : 92400
    "SHIPPED-STRIPPED — compiled but inert in Demo" : 14350
    "EDITOR-TOOL — separate project, never ships" : 5372
    "TEST-ONLY — only for dotnet test" : 4696
```

### The answer to "how big is this game?"

| | Files | Lines |
|---|---:|---:|
| **C#** | 430 | **116,800** |
| **YAML** | 374 | **16,326** |
| **Combined first-party** | **804** | **133,126** |

Retail binary that actually runs in a player's hands (Demo build with dev tools stripped):
**~92K lines of C# + ~16K lines of YAML data = ~108K shipped.**
The remaining ~25K lines are tooling: Avalonia config editor, Roslyn analyzers, atlas/config bundlers, unit test suites, F1–F6 ImGui debug menus, autotest / autoplay / godmode harness, in-engine profiler / flame graph / entity inspector.

---

## 🏗️ Where it all fits

The system architecture (engine layer ↔ framework layer ↔ game layer) is documented in the master diagram. This inventory is the "per-file receipt" that sits behind it.

[![Master Architecture](images/MASTER_ARCHITECTURE.svg)](images/MASTER_ARCHITECTURE.svg)

---

## 🎯 Category Legend

- **SHIPPED** — part of the game binary, active in every build type, runs for every player.
- **SHIPPED‑STRIPPED** — compiled into the game binary, but only does something when the player explicitly opts in (env var `EPIC_DEVTOOLS=1`, CLI flag like `--autotest`, or a DEBUG-only build). Retail customers on Steam never see this. In `Demo` build config it's either compile-stripped entirely or guarded behind `BuildGuards` so the hotkeys / flags do nothing.
- **TEST-ONLY** — only referenced by `dotnet test -f net8.0-windows`. Not in the game `.csproj`'s compile output.
- **EDITOR-TOOL** — a separate project or build-time tool. Runs on the dev machine, never ships to players.

**Build flag hierarchy**

```
DEMO (strips everything debug)
  > DEVTOOLS (enables F1 menu in Release)
    > DEBUG (full dev mode)
      > default Release (no tools)
```

---

## 📈 The biggest files

```mermaid
---
config:
    xyChart:
        width: 900
        height: 500
        xAxis:
            labelFontSize: 12
---
xychart-beta horizontal
    title "Top 15 largest C# files (lines)"
    x-axis ["Bazooka.yaml (3)", "Shuriken.cs (38)", "BulletCurtain (465)", "HUD (2484)", "TestModeUI (2544)", "DebugMenuImGui (2519)", "Player (2729)", "Enemy (2849)", "AnimationComponent (2965)", "Game1 (3351)", "LevelBase (4003)"]
    y-axis "Lines" 0 --> 4200
    bar [3, 38, 465, 2484, 2544, 2519, 2729, 2849, 2965, 3351, 4003]
```

The single biggest shipping files:

| File | Lines | Category |
|---|---:|---|
| `GameEngineFramework/Core/LevelBase.cs` | **4,003** | SHIPPED — base gameplay loop |
| `Game1.cs` | **3,351** | SHIPPED — MonoGame entry |
| `Scripts/Gameplay/Systems/AnimationComponent.cs` | **2,965** | SHIPPED — atlas-aware animation |
| `Scripts/Entities/Enemies/Enemy.cs` | **2,849** | SHIPPED — 228-enemy base class |
| `Scripts/PlayerModule/Player.cs` | **2,729** | SHIPPED |
| `GameEngineFramework/UI/TestModeUI.cs` | **2,544** | SHIPPED‑STRIPPED |
| `Scripts/UI/DebugMenuImGui.cs` | **2,519** | SHIPPED‑STRIPPED — F1 menu |
| `GameEngineFramework/UI/HUD.cs` | **2,484** | SHIPPED |
| `Scripts/Testing/TestController.cs` | **1,596** | SHIPPED‑STRIPPED — autotest |
| `Scripts/Scenes/Menus/SkillTreeTestScene.cs` | **1,519** | SHIPPED |
| `GameEngineFramework/Core/EnemyManager.cs` | **1,635** | SHIPPED |
| `GameEngineFramework/Core/EnemySpawner.cs` | **1,267** | SHIPPED — waves |
| `Scripts/Gameplay/Systems/TileMap.cs` | **1,453** | SHIPPED |
| `Scripts/Gameplay/Systems/LevelUpSystem.cs` | **1,376** | SHIPPED |
| `Scripts/Scenes/Menus/ResultSceneBase.cs` | **1,386** | SHIPPED |

---

## 🧩 Top-level directory map

```mermaid
graph LR
    ROOT["/ (repo root)"]
    ROOT --> GAME[Game code]
    ROOT --> DEV[Dev-only code]
    ROOT --> DATA[YAML data]

    GAME --> G1["Game1.cs (3,351)"]
    GAME --> GEF["GameEngineFramework/<br/>51 files · 22,378 lines"]
    GAME --> SCR["Scripts/<br/>309 files · 80,435 lines"]

    DEV --> TESTS["Tests/<br/>24 files · 4,696 lines<br/>TEST-ONLY"]
    DEV --> ED["EpicSurvivorsConfigEditor/<br/>24 files · 3,876 lines<br/>EDITOR-TOOL"]
    DEV --> TOOLS["Tools/<br/>12 files · 1,011 lines<br/>EDITOR-TOOL"]
    DEV --> AN["EpicSurvivors.Analyzers/<br/>4 files · 485 lines<br/>EDITOR-TOOL (Roslyn)"]

    DATA --> CFG["Config/<br/>374 YAML files · 16,326 lines"]

    style GAME fill:#1e3a5f,stroke:#00d4ff,color:#fff
    style DEV fill:#3f2a1a,stroke:#ff8800,color:#fff
    style DATA fill:#1a3f2a,stroke:#4ade80,color:#fff
```

---

## 🎮 Root-Level C# Files — SHIPPED

| File | Lines | Purpose |
|---|---:|---|
| `Game1.cs` | 3,351 | MonoGame main class — game loop, graphics, input, audio, ImGui integration |
| `Program.cs` | 461 | Entry point — ConfigRegistry init, logging, assembly preloading, creates Game1 |
| `ObfuscationPreserve.cs` | 33 | Marks types safe from Release-build obfuscator |
| `GlobalUsings.cs` | 33 | Global `using` directives |
| `GlobalSuppressions.cs` | 18 | Compiler / analyzer warning suppressions |
| `Interfaces/IGame.cs` | 11 | Game interface |
| `Properties/EpicAssemblyInfo.cs` | 12 | Assembly metadata |
| **Subtotal** | **3,919** | |

---

## ⚙️ `GameEngineFramework/` — Game Engine Layer

Generic engine pieces sitting above MonoGame. `LevelBase.cs` is the beating heart of a run — spawn loops, waves, events, pickups, camera.

### `GameEngineFramework/Core/` — SHIPPED

| File | Lines |
|---|---:|
| `LevelBase.cs` | 4,003 |
| `EnemyManager.cs` | 1,635 |
| `EnemySpawner.cs` | 1,267 |
| `LevelManager.cs` | 258 |
| `StateMachine.cs` | 253 |
| `SceneManager.cs` | 227 |
| `Wave.cs` | 189 |
| `Camera.cs` | 155 |
| `Scene.cs` | 64 |
| `ContentLoader.cs` | 54 |
| `IDrawable.cs` | 9 |
| `Extensions/ViewportExtensions.cs` | 15 |
| **SHIPPED subtotal** | **8,129** |
| `DummyGraphicsDeviceService.cs` | 16 (**TEST-ONLY** — headless graphics stub) |

### `GameEngineFramework/Core/Events/` — SHIPPED

The event system — BulletCurtain dodging, HoldArea zones, CatchTheOrb, Rhythm events, etc.

| File | Lines |
|---|---:|
| `EnemyEvent.cs` | 736 |
| `RhythmEvent.cs` | 715 |
| `HoldAreaEvent.cs` | 483 |
| `BulletCurtainEvent.cs` | 465 |
| `ConnectTheDotsEvent.cs` | 420 |
| `CatchTheOrbEvent.cs` | 375 |
| `HazardEvent.cs` | 281 |
| `AmbushSwarmEvent.cs` | 234 |
| `Event.cs` | 192 |
| `TreasureEvent.cs` | 153 |
| `EasyEventLoopEvent.cs` | 141 |
| `PickupEvent.cs` | 37 |
| **Subtotal** | **4,232** |

### `GameEngineFramework/UI/`

HUD, buttons, sliders, level-up UI, event card selection UI. `TestModeUI` is the only stripped file here.

| File | Lines | Category |
|---|---:|---|
| `HUD.cs` | 2,484 | SHIPPED |
| `TestModeUI.cs` | 2,544 | **SHIPPED‑STRIPPED** (F1 test mode overlay) |
| `LevelUpUI.cs` | 1,097 | SHIPPED |
| `Button.cs` | 480 | SHIPPED |
| `IconRenderer.cs` | 355 | SHIPPED |
| `EventCardSelectionUI.cs` | 347 | SHIPPED |
| `ArcadeFontRenderer.cs` | 300 | SHIPPED |
| `AnimatedCursor.cs` | 289 | SHIPPED |
| `Dropdown.cs` | 285 | SHIPPED |
| `ConfirmationDialog.cs` | 259 | SHIPPED |
| `Scrollbar.cs` | 234 | SHIPPED |
| `ArcadeFontConfig.cs` | 213 | SHIPPED |
| `DirectionalIndicator.cs` | 205 | SHIPPED |
| `ChestRewardUI.cs` | 173 | SHIPPED |
| `DashIndicator.cs` | 153 | SHIPPED |
| `EventAnnouncement.cs` | 113 | SHIPPED |
| `Slider.cs` | 111 | SHIPPED |
| `FontManager.cs` | 107 | SHIPPED |
| `Label.cs` | 70 | SHIPPED |
| `UIConstants.cs` | 47 | SHIPPED |
| `KeyBindingButton.cs` | 32 | SHIPPED |
| `UIElement.cs` | 27 | SHIPPED |
| `MenuController.cs` | 3 | SHIPPED |

### `GameEngineFramework/Extensions/` + `Utilities/` — SHIPPED

| File | Lines |
|---|---:|
| `Extensions/SpriteBatchExtensions.cs` | 36 |
| `Utilities/StringUtilities.cs` | 20 |
| `Utilities/ColorExtensions.cs` | 17 |

**`GameEngineFramework/` total: 51 files, 22,378 lines** (of which 2,544 is stripped TestModeUI and 16 is test-only DummyGraphicsDeviceService).

---

## 📜 `Scripts/` — Game Logic (309 files, 80,435 lines)

### `Scripts/Abilities/` — SHIPPED

Special abilities used by characters (ground pounds, barrages, multi-rockets).

| File | Lines |
|---|---:|
| `HammerSmash.cs` | 673 |
| `WhirlwindSlash.cs` | 455 |
| `SparkshardBarrage.cs` | 350 |
| `Ability.cs` | 105 |
| `IonstormWarhead.cs` | 54 |
| `IDebugHitboxProvider.cs` | 26 |

### `Scripts/Analysis/` — SHIPPED‑STRIPPED (offline simulation)

Weapon-acquisition math; not wired into retail play, only run from dev test harnesses.

| File | Lines |
|---|---:|
| `WeaponAcquisitionSimulator.cs` | 396 |
| `WeaponSimulationRunner.cs` | 67 |

### `Scripts/Diagnostics/` — SHIPPED‑STRIPPED (opt-in)

JSONL perf telemetry. Dormant unless `--perf-log`, `EPIC_PERF_LOG_AUTO`, or the F6 profiler is enabled.

| File | Lines |
|---|---:|
| `PerformanceTelemetryService.cs` | 551 |
| `AutonomousPerformanceLogging.cs` | 47 |
| `PerformanceSnapshotData.cs` | 26 |
| `PerformanceMemorySnapshot.cs` | 21 |

### `Scripts/Effects/` — SHIPPED

| File | Lines |
|---|---:|
| `SlimeEffect.cs` | 189 |

### `Scripts/Entities/` — SHIPPED

Entity base + destructible terrain objects.

| File | Lines |
|---|---:|
| `DestructibleTerrainObject.cs` | 210 |
| `Entity.cs` | 66 |

### `Scripts/Entities/Enemies/` — SHIPPED

`Enemy.cs` is the 2,849-line base class for all 228 enemies. Boss system, movement, drops, pickup config.

| File | Lines |
|---|---:|
| `Enemy.cs` | 2,849 |
| `EnemyMovementManager.cs` | 607 |
| `Boss.cs` | 576 |
| `EnemyDropManager.cs` | 486 |
| `BossPart.cs` | 464 |
| `BossPhase.cs` | 352 |
| `EnemyConfiguration.cs` | 212 |
| `BossPhaseConfig.cs` | 187 |
| `SharedHealthPool.cs` | 145 |
| `PickupConfiguration.cs` | 47 |
| `BehaviorConfig.cs` | 42 |
| `IBossPart.cs` | 20 |
| `BossType.cs` | 12 |
| `IDamageable.cs` | 11 |

### `Scripts/Entities/Enemies/Behaviors/` — SHIPPED

Modular behavior components attached to enemies via YAML `behaviors:` array.

> See the SlimeQueen anatomy diagram below — a 260-line YAML file composes 4 of these behaviors + 4 states + 3 spawned enemy types with zero boss-specific C# code.

[![SlimeQueen Anatomy](images/SLIMEQUEEN_ANATOMY_FULL.png)](images/SLIMEQUEEN_ANATOMY_FULL.svg)

| File | Lines |
|---|---:|
| `ArmorBreakBehavior.cs` | 442 |
| `BerserkOnLowHealthBehavior.cs` | 436 |
| `ShieldBehavior.cs` | 366 |
| `ReflectShieldBehavior.cs` | 340 |
| `DeathEffectsBehavior.cs` | 320 |
| `ContinuousSummonBehavior.cs` | 292 |
| `FormationBehavior.cs` | 263 |
| `HitEffectsBehavior.cs` | 256 |
| `FreezeOnLookBehavior.cs` | 199 |
| `AttackOnDeathBehavior.cs` | 189 |
| `DropOnDeathBehavior.cs` | 171 |
| `SlimeTrailBehavior.cs` | 157 |
| `GlowBehavior.cs` | 139 |
| `FleeOnHitBehavior.cs` | 122 |
| `SplitOnDeathBehavior.cs` | 121 |
| `DashOnHitBehavior.cs` | 107 |
| `DropOnHitBehavior.cs` | 104 |
| `InvulnerabilityOnHitBehavior.cs` | 90 |
| `BlocksPiercingBehavior.cs` | 69 |
| `EnemyBehaviorBase.cs` | 50 |
| `IEnemyBehavior.cs` | 26 |
| `FormationConfig.cs` | 18 |
| `FormationType.cs` | 14 |

### `Scripts/Entities/Enemies/Behaviors/DropPatterns/` — SHIPPED

| File | Lines |
|---|---:|
| `DropPatternLoader.cs` | 45 |
| `RandomDropPattern.cs` | 31 |
| `CircleDropPattern.cs` | 30 |
| `ExplosionDropPattern.cs` | 29 |
| `IDropPattern.cs` | 12 |

### `Scripts/Entities/Enemies/States/` — SHIPPED

AI state machines per enemy (charge, chase, beam attack, etc.).

| File | Lines |
|---|---:|
| `BeamAttack.cs` | 754 |
| `ProjectileAttack.cs` | 739 |
| `JumpAttack.cs` | 539 |
| `State.cs` | 524 |
| `LinearHazardAttack.cs` | 393 |
| `StatusEffectAttack.cs` | 367 |
| `HazardAttack.cs` | 326 |
| `ChargeAttack.cs` | 238 |
| `Chase.cs` | 70 |

### `Scripts/Entities/Pickups/` — SHIPPED

| File | Lines |
|---|---:|
| `Pickup.cs` | 417 |
| `PickupFactory.cs` | 285 |
| `ChestPickup.cs` | 236 |
| `MagnetPickup.cs` | 38 |
| `PickupConfig.cs` | 23 |
| `ChestPickupConfig.cs` | 15 |

### `Scripts/GameEngineFramework/` — SHIPPED

Extra engine-framework helpers that live inside `Scripts/` rather than the top-level `GameEngineFramework/`.

| File | Lines |
|---|---:|
| `Core/ContentPreloader.cs` | 240 |
| `UI/MenuController.cs` | 254 |
| `UI/UIProgressBar.cs` | 50 |

### `Scripts/Gameplay/AI/` — SHIPPED

| File | Lines |
|---|---:|
| `StateConfiguration.cs` | 226 |
| `IState.cs` | 19 |

### `Scripts/Gameplay/Achievements/` — SHIPPED

| File | Lines |
|---|---:|
| `AchievementSystem.cs` | 511 |
| `Achievement.cs` | 63 |
| `AchievementRequirements.cs` | 26 |
| `AchievementReward.cs` | 14 |

### `Scripts/Gameplay/Combat/` — SHIPPED

| File | Lines |
|---|---:|
| `AttackExecutor.cs` | 317 |
| `BeamEntity.cs` | 258 |
| `HazardZone.cs` | 205 |
| `BombEntity.cs` | 180 |
| `CombatRenderingUtils.cs` | 146 |

### `Scripts/Gameplay/Effects/` — SHIPPED

| File | Lines |
|---|---:|
| `AreaEffect.cs` | 147 |

### `Scripts/Gameplay/StatusEffects/` — SHIPPED

| File | Lines |
|---|---:|
| `PoisonStatusEffect.cs` | 87 |
| `BurnStatusEffect.cs` | 55 |
| `FreezeStatusEffect.cs` | 54 |
| `SlowStatusEffect.cs` | 50 |
| `StatusEffect.cs` | 41 |

### `Scripts/Gameplay/Systems/` — SHIPPED (with noted exceptions)

The single biggest directory in the project. Core runtime systems: rendering, particles, physics, input, save/load, achievements, level-up, settings, Steam, terrain, tilemap, unlocks.

| File | Lines | Category |
|---|---:|---|
| `AnimationComponent.cs` | 2,965 | SHIPPED |
| `TileMap.cs` | 1,453 | SHIPPED |
| `LevelUpSystem.cs` | 1,376 | SHIPPED |
| `EntityInspector.cs` | 997 | **SHIPPED‑STRIPPED** (F4 click-to-inspect) |
| `InputManager.cs` | 815 | SHIPPED |
| `SettingsManager.cs` | 701 | SHIPPED |
| `AudioManager.cs` | 647 | SHIPPED |
| `PhysicsSystem.cs` | 584 | SHIPPED |
| `TerrainGenerator.cs` | 566 | SHIPPED |
| `SnapshotSystem.cs` | 534 | SHIPPED |
| `CollisionHandler.cs` | 524 | SHIPPED |
| `TilesetManager.cs` | 430 | SHIPPED |
| `PassiveUpgrade.cs` | 399 | SHIPPED |
| `HitboxVisualizationSystem.cs` | 388 | **SHIPPED‑STRIPPED** (F8 hitbox overlay) |
| `RunStatsTracker.cs` | 385 | SHIPPED |
| `PlayerManager.cs` | 348 | SHIPPED |
| `OptimizedParticleSystem.cs` | 330 | SHIPPED |
| `SaveSystem.cs` | 324 | SHIPPED |
| `UnlockManager.cs` | 308 | SHIPPED |
| `GemCondensationManager.cs` | 285 | SHIPPED |
| `SteamManager.cs` | 268 | SHIPPED |
| `StreamingBackgroundManager.cs` | 215 | SHIPPED |
| `XPGemTierManager.cs` | 211 | SHIPPED |
| `PickupManager.cs` | 205 | SHIPPED |
| `TextureAtlas.cs` | 204 | SHIPPED |
| `EnemyMessageManager.cs` | 178 | SHIPPED |
| `SpriteOffsetRegistry.cs` | 177 | SHIPPED |
| `TutorialSystem.cs` | 173 | SHIPPED |
| `AnimationComponentPool.cs` | 170 | SHIPPED |
| `BloodParticleEmitter.cs` | 157 | SHIPPED |
| `PermanentUpgrade.cs` | 141 | SHIPPED |
| `DeferredWorkQueue.cs` | 137 | SHIPPED |
| `FireParticleEmitter.cs` | 135 | SHIPPED |
| `DamageNumber.cs` | 127 | SHIPPED |
| `ParticleSystem.cs` | 125 | SHIPPED |
| `DamageNumberManager.cs` | 124 | SHIPPED |
| `PermanentUpgradeManager.cs` | 118 | SHIPPED |
| `TilesetConfig.cs` | 114 | SHIPPED |
| `PlayAreaBoundary.cs` | 113 | SHIPPED |
| `GlobalHealthPotionDropManager.cs` | 112 | SHIPPED |
| `PassiveUpgradeConfigLoader.cs` | 111 | SHIPPED |
| `SimplexNoise.cs` | 96 |  SHIPPED |
| `HealingNumberManager.cs` | 82 | SHIPPED |
| `RewardGenerator.cs` | 81 | SHIPPED |
| `YamlExtensions.cs` | 73 | SHIPPED |
| `HealingNumber.cs` | 69 | SHIPPED |
| `DefaultSettings.cs` | 59 | SHIPPED |
| `DamageAggregator.cs` | 54 | SHIPPED |
| `Particle.cs` | 42 | SHIPPED |
| `EnemyDamageCalculator.cs` | 38 | SHIPPED |
| `InputEnums.cs` | 25 | SHIPPED |
| `PlayerDamageCalculator.cs` | 25 | SHIPPED |
| `BackgroundManager.cs` | 19 | SHIPPED |
| `ICollidable.cs` | 16 | SHIPPED |
| `IPowerup.cs` | 15 | SHIPPED |

#### `Scripts/Gameplay/Systems/AutoPlay/` — SHIPPED‑STRIPPED

AI that pilots the player during autotests / benchmarks. `--autoplay` flag only works in DEBUG or with `EPIC_DEVTOOLS=1`; Release ignores it.

| File | Lines |
|---|---:|
| `SkilledAutoPlayStrategy.cs` | 1,109 |
| `SharedAIState.cs` | 281 |
| `AutoPlaySystem.cs` | 239 |
| `AutoPlayDebugUI.cs` | 209 |
| `BaseAutoPlayStrategy.cs` | 173 |
| `RandomAutoPlayStrategy.cs` | 116 |
| `AutoPlayConfig.cs` | 64 |
| `IAutoPlayStrategy.cs` | 27 |
| `ProjectileImpactPrediction.cs` | 12 |

#### `Scripts/Gameplay/Systems/Broadphase/` — SHIPPED

Spatial indexes (QuadTree + SpatialHash) used by collision.

| File | Lines |
|---|---:|
| `SpatialHashBroadphase.cs` | 177 |
| `QuadTreeBroadphase.cs` | 118 |
| `BroadphaseFactory.cs` | 49 |
| `IBroadphase.cs` | 38 |
| `BroadphaseSettings.cs` | 31 |
| `PhysicsConstants.cs` | 9 |

#### `Scripts/Gameplay/Systems/CloudSave/` — SHIPPED

| File | Lines |
|---|---:|
| `FallbackCloudSaveProvider.cs` | 113 |
| `LocalCloudSaveProvider.cs` | 31 |
| `SteamCloudSaveProvider.cs` | 31 |
| `ICloudSaveProvider.cs` | 11 |

#### `Scripts/Gameplay/Systems/EventCards/` — SHIPPED

Augment/modifier card system (BloodDebt, GlassCannon, LuckyRerolls, etc.).

| File | Lines |
|---|---:|
| `EventCardConfigLoader.cs` | 239 |
| `EventCardSystem.cs` | 141 |
| `EventCardInstance.cs` | 140 |
| `EventCardValueParser.cs` | 110 |
| `EventCardsConfig.cs` | 62 |
| `EventCardConfig.cs` | 22 |
| `EventCardEffectConfig.cs` | 15 |
| `IEventCardTarget.cs` | 10 |

#### `Scripts/Gameplay/Systems/Migrations/` — SHIPPED

| File | Lines |
|---|---:|
| `CharacterValidator.cs` | 287 |

#### `Scripts/Gameplay/Systems/SkillTrees/` — SHIPPED

Skill-tree engine, graph, player state, stat-effect registry. Includes a dev-only editor subdir for authoring trees.

| File | Lines | Category |
|---|---:|---|
| `SkillTreeEngine.cs` | 264 | SHIPPED |
| `SkillTreeGraph.cs` | 155 | SHIPPED |
| `SkillTreePlayerState.cs` | 155 | SHIPPED |
| `Effects/StatEffectHandlers.cs` | 142 | SHIPPED |
| `Effects/SkillTreeEffectRegistry.cs` | 140 | SHIPPED |
| `SkillTreeManager.cs` | 137 | SHIPPED |
| `PlayerDataUnlockConditionProvider.cs` | 99 | SHIPPED |
| `SkillTreeState.cs` | 84 | SHIPPED |
| `PlayerDataStateStore.cs` | 52 | SHIPPED |
| `SkillTreeNodeDefinition.cs` | 36 | SHIPPED |
| `SkillTreeUnlockConditions.cs` | 18 | SHIPPED |
| `ISkillTreeStateStore.cs` | 17 | SHIPPED |
| `SkillTreeDefinition.cs` | 15 | SHIPPED |
| `IUnlockConditionProvider.cs` | 13 | SHIPPED |
| `SkillTreeEffectDefinition.cs` | 11 | SHIPPED |
| `SkillTreePrerequisites.cs` | 11 | SHIPPED |
| `SkillTreeCostFormula.cs` | 10 | SHIPPED |
| `Effects/ISkillTreeEffectHandler.cs` | 9 | SHIPPED |
| `SkillTreeNodePosition.cs` | 9 | SHIPPED |
| `SkillTreeRequirement.cs` | 9 | SHIPPED |
| `SkillTreeVisibilitySettings.cs` | 9 | SHIPPED |
| `Effects/ISkillTreeEffectTarget.cs` | 13 | SHIPPED |
| `Editor/SkillTreeEditorState.cs` | 299 | **SHIPPED‑STRIPPED** (in-engine tree editor) |
| `Editor/EditorCommands.cs` | 152 | **SHIPPED‑STRIPPED** |
| `Editor/GridPosition.cs` | 101 | **SHIPPED‑STRIPPED** |

### `Scripts/Gameplay/Utilities/` — SHIPPED

| File | Lines | Category |
|---|---:|---|
| `LevelBackgroundPreviewGenerator.cs` | 1,212 | **EDITOR-TOOL** (build-time thumbnail generation) |
| `ConfigRegistry.cs` | 269 | SHIPPED |
| `YamlHelper.cs` | 98 | SHIPPED |
| `CultureSafeParsing.cs` | 97 | SHIPPED |
| `ListPool.cs` | 48 | SHIPPED |

### `Scripts/Infrastructure/` — SHIPPED

Build-flag detection + zero-overhead conditional logging.

| File | Lines |
|---|---:|
| `LogHelper.cs` | 96 |
| `RuntimeFeatureFlags.cs` | 85 |
| `BuildGuards.cs` | 65 |
| `ConditionalLoggingEnricher.cs` | 24 |

### `Scripts/Levels/` — SHIPPED

| File | Lines |
|---|---:|
| `GenericLevel.cs` | 32 |

### `Scripts/PlayerModule/` — SHIPPED

| File | Lines |
|---|---:|
| `Player.cs` | 2,729 |
| `PlayerAttackEffectManager.cs` | 722 |
| `PlayerData.cs` | 683 |
| `PlayerCharacter.cs` | 324 |

### `Scripts/Projectiles/` — SHIPPED

Base `Projectile.cs` (601 lines) + 24 weapon-specific projectile subclasses.

| File | Lines |
|---|---:|
| `Projectile.cs` | 601 |
| `BombTruckProjectile.cs` | 357 |
| `ResonancePulseProjectile.cs` | 354 |
| `FlowerProjectile.cs` | 321 |
| `EchoPrismProjectile.cs` | 320 |
| `SnakeProjectile.cs` | 286 |
| `EnemyProjectile.cs` | 271 |
| `TransformableEnemyProjectile.cs` | 229 |
| `GravityProjectile.cs` | 217 |
| `IonstormWarheadProjectile.cs` | 217 |
| `ChakramProjectile.cs` | 200 |
| `BoomerangProjectile.cs` | 161 |
| `StormpulseProjectile.cs` | 151 |
| `AbilityProjectile.cs` | 150 |
| `BubbleProjectile.cs` | 112 |
| `ShrapnelPrimaryProjectile.cs` | 108 |
| `OrbitalProjectile.cs` | 97 |
| `ShurikenProjectile.cs` | 96 |
| `ShrapnelSecondaryProjectile.cs` | 90 |
| `HomingProjectile.cs` | 87 |
| `AOEProjectile.cs` | 78 |
| `AxeProjectile.cs` | 56 |
| `BazookaProjectile.cs` | 54 |
| `ShotgunProjectile.cs` | 34 |
| `ProjectileExplosionConfig.cs` | 18 |
| `ITransformableProjectile.cs` | 14 |

### `Scripts/Rendering/` — SHIPPED

Cross-platform silhouette-outline renderer for elite/boss/treasure enemies.

| File | Lines |
|---|---:|
| `OutlineRenderer.cs` | 211 |
| `OutlineType.cs` | 38 |

### `Scripts/Scenes/Levels/` — SHIPPED

Custom level subclasses. Most levels use `GenericLevel`; these four override behavior.

| File | Lines |
|---|---:|
| `HauntedForest.cs` | 115 |
| `LostRuins.cs` | 107 |
| `Abyss.cs` | 91 |
| `FrozenTundra.cs` | 74 |
| `TestLevel.cs` | 27 |

### `Scripts/Scenes/Menus/` — SHIPPED

Main menu stack: main menu, player select, level select, options, pause, game over, victory, loading, achievements, beastiary, shop, skill-tree test, keybinding, error screen.

| File | Lines |
|---|---:|
| `SkillTreeTestScene.cs` | 1,519 |
| `ResultSceneBase.cs` | 1,386 |
| `PlayerSelectScene.cs` | 1,119 |
| `ShopScene.cs` | 1,018 |
| `LevelSelectScene.cs` | 998 |
| `MainMenuScene.cs` | 859 |
| `BeastiaryScene.cs` | 782 |
| `OptionsMenuScene.cs` | 546 |
| `LoadingScene.cs` | 467 |
| `PauseMenuScene.cs` | 442 |
| `AchievementsScene.cs` | 363 |
| `KeyBindingScene.cs` | 298 |
| `ErrorScene.cs` | 224 |
| `VictoryScene.cs` | 210 |
| `GameOverScene.cs` | 163 |

### `Scripts/Testing/` — SHIPPED‑STRIPPED

Autotest harness (`--autotest=`, `--autoplay`, `--godmode`, stress tests). Per the project docs: "Release builds ignore the flags and log a warning" — compiled into the binary but dormant in retail.

| File | Lines |
|---|---:|
| `TestController.cs` | 1,596 |
| `StressTestPresets.cs` | 314 |
| `AbandonRestartOrchestrator.cs` | 294 |
| `TestParameters.cs` | 277 |
| `AutoTestLogger.cs` | 137 |
| `GodMode.cs` | 83 |

### `Scripts/Tools/` — EDITOR-TOOL

Build-time thumbnail generation for level previews.

| File | Lines |
|---|---:|
| `LevelPreviewCacheGenerator.cs` | 223 |
| `PreviewGeneratorTool.cs` | 80 |

### `Scripts/UI/` — mixed

| File | Lines | Category |
|---|---:|---|
| `AchievementUI/AchievementWidget.cs` | 533 | SHIPPED |
| `DebugMenuImGui.cs` | 2,519 | **SHIPPED‑STRIPPED** (F1 ImGui menu — weapons/enemies/visuals/level-ups) |
| `SaveStateDebugWindow.cs` | 370 | **SHIPPED‑STRIPPED** (save-file inspector) |

### `Scripts/Weapons/` — SHIPPED

Base `Weapon.cs` (604) + `MeleeWeapon.cs` (816) + factory/loader + ~23 weapon implementations.

| File | Lines |
|---|---:|
| `MeleeWeapon.cs` | 816 |
| `Weapon.cs` | 604 |
| `VoidLance.cs` | 443 |
| `WeaponConfigLoader.cs` | 385 |
| `OrbitalWeapon.cs` | 317 |
| `Nunchuck.cs` | 288 |
| `WeaponFactory.cs` | 259 |
| `ChakramMaster.cs` | 246 |
| `RangedWeapon.cs` | 243 |
| `StormpulseMinigun.cs` | 231 |
| `HomingMissile.cs` | 178 |
| `ChainLightning.cs` | 157 |
| `Shadowblade.cs` | 146 |
| `ResonancePulse.cs` | 137 |
| `AOEWeapon.cs` | 125 |
| `RandomAreaWeapon.cs` | 121 |
| `ShrapnelGun.cs` | 121 |
| `Boomerang.cs` | 117 |
| `SnakeGun.cs` | 107 |
| `EchoPrism.cs` | 92 |
| `FlameSword.cs` | 91 |
| `FlowerGun.cs` | 87 |
| `Shotgun.cs` | 77 |
| `BubbleGun.cs` | 63 |
| `GravityGun.cs` | 61 |
| `MachineGun.cs` | 56 |
| `BombTruck.cs` | 56 |
| `Axe.cs` | 55 |
| `FrostbiteRifle.cs` | 53 |
| `Shuriken.cs` | 38 |
| `IDebugMeleeHitbox.cs` | 14 |
| `AimType.cs` | 13 |
| `Bazooka.cs` | 3 |

---

## 🧪 `Tests/` — TEST-ONLY (24 files, 4,696 lines)

Never compiled into the game binary. Run via `dotnet test -f net8.0-windows`.

| File | Lines |
|---|---:|
| `Gameplay/Systems/TilesetManagerTests.cs` | 803 |
| `Gameplay/Systems/TerrainGeneratorLogicTests.cs` | 499 |
| `Gameplay/Systems/SkillTreePersistenceTests.cs` | 486 |
| `Entities/Enemies/EnemyPickupTests.cs` | 455 |
| `Gameplay/Systems/TerrainGeneratorTests.cs` | 341 |
| `TestHelpers/TestGameSetup.cs` | 339 |
| `Gameplay/Systems/AchievementResourceBugTests.cs` | 215 |
| `TestHelpers/TilesetTestHelper.cs` | 181 |
| `Gameplay/Systems/CharacterValidatorTests.cs` | 170 |
| `TestHelpers/TestLevel.cs` | 154 |
| `Gameplay/Systems/EventCardSystemTests.cs` | 148 |
| `Gameplay/Systems/SkillTreeEngineTests.cs` | 137 |
| `Gameplay/Systems/AchievementUnlockTimingTests.cs` | 125 |
| `Gameplay/Systems/SaveSystemIntegrityTests.cs` | 111 |
| `Gameplay/Systems/PermanentUpgradeTests.cs` | 108 |
| `Gameplay/Systems/EventCardSelectionAutoSelectTests.cs` | 101 |
| `Gameplay/Systems/PlayerDataPersistenceTests.cs` | 69 |
| `Gameplay/Systems/ChestUpgradeTests.cs` | 67 |
| `Gameplay/Systems/UnlockManagerTests.cs` | 47 |
| `Gameplay/Systems/LevelRestartTests.cs` | 42 |
| `AnalyzerTest.cs` | 34 |
| `TestHelpers/TestTimingAttribute.cs` | 31 |
| `WarningSuppressionTest.cs` | 28 |
| `TestAssemblyInfo.cs` | 5 |

---

## 🔧 `Tools/` — EDITOR-TOOL (12 files, 1,011 lines)

Build-time tools. Only used on the dev machine — none of this is in the shipped game binary.

| File | Lines | Purpose |
|---|---:|---|
| `AtlasGenerator/AtlasGenerator.cs` | 283 | Texture atlas builder (Release generates 207 atlases) |
| `DecryptUserFiles.cs` | 207 | Save-file decryption helper |
| `ConfigBundler/Program.cs` | 186 | Packs YAML configs into `config.pak` |
| `Tests/UI/TestGameInstance.cs` | 117 | Harness for UI tests |
| `Tests/UI/MenuNavigationTests.cs` | 103 | UI navigation tests |
| `Tests/UI/UINavigator.cs` | 45 | UI test driver |
| `Tests/UI/SDLHelper.cs` | 44 | SDL helper for UI tests |
| `Tests/TestHelpers/DummyGraphicsDeviceService.cs` | 17 | Test graphics stub |
| `Templates/Scaffold/CharacterTemplate.cs` | 3 | Scaffold stub |
| `Templates/Scaffold/EnemyTemplate.cs` | 3 | Scaffold stub |
| `Templates/Scaffold/WeaponTemplate.cs` | 3 | Scaffold stub |

---

## 🎨 `EpicSurvivorsConfigEditor/` — EDITOR-TOOL (24 files, 3,876 lines)

Standalone Avalonia WPF-style editor for authoring YAML configs — weapons, enemies, characters, passive upgrades, levels. Separate `.csproj`, separate binary, never shipped with the game.

| File | Lines |
|---|---:|
| `ViewModels/LevelEditorViewModel.cs` | 1,265 |
| `ViewModels/CharacterEditorViewModel.cs` | 489 |
| `ViewModels/EnemyEditorViewModel.cs` | 488 |
| `ViewModels/WeaponEditorViewModel.cs` | 390 |
| `ViewModels/PassiveUpgradeEditorViewModel.cs` | 258 |
| `Views/LevelEditorView.axaml.cs` | 241 |
| `ViewModels/PassiveLevelViewModel.cs` | 121 |
| `ViewModels/EvolutionViewModel.cs` | 108 |
| `ViewModels/ProjectileInfoViewModel.cs` | 87 |
| `ViewModels/UpgradeViewModel.cs` | 85 |
| `ViewModels/TimelineItemViewModel.cs` | 59 |
| `RepoPaths.cs` | 58 |
| `App.axaml.cs` | 46 |
| `ViewModels/LevelLaneViewModel.cs` | 40 |
| `ViewLocator.cs` | 31 |
| `Program.cs` | 21 |
| `ViewModels/TimelineTickViewModel.cs` | 18 |
| `Views/WeaponEditorView.axaml.cs` | 11 |
| `Views/PassiveUpgradeEditorView.axaml.cs` | 11 |
| `Views/EnemyEditorView.axaml.cs` | 11 |
| `Views/CharacterEditorView.axaml.cs` | 11 |
| `ViewModels/MainWindowViewModel.cs` | 10 |
| `Views/MainWindow.axaml.cs` | 10 |
| `ViewModels/ViewModelBase.cs` | 7 |

---

## 🔍 `EpicSurvivors.Analyzers/` — EDITOR-TOOL (4 files, 485 lines)

Roslyn source analyzers. Run at compile time only, emit warnings/errors on common MonoGame pitfalls. Not shipped.

| File | Lines |
|---|---:|
| `GameLoopAnalyzer.cs` | 154 |
| `GamePerformanceAnalyzer.cs` | 147 |
| `UpdateDrawAnalyzer.cs` | 109 |
| `MonoGameNullableAnalyzer.cs` | 75 |

---

## 🧬 Why YAML? Convention over Configuration

**Why 16,326 lines of YAML exist in a game engine:** Epic Survivors pushes content definition out of C# and into data files. 228 enemies, 27 weapons, 15 levels, 9 event cards, 8 characters, 7 passive upgrades — all described in YAML rather than hand-coded classes.

This is the pattern Rails uses for web apps, applied to game content. A weapon isn't a `class Shotgun : Weapon { override Fire() ... }` — it's a YAML file whose `Type:` field points to a reusable base class. A boss isn't a bespoke 3,000-line C# behemoth — it's a YAML file composing existing behaviors and state machines.

### What this buys us

| Without YAML (traditional) | With YAML (this codebase) |
|---|---|
| Adding a new basic enemy = write a new `Enemy` subclass, compile, redeploy | Adding a new basic enemy = 5-line YAML file, hot-reloads in 0.3s |
| Rebalancing damage = change C# constant, recompile | Rebalancing damage = edit YAML, restart run (or hot-reload) |
| Game designer needs to learn C# + IDE | Game designer edits YAML in VSCode / config-editor GUI |
| Boss behavior = boss-specific class | Boss behavior = compose 4 reusable behaviors + 4 reusable states |
| Balance changes = git history of `.cs` edits | Balance changes = git history of `.yaml` edits, reviewable by non-coders |

### How it resolves to code

The `ConfigRegistry` loads all YAML at startup. In Debug builds it reads raw files from `Config/`; in Release the `ConfigBundler` tool packs them into an encrypted `config.pak`. Each config's `Type:` field (or the filename itself) resolves to a C# class via reflection:

```
Config/Weapons/Boomerang.yaml  → Type: Boomerang    → Scripts/Weapons/Boomerang.cs
Config/Weapons/MachineGun.yaml → Type: RangedWeapon → Scripts/Weapons/RangedWeapon.cs (shared)
Config/Enemies/Ant.yaml        → no Type field      → Scripts/Entities/Enemies/Enemy.cs (base class)
```

**Result:** 18 of the 27 weapons use a shared `RangedWeapon.cs` base with zero custom code — the YAML alone is the "implementation."

### Four escalating examples

#### 1. The 5-line mook — `Config/Enemies/Ant.yaml`

Simplest possible enemy. No behaviors, no state machine, just stats. Plugs into the shared `Enemy.cs` base.

```yaml
Description: "Small but mighty, this little critter is always ready to carry more than its weight."
Scale: 0.5
IdleFramesPerSecond: 10
WalkFramesPerSecond: 15
StatModifiers:
  Health: 5
  Speed: 20%
  Damage: 1
  CriticalChance: 0.02
  Defense: 0
```

That's the whole definition. Drop an `Ant.yaml` in `Config/Enemies/` + sprites in `Content/Sprites/Enemies/Ant/` and you have a new enemy. ~165 enemies in the roster look like this.

#### 2. A weapon with progression — `Config/Weapons/Boomerang.yaml`

A Boomerang weapon with 8 upgrade tiers. The C# class `Boomerang.cs` (117 lines) handles the return-to-player logic; the YAML handles all stats, ranges, and what each upgrade level does.

```yaml
Name: Boomerang
Description: Throws spinning crosses that return after hitting enemies
Type: Boomerang            # → Scripts/Weapons/Boomerang.cs
Damage: 7
Cooldown: 2.0
WeaponRange: 500
Rarity: 100
ProjectileInfo:
  Speed: 450
  Lifetime: 4
  Count: 1
  Pierce: 1
Upgrades:
  "2": { Damage: 0.2, ProjectileCount: 1 }      # +20% damage, +1 projectile
  "3": { WeaponRange: 0.1, ProjectileSpeed: 0.25 }
  "4": { ProjectileCount: 1 }                    # +1 projectile
  "5": { Damage: 0.3 }                           # +30% damage
  "6": { WeaponRange: 0.2, Pierce: 1 }
  "7": { Damage: 0.2 }
  "8": { Damage: 0.2, ProjectileCount: 1, Pierce: 1 }
```

**Upgrade values follow a rule**: percentages for stats (`Damage: 0.2` = +20%), flat additions for counts (`ProjectileCount: 1` = +1 projectile). No code needed — the level-up system reads these directly.

#### 3. A run modifier — `Config/EventCards/BloodDebt.yaml`

Event cards are mid-run augments. BloodDebt trades upfront power for scaling — a classic roguelike pattern, written in 20 lines of YAML with zero card-specific code.

```yaml
Name: BloodDebt
DisplayName: "Blood Debt"
Description: "Lose 30% Damage. Gain 5% Damage every level."
Rarity: 30
Tags: [Damage, Scaling]
TagRarityBonuses:
  Damage: 15                 # Tank builds see this more
Effects:
  - Trigger: OnAcquire
    Type: StatUpgrade
    Stat: Damage
    Value: -30%
  - Trigger: OnLevelUp
    Type: StatUpgrade
    Stat: Damage
    Value: 5%
    StartLevel: 2
    EveryLevels: 1
```

Every card in the game (BloodDebt, GlassCannon, IronWill, LuckyRerolls, ArmoredTitan, AdrenalRush, BarrageProtocol, PrecisionTraining, VacuumCore) is a YAML variation on the same `Trigger / Type / Stat / Value` schema. The `EventCardSystem.cs` (141 lines) parses all of them.

#### 4. The big one — `Config/Enemies/SlimeQueenTwo.yaml` (262 lines)

**This is the longest single YAML file in the game.** It defines a full mini-boss fight with zero boss-specific C#. The SlimeQueen is composed entirely of reusable parts: 4 behaviors + 4 states (each a reusable system used by dozens of other enemies).

[![SlimeQueen Anatomy](images/SLIMEQUEEN_ANATOMY_FULL.png)](images/SLIMEQUEEN_ANATOMY_FULL.svg)

Excerpt — stats + behaviors:

```yaml
Description: "A royal slime that alternates between charges and projectile attacks"
Scale: 1.25
XPValue: 15

BossConfig:
  BossType: MiniBoss         # → orange outline, guaranteed XP drop

StatModifiers:
  Health: 500
  Speed: 50%
  Damage: 20
  CriticalChance: 0.05
  Defense: 3

Behaviors:
  - Type: HitEffects              # violet blood splatter on hit
    Parameters:
      EffectNames: [BloodSplashLargeViolet_01, ..., BloodStreamLargeViolet_03]
      EffectScale: 3
  - Type: DeathEffects
    Parameters:
      EffectNames: [BloodBurstLargeViolet_01, BloodBurstLargeViolet_02, BloodBurstLargeViolet_03]
      EffectScale: 3.0
  - Type: SplitOnDeath           # on death spawn 2 smaller slimes
    Parameters:
      SpawnType: SlimeTallPurple
      Count: 2
      SpawnRadius: 50
      SpawnPattern: Random
  - Type: DropOnDeath
    Parameters:
      PickupTypes:
        - { Type: Emerald, Chance: 1.0 }
        - { Type: HealthPotion, Chance: 1.0 }
      DropPattern: Explosion
```

The state machine — five seconds of boss behavior composed from existing states:

```yaml
StateMachine:
  InitialState: Chase
  ActivationRange: 200
  States:
    Chase:
      Parameters: { Duration: 2.5 }
      Transitions:
        - { State: ProjectileAttack, Chance: 0.3 }
        - { State: ChargeAttack,     Chance: 0.4 }
        - { State: HazardAttack,     Chance: 0.3 }

    ProjectileAttack:
      Parameters:
        Stages:
          Telegraph:  { Duration: 0.5 }
          Shooting:   { Duration: 2.0 }
          Recover:    { Duration: 0.3 }
        AttackPatterns:
          SpreadBurst:    # 8-way 360° burst
            Weight: 0.4
            ProjectilesPerBurst: 8
            BurstSpread: 360
            Pattern: fixed
            ProjectileSpeed: 350
          SpiralFast:     # rotating spiral
            Weight: 0.3
            Pattern: spiral
            SpiralSpeed: 360
          AimedBarrage:   # aimed at player
            Weight: 0.3
            Pattern: aimed
            ProjectilesPerBurst: 5

    ChargeAttack:
      Parameters:
        TelegraphDuration: 0.8
        ChargeDuration: 0.65
        ChargeSpeed: 850
        ChargeDamage: 12
      SpawnEvents:                  # mid-attack summons
        - { EnemyType: SlimePink,       Trigger: OnStart, Count: 1 }
        - { EnemyType: SlimeTallPurple, Trigger: OnEnd,   Count: 1 }

    HazardAttack:
      Parameters:
        Duration: 5.0
        HazardCount: 3
        WarningDuration: 1.0
        HazardDamage: 15
      SpawnEvents:
        - { EnemyType: SlimePink, Trigger: OnImpact, Count: 1 }
```

**What makes this fight unique** — the values, the weights, the enemy types it summons — lives in YAML. The state classes (`Chase.cs` 70 lines, `ProjectileAttack.cs` 739 lines, `ChargeAttack.cs` 238 lines, `HazardAttack.cs` 326 lines) and the behavior classes (`HitEffectsBehavior` 256 lines, `DeathEffectsBehavior` 320 lines, `SplitOnDeathBehavior` 121 lines, `DropOnDeathBehavior` 171 lines) are all shared with other enemies. SlimeQueenTwo is 0 lines of bespoke C# + 262 lines of YAML that composes the shared systems into a specific fight.

### The headline insight

> **262 lines of YAML connecting to ~2,750 lines of shared C# = a complete boss fight.**
> **Zero boss-specific code.**

That's why the Config/ folder exists and why it's 16K lines. Every boss, every weapon, every character, every event card follows this pattern. When the team adds a new mini-boss to a level, the diff is usually one new YAML file and zero C# changes.

### Hot-reload in Debug

In Debug builds, edit a YAML, press F1 → Reload Configs, and the change is live in ~0.3s without restarting. In Release the whole folder is packed into an encrypted `config.pak` at build time.

---

## 📦 `Config/` — YAML Data (374 files, 16,326 lines — all SHIPPED)

All YAML is packed into `config.pak` for retail builds (`Tools/ConfigBundler`). In Debug the game loads them raw via `LOOSE_CONFIG`. This is the game's content, not code.

```mermaid
pie showData title YAML data distribution (16,326 lines across 374 files)
    "Config/Enemies — 228 enemy types (7,048)" : 7048
    "Config/Levels — level waves (6,127)" : 6127
    "Config/Weapons — 27 weapons (1,093)" : 1093
    "Config/SkillTrees — skill tree (463)" : 463
    "Config/Tilesets — tile composition (323)" : 323
    "Config/Tiles — tile defs (210)" : 210
    "Config/EventCards — 9 cards (184)" : 184
    "Config/Characters — 8 chars (180)" : 180
    "Config/PermanentUpgrades — 7 meta (168)" : 168
    "Config/Achievements — 15 (164)" : 164
    "Config/Pickups — 16 items (116)" : 116
    "Config/PassiveUpgrades — 8 (114)" : 114
    "Other (Abilities, Migrations, root)" : 136
```

### `Config/Weapons/` — 27 files, 1,093 lines

| File | Lines |
|---|---:|
| `StormpulseMinigun.yaml` | 66 |
| `ShrapnelGun.yaml` | 61 |
| `SnakeGun.yaml` | 58 |
| `VoidLance.yaml` | 55 |
| `Shadowblade.yaml` | 50 |
| `EchoPrism.yaml` | 46 |
| `FlowerGun.yaml` | 45 |
| `MachineGun.yaml` | 45 |
| `ResonancePulse.yaml` | 43 |
| `ArcSentinel.yaml` | 42 |
| `Boomerang.yaml` | 42 |
| `Shotgun.yaml` | 42 |
| `Axe.yaml` | 41 |
| `HomingMissile.yaml` | 40 |
| `ChainLightning.yaml` | 38 |
| `FrostbiteRifle.yaml` | 35 |
| `GravityGun.yaml` | 35 |
| `Nunchuck.yaml` | 35 |
| `BubbleGun.yaml` | 34 |
| `BombTruck.yaml` | 33 |
| `FlameSword.yaml` | 33 |
| `AuraBloom.yaml` | 32 |
| `CelestialDew.yaml` | 29 |
| `ChakramMaster.yaml` | 29 |
| `Shuriken.yaml` | 29 |
| `Moonstaff.yaml` | 30 |
| `Bazooka.yaml` | 25 |

### `Config/Enemies/` — 233 files, 7,048 lines

Boss / mini-boss configs are the longest; basic mooks are ~10-line YAMLs extending a shared behavior.

**Longest (boss/mini-boss tier):**

| File | Lines |
|---|---:|
| `SlimeQueenTwo.yaml` | 262 |
| `DogArmoured.yaml` | 252 |
| `SlimeKingTwo.yaml` | 250 |
| `Wendigo.yaml` | 224 |
| `FrostSerpent.yaml` | 222 |
| `SlimeQueen.yaml` | 218 |
| `FrostTitan.yaml` | 209 |
| `SlimeKing.yaml` | 195 |
| `DreadLord.yaml` | 180 |
| `FrostbiteSpider.yaml` | 127 |
| `TestBeamPatterns.yaml` | 113 |
| `SkeletonMarksman.yaml` | 108 |
| `SlimeTallPurple.yaml` | 97 |
| `IceWraith.yaml` | 97 |
| `FrostWizard.yaml` | 93 |
| `SlimeTallRed.yaml` | 92 |
| `SlimeTallYellow.yaml` | 92 |
| `TestBeamBoss.yaml` | 88 |
| `SlimeTallGreen.yaml` | 80 |
| `PurpleSlime.yaml` | 78 |
| `KnightDark.yaml` | 77 |
| `SlimeCursedKnightTwo.yaml` | 76 |
| `KnightCursed.yaml` | 75 |
| `SkeletonWitch.yaml` | 69 |
| `SkeletonMagician.yaml` | 68 |
| `SkeletonArcher.yaml` | 68 |
| `SlimeTall.yaml` | 67 |
| `SkeletonMage.yaml` | 67 |
| `TestBeamRandom.yaml` | 66 |
| `SkeletonWarlord.yaml` | 62 |
| `GolemBlue.yaml` | 61 |
| `GolemRed.yaml` | 61 |
| `Whale.yaml` | 59 |
| `WhaleTwo.yaml` | 57 |
| `TestChaosBomber.yaml` | 56 |
| `TestDistanceAI.yaml` | 54 |
| `Goblin.yaml` | 52 |
| `Orc.yaml` | 50 |

**Test/sandbox enemies** (`TestBeam*`, `TestLaser*`, etc. — dev-only, not in retail spawn tables): 22 files, ~850 lines.

**Standard roster** (basic mooks, ~10 lines each): remaining ~165 files. Includes: Ant, Bat, Bear, Bee, Beetle, Bird (8 variants), Bobcat, DangerNoodle, Deer, Dog (3), Dragon family (4), Dragonfly, Elementals (12 Air/Earth/Fire/Water variants), Eye, Firefly, Fly, Ghost, Ghoul, Goblin (4), Harpy, Horse, Icer, Ishi, Knight (16 variants), Latabi, Monk, Mutant, Nagaraja, Necromancer, Octopus, Panther, Peasant (6), Penguin, Pig (3), Pirate (6), Plant (20 variants), Platypus, Priest, Pumpkin, Puppet (7), Rat, Raccoon, Scorpion, Seeder, Shield, Skeleton (11), Slime (20+), Snowman, Spicewing, Spider (3), SunmaneLion, Toad, Treant, Troll, Turtle, WendigoDark, WidowFrozen, WitchDoctor, Wizard, Wolf (7).

### `Config/Levels/` — 16 files, 6,127 lines

| File | Lines |
|---|---:|
| `HauntedForest_trailer.yaml` | 1,428 |
| `HauntedForest.yaml` | 1,241 |
| `HauntedForest_2_player.yaml` | 968 |
| `FrozenTundra.yaml` | 858 |
| `HauntedForest120225backup.yaml` | 653 |
| `CursedCatacombs.yaml` | 540 |
| `Abyss.yaml` | 154 |
| `SpawnTest.yaml` | 81 |
| `TestArena.yaml` | 80 |
| `HauntedForestBenchmark.yaml` | 53 |
| `DarkCatacombs.yaml` | 27 |
| `TestModifiers.yaml` | 24 |
| `TestLevel.yaml` | 11 |
| `LostRuins.yaml` | 9 |

### `Config/Characters/` — 8 files, 180 lines

| File | Lines |
|---|---:|
| `VoltinaNova.yaml` | 46 |
| `Salvo.yaml` | 46 |
| `Voltina.yaml` | 16 |
| `LunarMage.yaml` | 16 |
| `TestCharacter.yaml` | 14 |
| `ShadowKnight.yaml` | 14 |
| `Gunslinger.yaml` | 14 |
| `Demolitionist.yaml` | 14 |

### `Config/Achievements/` — 15 files, 164 lines

Subfolders: `Collection/` (2), `KillCount/` (11), `Survival/` (2).

| File | Lines |
|---|---:|
| `KillCount/SkeletonHunter.yaml` | 19 |
| `KillCount/BossKiller.yaml` | 15 |
| `KillCount/FlySwatter.yaml` | 15 |
| `KillCount/BeeKeeper.yaml` | 14 |
| `KillCount/SlimeNovice.yaml` | 12 |
| `KillCount/KingSlayer.yaml` | 11 |
| `Survival/Survivor.yaml` | 11 |
| `KillCount/VampireSlayer.yaml` | 10 |
| `KillCount/GoblinDestroyer.yaml` | 9 |
| `KillCount/WendigoHunter.yaml` | 9 |
| `Collection/Millionaire.yaml` | 8 |
| `KillCount/AuraBloomUnlocker.yaml` | 8 |
| `KillCount/QueenSlayer.yaml` | 8 |
| `Survival/Endurance.yaml` | 8 |
| `Collection/Destroyer.yaml` | 7 |

### `Config/EventCards/` — 9 files, 184 lines

| File | Lines |
|---|---:|
| `LuckyRerolls.yaml` | 25 |
| `BarrageProtocol.yaml` | 21 |
| `BloodDebt.yaml` | 21 |
| `ArmoredTitan.yaml` | 20 |
| `GlassCannon.yaml` | 20 |
| `IronWill.yaml` | 20 |
| `AdrenalRush.yaml` | 19 |
| `PrecisionTraining.yaml` | 19 |
| `VacuumCore.yaml` | 19 |

### `Config/PassiveUpgrades/` — 8 files, 114 lines

| File | Lines |
|---|---:|
| `ArcaneBarrier.yaml` | 22 |
| `DashMastery.yaml` | 17 |
| `MagnetMaster.yaml` | 17 |
| `SpeedMaster.yaml` | 17 |
| `HealthBoost.yaml` | 12 |
| `DamageBoost.yaml` | 11 |
| `PierceMaster.yaml` | 9 |
| `ProjectileMaster.yaml` | 9 |

### `Config/PermanentUpgrades/` — 7 files, 168 lines

| File | Lines |
|---|---:|
| `HealthyBooster.yaml` | 37 |
| `DamageBooster.yaml` | 31 |
| `RerollMaster.yaml` | 24 |
| `CriticalChanceBooster.yaml` | 22 |
| `DefenseBooster.yaml` | 21 |
| `SpeedyBooster.yaml` | 17 |
| `MagnetBooster.yaml` | 16 |

### `Config/Pickups/` — 16 files, 116 lines

| File | Lines |
|---|---:|
| `Chests/RareChest.yaml` | 16 |
| `Chests/CommonChest.yaml` | 14 |
| `Diamond.yaml` | 7 |
| `GemHuge.yaml` | 7 |
| `GemLarge.yaml` | 7 |
| `GemMedium.yaml` | 7 |
| `GemSmall.yaml` | 7 |
| `GemTiny.yaml` | 7 |
| `BlackPearl.yaml` | 6 |
| `Emerald.yaml` | 6 |
| `Gem.yaml` | 6 |
| `HealthPotion.yaml` | 6 |
| `MoneyBag.yaml` | 6 |
| `Ruby.yaml` | 6 |
| `Coin.yaml` | 4 |
| `Magnet.yaml` | 4 |

### `Config/Tiles/` — 15 files, 210 lines

All 14 lines each — tile descriptors (Grass, Water, WaterDeep, Grass↔Water transitions N/S/E/W variants).

### `Config/Tilesets/` — 8 files, 323 lines

| File | Lines |
|---|---:|
| `ForestPerimeter.yaml` | 212 |
| `Pond.yaml` | 17 |
| `StoneCircle.yaml` | 17 |
| `ForestRuin.yaml` | 16 |
| `ArenaBorder.yaml` | 16 |
| `ArtDudePreview.yaml` | 15 |
| `ArtDudePreviewAbyss.yaml` | 15 |
| `SimpleBorder.yaml` | 15 |

### Miscellaneous Config

| File | Lines |
|---|---:|
| `SkillTrees/TestTree.yaml` | 463 |
| `XPGemTiers.yaml` | 37 |
| `GemCondensationConfig.yaml` | 30 |
| `Migrations/CharacterMigrations.yaml` | 25 |
| `EventCardsConfig.yaml` | 16 |
| `Abilities/HammerSmash.yaml` | 15 |
| `Abilities/WhirlwindSlash.yaml` | 13 |
| `Abilities/SparkshardBarrage.yaml` | 0 |
| `Localization/en.yaml` | 0 |
| `GameConfig.yaml` | 0 |
| `InputConfig.yaml` | 0 |
| `AudioConfig.yaml` | 0 |

Empty `Config/` subdirs: `Crafting/`, `Objects/`, `Resources/` — placeholder folders, no active content.

---

## 🚢 Ship-vs-Dev cross-reference

### What's in the retail Steam build (Demo config)?

**Always running:**
- Root entry points (`Game1`, `Program`): 3,896 lines
- `GameEngineFramework/` minus `TestModeUI` + `DummyGraphicsDeviceService`: 19,818 lines
- All `Scripts/` except the stripped categories listed below: ~68,750 lines
- All YAML (bundled into `config.pak`): 16,326 lines

**Compiled in but inert / disabled in Demo build:**

| System | Lines | What it does (when enabled) |
|---|---:|---|
| `Scripts/UI/DebugMenuImGui.cs` | 2,519 | F1 ImGui menu — weapons / enemies / visuals / level-ups |
| `GameEngineFramework/UI/TestModeUI.cs` | 2,544 | F1 test-mode overlay |
| `Scripts/Testing/` (autotest / GodMode / stress tests) | 2,701 | `--autotest=`, `--godmode`, stress presets |
| `Scripts/Gameplay/Systems/AutoPlay/` | 2,230 | AI that drives the player for benchmarks |
| `Scripts/Gameplay/Utilities/LevelBackgroundPreviewGenerator.cs` | 1,212 | Build-time thumbnail generation |
| `Scripts/Gameplay/Systems/EntityInspector.cs` | 997 | F4 click-to-inspect |
| `Scripts/Diagnostics/` | 645 | JSONL perf telemetry (`--perf-log`) |
| `Scripts/Gameplay/Systems/SkillTrees/Editor/` | 552 | In-engine tree editor |
| `Scripts/Analysis/` | 463 | Offline weapon-acquisition simulator |
| `Scripts/Gameplay/Systems/HitboxVisualizationSystem.cs` | 388 | F8 hitbox overlay |
| `Scripts/UI/SaveStateDebugWindow.cs` | 370 | Save-file inspector |

**Stripped subtotal: ~14,621 lines** — roughly 12.5% of the C# in the repo exists for dev/debug and does nothing for a retail player.

### What never ships at all

| Project | Files | Lines | Purpose |
|---|---:|---:|---|
| `Tests/` | 24 | 4,696 | Unit + integration tests. `dotnet test` only. |
| `EpicSurvivorsConfigEditor/` | 24 | 3,876 | Separate Avalonia app for authoring YAMLs. |
| `Tools/` | 12 | 1,011 | Atlas builder, config bundler, save-file decryptor, UI test harness, scaffolding. |
| `EpicSurvivors.Analyzers/` | 4 | 485 | Roslyn compile-time analyzers. |
| `DummyGraphicsDeviceService.cs` | 1 | 16 | Test stub. |
| **Non-shipping total** | **65** | **10,084** | |

### Retail binary footprint estimate

Active executable code path in a retail Demo build:
- **C# (SHIPPED only, excluding stripped dev tools): ~92,400 lines**
- **YAML (all of it, packed): 16,326 lines**
- **Combined: ~108,700 lines** running in a player's hands.

---

## 📝 Methodology / caveats

- `wc -l` counts every newline, so blank lines and closing braces inflate numbers vs. real SLOC. The ratio of non-blank, non-comment SLOC is typically 60–75% of `wc -l` for C#.
- The SHIPPED‑STRIPPED categorization is reconstructed from `CLAUDE.md`, `Scripts/Infrastructure/BuildGuards.cs`, and `epic_survivors.csproj` `DefineConstants`. Some files are partially gated (a class may contain both shipping and stripped methods via `#if DEBUG`); classification reflects the primary intent of each file.
- A handful of YAML files have non-ASCII names or spaces that broke strict `xargs wc -l` parsing — those count against the total but may not appear individually in the tables above.
- MonoGame MGCB `.xml` files (1,072 of them) are content-pipeline metadata, not source; excluded from the headline totals because each is typically 5–15 lines of auto-generated asset wiring.
- Vendored third-party code (`MonoGame.ImGuiNet/`, `ThirdParty/`) is excluded entirely.
- The homepage stat "104,126 lines" is a fixed historical snapshot; the numbers in this document reflect a later tree with a few thousand extra lines of skill-tree, event-card, and boss-phase code added since.

---

_See also: [index.html](index.html) · [TIMELINE_EXPANDED.md](TIMELINE_EXPANDED.md) · [README.md](README.md)_
