docs: add vertical slice spec
This commit is contained in:
525
docs/spec-vertical-slice.md
Normal file
525
docs/spec-vertical-slice.md
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
# Vertical-Slice-Spec: InfiniTower
|
||||||
|
|
||||||
|
- **Status:** Angenommen
|
||||||
|
- **Datum:** 2026-08-10
|
||||||
|
- **Betrifft:** Den vollständigen Funktionsumfang des Vertical Slice — was gebaut wird und woran
|
||||||
|
wir erkennen, dass es fertig ist
|
||||||
|
- **Baut auf:** [ADR-0001](adr/0001-balancing-daten-als-rust-konstanten.md) (Balancing-Daten),
|
||||||
|
[ADR-0002](adr/0002-stat-und-modifier-pipeline.md) (Stat- und Modifier-Pipeline),
|
||||||
|
[ADR-0003](adr/0003-save-format-ort-und-migration.md) (Save-Format), `CONTEXT.md` (Glossar und
|
||||||
|
Slice-Scope), Karte in Issue #1
|
||||||
|
- **Vokabular:** verbindlich aus `CONTEXT.md`. Diese Spec führt keine neuen Begriffe ein, außer den
|
||||||
|
beiden in Abschnitt „Zwei Grenzwerte, zwei Begriffe" ausgewiesenen.
|
||||||
|
|
||||||
|
Diese Spec sagt, **was** gebaut wird. Die ADRs sagen, **warum es so** gebaut wird — ihre Argumente
|
||||||
|
werden hier nicht wiederholt, sondern verlinkt. Wo eine Zahl noch nicht feststeht, steht sie als
|
||||||
|
‹Platzhalter›; sie lebt dann in `Balance` (ADR-0001) und wird durch Spielen gefunden, nicht hier.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Der Loop
|
||||||
|
|
||||||
|
Der Spieler startet einen Run. Der Turm steht in der Mitte der Arena und schießt von selbst auf
|
||||||
|
Gegner, die in Wellen radial von außen anlaufen; jeder Kill gibt Coins, und aus Coins kauft der
|
||||||
|
Spieler jederzeit In-Run-Upgrades, die den Turm für diesen Run stärker machen. Die Wellen wachsen
|
||||||
|
schneller als das, was er sich leisten kann — nach sechs bis neun Minuten überrennen sie ihn, der
|
||||||
|
Turm stirbt, und alle In-Run-Upgrades verfallen mit ihm. Was bleibt, ist die Meta-Währung, die die
|
||||||
|
Gegner unterwegs gedroppt haben, und was der Boss auf Welle 10 fallen gelassen hat. Damit kauft er
|
||||||
|
zwischen den Runs permanente Workshop-Upgrades und rüstet gedroppte Cards aus. Der nächste Run
|
||||||
|
beginnt mit einem stärkeren Turm, kommt tiefer, wirft mehr ab — und endet wieder. Das ist das
|
||||||
|
Spiel: sterben ist der Fortschrittsmechanismus, nicht sein Gegenteil.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zwei Grenzwerte, zwei Begriffe
|
||||||
|
|
||||||
|
Die Karte nennt beides „Cap", meint aber zwei verschiedene Dinge. Diese Spec trennt sie, und der
|
||||||
|
Code tut es auch:
|
||||||
|
|
||||||
|
| Begriff | Code | Bedeutung |
|
||||||
|
|---|---|---|
|
||||||
|
| **Harte Obergrenze** | `HARD_ENEMY_CAP` | 10 000 gleichzeitige Gegner. Ein Perf-Grenzwert aus #4, kein Design-Werkzeug. Wird nie überschritten, von nichts. |
|
||||||
|
| **Soll-Population** | `target_population(wave)` | Die für die aktuelle Welle angestrebte Zahl lebender Gegner. Wächst mit dem Wellenzähler und ist selbst Teil der Schwierigkeitskurve. Bindet ständig — sie ist die Design-Zielgröße. |
|
||||||
|
|
||||||
|
Ein Effekt, der „mehr Gegner" verspricht, hebt die **Soll-Population** an, nie eine Spawn-Zahl
|
||||||
|
(Begründung: Cap-Analyse in Issue #1 — bei bindender Soll-Population wäre ein Spawn-Multiplikator
|
||||||
|
exakt wirkungslos). Die harte Obergrenze bleibt davon unberührt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Feststehende Zahlen
|
||||||
|
|
||||||
|
Alles hier ist entschieden. Alles andere ist ‹Platzhalter› oder steht unter „Offen".
|
||||||
|
|
||||||
|
| Größe | Wert | Quelle |
|
||||||
|
|---|---|---|
|
||||||
|
| Wellen-Takt | ‹26 s› Spawn-Phase + ‹9 s› Cooldown-Phase = ‹35 s› bei Normalgeschwindigkeit | Primärtext, als Startwert übernommen (#8) |
|
||||||
|
| Wellen pro Spielzeit | 10 min ≈ 17 Wellen · 20 min ≈ 34 · 30 min ≈ 51 | Folge des Takts (#8) |
|
||||||
|
| Boss-Welle | jede 10. Welle | Primärtext (#3), übernommen |
|
||||||
|
| Ziel für Run 1 | Tod zwischen **Welle 10 und 15** — genau ein Boss gesehen, kurz danach tot; 6–9 Minuten | #8 |
|
||||||
|
| Wachstumsform | konstant exponentiell pro Welle, plus ein Multiplikator auf Boss-Wellen | #8 |
|
||||||
|
| Kosten- vs. HP-Verlauf | Kosten wachsen anfangs langsamer als Gegner-HP, ab ca. zwei Dritteln der Runlänge überholt die HP-Kurve. Entsteht von selbst, wenn der Kosten-Exponent das Einkommenswachstum übersteigt — **kein separater Knick** | #8 |
|
||||||
|
| Meta-Ertrag | Drop-basiert: Chance je Normalgegner, **garantiert je Boss**; gedroppte Menge wellenabhängig | #8 |
|
||||||
|
| Workshop-Kosten | exponentiell pro Level | #8 |
|
||||||
|
| Tuning-Zielgröße im Run | Zeit zwischen zwei bezahlbaren Käufen: früh ‹10–20 s›, später seltener | #8 |
|
||||||
|
| Harte Gegner-Obergrenze | 10 000 gleichzeitig (gemessener Bruch bei ~70 000, ohne Texturen/UI/Audio) | #4, Issue #1 |
|
||||||
|
| Perf-Budget bei 10 000 | Gameplay-Logik 0,114 ms von 16,67 ms; Rendering 96–98 % | #4 |
|
||||||
|
| In-Run-Shop-Struktur | vier Tabs: **Attack Shop · Defence Shop · Utility Shop · Ultimates** | HUD-Mockup, #10 |
|
||||||
|
| Shop-Kapazität | ~8 Zeilen je Tab ohne Scrollen → Größenordnung **~24 In-Run-Upgrades** | HUD-Mockup, #10 |
|
||||||
|
| Kauf-Modus | Buy x1, Kosten pro Kauf, **jederzeit** im Run — kein Wellenende, keine Freigabe | Issue #1, #8 |
|
||||||
|
| Card-Seltenheiten | drei: **Common / Rare / Epic** | #11 |
|
||||||
|
| Card-Slots | Start **1**, Wachstum auf **5**; die Slot-Zahl ist selbst Progression | #11 |
|
||||||
|
| Card-Quelle | Drop aus Fortschritt (Boss-Kill, neuer Wellen-Rekord). Kein Kauf, keine dritte Währung | #11 |
|
||||||
|
| Card-Randbedingungen | Slot 2 fällt **früh** (erste paar Runs); **mindestens zwei Epics** | #11 |
|
||||||
|
| Ultimate | genau eine: **Death Wave**, radialer Sweep, automatisch ausgelöst | #9 |
|
||||||
|
| Auslöse-Regel | **Cooldown UND ein Weltzustand**, je Fähigkeit fest verdrahtet, nicht einstellbar; feuern mehrere gleichzeitig, feuern alle | #12 |
|
||||||
|
| Währungen | zwei: `Coins` (In-Run, verfällt) und die Meta-Währung (Workshop). Nicht ineinander konvertierbar | Issue #1, #11 |
|
||||||
|
| Turm-Stats | 12, siehe Tabelle in ADR-0002 §3 | ADR-0002 |
|
||||||
|
|
||||||
|
**Prüfkriterium für die fertige Kurve** (#8, gilt für die vier freien Zahlen):
|
||||||
|
|
||||||
|
1. Run 1 endet zwischen Welle 10 und 15.
|
||||||
|
2. Jeder Run trägt mindestens ein Workshop-Level ein.
|
||||||
|
3. Die Run-Tiefe wächst über die ersten zehn Runs monoton, ohne dass ein Run mehr als etwa das
|
||||||
|
Doppelte des vorigen erreicht.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Was im Slice ist
|
||||||
|
|
||||||
|
### 1. Arena, Turm und Kamera
|
||||||
|
|
||||||
|
2D, `bevy_sprite`, orthographische Kamera. Ein `Tower` fest in der Mitte, Programmer-Art. Kein
|
||||||
|
Scrollen, kein Zoom, keine Turm-Platzierung.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Nach Programmstart und Run-Start ist der Turm sichtbar in der Bildmitte des Gameplay-Fensters, und
|
||||||
|
die gesamte Spawn-Peripherie liegt innerhalb des sichtbaren Bereichs.
|
||||||
|
- Die Turm-Entity wird beim Run-Start gespawnt und beim Run-Ende despawnt (ADR-0002 §6); zwischen
|
||||||
|
zwei Runs existiert keine Entity mit `EffectiveStats`.
|
||||||
|
|
||||||
|
### 2. Wellen-Takt
|
||||||
|
|
||||||
|
Eine `Wave` besteht aus zwei separat getakteten Phasen. Die nächste Welle beginnt, wenn **beide**
|
||||||
|
Timer abgelaufen sind — nicht wenn alle Gegner tot sind. Eine einzige endlose Kurve, keine Tiers.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Während der Spawn-Phase erscheinen Gegner; nach ‹26 s› hören Spawns auf, während bereits
|
||||||
|
vorhandene Gegner weiter laufen und angreifen; nach weiteren ‹9 s› beginnt Welle N+1.
|
||||||
|
- Wird Welle N+1 gestartet, während noch Gegner aus Welle N leben, laufen diese unverändert weiter
|
||||||
|
und werden nicht entfernt.
|
||||||
|
- Der aktuelle Wellenzähler ist im HUD ablesbar und stimmt mit dem Telemetrie-Log überein.
|
||||||
|
- Auf jeder Welle mit `wave % 10 == 0` spawnt genau ein Boss.
|
||||||
|
|
||||||
|
### 3. Gegner und Population
|
||||||
|
|
||||||
|
Drei bis vier Normal-Archetypen plus ein Boss (#3): ein Tempo/HP-Tradeoff-Paar, ein Fernkämpfer und
|
||||||
|
**eine** Sondermechanik, die Ziel-Priorisierung erzwingt (Splitter oder Schutz-Aura). Der Boss ist
|
||||||
|
ein einzelner schwerer, langsamer Meilenstein-Gegner. Keine Elite-Klasse, keine Fleet-Klasse, keine
|
||||||
|
Immunitätsmatrix.
|
||||||
|
|
||||||
|
Der Spawner ist **cap-getrieben, nicht plan-getrieben**: er füllt bis zur `target_population(wave)`
|
||||||
|
auf, statt N Gegner nach Zeitplan zu setzen (Cap-Analyse, Issue #1). Gegner laufen radial von außen
|
||||||
|
auf den Turm zu und greifen ihn im Nahbereich an.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Bei laufender Spawn-Phase pendelt die Zahl lebender Gegner um `target_population(wave)`, mit einer
|
||||||
|
Abweichung von höchstens ‹±10 %› über ein 5-Sekunden-Fenster.
|
||||||
|
- Die Zahl lebender Gegner überschreitet **nie** `HARD_ENEMY_CAP` — auch nicht bei einem
|
||||||
|
Sprung-zu-Welle auf die höchste im Debug-Panel erreichbare Welle.
|
||||||
|
- Bei 10 000 gleichzeitigen Gegnern bleibt die Frametime unter 16,67 ms (Nachmessung mit dem Aufbau
|
||||||
|
aus `examples/perf_spike.rs`, nach dem Wechsel auf echte Sprites zu wiederholen).
|
||||||
|
- Jeder Archetyp ist an Sprite-Farbe oder -Form ohne Text unterscheidbar.
|
||||||
|
|
||||||
|
### 4. Turm-Dauerfeuer und geteilter Reichweiten-Scan
|
||||||
|
|
||||||
|
Der Turm schießt selbstständig auf Gegner in Reichweite. Genau **ein** System ermittelt pro Frame
|
||||||
|
den Reichweiten-Zustand; `tower_fire` und **alle** Auslöse-Bedingungen (Feature 7) lesen dessen
|
||||||
|
Ergebnis. Das ist keine Optimierung für später, sondern die Bedingung, unter der die
|
||||||
|
Auslöse-Entscheidung aus #12 tragfähig ist.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Bei mindestens einem Gegner in Reichweite feuert der Turm ohne jede Eingabe innerhalb von
|
||||||
|
`EffectiveStats.AttackInterval` Sekunden.
|
||||||
|
- Ohne Gegner in Reichweite feuert er nicht.
|
||||||
|
- Es existiert genau ein System, das die Gegnermenge in Turm-Reichweite bestimmt; ein `grep` nach
|
||||||
|
einem zweiten Reichweiten-Scan über die Gegner-Query findet keinen.
|
||||||
|
|
||||||
|
### 5. Stat- und Modifier-Pipeline
|
||||||
|
|
||||||
|
Vollständig nach [ADR-0002](adr/0002-stat-und-modifier-pipeline.md): drei Akkumulatoren (`flat`,
|
||||||
|
`points`, `mult`), ein `Direct`/`Interval`-Bit je Stat, Clamp einmal auf die Summe, `EffectiveStats`
|
||||||
|
als `Component` an der Turm-Entity, Neuberechnung bei Änderung. `type Stat = f32`. Alle Zahlen aus
|
||||||
|
`Res<Balance>` (ADR-0001).
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Das durchgerechnete Beispiel aus ADR-0002 („Durchgerechnetes Beispiel") ist als Test hinterlegt
|
||||||
|
und grün — mit den dort genannten Platzhalterwerten, nicht mit den späteren echten.
|
||||||
|
- Nach einer Änderung an `Workshop`, `EquippedCards` oder `RunUpgrades` läuft die Neuberechnung
|
||||||
|
genau einmal; ohne Änderung läuft sie nicht (nachweisbar über einen Zähler im Debug-Panel).
|
||||||
|
- `sync_tower_abilities` ist der einzige Schreiber von Fähigkeits-Components; sein `debug_assert`
|
||||||
|
am Ende des Abgleichs ist vorhanden und greift im Debug-Build.
|
||||||
|
- Jeder Modifikator, der in den Slice aufgenommen wird, hat die Sichtbarkeitsanforderung aus
|
||||||
|
ADR-0002 §11 vor dem Merge durchlaufen — inklusive Punkt 3 (beobachtbare Folge in der
|
||||||
|
Run-Telemetrie).
|
||||||
|
|
||||||
|
### 6. Coins und In-Run-Upgrades
|
||||||
|
|
||||||
|
`Coins` fallen bei jedem Kill an und werden **beim Tod gutgeschrieben** — kein einsammelbares Objekt,
|
||||||
|
keine Entity (Cap-Analyse, Issue #1: bei tausenden Kills pro Welle wäre das ein Entity-Sturm). Damit
|
||||||
|
kauft der Spieler In-Run-Upgrades in drei Tabs (Attack / Defence / Utility), jederzeit, einzeln
|
||||||
|
(Buy x1). Alle verfallen am Run-Ende, weil sie als `RunUpgrades`-Component an der Turm-Entity hängen
|
||||||
|
(ADR-0002 §6).
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Ein Kauf ist zu jedem Zeitpunkt eines laufenden Runs möglich, auch mitten in der Spawn-Phase, ohne
|
||||||
|
dass die Simulation anhält.
|
||||||
|
- Ein Klick auf „Buy x1" zieht genau die angezeigten Kosten ab, erhöht das Upgrade um eine Stufe,
|
||||||
|
und der betroffene Wert in `EffectiveStats` ändert sich im selben Frame ablesbar.
|
||||||
|
- Ist der Coin-Stand kleiner als die Kosten, ist die Zeile nicht klickbar und als solche erkennbar.
|
||||||
|
- Nach einem Run-Ende und Run-Start stehen alle In-Run-Upgrades wieder auf Stufe 0, ohne dass
|
||||||
|
irgendein System sie zurücksetzt.
|
||||||
|
- Kosten und Wirkung unterscheiden sich zwischen den drei Tabs merklich genug, dass die
|
||||||
|
Telemetrie über zehn Runs **nicht** dieselbe Kaufreihenfolge zeigt (#8: sonst ist die
|
||||||
|
Kaufreihenfolge eine Sortierung, keine Entscheidung).
|
||||||
|
|
||||||
|
### 7. Auslöse-System für Fähigkeiten
|
||||||
|
|
||||||
|
**Ein** System wertet die Auslöse-Bedingungen aller aktiven Fähigkeiten aus — der Ultimate und jeder
|
||||||
|
Fähigkeits-Card. Eine Bedingung ist **Cooldown UND ein Weltzustand** (z. B. „‹N› Gegner in
|
||||||
|
Reichweite"), je Fähigkeit fest verdrahtet und nicht vom Spieler einstellbar. Die Werte kommen wie
|
||||||
|
alle Zahlen aus `Balance`. Feuern mehrere im selben Frame, feuern alle — keine Sperre, keine
|
||||||
|
Priorität.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Eine Fähigkeit feuert erst, wenn beide Teile der Bedingung erfüllt sind; ein abgelaufener Cooldown
|
||||||
|
allein löst nachweislich nicht aus (prüfbar, indem man die Arena leerräumt und wartet).
|
||||||
|
- Sind zwei Fähigkeiten im selben Frame auslösebereit, feuern beide im selben Frame.
|
||||||
|
- Die Bedingungswerte stehen in `Balance` und sind über das Debug-Panel zur Laufzeit änderbar; keine
|
||||||
|
Schwelle steht als Literal im Gameplay-Code (ADR-0001 §4).
|
||||||
|
- Das System liest den Reichweiten-Zustand aus Feature 4 und führt keinen eigenen Scan aus.
|
||||||
|
|
||||||
|
### 8. Ultimate: Death Wave
|
||||||
|
|
||||||
|
Ein radialer Sweep von der Turmmitte nach außen, automatisch ausgelöst über Feature 7. Kein
|
||||||
|
Zielsystem, kein Knopf, kein Eingabepfad. Die Systemanforderung, die sie aufdeckt, ist der
|
||||||
|
**gebatchte Massentod**: ein Sweep kann in einem Tick tausende Gegner treffen.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Bei erfüllter Bedingung startet der Sweep ohne Eingabe; ein sichtbarer Ring wandert von der
|
||||||
|
Turmmitte nach außen und trifft Gegner in der Reihenfolge ihres Abstands.
|
||||||
|
- Ein Sweep, der ‹5 000› Gegner gleichzeitig tötet, erzeugt keinen Frame über 16,67 ms — der
|
||||||
|
Massentod wird gebatcht, nicht als tausende Einzelereignisse abgearbeitet.
|
||||||
|
- Der verbleibende Cooldown ist im Ultimates-Tab ablesbar.
|
||||||
|
- Flächenwirkung ist über ein **Ziel-Limit pro Auslösung** gedeckelt, nicht über einen schrumpfenden
|
||||||
|
Radius (Cap-Analyse, Issue #1).
|
||||||
|
|
||||||
|
### 9. Cards, Slots und Loadout
|
||||||
|
|
||||||
|
Cards fallen als Drop aus Fortschritt: **Boss-Kill** oder **neuer Wellen-Rekord**. Sie sind nicht
|
||||||
|
kaufbar und haben keine eigene Währung. Eine Card ist entweder ein Stat-Modifikator oder eine
|
||||||
|
**Fähigkeit** (`CardEffect::Modifier` / `CardEffect::Ability`, ADR-0002 §8) — Fähigkeits-Cards feuern
|
||||||
|
über dasselbe System wie die Ultimate. Drei Seltenheiten, Slots von 1 auf 5.
|
||||||
|
|
||||||
|
Das **Loadout steht vor dem Run fest**. Im laufenden Run sind Cards über den Pause-Button nur
|
||||||
|
einsehbar, nicht wechselbar (Issue #1). Damit wird im laufenden Run nie eine Fähigkeits-Component
|
||||||
|
entfernt (ADR-0002 §10, Nachtrag zu #6).
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Nach einem Boss-Kill oder einem neuen Wellen-Rekord ist die Card-Ausbeute des Runs auf dem
|
||||||
|
Meta-Screen sichtbar, spätestens beim ersten Betreten nach dem Run-Ende.
|
||||||
|
- Der Spieler kann vor dem Run so viele Cards ausrüsten, wie er Slots hat, und keine mehr.
|
||||||
|
- Eine ausgerüstete Fähigkeits-Card erzeugt beim Run-Start genau eine Fähigkeits-Component am Turm;
|
||||||
|
eine abgelegte erzeugt keine.
|
||||||
|
- Während eines Runs ändert sich `EquippedCards` nicht — kein Pfad in der UI erlaubt es.
|
||||||
|
- Der Card-Pool enthält mindestens zwei Epics, und Slot 2 ist innerhalb der ersten ‹drei› Runs
|
||||||
|
erreichbar (#11; beide Bedingungen sind an das Abnahmekriterium des Slice gebunden).
|
||||||
|
|
||||||
|
### 10. Meta-Währung und Workshop
|
||||||
|
|
||||||
|
Die zweite Währung fällt aus denselben Kill-Events wie `Coins`, ist aber nicht in sie konvertierbar.
|
||||||
|
Drop-Chance je Normalgegner, garantiert je Boss, Menge wellenabhängig. Gutschrift beim Tod des
|
||||||
|
Gegners, kein Pickup. Der `Workshop` kauft davon permanente Stat-Upgrades mit exponentiell
|
||||||
|
wachsenden Kosten.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Eine Ausgabe von `Coins` im Run verringert den Meta-Währungs-Stand nicht, und umgekehrt.
|
||||||
|
- Ein Boss-Kill schreibt garantiert Meta-Währung gut; die gutgeschriebene Menge auf Welle 20 ist
|
||||||
|
höher als auf Welle 10.
|
||||||
|
- Ein Workshop-Kauf erhöht den `flat`- bzw. `mult`-Beitrag des betroffenen Stats sofort und
|
||||||
|
überlebt ein Run-Ende sowie einen Programm-Neustart.
|
||||||
|
- Über die ersten zehn Runs trägt jeder Run mindestens ein Workshop-Level ein (#8, Prüfkriterium 2).
|
||||||
|
|
||||||
|
### 11. Run-Ende und Meta-Übergang
|
||||||
|
|
||||||
|
Fällt die Turm-HP auf 0, endet der Run. **Genau ein System** überführt am Run-Ende die aus dem Run
|
||||||
|
abgeleiteten Meta-Werte (`highest_wave`, verdiente Meta-Währung, Card-Ausbeute) in die persistierten
|
||||||
|
Resources (ADR-0003 §6). Danach wird die Turm-Entity despawnt; alles Run-gebundene verschwindet mit
|
||||||
|
ihr, ohne Aufräum-Code.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Bei HP ≤ 0 endet der Run innerhalb eines Frames; danach existiert keine Entity mit
|
||||||
|
`EffectiveStats`, `RunUpgrades` oder einer Fähigkeits-Component mehr.
|
||||||
|
- `highest_wave` wächst nur, wenn die erreichte Welle den bisherigen Stand übersteigt, und wird
|
||||||
|
genau einmal pro Run geschrieben.
|
||||||
|
- Kein anderes System als dieses eine schreibt aus Run-Zustand in eine persistierte `Resource`
|
||||||
|
(prüfbar über die Schreibstellen der `SettingsGroup`-Resources).
|
||||||
|
- Der Spieler landet nach dem Run-Ende auf dem Meta-Screen, ohne Zwischenschritt und ohne dass ein
|
||||||
|
weiterer Run automatisch startet.
|
||||||
|
|
||||||
|
### 12. In-Run-HUD und Pause
|
||||||
|
|
||||||
|
Links das Gameplay-Fenster, rechts ein vertikales Panel über die volle Höhe. Das Panel trägt oben
|
||||||
|
den Namen des aktiven Tabs, darunter ~8 Zeilen im Schema `<Stat Name>` / `<Stat Value>` links und
|
||||||
|
`Buy x1` / `<Cost>` rechts. Unten vier Tabs: **Attack Shop · Defence Shop · Utility Shop ·
|
||||||
|
Ultimates**. Der Ultimates-Tab trägt die Cooldown-Anzeige (#12). Ein Pause-Button friert die
|
||||||
|
**gesamte** Simulation ein und gibt Einsicht in die ausgerüsteten Cards.
|
||||||
|
|
||||||
|
Das Mockup (`docs/design/hud-in-run.png`) legt Panel und Tabs fest, zeigt aber weder Turm-HP,
|
||||||
|
Wellenzähler, Währungsstände noch den Pause-Button. Diese vier gehören ins Gameplay-Fenster oder
|
||||||
|
dessen Rand; ihre Platzierung ist frei, ihre Existenz nicht.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Die vier Tabs sind vorhanden und schaltbar; ein Tab-Wechsel hält die Simulation nicht an.
|
||||||
|
- Turm-HP, aktuelle Welle, `Coins`-Stand und Meta-Währungs-Stand sind während des Runs jederzeit
|
||||||
|
ohne Tab-Wechsel ablesbar.
|
||||||
|
- Der Pause-Button friert Gegnerbewegung, Turmfeuer, Wellen-Timer und Fähigkeits-Cooldowns
|
||||||
|
gleichzeitig ein; nach dem Fortsetzen laufen alle vier von genau ihrem Stand weiter.
|
||||||
|
- Im Pause-Zustand sind die ausgerüsteten Cards einsehbar und **nicht** wechselbar.
|
||||||
|
- Es gibt **keine** „Gespeichert"-Bestätigung — das Programm kann sie nicht belegen (ADR-0003 §8).
|
||||||
|
|
||||||
|
### 13. Meta-Screen zwischen den Runs
|
||||||
|
|
||||||
|
Der Zustand zwischen zwei Runs. Er trägt Workshop-Käufe, das Card-Loadout, den Slot-Fortschritt und
|
||||||
|
den Start-Knopf für den nächsten Run. **Sein Aufbau ist offen** (siehe „Offen"); was hier steht, ist
|
||||||
|
seine Funktion, nicht sein Layout.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Ein neuer Run ist nur von hier aus startbar.
|
||||||
|
- Workshop-Käufe, Card-Loadout und Slot-Stand sind von hier aus erreichbar und änderbar.
|
||||||
|
- Beim Betreten nach einem Run zeigt der Screen, was dieser Run eingebracht hat: erreichte Welle,
|
||||||
|
verdiente Meta-Währung, gedroppte Cards.
|
||||||
|
- Steht `version` nach dem Laden auf `0`, erscheint hier die Meldung aus ADR-0003 §8 — und bis zur
|
||||||
|
ersten bewussten Aktion des Spielers wird nicht geschrieben.
|
||||||
|
|
||||||
|
### 14. Save/Load
|
||||||
|
|
||||||
|
Vollständig nach [ADR-0003](adr/0003-save-format-ort-und-migration.md): `progress.toml` über
|
||||||
|
`bevy_settings`, `version` als Sentinel, Feldnamen als Vertrag, namensbasierte Ablage. Persistiert
|
||||||
|
werden nur Quellen, nie berechnete Werte (ADR-0002 §5). Kein laufender Run, kein `Balance`, kein
|
||||||
|
Zeitstempel.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Nach einem Programmneustart stehen Workshop-Level, Card-Bestand, Loadout, Slot-Zahl,
|
||||||
|
Meta-Währungsstand und `highest_wave` unverändert da.
|
||||||
|
- Ein von Hand beschädigtes `progress.toml` führt zur Meldung aus ADR-0003 §8 und **nicht** zu einem
|
||||||
|
Schreibvorgang, bevor der Spieler etwas tut. Die beschädigte Datei liegt danach unverändert da.
|
||||||
|
- Ein `progress.toml` mit `version` größer als `CURRENT` sperrt alle Schreibvorgänge für die Sitzung
|
||||||
|
und lässt die Datei unangetastet.
|
||||||
|
- Ein Umbenennen eines Feldes lässt den restlichen Spielstand intakt und setzt genau einen Wert auf
|
||||||
|
`Default`.
|
||||||
|
- Die Datei ist in einem Texteditor lesbar und von Hand editierbar — Schummeln ist ausdrücklich
|
||||||
|
akzeptiert, nicht übersehen.
|
||||||
|
|
||||||
|
### 15. Debug-Panel und Run-Telemetrie
|
||||||
|
|
||||||
|
**Kein Nice-to-have.** ADR-0001 und #8 benennen dieses Werkzeug als den eigentlichen Hebel, um die
|
||||||
|
vier freien Zahlen überhaupt finden zu können: ohne Sprung-zu-Welle kostet jeder Datenpunkt einen
|
||||||
|
Run von Welle 1 an, bei ‹35 s› pro Welle also Minuten. Das Panel mutiert `Balance` im laufenden
|
||||||
|
Prozess und nutzt dieselbe Naht wie der spätere Asset-Ladepfad (ADR-0001 §3).
|
||||||
|
|
||||||
|
Umfang: Sprung zu einer beliebigen Welle · Live-Mutation der `Balance`-Werte · Anzeige von
|
||||||
|
`EffectiveStats` samt der **ungeclampten** Summen (ADR-0002 §2) · Herkunfts-Aufschlüsselung pro Stat
|
||||||
|
(ADR-0002 §6) · Run-Telemetrie: Zeit bis Tod, erreichte Welle, Coins pro Minute, Kills pro Welle,
|
||||||
|
DPS-Verlauf, Zeit zwischen zwei bezahlbaren Käufen.
|
||||||
|
|
||||||
|
**Akzeptanz**
|
||||||
|
- Ein Sprung zu Welle N versetzt den laufenden Run in Welle N mit der für N vorgesehenen
|
||||||
|
Soll-Population und Gegner-Skalierung, ohne Programmneustart, in unter ‹2 s›.
|
||||||
|
- Eine Änderung an einem `Balance`-Wert im Panel wirkt ohne Neustart auf die nächste Neuberechnung
|
||||||
|
von `EffectiveStats`.
|
||||||
|
- Am Run-Ende liegt ein Telemetrie-Datensatz vor, der alle oben genannten Größen enthält und sich
|
||||||
|
maschinenlesbar exportieren lässt.
|
||||||
|
- **Ein Run, in dem das Debug-Panel benutzt wurde, schreibt nichts in `progress.toml`.** Weder
|
||||||
|
`highest_wave` noch Meta-Währung noch Card-Drops. Ein Sprung zu Welle 500 darf keinen
|
||||||
|
Wellen-Rekord und keinen Card-Drop erzeugen.
|
||||||
|
- Das Panel ist im Release-Build nicht erreichbar, ohne dass ein Schalter dafür umgelegt wird.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Was ausdrücklich nicht drin ist
|
||||||
|
|
||||||
|
| Nicht im Slice | Warum |
|
||||||
|
|---|---|
|
||||||
|
| Pfadfindung, Turm-Platzierung, Maze-Building | die Arena ist radial und hat genau einen Turm — es gibt nichts zu platzieren und keinen Pfad zu finden. |
|
||||||
|
| Tiers | wir haben uns bewusst für **eine** endlose Kurve entschieden; Tier-Resets sind das Langzeit-Muster des Originals, nicht unser Slice-Problem. |
|
||||||
|
| Labs, Modules, Perks | dritte, vierte und fünfte Meta-Achse neben Workshop und Cards — der Slice soll zeigen, dass **eine** Progressionsschleife trägt, nicht dass fünf sich addieren. |
|
||||||
|
| Offline-Progress | braucht einen Zeitstempel im Save, und ein Feld ohne Leser ist genau der Fehler, den ADR-0002 §5 verbietet. |
|
||||||
|
| Elite- und Fleet-Klasse | ihre Mechanik im Original ist eine Anti-Cheese-Antwort auf ein Fähigkeiten-Arsenal, das wir gar nicht haben (#3). |
|
||||||
|
| Immunitätsmatrix | dieselbe Begründung — sie schützt vor Fähigkeiten, die der Slice nicht kennt. |
|
||||||
|
| Wall als zweiter HP-Pool | ein zweiter HP-Pool verdoppelt die Schadenslogik, ohne eine neue Frage zu beantworten (#3). |
|
||||||
|
| Coin- und Card-Pickups als Entities | bei tausenden Kills pro Welle ist ein einsammelbares Objekt pro Drop ein Entity-Sturm (Cap-Analyse #1). |
|
||||||
|
| Coin Decay, Heat-up, Enemy-Mass-Wachstum | Coin Decay und Mass sind dichte-neutral, aber ohne Nutzen im Slice; Heat-up ist bei 13-facher Angreiferzahl schlicht nicht übertragbar und müsste neu erfunden statt übernommen werden (Cap-Analyse #1). |
|
||||||
|
| Gacha-Kopien, Card-Mastery, Pity-System | das Original kauft Cards mit einer Währung, die es bei uns nicht gibt (Ads, IAP) — Drop-Verteilung ersetzt beides ersatzlos (#11). |
|
||||||
|
| Manuelle Ultimate-Auslösung | ein Knopf wäre der einzige Moment aktiver Kontrolle im ganzen Spiel und würde das Kern-Gefühl „Idle" brechen statt bestätigen (#9). |
|
||||||
|
| Einstellbare Auslöse-Bedingungen | die Bedingungen liegen bereits als Daten in `Balance`; sie einstellbar zu machen ist reine UI-Arbeit und kauft im Slice nichts (#12). |
|
||||||
|
| Buy x10 / Buy Max | das HUD-Schema lässt Platz dafür, ohne das Layout zu ändern — der Slice braucht es nicht (#10). |
|
||||||
|
| Spielgeschwindigkeits-Multiplikator | nicht entschieden und nicht im HUD; das Debug-Panel deckt den Zeitraffer-Bedarf beim Tunen ab (siehe „Lücken"). |
|
||||||
|
| Bots, Wave Skip, Recovery Packages | Systeme, die eine bereits laufende Schleife garnieren — der Slice muss erst zeigen, dass die Schleife läuft. |
|
||||||
|
| Guilds, Tournaments, Cloud-Saves, Accounts, IAP, Leaderboards | alles Server-seitige ist out of scope; ein Vergleichswert, der das Gerät verlässt, würde außerdem ADR-0003 §1 (Klartext-Save) neu aufmachen. |
|
||||||
|
| Mobile- und Web-Port | `bevy_settings` persistiert auf Android und iOS **nichts** und meldet es nur als `warn!` — der Port braucht eigene Arbeit (ADR-0003, Revisions-Auslöser 2). |
|
||||||
|
| Art-Direction, Audio | Programmer-Art ist eine Entscheidung, kein Zwischenstand; ein Art-Strang beantwortet keine der offenen Fragen. |
|
||||||
|
| Hot-Reload für Balancing-Daten | der Edit-to-see-Loop kostet gemessene ~11 s, und der teure Teil eines Tuning-Zyklus ist das Spielen (ADR-0001). |
|
||||||
|
| „Gespeichert"-Bestätigung | das Programm kann sie nicht belegen — es gibt in Bevy 0.19 keinen Rückkanal (ADR-0003 §8). |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Abnahmekriterium für den Slice
|
||||||
|
|
||||||
|
Genau eines, überprüfbar, ohne Debug-Panel:
|
||||||
|
|
||||||
|
> **In einer ununterbrochenen Sitzung von höchstens 60 Minuten auf einem frisch angelegten
|
||||||
|
> Spielstand spielt ein Spieler Runs, bis er einen zweiten Card-Slot besitzt und zwischen
|
||||||
|
> mindestens zwei Cards wählen kann, startet danach einen weiteren Run und erreicht darin eine
|
||||||
|
> höhere Welle als in Run 1; nach einem Neustart des Programms steht derselbe Meta-Stand wieder da.**
|
||||||
|
|
||||||
|
Warum genau dieses: Es prüft alle vier Takte des Loops in einer Beobachtung — Run starten, sterben,
|
||||||
|
aufwerten, stärker starten — und bindet zusätzlich die Randbedingung aus #11 ein, dass der Slice das
|
||||||
|
Card-System nicht nur enthalten, sondern **zeigen** muss. Ein Slice, in dem Slot 2 ein Fernziel
|
||||||
|
bleibt, hat Cards gebaut und nie vorgeführt. Der Neustart am Ende prüft Feature 14 dort, wo es zählt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Offen — bewusst nicht entschieden
|
||||||
|
|
||||||
|
Für keinen dieser Punkte wird hier eine Antwort erfunden.
|
||||||
|
|
||||||
|
| Punkt | Wer entscheidet | Wann |
|
||||||
|
|---|---|---|
|
||||||
|
| **Die vier freien Zahlen**: Wachstumsfaktor pro Welle, Boss-Multiplikator, Drop-Chance mal Wellenwert, Kosten-Exponent des Workshops | Der Entwickler beim Tunen. Form und Prüfkriterien stehen in #8, die Werte findet nur Spielen | Nach Feature 15 (Debug-Panel), vor dem Abnahmekriterium |
|
||||||
|
| **Name der Meta-Währung** | `CONTEXT.md` — der Glossar-Eintrag ist der Vertrag, der Save-Feldname folgt ihm | Bevor der erste Workshop-Preis geschrieben wird. `Coins` ist an die In-Run-Währung vergeben; ADR-0003 lässt das Feld unbenannt, weil ein vorläufiger Name nach der Migrationsregel (§4) teuer zu korrigieren wäre |
|
||||||
|
| **Aufbau des Meta-Screens** (Workshop, Cards, Slot-Fortschritt) | Ein eigenes Design-Ticket, analog zum HUD-Mockup | Vor Feature 13. Nur das In-Run-HUD ist entworfen |
|
||||||
|
| **`MaxHealth` mitten im Run erhöht** — wächst die aktuelle HP mit, behält sie ihren Anteil, oder bleibt sie unverändert? | Das Health-System, nicht die Pipeline (ADR-0002, „Offene Punkte") | **Vor dem ersten Defence-Shop-Upgrade.** Die ADR-0002-Stat-Tabelle weist `MaxHealth` ausdrücklich `flat` aus In-Run-Upgrades zu — der Fall tritt bei jedem Health-Kauf ein, nicht theoretisch |
|
||||||
|
| **`SlowAura`** — modifiziert Gegner statt den Turm und ist deshalb kein Stat | Fällt mit der Card-Liste; ADR-0002 §9 legt die Form fest (Component am Turm, das das Gegner-Bewegungssystem liest), nicht den Inhalt | Mit der Card-Liste |
|
||||||
|
| **Zusammensetzung der Card-Liste**: Anzahl, Wirkungen, Verteilung auf die drei Seltenheiten, Drop-Wahrscheinlichkeiten je Stufe, Stufenzahl je Card | Ein Card-Inhalts-Ticket, gebunden an #8 (Zahlen) und #11 (Randbedingungen) | Vor Feature 9. **Zwei Randbedingungen sind bereits verbindlich**: Slot 2 muss früh fallen, und es braucht mindestens zwei Epics — sonst ist die Epic-Stufe eine Behauptung statt einer Mechanik |
|
||||||
|
| **Slot-Kurve**: wodurch ein Card-Slot freigeschaltet wird | Niemand — siehe „Lücken", Punkt 2 | offen |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Widersprüche und Lücken
|
||||||
|
|
||||||
|
Beim Zusammentragen aller Entscheidungen sind Stellen aufgefallen, an denen zwei Quellen sich
|
||||||
|
widersprechen oder an denen eine Frage niemandem gehört. Sie stehen hier, statt geglättet zu werden.
|
||||||
|
|
||||||
|
### Widersprüche
|
||||||
|
|
||||||
|
1. **Card-Drops überqueren die Run-Grenze, aber ADR-0003 kennt sie nicht.** ADR-0003 §6 nennt
|
||||||
|
ausdrücklich **genau eine** Ausnahme von der Regel „während eines Runs ändert sich keine
|
||||||
|
persistierte Quelle": `highest_wave` und die verdiente Meta-Währung, überführt genau einmal am
|
||||||
|
Run-Ende. `card_levels` steht nicht in dieser Ausnahme — obwohl #11 (entschieden 12:48, also vor
|
||||||
|
ADR-0003 um 13:46) Cards aus **Boss-Kills und neuen Wellen-Rekorden** droppen lässt, beides
|
||||||
|
Ereignisse *im* Run. Die Spec löst das oben nach ADR-0003 auf: Card-Drops werden im Run gepuffert
|
||||||
|
und zusammen mit den übrigen Meta-Werten am Run-Ende überführt. Wer das anders bauen will, muss
|
||||||
|
zuerst die Ausnahmeliste in ADR-0003 §6 erweitern — nicht stillschweigend ein zweites System
|
||||||
|
schreiben lassen.
|
||||||
|
|
||||||
|
2. **Die Slot-Kurve gehört niemandem, ist aber Abnahmebedingung.** #11 entscheidet „Start bei 1,
|
||||||
|
wächst auf 5, die Slot-Zahl ist selbst Progression" und bindet Slot 2 ausdrücklich ans
|
||||||
|
Abnahmekriterium des Slice. **Wodurch** ein Slot freigeschaltet wird, sagt niemand: nicht #11
|
||||||
|
(schiebt es an #8/#10), nicht #8 (die vier freien Zahlen enthalten keine Slot-Kurve), nicht die
|
||||||
|
Karte (der Fog nennt nur den Meta-Screen-Aufbau). `card_slots: u8` ist in ADR-0003 persistiert,
|
||||||
|
aber es gibt keinen Mechanismus, der ihn erhöht. Das ist keine Zahl, die man beim Tunen findet —
|
||||||
|
es ist eine unentschiedene Mechanik: Kauf aus Meta-Währung? Wellen-Meilenstein? Boss-Zahl? Sie
|
||||||
|
blockiert das Abnahmekriterium und muss vor Feature 9 entschieden werden.
|
||||||
|
|
||||||
|
3. **Die Ticket-Überschrift von #8 verspricht 10–20 Minuten, die Entscheidung liefert 6–9.** #8
|
||||||
|
heißt „Wellen- und Economy-Kurve für einen **10–20-Minuten-Run**", sein erster Kommentar
|
||||||
|
verlangt Tod „um Welle 20–40", und die Entscheidung im zweiten Kommentar setzt Run 1 auf **Welle
|
||||||
|
10–15 = 6–9 Minuten**. Die Karte hat die letzte Fassung übernommen, die frühere steht unwidersprochen
|
||||||
|
daneben. Wahrscheinlich gemeint: 10–20 Minuten gilt für den **eingespielten** Run nach einigen
|
||||||
|
Workshop-Leveln, 6–9 Minuten für Run 1. Das steht so aber nirgends, und die Kurve wird gegen die
|
||||||
|
Zahl getunt, die man liest. Diese Spec folgt der Entscheidung (Welle 10–15) und hält fest, dass
|
||||||
|
für Run *n* keine Ziel-Runlänge existiert.
|
||||||
|
|
||||||
|
4. **Die Cap-Analyse balanciert Sub-Caps für Gegnerklassen, die #3 abgeschafft hat.** Der
|
||||||
|
#1-Kommentar teilt die Sub-Caps sorgfältig in Modifikator-Caps (Protector 8, **Elite pro Typ 8**)
|
||||||
|
und Event-Caps (Boss 10, **Elite gesamt 20**). #3 wirft Elite und Fleet aber komplett aus dem
|
||||||
|
Slice. Damit ist die Hälfte der Analyse gegenstandslos: übrig bleiben genau **ein** mitskalierendes
|
||||||
|
Modifikator-Cap (die eine Sondermechanik-Einheit, Protector-artig) und **ein** absolutes
|
||||||
|
Event-Cap (Boss). Die Regel bleibt richtig, ihr Anwendungsbereich ist ein Viertel so groß wie
|
||||||
|
beschrieben — wer sie liest, baut sonst eine Klassifizierung für Klassen, die es nicht gibt.
|
||||||
|
|
||||||
|
5. **~24 Shop-Zeilen stehen gegen 12 Stats.** Der HUD-Kommentar in #10 leitet aus 8 Zeilen × 3 Tabs
|
||||||
|
„etwa 24 In-Run-Upgrades" ab und macht daraus eine Design-Aussage („der Spieler kann in einem Run
|
||||||
|
nicht alles kaufen"). ADR-0002 §3 kennt aber insgesamt **12** Stats, und davon gehören
|
||||||
|
`UltimateCooldown` und `WaveCooldown` nicht in die drei Shop-Tabs. Die Aufteilung ergibt grob
|
||||||
|
Attack 5 (`Damage`, `AttackInterval`, `Range`, `CritChance`, `CritFactor`), Defence 4
|
||||||
|
(`MaxHealth`, `DefensePercent`, `DefenseFlat`, `HealthRegen`) und **Utility 1** (`CoinGain`). Ein
|
||||||
|
Utility-Tab mit einer Zeile ist kein Tab. Entweder das Panel füllt nur die Hälfte der Zeilen —
|
||||||
|
dann trägt die Folgerung „kann nicht alles kaufen" nicht mehr —, oder es braucht In-Run-Upgrades,
|
||||||
|
die keine Stats aus ADR-0002 sind, und dann ist ADR-0002 §3 unvollständig. Beides ist eine
|
||||||
|
Entscheidung, keine Detailfrage.
|
||||||
|
Verschärfend: #3 empfiehlt für Utility ausdrücklich „stark vereinfachen", weil das Utility-System
|
||||||
|
des Originals an Labs und Perks hängt — beides im Nebel. Der Utility-Tab ist damit der schwächste
|
||||||
|
Teil der HUD-Struktur.
|
||||||
|
|
||||||
|
6. **Die „12–17 Kaufmomente" sind zweimal überholt, stehen aber noch in der Kette.** Der
|
||||||
|
HUD-Kommentar (13:38) rechnet mit 12–17 Kaufmomenten aus einer 20-Minuten-Session, #8 (13:51)
|
||||||
|
verwirft die Rechnung ausdrücklich („die trägt nicht mehr", weil jederzeit gekauft wird) **und**
|
||||||
|
verkürzt Run 1 auf 10–15 Wellen. Was aus dem HUD-Kommentar überlebt, ist allein die Zahl 24 —
|
||||||
|
sie kommt aus dem Layout, nicht aus der Session-Rechnung. Die Tuning-Zielgröße ist die **Zeit
|
||||||
|
zwischen zwei bezahlbaren Käufen** (‹10–20 s› früh), nicht eine Kaufzahl pro Run.
|
||||||
|
|
||||||
|
### Lücken, die niemandem gehören
|
||||||
|
|
||||||
|
7. **Das Debug-Panel kann den echten Spielstand zerstören, und niemand hat es benannt.** Feature 15
|
||||||
|
springt zu Welle N. Feature 11 schreibt am Run-Ende `highest_wave` und die Meta-Währung in die
|
||||||
|
persistierte Resource, und #11 macht „neuer Wellen-Rekord" zu einer **Card-Drop-Quelle**. Ein
|
||||||
|
Sprung zu Welle 500 beendet einen Run also mit `highest_wave = 500`, einem gewaltigen Card-Drop
|
||||||
|
und einem Meta-Währungsstand, der den ganzen Slice trivialisiert. Weder ADR-0001 noch #8 noch
|
||||||
|
ADR-0003 erwähnen das. Diese Spec zieht die Konsequenz oben als Akzeptanzkriterium ein: ein Run
|
||||||
|
mit benutztem Debug-Panel schreibt **nichts**. Wer das Panel baut, muss die Schreibsperre
|
||||||
|
zuerst bauen.
|
||||||
|
|
||||||
|
8. **Die Card-Nachschubquelle „neuer Wellen-Rekord" versiegt eingebaut.** Beide Card-Quellen hängen
|
||||||
|
an Fortschritt: Boss-Kill und neuer Wellen-Rekord. Solange die Run-Tiefe monoton wächst (#8,
|
||||||
|
Prüfkriterium 3, gilt für die **ersten zehn** Runs), fließt Nachschub. Danach ist unbestimmt, was
|
||||||
|
passiert — ein Spieler, der zehn Runs lang auf derselben Welle hängen bleibt, bekommt keine neue
|
||||||
|
Card mehr und hat gleichzeitig keinen anderen Hebel, tiefer zu kommen als den Workshop. Ob das
|
||||||
|
ein Feature ist (Cards folgen dem Fortschritt) oder eine Sackgasse (Fortschritt braucht Cards),
|
||||||
|
hat niemand entschieden. Bei einem Run 1, der auf Welle 10–15 endet, ist außerdem der
|
||||||
|
**eine** Boss-Kill pro Run in der Frühphase der einzige garantierte Drop überhaupt — er trägt
|
||||||
|
Meta-Währung und Card-Chance gleichzeitig.
|
||||||
|
|
||||||
|
9. **Gegner-gegen-Gegner-Kollision ist seit #4 offen und steht auf keiner Liste.** #4 und die
|
||||||
|
Cap-Analyse nennen sie als „offene Architekturfrage": Stapeln zulassen oder Spatial Grid mit
|
||||||
|
weicher Separation. Bei tausenden radial konvergierenden Körpern kommen O(n²) und ein Stau am
|
||||||
|
Turmring zusammen, den keine DPS-Menge auflöst. Sie steht **nicht** im Fog der Karte, in keiner
|
||||||
|
ADR und in keinem der offenen Punkte, die diese Spec zugewiesen bekommen hat. Sie entscheidet
|
||||||
|
aber, ob 10 000 Gegner überhaupt spielbar sind, und sie ist teuer nachzurüsten.
|
||||||
|
*Vorschlag zur Auflösung, nicht Entscheidung:* Stapeln zulassen — bei Programmer-Art in 2D
|
||||||
|
vertretbar, und der Spatial Grid ist der teure Weg, der jederzeit nachrüstbar bleibt.
|
||||||
|
|
||||||
|
10. **Ziel-Limit für Flächeneffekte und gebatchter Massentod haben keine ADR.** Die Cap-Analyse
|
||||||
|
ordnet beides ausdrücklich „der Architektur" zu, aber ADR-0002 regelt Stats und
|
||||||
|
Fähigkeits-Components, nicht Massenwirkung. Death Wave (#9) trifft beide Punkte sofort. Diese
|
||||||
|
Spec hat sie deshalb als Akzeptanzkriterien in Feature 8 aufgenommen — das ersetzt keine ADR,
|
||||||
|
macht sie aber wenigstens prüfbar.
|
||||||
|
|
||||||
|
11. **Ein Spielgeschwindigkeits-Multiplikator ist weder entschieden noch verworfen.** Die
|
||||||
|
Cap-Analyse wirft ihn auf („ein Idle-Spiel mit 35-Sekunden-Wellen will fast sicher einen") und
|
||||||
|
entschärft ihn nur perf-seitig; das Referenzspiel hat ihn; das HUD-Mockup zeigt ihn nicht.
|
||||||
|
Diese Spec listet ihn oben unter „nicht drin", weil das Debug-Panel den Zeitraffer-Bedarf beim
|
||||||
|
Tunen abdeckt — aber das ist eine Entscheidung, die hier zum ersten Mal getroffen wird und
|
||||||
|
jederzeit umkehrbar ist.
|
||||||
|
|
||||||
|
12. **`WaveCooldown` hat einen Cap, aber im Slice keine Quelle.** ADR-0002 §3 führt den Stat samt
|
||||||
|
`caps.wave_cooldown_reduction`; im Original liefert ihn die Epic-Card „Wave Accelerator". Enthält
|
||||||
|
die noch offene Card-Liste keine entsprechende Card, sind Stat und Cap toter Code. Kein Fehler,
|
||||||
|
aber ein Punkt, der bei der Card-Liste mitentschieden werden sollte.
|
||||||
|
|
||||||
|
13. **Die Fehlermeldung aus ADR-0003 hat keinen Ort.** ADR-0003 §3 und §8 verlangen bei `version == 0`
|
||||||
|
und bei `version > CURRENT` eine Meldung an den Spieler, bevor irgendetwas geschrieben wird. Der
|
||||||
|
Slice hat nur das In-Run-HUD (entworfen) und den Meta-Screen (offen). Diese Spec hängt die
|
||||||
|
Meldung an den Meta-Screen — womit der offene Meta-Screen-Entwurf eine Anforderung erbt, die
|
||||||
|
aus einer ganz anderen Ecke kommt.
|
||||||
Reference in New Issue
Block a user