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