# 01 – Debug-API & In-Game-Console

> Die **Test-Orakel-Schicht** des Games: `window.__AEGIS_DEBUG__` und die eingebauten Audits.
> Die gesamte Test-Suite in `tests/` hängt an dieser API – sie ist die einzige stabile Schnittstelle zwischen den Skripten und der Game-Source.

---

## 1. Grundprinzip

`Aegis-Labyrinth.html` ist eine Single-File-App. Für Automatisierung stellt sie zwei Dinge bereit:

1. **`window.__AEGIS_DEBUG__`** – ein explizit auf `window` gehängtes Objekt (stabil in `page.evaluate()` referenzierbar).
2. **Funktionen im Global Scope** (`placeTower`, `buySkill`, `simulate`, `triggerVictory`, `TOWER_TYPES`, `Game`, …) – frei verfügbar, aber **`const`/`let`-basiert**, d.h. **nicht** auf `window`.

### Playwright-Fallstricke (WICHTIG)

| Identifier | Auf `window`? | Referenz in `page.evaluate()` |
|---|---|---|
| `__AEGIS_DEBUG__` | ✅ ja | `window.__AEGIS_DEBUG__` |
| `TOWER_TYPES` | ❌ nein (const) | `TOWER_TYPES` (bare) |
| `Game` | ❌ nein | `Game` (bare) |
| `placeTower`, `buySkill`, `simulate` | ❌ nein | bare Identifier |

> `window.TOWER_TYPES` → `undefined`. Immer bare Identifier verwenden.

---

## 2. `window.__AEGIS_DEBUG__` – Komplette API

### 2.1 Audit-Funktionen

| Funktion | Prüft (Kurz) |
|---|---|
| `runSelfAudit()` | Konnektivität aller 11 Levels, alle 9 Turm-Attacks, Skill-Käufe (4 Ränge), Platzierungs-Validierung, AutoWave, Endless-Transition |
| `runExtensionAudit()` | Mortar-Splash (2 Ziele), Tesla-AoE (5 Feinde + Freeze), Reward-Dedup, Blocker-Alternate/Closed-Path |
| `runRedesignAudit()` | Sniper-Priorisierung (niedriger HP zuerst), Quantum-Beam-Alignment, Nano-Spawner (Limit/Damage/Cleanup) |

Jede Funktion gibt ein **Report-Objekt** zurück (Schema: [`02_Audits.md`](./02_Audits.md)).

### 2.2 State & Utility

```
window.__AEGIS_DEBUG__
├── runSelfAudit()           → report object
├── runExtensionAudit()      → report object
├── runRedesignAudit()       → report object
├── getState()               → { state, credits, lives, waveIndex, enemies, towers, … }
├── startEndlessLevel(n)     → startet Endless ab Level n (0-basiert)
├── selectLevel(n)           → lädt Level n (0-basiert)
├── startWave()              → manuelle Wave-Start
├── setCredits(n)            → Credits setzen
├── towerTypes[]             → 9 Einträge {id, name, cost, range, damage, fireRate, skills}
├── skilltree
│   ├── version, points, nodes, completed, endless20Rewards
│   ├── getState() → deep clone
│   ├── buy(nodeId)
│   └── reset()
├── levels[]                 → 11 Einträge {id, name, waves, difficulty, endlessAvailable}
├── effectMetadata
│   ├── towerTypes[] (ohne cost, mit skillIds)
│   ├── enemyTypes[] ({id, hp, speed, radius, color})
│   └── effectLimits ({maxParticles:200, maxProjectiles:100, maxHolos:20, particleLife:0.8, projectileLife:1.6})
├── effectTuning
│   ├── holo ({influenceRadius, pullStrength})
│   └── grav ({basePull, baseSlow})
├── aura
│   ├── getAuraState()
│   ├── getBonuses()
│   └── upgrade(tower)
└── audio
    ├── state() → {initialized, muted, volume, voices}
    ├── sounds[] → 20 Namen
    ├── test(name)
    ├── setMuted(bool)
    └── setVolume(0–1)
```

---

## 3. `getState()` – typisches Schema

```js
{
  state: "menu" | "playing" | "victory" | "defeat" | "endless",
  credits: number,
  lives: number,
  waveIndex: number,
  totalWaves: number,
  kills: number,
  leaked: number,
  enemies: number | Enemy[],   // je nach Version Zähler oder Array
  towers: number | Tower[],
  // …
}
```

> Die Suite nutzt `getState()` primär als **Beobachtungsschnittstelle** für Self-Play & Perf. Exakte Felder: [`02_Audits.md`](./02_Audits.md) §getState.

---

## 4. In-Game-Debug-Console (manuell)

**Aufruf:** Im Browser mit Taste `` ` `` (Backtick) die Debug-Console öffnen.

| Befehl | Beschreibung |
|---|---|
| `help` | Alle Befehle anzeigen |
| `state` | Kompletten Game-State als JSON in der Konsole |
| `credits [Zahl]` | Credits setzen (z. B. `credits 99999`) |
| `unlock all` | Alle Türme entsperren |
| `level [1–11] [normal\|endless]` | Level laden (1-basiert) |
| `wave` | Nächste Wave starten |
| `audit [self\|extension\|redesign]` | Das entsprechende Audit ausführen |
| `sound [Name]` | Sound testen (einer der 20 Sounds) |
| `clear` | Konsole leeren |

> Die In-Game-Console ist für **manuelle** Debugging-Zwecke gedacht. Die automatisierte Suite nutzt direkt `window.__AEGIS_DEBUG__` (ohne UI-Overlay).

---

## 5. Neue Mechanismen auditierbar machen (Konvention)

Jeder neue Mechanismus sollte **vor Merge** einen Audit-Eintrag in `window.__AEGIS_DEBUG__` erhalten, damit `tests/audit.mjs` ihn automatisch abdeckt:

```js
// Beispiel: neuer Turm "tesla2"
function runTesla2Audit() {
  loadLevel(0);
  const t = new Tower(TOWER_BY_ID.tesla2, 5, 5);
  const e = new Enemy('tank', t.x + 30, t.y);
  Game.towers = [t]; Game.enemies = [e];
  towerFire(t, 1/60);
  return { hit: e.hp < e.maxHp, beam: Game.beams.length > 0 };
}
window.__AEGIS_DEBUG__.runTesla2Audit = runTesla2Audit;
```

Anschließend die neue Funktion in `tests/audit.mjs` anbinden und hier + in `02_Audits.md` dokumentieren.

---

## 6. Glossar (interner Jargon)

| Begriff | Bedeutung |
|---|---|
| `grid[y][x] === 0` | Bau-Kachel (Wand) – Turm/Blocker hier erlaubt |
| `grid[y][x] === 1` | Pfad-Kachel – Feinde laufen hier |
| `grid[y][x] === 2` | Start-Kachel (Entry) |
| `grid[y][x] === 3` | Exit-Kachel (Base) |
| `flow.field[idx] === INF` | Zelle nicht erreichbar |
| `NANITE_LIMIT` | Max. gleichzeitig aktive Naniten |
| `autoWave` / `autoWaveActive` | Verzögerung zwischen Wellen |
| `TOWER_BY_ID` | Map: `"barrier"` → Definition, `"tesla"` → Definition, etc. |