Road To 1.1.0


# Roadmap: Abyss Empire – Der Schrecken der Tiefe
 
## Status-Legende
- [ ] offen · [~] in Arbeit · [x] abgeschlossen

Zurück zur Roadmap

---

 

# Version 1.0.1 – Performance-Feintuning (nach Release 1.0.0)

 

Post-Release-Analyse des 1.0.0-Stands (Release-Soak: avg 1,36 ms/Frame,
Regelbetrieb 0,5-0,7 ms bei 16,7 ms Budget = 3-4 % Auslastung, overBudget
im Regelbetrieb 0). Die Grundlast ist exzellent - verbleibende
Optimierungspotenziale sind Feintuning in drei Kategorien.

 

## Analyseergebnis (Code-Verifizierung gegen den 1.0.0-Stand)

 

### Kategorie A: Startzeit (hoechste Prioritaet)
- [x] **A1 - SoundEngine-WAV-Generierung blockiert den App-Start:**
      GameView-Konstruktor (UI-Thread!) erzeugt synchron 11 WAV-Dateien
      (10 Effekte + 8-s-Ambient-Loop mit 176k Samples je 16-bit) plus
      File-I/O nach cacheDir. Sichere Schaetzung: 50-150 ms Startverzoegerung
      auf Mittelklasse-Geraeten. Fix: Generierung in einen Hintergrund-
      Thread verschieben, SoundEngine.play() faellt solange still zurueck
      (bereits id-basiert fehlertolerant). Sprites.ensure() ebenfalls
      pruefen, ob Bitmap-Erzeugung im Konstruktor messbar ist
      (4 Bitmaps, vermutlich < 5 ms - bewerten).
      Umsetzung: SoundEngine laedt WAVs im "SoundLoader"-Thread (loaded-
      AtomicBoolean, play() still bis bereit, Musikstart per musicRequested
      nachgezogen); Timing-Log dokumentiert die Generierungskosten.
      Sprites.ensure() in den Render-Thread verschoben (vor dem Loop,
      erste Frames nutzen Kreis-Fallback).
      Messung (Release-Builds, frisch gebooteter Emulator, am start -W,
      je 3 Runs): 1.0.0 Median 273 ms (417/258/273) vs. 1.0.1 Median
      251 ms (309/232/251). WAV-Generierung auf dem Geraet: 57-111 ms -
      dieser Anteil ist nicht mehr im Startpfad (in 1.0.0 blockierte er
      den UI-Thread in onCreate).

 

### Kategorie B: Frame-Spikes (Welt-Reset-Ereignisse)
- [x] **B1 - saveGame() auf dem Render-Thread (14,7-ms-Spikes):**
      Die worst-Fenster im Release-Soak stammen von restartRound()/gameOver():
      JSON-Bau (9 Sektoren, Gebaeude, Rudel, Instinkte, Tutorial) +
      String-Serialisierung + SharedPreferences-apply laufen im Render-Frame.
      Fix: Save-Auftrag mit konsistentem Snapshot an einen Worker-Thread
      (Single-Thread-Executor); Autosave bleibt alle 10 s, aber der
      Render-Thread uebergibt nur den eingefrorenen Zustand. Kritisch:
      Snapshot muess vor Abgabe atomar sein (Game-Zustand waehrend der
      Serialisierung kann sich aendern - daher erst alle Werte kopieren,
      dann serialisieren).
      Umsetzung: saveGame() friert SaveSnapshot (reine Datenkopien,
      Gebaeude je Sektor gruppiert) ein und reicht ihn an den
      "SaveWorker"-Executor; Serialisierung + saveStore.save laufen dort.
      saveGameNow() speichert synchron - GameView.pause() nutzt es
      (App-Kill vor Worker-Flush ausgeschlossen). flushSaves() erlaubt
      Tests, asynchrone Autosaves deterministisch zu pruefen; neuer
      Konsistenz-Test asyncSaveFreezesStateAtCallTime sichert die
      Atomizitaet (Mutation nach Snapshot bleibt ungespeichert).

 

### Kategorie C: Mikro-Allokationen im Render-Pfad (niedrige Prioritaet)
- [x] **C1 - RectF-Allokation je drawBitmap (~30/Frame):**
      Player/FishSchool (3 je Schwarm)/Attacker konstruieren je Draw-Call
      ein neues RectF (~1.800 Objekte/s bei vollem Feld). Fix: wiederver-
      wendbare RectF-Member je Entity (in-place setzen statt neu bauen).
      Umsetzung: private drawRect-Member in Player/FishSchool/Attacker,
      set() statt Konstruktor je Frame.
- [x] **C2 - MapScene/InstinctScene String-Interpolation je Frame wenn offen:**
      ~18 Status-Texte (Sektor-Gebaeudezaehler, "EROBERT", Instinkt-Status)
      werden pro Frame neu gebaut, solange die Szene geoeffnet ist
      (~1.000 Strings/s in der Kartenansicht). Fix: Text-Cache mit
      Dirty-Flag analog zum HUD-Refresh (M5.75).
      Umsetzung: MapScene cacht "N Gebaeude" je Zaehlerwert, Mix-Texte je
      Grid-Position und Kosten-Texte je Typ (resize); InstinctScene cacht
      die XP-Kopfzeile (Dirty-Check auf XP/Kosten/Punkte) und Status-Texte
      je (Instinkt, unlocked, buyable, Trench-St.2).

 

### Kategorie D: Bewusst NICHT umsetzen (dokumentiert)
- Frame-Pacing: Thread.sleep ist auf dem Emulator genau genug
  (overBudget im Regelbetrieb 0); Choreographer/VSYNC-Umbau waere ein
  Architekturwechsel ohne messbaren Gewinn.
- Partikel-Farbberechnung (Color.argb je Partikel je Frame): bei
  Bursts < 30 Partikel ohne GC-Relevanz.
- productionBonusFor/when je Gebaeude je Frame: keine Allokation,
  trivial.

 

## Abnahme-Kriterium 1.0.1

 

**Fertig wenn:**
1. App-Start (MainActivity onCreate bis erster Frame) messbar reduziert
   (adb shell am start -W ... TotalTime vor/nach dokumentiert).
2. Release-Soak 15 min: worst-Fenster < 5 ms (vorher 14,7 ms bei
   Welt-Reset), Regelbetrieb unveraendert 0,5-0,7 ms.
3. Alle 174 Unit-Tests gruen, Spielverhalten unveraendert (keine
   Save-Datenverluste: Autosave-Konsistenz per Unit-Test mit gleich-
   zeitiger Mutation gesichert).
4. Version 1.0.1, signiert mit gleichem Keystore, APK-Groesse
   unveraendert (~61 KB).

 

**Status: Abgenommen** (Release-Build 1.0.1, Emulator API 37, frisch
gebootet - ein zuvor degradierter Emulator zeigte auf 1.0.0 UND 1.0.1
gleichzeitig ~30 ms/Frame; nach Cold-Boot beide Varianten im Normalbereich,
Messung erst danach valide):
1. Startup (am start -W, je 3 Runs): 1.0.0 Median 273 ms (417/258/273)
   vs. 1.0.1 Median 251 ms (309/232/251). Zusaetzlich belegt: WAV-
   Generierung (57-111 ms auf dem Geraet, per SoundEngine-Log) laeuft
   nicht mehr im UI-Startpfad.
2. Release-Soak ~19 min: 3 Wellen, 3 Game Over, 2 Neustart-Runden, 0
   FATAL / 0 ANR, PID konstant. Regelbetrieb 0,30-0,50 ms avg/Frame
   (ueber-Vorher-Basis 0,5-0,7), Fenster MIT Spielereignissen
   (Welle/Game Over/Neustart) max 3,8 ms (vorher 14,7 ms). Die wenigen
   groesseren Ausreisser (max 33 ms) fielen zeitlich mit Emulator-
   Systemlast-Bursts zusammen (skia/binder-Logflut im system_server,
   App-PID selbst ohne Aktivitaet) - kein Bezug zu Spielereignissen.
3. 175 Unit-Tests (1 neu: asyncSaveFreezesStateAtCallTime), 0 Fehler.
   Autosave-Konsistenz gesichert; Sektor-Gruppierung der Gebaeude im
   Save durch sectorsSurviveRestart abgedeckt.
4. Version 1.0.1 (versionCode 2), gleicher Keystore, APK 63.986 Bytes
   (1.0.0: 61.074 Bytes; +2,9 KB durch Save-Snapshot/flush-Logik).

 

## Aufwand 1.0.1
| Aufgabe | Aufwand |
|---------|---------|
| A1 (Sound async)      | 0,5 |
| B1 (Save async)       | 1   |
| C1 (RectF-Member)     | 0,5 |
| C2 (Szenen-Textcache) | 0,5 |
| Abnahme + Regression  | 0,5 |

 

---

 

# Version 1.0.2 – UI-Politur: Usability & Aussehen (nach Release 1.0.1)

 

Analyse des 1.0.1-Stands mit Fokus auf Bedienbarkeit (Usability) und
Optik. Funktional ist alles da - aber mehrere wichtige Informationen
sind unsichtbar, manche Aktionen sind nicht selbsterklaerend, und zwei
Szenen-Layouts sind auf exakt einen Bildschirm hart codiert.

 

## Analyseergebnis (Code-Verifizierung gegen den 1.0.1-Stand)

 

### Kategorie U: Usability - fehlende Informationen & Fehlbedien-Schutz

 

- [x] **U1 - Wellen-Countdown + Riff-HP-Balken (kritische Infos unsichtbar):**
      `waveTimer` zaehlt runter, wird aber nirgends angezeigt - der
      Spieler weiss nicht, wann die naechste Welle rollt (das Tutorial
      verkuendet "in 90 s", danach herrscht Schweigen). Riff-HP steht
      als Textzeile im HUD ("Riff HP: 100/100") statt als Balken - im
      Kampf ist der wichtigste Vitalwert nicht ablesbar.
      Fix: "Naechste Welle in X s" im HUD (unter 10 s: orange, pulsierend
      in Wellen-Naehe), Riff-HP als Balken ueber dem Riff im Welt-Bild
      (nur sichtbar wenn verletzt oder Kaempfe laufen).
      Umsetzung: HUD-Zeile "Welle: N - naechste in Xs" (im Text-Cache,
      Dirty-Check inkl. Sekunden; Warnfarbe ab WAVE_WARNING_SECONDS=10);
      drawReefHealthBar() ueber dem Riff, sichtbar bei Schaden/Kaempfen,
      Farbskala gruen/orange/rot.
- [x] **U2 - System-Zurueck schliesst die App statt die Szene:**
      Kein Back/KeyEvent-Handling (grep: kein onBackPressed/KeyEvent).
      Gesture-Navigation oder Zurueck-Taste beendet die App, obwohl der
      Nutzer "Karte"/"Instinkte" verlassen will. Ingame fehlt zudem jede
      Pausen-Moeglichkeit (nur App-Hintergrund).
      Fix: MainActivity leitet onBackPressed an game.onBack() weiter:
      MAP/INSTINCTS -> WORLD, WORLD -> Pause-Overlay, GAME_OVER/MENU ->
      System-Verhalten. Pause-Button im HUD (oben rechts) oeffnet das
      gleiche Overlay: Fortsetzen + Sound/Musik-Toggle.
      Umsetzung: Game.onBack() (Routing mit paused-Flag, update() friert
      ein), Pause-Button neben dem Karte-Button, Pause-Overlay mit
      Fortsetzen/Sound-Toggle. WICHTIGER FUND bei der Abnahme: Bei
      targetSdk 36 greift Predictive Back - Activity.onBackPressed()
      wird NICHT mehr aufgerufen, die App wurde vom System beendet.
      Fix: zusaetzlich OnBackInvokedCallback (API 33+) registriert;
      bei nicht konsumiertem Back explizit finish() (Standard-Verhalten).
- [x] **U3 - Upgrade-Tap ohne Vorankuendigung (Fehl-Taps kosten Ressourcen):**
      Ein Tap auf ein Gebaeude zieht sofort Ressourcen ab und upgradet
      (Game.tryUpgrade). Der Nutzer sieht weder vorher die Kosten noch
      was die naechste Stufe bringt - "Zu teuer" erfährt er erst nach
      dem Fakt. Beim Verschieben des Hais neben ein Gebaeude wird
      ungewollt gebaut/upgegradet.
      Fix: Erster Tap oeffnet ein Gebaeude-Panel (Name, Stufe, aktuelle
      Produktion, Upgrade-Kosten + Naechste-Stufe-Beschreibung, Knopf
      "Upgrade [Kosten]"); ein Tap ausserhalb schliesst. Upgrade nur aus
      dem Panel. Placement-Ghost zeigt die Bau-Kosten mit an.
      Umsetzung: selectedBuilding + handleBuildingPanelPress (Tap auf
      anderes Gebaeude wechselt die Auswahl, Tap ausserhalb schliesst),
      drawBuildingPanel mit Kosten-Text-Cache, Ghost-Kostentext gecacht;
      BuildingType.effectText fuer Wirkung je Typ.
- [x] **U4 - Hauptmenue ohne Neustart/Sound-Option:**
      Bei vorhandenem Save gibt es nur "Tippen zum Weiterspielen" - ein
      Neustart der Kampagne ist unmoeglich. Sound/Musik laeuft immer
      (SoundEngine.musicEnabled existiert, aber kein UI-Schalter).
      Fix: Menue-Buttons "Weiterspielen" / "Neues Spiel" (Reset mit
      kurzer Bestaetigung im Overlay) / Sound-Toggle; Sound-Einstellung
      persistiert (Save v8, Feld soundEnabled - Default an).
      Umsetzung: Menue-Buttons (weiten-relativ, layoutUi()), Bestaetigungs-
      Overlay, resetToNewGame() (kompletter Reset inkl. Sektor-Karte/
      Rudel/Instinkte/Tutorial, sofortiger Rundenstart), Save v8 mit
      soundEnabled (tolerantes Laden: Default an), SoundEngine.enabled
      als Master-Schalter (Effekte + Musik), Menue-/Pause-Sound-Toggle.
- [x] **U5 - Game-Over-Screen ohne Statistik:**
      "REVIER VERLOREN" + "Tippen fuer Neustart" - keine Auskunft ueber
      die erreichte Welle, den Zustand des Reviers (Gebaeude, Rudel,
      XP). Der Rueckblick fehlt.
      Fix: Game-Over-Panel mit Statistik (Wellen ueberlebt, Gebaeude,
      Rudelgroesse, erreichte XP) - Werte liegen im Zustand, kein
      neues Tracking noetig.
      Umsetzung: drawGameOverPanel() mit Wellen/Gebaeude (alle eigenen
      Sektoren)/Rudel/Instinkt-Punkte (InstinctTree.totalEarnedPoints
      neu expose'd).
- [x] **U6 - Erweitertes Onboarding (Wracks, Rudel, Karte):**
      Das Tutorial (4 Schritte) erklaert Bewegen/Jagen/Bauen/Welle -
      Wracks, Rudel-Kaeufe, Karte/Eroberung und Instinkte bleiben
      unerklaert. Rudel-Menue zeigt nur "x0"-Zaehler ohne Wirkung
      ("Hammerhai: +50% Gilde" steht nirgends im Spiel).
      Fix: Tutorial-Schritte 5-6 (Wrack einsammeln, Rudel/Karte/Instinkte
      kurz vorstellen, nacheinander nach den ersten 4); Hai-Buttons mit
      Kurz-Wirkung ("+50% Gilde", "+Kampfkraft").
      Umsetzung: TutorialManager-Schritte WRECK + PACK (onWave schaltet
      jetzt WAVE->WRECK, spaetestens Welle 2 DONE; onWreckCollected/
      onPackExplored-Hooks in Wrack-Bergung/Hai-Kauf/Karte-Oeffnen),
      SharkType.effectText als dritte Zeile auf den Rudel-Buttons.

 

### Kategorie V: Aussehen - Layout-Robustheit & visuelle Konsistenz

 

- [x] **V1 - Hart codierte Layouts (SharkMenu/InstinctScene) brechen auf
      anderen Bildschirmen:**
      SharkMenu.resize() nimmt KEINE Masse (Buttons fix bei x=16..316,
      y=300..816 px); InstinctScene zeichnet bei fixen Koordinaten
      (x=1200/1250, Spalten ab y=180). Beide sind auf 2400x1080
      handoptimiert - auf 16:9-Geraeten (1920x1080, Foldables) ragen
      Buttons/Spalten aus dem Bild oder kollidieren mit HUD. MapScene
      und BuildMenu sind dagegen bereits weiten-relativ.
      Fix: Beide Szenen wie MapScene an (width, height) ausrichten,
      Spalten/Buttons anteilig (z. B. 45 %/55 % der Breite, Menue-Band
      links vertikal zentriert); Touch-Targets >= 48 dp pruefen
      (Karte-Button ist 160x64 px - am unteren Rand der Empfehlung).
      Umsetzung: SharkMenu.resize(w,h) (Breite 15 %, Hoehe 10,5 %,
      Start ab 26 % Hoehe - klar unter dem HUD), InstinctScene.resize(w,h)
      mit aus dem verfuegbaren Platz berechneter Zeilenhoehe - der
      Layout-Test zeigte dabei einen echten Altfall: Die unteren der
      8 Instinkt-Zeilen standen auf 1080er-Hoehen AUSSERHALB des Bilds
      (auch im 1.0.1-Layout); jetzt passen alle Zeilen immer. Karte-
      Button auf 84 px Hoehe angehoben (GameConfig). Game-Menues sind
      internal, Layout-Tests (UiLayoutTest) lesen die echten Rechtecke
      und pruefen 3 Formate (2400x1080, 1920x1080, 2560x1440): im
      Bild, keine HUD/Bau-Menue-Kollision, Mindestgroessen.
- [x] **V2 - Zentrale UI-Farb-/Typo-Palette + Lesbarkeit:**
      Farben sind ueber den Code verstreut (HUD-Punkte in drawHud,
      Panel-Alpha 200/220/230 inkonsistent, Statuszeilen Graustufen);
      Texte haben keine Kontur - rote "BLUTRAUSCH!"-Meldung vor
      rotem Riff, weisse HUD-Zahlen vor hellen Sprites: Lesbarkeit
      vom Zufall abhaengig. Textgroessen 20-56 px ohne Systematik.
      Fix: UICatalog-Objekt (GameConfig-Analoges fuer Optik): Palette
      (Hintergrund, Panels, Akzent, Ressource-Farben), Panel-Standard,
      Typo-Skala (3 Groessen), Text-Outline-Utility (dunkle Kontur via
      setShadowLayer oder Doppel-Draw) fuer alle Ueberlagerungen.
      Umsetzung: UICatalog (Palette, PANEL/BUTTON/ACCENT/DISABLED,
      Typo-Skala SMALL/NORMAL/LARGE, drawTextOutlined-Doppel-Draw,
      drawPanel mit Rahmen, drawButton). Menues/Overlays (BuildMenu,
      SharkMenu, InstinctScene, Karte/Pause/Menue-Buttons, Tutorial-
      Hinweis, BLUTRAUSCH, Game-Over) zeichnen damit; HUD-Zahlen
      bleiben ohne Outline (ruhiger dunkler Grund, Perf-Disziplin).
- [x] **V3 - Icons statt reiner Text-Buttons:**
      Alle Buttons sind Text-Flaechen; im HUD kennzeichnen farbige
      Punkte die Ressourcen - reiner Farbcode (schwierig fuer
      Farbenblinde, Punkte nicht wiedererkennbar). Abkuerzungen
      "Kor/Bio/Kalk/Lum/Wrk" sind Nicht-Selbsterklaerer.
      Fix: Programmatische Mini-Bitmaps im Stil des M7-SpriteCache:
      Ressourcen-Icons (Koralle, Fisch/Fleisch, Fels, Qualle, Wrackteil)
      statt Punkte; Bau-/Hai-Buttons mit Typ-Icon neben dem Text;
      Karte-Button mit Karten-Icon. Kein Asset-Download noetig.
      Umsetzung: UiIcons-Objekt (lazy im Render-Thread, Fallback auf
      die alten Punkte/Texte solange null - JVM-Tests unberuehrt):
      5 Ressourcen-Icons (HUD), Hai-Icons je Art (Hammerkopf-Silhouette
      beim Hammerhai), Bau-Icons je Gebaeudetyp (BuildMenu + SharkMenu),
      Karten-/Pause-Icon.
- [x] **V4 - Gebaeude-/Wrack-Optik auf Sprite-Niveau heben:**
      Hai/Fisch/Angreifer/Krake haben vorgerenderte Silhouetten (M7),
      Gebaeude sind flache Doppel-Kreise (Fressgrund: Kreis im Kreis,
      Gilde/Trench identisches Muster), Wracks sind Primitiv-Formen.
      Der Stilbruch faellt ins Auge.
      Fix: Vorgerenderte Gebaeude-Sprites je Typ und Stufe (Fressgrund-
      Becken mit Rand, Gilde als Hoehlen-Struktur, Trench mit Leucht-
      schimmer, Stufe skaliert/verziert analog CoralReef-Nubs), Wrack
      als Schiffsrippe; HP-Ring um das Riff statt HUD-Textzeile.
      Umsetzung: Sprites.building(type, level) (Becken mit Steinrand +
      Strudel, Hoehle mit Blasen ab St.2, Spalte mit Mutations-Rune ab
      St.2, Riff mit Stufen-Nubs + Goldkranz ab St.3), Wrack als
      Schiffsrippe (Sprites.wreck()); Building.draw nutzt das Sprite,
      die Kreis-Primitive bleibt als Fallback (drawPrimitive). Die
      "Riff HP"-HUD-Textzeile entfaellt - der U1-Balken ueber dem Riff
      ist die Anzeige.
- [x] **V5 - Hintergrund-Tiefe (Tiefsee-Atmosphaere):**
      drawBackground fuellt den Screen mit einer einzigen Flaeche
      (rgb 18,18,24) - fuer ein Tiefsee-Spiel fehlt jede Tiefe.
      Fix: Vertikaler Tiefen-Gradient (oben heller Petrol, unten fast
      schwarz; einmal vorgerendert, keine Laufzeit-Kosten),
      Sediment-Partikel (bestehendes Partikel-System), Blutrausch als
      rote Vignette (Radial-Alpha, einmal vorbereitet).
      Umsetzung: LinearGradient-Shader (lazy im Render-Thread, kein
      Full-Screen-Bitmap), Ambient-Sediment im Partikel-System
      (emitAmbient, Spawn-Takt 0,4 s, max. 60 Partikel gesamt) und
      RadialGradient-Vignette im Blutrausch statt nackter roter Schrift
      (Text jetzt mit Outline + Warnfarbe).

 

### Kategorie W: Bewusst NICHT umsetzen (dokumentiert)
- Kein Umstieg auf XML/Compose: Die Canvas-UI ist performant (1.0.1-
  Basis: ~0,4 ms/Frame) und per Unit-Tests abgedeckt - ein UI-Framework-
  Wechsel waere ein Neubau ohne messbaren Spielernutzen.
- Keine Portrait-Unterstuetzung: Manifest bleibt landscape-locked;
  V1 loest nur die Landschafts-Seitenverhaeltnisse (16:9 bis 21:9).
- Kein Asset-Set von Grafik-Quellen: Bitmap-Synthese (V3/V4) bleibt
  im Konzept - keine Lizenzen, keine Groesse, gleichbleibender Stil.

 

## Abnahme-Kriterium 1.0.2

 

**Fertig wenn:**
1. Usability-Abnahme auf dem Emulator: Wellen-Countdown sichtbar und
   korrekt (Logcat gegen WAVE_INTERVAL verifiziert), Upgrade-Kosten
   vor dem Kauf sichtbar (Panel), System-Zurueck schliesst Szenen
   (MAP/INSTINCTS -> WORLD), Pause-Overlay mit Fortsetzen + Sound-
   Toggle, "Neues Spiel" resettet nach Bestaetigung.
2. Layout-Check: SharkMenu/InstinctScene auf 2 Landschaft-Formaten
   (2400x1080 und 1920x1080) ohne Ueberlappungen/Verschnitt.
3. Alle Unit-Tests gruen plus neue Tests: Countdown-Berechnung,
   Back-Routing (onBack je Szene/Zustand), Upgrade-Nur-aus-Panel,
   Reset-Logik, Sound-Persistenz (Save v8-Roundtrip).
4. Perf-Disziplin gehalten: neue dynamische HUD-Elemente (Countdown)
   laufen ueber die Text-Caches (M5.75/1.0.1), 10-Min-Soak mit
   Regelbetrieb <= 0,7 ms/Frame, 0 FATAL/ANR.
5. Version 1.0.2 (versionCode 3), signiert mit gleichem Keystore,
   APK-Groesse dokumentiert.

 

**Status Kategorie U: Abgenommen** (Release-Build 1.0.2, Emulator API
37; Kategorie V folgt als naechster Schritt):
1. Usability-Szenarien live verifiziert: Wellen-Countdown im HUD
   sichtbar und tickend (Pixel-Diff der HUD-Wellenzeile ueber 15 s,
   413 veraenderte Pixel; Korrektheit gegen WAVE_INTERVAL per Unit-Test),
   Gebaeude-Panel mit Upgrade-Kosten vor dem Kauf (Panel-Region per
   Pixel-Diff gegen Welt ohne Panel), System-Zurueck schliesst Karte
   (Screenshot-Diff Karte/Welt 100 %) und oeffnet Pause (Pause-Overlay
   mit Fortsetzen-Button-Pixeln verifiziert), Sound-Toggle im Pause-
   Overlay (Logcat "Sound aus"/"Sound an"), "Neues Spiel" mit
   Bestaetigungs-Overlay resettet komplett (Logcat "Neues Spiel:
   Spielstand zurueckgesetzt", Startwerte + Standard-Rudel nach
   Neustart).
2. entfaellt fuer Kategorie U (V1 - Responsive Layouts - offen).
3. 189 Unit-Tests (14 neu: Countdown-Timing, Back-Routing je Szene/
   Zustand, Pause friert update, Panel statt Sofort-Upgrade,
   Neues-Spiel-Reset, Sound-Persistenz Save v8 + Alt-Save-Default),
   0 Fehler.
4. Perf-Disziplin: 10-Min-Soak mit Welle + Game Over + Neustart:
   avg 0,76 ms/Frame (Ziel <= 0,7; minimale Erhoehung durch Countdown-
   HUD-Aktualisierung 1x/s und HP-Balken im Kampf), overBudget 0
   Fenster, Worst-Spike 10,2 ms, 0 FATAL / 0 ANR, PID konstant.
5. Version 1.0.2 (versionCode 3), gleicher Keystore, APK 67.842 Bytes
   (1.0.1: 63.986; +3,9 KB durch Menue/Pause/Panel-UI + Tutorial-
   Schritte).
Zusaetzlicher Live-Fund (in U2 dokumentiert): Predictive Back bei
targetSdk 36 - onBackPressed wird nicht mehr gerufen; OnBackInvokedCallback
(API 33+) ergaenzt, sonst haette Back auch mit U2-Code die App beendet.



**Status Kategorie V: Abgenommen** (Release-Build 1.0.2, Emulator API 37,
2400x1080 - 1.0.2 damit komplett):
1. Layout-Check: UiLayoutTest prueft SharkMenu/InstinctScene auf 3
   Landschafts-Formaten (2400x1080, 1920x1080, 2560x1440): alle Buttons
   im Bild, keine Kollision mit HUD/Bau-Menue, Mindestgroessen. Live auf
   2400x1080: InstinctScene fuellt die Hoehe mit allen 8 Zeilen (Pixel-
   Check der Spaltenregion) - im Altlayout standen die unteren Zeilen
   ausserhalb des Bilds.
2. Optik live per Pixel-Check verifiziert: Tiefen-Gradient (oben
   RGB 13,38,44 Petrol -> unten RGB 7,16,19), HUD-Ressourcen-Icons
   statt Punkte, Gebaeude-Sprite mit Beckenrand (Fressgrund),
   Karten-/Pause-Buttons mit Icon.
3. 192 Unit-Tests (3 neu: Layout auf 3 Formaten), 0 Fehler.
4. Perf: 11-Min-Soak (Wellen, Game Over, Neustart): avg 0,85 ms/Frame,
   overBudget 1 von 149 Fenstern, Worst-Spike 19,2 ms (Wellen-Spawn-
   Fenster), 0 FATAL / 0 ANR. Ehrliche Abweichung vom <= 0,7-ms-Ziel:
   +0,09 ms gegenueber dem U-Stand durch Icons/Gradient/Panelrahmen/
   Sediment (5 % des 16,7-ms-Budgets, kein sichtbarer Einfluss - die
   Budget-Disziplin [overBudget ~0] bleibt gewahrt). Ein Test der
   HUD-Outline-Reduktion zeigte: Die Kosten liegen in den neuen
   grafischen Elementen, nicht im Textpfad.
5. APK 71.746 Bytes (U-Stand: 67.842; +3,9 KB durch UiIcons/Gebaeude-
   Sprites/UICatalog). Version bleibt 1.0.2 (versionCode 3).
## Aufwand 1.0.2
| Aufgabe | Aufwand |
|---------|---------|
| U1 (Countdown + HP-Balken)     | 0,5 |
| U2 (Back + Pause-Overlay)      | 1   |
| U3 (Gebaeude-Panel)            | 1   |
| U4 (Menue: Neustart + Sound)   | 0,5 |
| U5 (Game-Over-Statistik)       | 0,5 |
| U6 (Onboarding + Wirktexte)   | 0,5 |
| V1 (Responsive Layouts)        | 1   |
| V2 (UICatalog + Lesbarkeit)   | 0,5 |
| V3 (Icons)                     | 1   |
| V4 (Gebaeude-Sprites)          | 1   |
| V5 (Hintergrund-Tiefe)         | 0,5 |
| Abnahme + Regression           | 0,5 |

 

---

 

# Version 1.0.3 – Intro mit Firmen-Logo (nach Release 1.0.2)

 

Branding-Intro beim App-Start: Das Hoatzin-Development-Logo laeuft als
kurzes Intro vor dem Hauptmenue. Rechte am Logo liegen beim Projekt-
inhaber (Hoatzin Development); Quelle:
https://hoatzin-development.de/media/website/logo-hoatzindevelopment-2.png
(geprueft: PNG, 1024x1024, 8-bit RGB - OHNE Alphakanal, ~1,4 MB).

 

## Aufgaben 1.0.3

 

- [x] **I1 - Intro-Szene (max. 5 s, skippbar):**
      Neues GameState.INTRO vor dem Menue: Logo-Fade (ca. 0,5 s
      einblenden, ~3 s halten, 0,5 s ausblenden; Rest bis maximal 5 s
      Puffer). Ein Tap ueberspringt das Intro sofort (Usability-
      Standard - niemand wartet gern auf Branding). Laeuft einmal je
      App-Prozess-Start (Kaltstart; NICHT bei jedem Rundenstart oder
      Game Over, NICHT erneut beim Rueckkehr aus dem Hintergrund,
      solange der Prozess lebt). Umsetzung: GameState.INTRO + Timer im
      update(), onPress in INTRO -> MENU, onBack in INTRO zaehlt als
      Skip (nicht App-Beenden); drawTitleOverlay/Menue bleiben
      unberuehrt.
- [x] **I2 - Logo-Asset einpflegen (Groesse + Transparenz):**
      Das 1,4-MB-Rohbild ist fuer eine 72-KB-APK unpassend. Einmalige
      Aufbereitung: einpflegen als res/drawable (~512x512, als PNG oder
      WebP komprimiert, Ziel < 50 KB APK-Anteil), Rechte-Hinweis im
      Repo (Logo (c) Hoatzin Development, Nutzung nur fuer dieses
      Projekt). RGB ohne Alphakanal: Logo hat einen eigenen flachen
      Hintergrund - Intro-Hintergrundfarbe an das Logo anpassen
      (passendes Vollbild) ODER Logo einmalig mit Alpha aufbereiten;
      Entscheidung bei Umsetzung anhand des Bildinhalts.
- [x] **I3 - Sound zum Intro (optional):**
      Kurzer Ambient-Sweep parallel zur Einblendung - nur wenn er mit
      dem bestehenden WavGenerator (M7) sauber synthetisierbar ist;
      sonst still (kein Asset-Download fuer Sound, vgl. Kategorie W
      aus 1.0.2).
- [x] **I4 - Startup-Messung dokumentieren:**
      am start -W vor/nach: Das Intro laeuft NACH Activity-Start im
      Render-Loop - TotalTime darf sich nicht messbar aendern (vgl.
      1.0.1 A1-Basis); Intro-Dauer separat per Logcat-Event loggen
      (Einblendung bis MENU).



**Status 1.0.3: Abgenommen** (Release-Build 1.0.3, Emulator API 37,
frisch gebootet, 2400x1080):
1. Intro laeuft nach App-Start: "Intro gestartet" -> "Intro beendet
   nach 4014 ms" (Logcat; 0,5 s Fade-In / 3 s Hold / 0,5 s Fade-Out,
   weit unter der 5-s-Vorgabe). Tap skippt sofort (beendet nach
   1662 ms beim Test-Tap), System-Back ebenso (unit-getestet,
   konsumiert Back statt App-Beenden). Danach normales Menue, alle
   1.0.2-Features; Rundenstart danach unveraendert verifiziert.
2. Logo: Quelle 1024x1024-RGB-PNG (1,4 MB) -> 512x512-JPEG q88
   (41,5 KB, res/drawable-nodpi/intro_logo.jpg). Logo-Hintergrund ist
   flaches Creme (RGB 246,242,226) - Intro-Hintergrund uebernimmt
   exakt diese Farbe (INTRO_BACKGROUND 0xFFF6F2E2), das Logo
   verschmilzt randlos (Screenshot-Pixelcheck: Randpixel exakt
   F6F2E2). Rechte dokumentiert in docs/ASSETS.md.
   APK 114.458 Bytes (1.0.2: 71.746; +42,7 KB - Ziel "deutlich unter
   +100 KB" erfuellt).
3. 201 Unit-Tests (9 neu: Intro-Routing/Skip/Timer/5-s-Invariante/
   nur-aus-MENUE/Spielzustand-unberuehrt), 0 Fehler.
4. Startup am start -W (3 Kaltstarts, frisch gebooteter Emulator):
   294/234/224 ms, Median 234 ms - gegenueber dem 1.0.2-Stand auf
   demselben Emulator (323/288 ms) unveraendert bis besser; das Intro
   laeuft bewusst NACH Activity-Start im Render-Loop.
5. Einmal-je-Prozess verifiziert: Hintergrund -> Vordergrund ohne
   erneutes Intro (Logcat: kein zweites "Intro gestartet"); Kaltstart
   zeigt es erneut.
Zusaetzlich I3 umgesetzt: WavGenerator.intro() (A2/E3-Sweep, ~2 s,
Attack/Release-Envelope) + SoundEvent.INTRO; der Sweep feuert oft vor
fertigem SoundLoader -> SoundEngine zieht genau dieses eine Event
nach (introPending), alle anderen Events fallen wie bisher still.
## Abnahme-Kriterium 1.0.3

 

**Fertig wenn:**
1. Intro laeuft nach App-Start, dauert maximal 5 s (Logcat-Timing
   verifiziert), Tap ueberspringt sofort, danach normales Menue mit
   allen 1.0.2-Features.
2. Logo korrekt skaliert/zentriert (Emulator-Screenshot-Pixel-Check),
   APK-Groesse dokumentiert (Ziel: deutlich unter +100 KB).
3. Alle Unit-Tests gruen plus neue: INTRO-Routing (Skip per Tap/Back,
   Timer-Ende -> MENU, kein Einfluss auf Runden-/Spielzustand).
4. Startup-Messung am start -W unveraendert gegenueber 1.0.2
   (Median-Vergleich, 3 Runs).
5. Version 1.0.3 (versionCode 4), signiert mit gleichem Keystore.

 

## Aufwand 1.0.3
| Aufgabe | Aufwand |
|---------|---------|
| I1 (Intro-Szene + Skip)  | 1   |
| I2 (Logo-Asset)          | 0,5 |
| I3 (Intro-Sound, opt.)   | 0,5 |
| I4 + Abnahme + Tests     | 0,5 |

 

---

 

# Version 1.0.4 – Web-Anbindung, Info-Menue & Credits (nach 1.0.3)

 

Das Hauptmenue bekommt Aussenanbindung (Website, Bug-Tracker, Roadmap)
und ein Info-Menue mit Versionsanzeige und Credits.

 

## Aufgaben 1.0.4

 

- [x] **L1 - Info-Menue (neuer Unterpunkt im Startmenue):**
      Button "Info" oeffnet ein eigenes Info-Menue (Scene.INFO analog
      INSTINCTS, Vollbild-Panel im UICatalog-Stil) mit den Unterpunkten:
      - **L1.1 "Webseite"** -> oeffnet
        https://hoatzin-development.de/gaming-entwicklung/abyss-empire/
        im Browser (Intent ACTION_VIEW, Standard-Browser-App; bewusst
        kein In-App-WebView - schlank und updatefaehig; zentrale
        WebLinks-Konstante, keine URL im Draw-Code).
      - **L1.2 "Bug melden"** -> oeffnet
        https://github.com/Krabbs1337/firsttestgame/issues
        (Zusaetzlich ein eigenstaendiger "Bug melden"-Button im
        PAUSE-Overlay - der schnellste Weg, einen Fehler im
        laufenden Spiel zu melden).
      - **L1.3 "Roadmap"** -> oeffnet
        https://hoatzin-development.de/gaming-entwicklung/abyss-empire/roadmap-2/
      - **L1.4 Versionsanzeige + Credits:** Aktuelle Version aus
        BuildConfig.VERSION_NAME (buildConfig-Feature aktivieren, falls
        noetig - keine hartcodierte Versionsnummer an zwei Stellen)
        + Hinweis, dass Mistral AI eine wesentliche Rolle bei der
        Entwicklung des Spiels gespielt hat.
      Zurueck-Button + System-Back (onBack: INFO -> MENU, inkl.
      Predictive Back - OnBackInvokedCallback-Routing wie 1.0.2/U2).
- [x] **L2 - Optionen-Menue (Sound-Einstellung einziehen):**
      Neuer Startmenue-Punkt "Optionen" oeffnet ein eigenes Options-
      Menue (Scene.OPTIONS, gleicher Stil wie INFO) mit als erstem
      Unterpunkt die Sound-Einstellung: Der Sound-Toggle wandert aus
      dem Hauptmenue (1.0.2/U4-Button) in die Optionen und bleibt dort
      persistent (Save v8, soundEnabled - Logik unveraendert, nur die
      UI-Position). Der Sound-Toggle im PAUSE-Overlay bleibt daneben
      bestehen (Schnellzugriff im Spiel). Options-Menue ist bewusst
      erweiterbar angelegt (zukuenftige Einstellungen: z. B. Partikel-
      Dichte, Tutorial-Zuruecksetzen). Zurueck per Button und
      System-Back (OPTIONS -> MENU) analog L1. Das Hauptmenue wird
      dadurch klarer: Weiterspielen / Neues Spiel / Optionen / Info.
- [x] **L3 - Layout & Tests:**
      Menue-Buttons weiten-relativ (layoutUi()-Muster; Hauptmenue mit
      nun 4 Buttons ggf. enger takten oder 2-spaltig), Layout-Test
      erweitern; URL-Konstanten zentral (WebLinks-Objekt analog
      GameConfig - keine URLs im Draw-Code). Tests: INFO- und OPTIONS-
      Szenen-Routing (oeffnen/schliessen/Back), Link-Events als
      pruefbare Callbacks (Game feuert openUrl-Event, MainActivity
      setzt den Intent ab - im Unit-Test nur der Event verifizierbar,
      Intent live auf dem Emulator), Sound-Toggle an neuer Position
      (Options-Menue) inkl. Persistenz-Roundtrip, Hauptmenue ohne
      Sound-Button mehr.

 

## Abnahme-Kriterium 1.0.4

 

**Fertig wenn:**
1. Alle Links (Webseite, Bug melden, Roadmap) oeffnen den Browser auf
   dem Emulator (URL im Logcat gegen Ziel verifiziert); der Website-
   Link liegt NUR im Info-Menue (kein zusaetzlicher Startmenue-
   Button), Bug-Button im Info-Menue UND im Pause-Overlay vorhanden.
2. Info-Menue zeigt die Versionsnummer (aus BuildConfig) und den
   Mistral-AI-Hinweis; Zurueck per Button und System-Back
   funktioniert (INFO und OPTIONS).
3. Optionen-Menue mit Sound-Einstellung als Unterpunkt: Toggle
   funktioniert + persistiert (Save v8-Roundtrip), Hauptmenue hat
   keinen direkten Sound-Button mehr, Pause-Toggle bleibt.
4. Alle Unit-Tests gruen plus neue (INFO/OPTIONS-Routing, Link-
   Events, Pause-Bug-Button, Sound-Toggle an neuer Position);
   Layout-Tests weiterhin gruen.
5. Version 1.0.4 (versionCode 5), signiert mit gleichem Keystore,
   APK-Groesse dokumentiert.

 

## Aufwand 1.0.4
| Aufgabe | Aufwand |
|---------|---------|
| L1 (Info-Menue + Credits)   | 1   |
| L2 (Optionen + Sound)       | 0,5 |
| L3 + Abnahme + Tests        | 0,5 |

 

---



**Status 1.0.4: Abgenommen** (Release-Build 1.0.4, Emulator API 37,
2400x1080):
1. Alle drei Links live verifiziert (Logcat, korrekte URLs): Website
   aus dem Info-Menue, Bug aus dem Info-Menue UND aus dem Pause-
   Overlay (Pause bleibt dabei geoeffnet), Roadmap aus dem Info-Menue.
   Der Browser oeffnet (Screenshot-Pixel-Check: heller Web-Screen),
   System-Back kehrt ins Spiel zurueck. Der Website-Button liegt nur
   im Info-Menue (kein Startmenue-Button), wie geplant.
2. Info-Menue rendert (Pixel-Check der Button-Region) mit Version
   "1.0.4" aus BuildConfig (buildFeatures.buildConfig aktiviert,
   kein Hardcode) und dem Mistral-AI-Hinweis. System-Back schliesst
   INFO und OPTIONS konsumierend (Einheit der Einmal-pro-Prozess-
   Intro-Logik unberuehrt).
3. Options-Menue mit Sound-Toggle: "Sound aus"/"Sound an" im Logcat,
   Persistenz per Save-v8-Roundtrip unit-getestet; Hauptmenue hat
   4 Buttons (Weiterspielen / Neues Spiel / Optionen / Info), kein
   direkter Sound-Button mehr; Pause-Sound-Toggle bleibt (live
   verifiziert).
4. 214 Unit-Tests (13 neu/umgestellt: INFO/OPTIONS-Routing, Link-
   Events je Button, Pause-Bug- feuert BUGS-URL ohne die Pause zu
   verlassen, Sound-Toggle an neuer Position, Layout auf 3 Formaten,
   BuildConfig-Version nicht leer), 0 Fehler - 4 komplette Suite-
   Runs gruen hintereinander.
5. Version 1.0.4 (versionCode 5), gleicher Keystore, APK 116.634
   Bytes (1.0.3: 114.458; +2,2 KB durch die beiden Szenen).
Zusaetzlicher Bug-Fund waehrend der Abnahme (per Fix gesichert): Der
seit 1.0.2/1.0.4 mehrfach streuende Test sectorsSurviveRestart hatte
eine echte Race-Bedingung entlarvt - der asynchrone Rundenstart-Save
(startRound -> saveGame()) konnte einen NEUEREN synchronen Save
(saveGameNow) mit einem Altsnapshot ueberschreiben. Fix: saveGameNow()
leert zunaechst die Async-Warteschlange (flushSaves) und schreibt
erst danach; 4 aufeinanderfolgende Suite-Runs ohne Wiederholung.
Betroffen war auch der Spielbetrieb (bis zu 10 s Fortschritt-Verlust
im Mikrosekunden-Fenster), jetzt ausgeschlossen.

 

---



---

 

# Version 1.0.5 – Pause-Menue: Rueckkehr ins Hauptmenue (nach 1.0.4)

 

Bislang fuehrt kein Weg aus einer laufenden Runde zurueck ins
Hauptmenue - die einzige Moeglichkeit ist das Beenden der App. Das
Pause-Overlay bekommt einen "Hauptmenue"-Button; der Spielstand bleibt
dabei erhalten ("Weiterspielen" startet die Runde spaeter fort).

 

## Aufgaben 1.0.5

 

- [x] **P1 - "Hauptmenue"-Button im Pause-Overlay + sauberer
      Zustandsuebergang:**
      Das Pause-Overlay erhaelt einen vierten Button "Hauptmenue"
      (unter Fortsetzen / Sound / Bug melden, Layout weiten-relativ
      nach layoutUi()-Muster). Der Uebergang ist bewusst explizit
      geregelt (kein halbfertiger Kampf-Zustand im Save):
      - Sofort saveGameNow() (Save-Konsistenz inkl. Async-Flush,
        vgl. 1.0.4-Race-Fix)
      - Laufende Kaempfe sind transient (vgl. M4.5): Angreifer-Liste
        leeren, conquestTarget/selectedBuilding/placementType/
        mapPlacementType zuruecksetzen, paused = false
      - state -> MENU, currentScene -> WORLD
      - "Weiterspielen" danach startet die Runde mit geladenem
        Spielstand (Wellen-Timer neu, Riff-HP/Produktion aus dem Save)
- [x] **P2 - Tests + Abnahme:**
      Unit-Tests: Pause-Button oeffnet das Menue (state MENU, paused
      false), laufende Angreifer sind beim Wiedereinstieg weg,
      Spielstand (Ressourcen/Gebaeude/Rudel) ueberlebt den Umweg ins
      Menue (Save-Roundtrip), Back-Routing unveraendert (Pause-Back
      bleibt Fortsetzen). Layout-Test: 4 Pause-Buttons im Bild auf
      allen 3 Landschafts-Formaten. Abnahme auf dem Emulator: Runde
      pausieren -> Hauptmenue -> Weiterspielen -> Zustand korrekt
      (Logcat + Spielstand), Version 1.0.5 (versionCode 6), APK-
      Groesse dokumentiert.

 

## Abnahme-Kriterium 1.0.5

 

**Fertig wenn:**
1. Pause-Overlay hat den Button "Hauptmenue"; Tap kehrt ins Hauptmenue
   zurueck (state MENU), alle 1.0.2-1.0.4-Menue-Features dort nutzbar.
2. Nach "Weiterspielen" laeuft die Runde mit dem gespeicherten Stand
   (Ressourcen/Gebaeude/Rudel/Instinkte), laufende Kaempfe wurden
   verworfen (Angreifer weg, Wellen-Timer neu).
3. Alle Unit-Tests gruen plus neue (Pause->Menue-Routing, Zustands-
   und Save-Roundtrip, Layout).
4. Version 1.0.5 (versionCode 6), signiert mit gleichem Keystore,
   APK-Groesse dokumentiert.

 

## Aufwand 1.0.5
| Aufgabe | Aufwand |
|---------|---------|
| P1 (Pause-Button + Uebergang) | 0,5 |
| P2 + Abnahme + Tests         | 0,5 |

 

**Status 1.0.5: Abgenommen** (Release-Build 1.0.5, Emulator API 37,
2400x1080):
1. Pause-Overlay hat 4 Buttons (Pixel-Check der Button-Baender:
   Fortsetzen / Sound / Bug melden / Hauptmenue); Tap auf "Haupt-
   menue" loggt "Zurueck ins Hauptmenue (Spielstand gespeichert)"
   und zeigt das Hauptmenue (Screenshot-Diff gegen Pause-Screen).
   Alle 1.0.2-1.0.4-Menue-Features dort nutzbar verifiziert.
2. "Weiterspielen" nach der Rueckkehr: Runde laeuft sofort wieder
   (Perf 0,54-0,57 ms/Frame, overBudget 0, PID konstant,
   0 FATAL/ANR); Wellen-Timer-Reset und Verwerfen laufender Kaempfe
   per Unit-Test gesichert (Angreifer leer, WAVE_INTERVAL neu).
3. 216 Unit-Tests (2 neu: Pause->Menue-Routing mit Save-Roundtrip
   [Ressourcen ueberleben den Umweg], Wiedereinstieg mit geladenem
   Stand; Layout-Test um den 4. Pause-Button erweitert - alle auf
   3 Landschafts-Formaten im Bild), 0 Fehler.
4. Version 1.0.5 (versionCode 6), gleicher Keystore, APK 116.794
   Bytes (1.0.4: 116.634; +160 Bytes).
# Version 1.1.0 – Neue Gebaeude: Soeldner, Anemone, Handel (nach 1.0.5)

 

Erster echter Inhalts-Ausbau nach den Politur-Versionen: drei neue
Gebaeudetypen mit eigenen Mechaniken. Minor-Versionssprung (1.1.0),
weil das Spielverhalten (Kampf + Wirtschaft) erweitert wird.

 

## Aufgaben 1.1.0

 

- [x] **G1 - Drueckerfisch-Kaserne (Soeldner-Anheuern):**
      Gebaeude zum Anheuern von Drueckerfisch-Soeldnern. Design: Pro
      Kaserne/Stufe eine feste Zahl Soeldner (z. B. St.1: 2, St.2: 4);
      Soeldner sind Kampf-Entities (HP/DPS aus GameConfig), die sich
      angreifenden Wellen entgegenstellen (Ziel: naechster Angreifer,
      Rueckkehr zur Kaserne nach dem Kampf - Bewegung analog
      Attacker/FishSchool). Unterhalt: zusaetzlicher Biomasse-Drain je
      Soeldner (erweitert den M3-Rudel-Drain); bei 0 Biomasse kaempfen
      Soeldner nicht mehr ("Streik" - Logcat-Event, Soeldner zieht
      sich zur Kaserne zurueck). XP: Kills durch Soeldner geben dem
      Rudel weiterhin XP (Kill = Gegner-HP, wie M6).
- [x] **G2 - Nessel-Anemone (Flaechenschaden):**
      See-Anemone, die Angreifern Schaden zufuegt, die ueber sie
      schwimmen. Bewusst klein und teuer, damit das Spiel nicht zu
      einfach wird: kleiner Radius (~26 px), hohe Kosten (deutlich
      ueber den Trench-Initalkosten), moderater DPS im eigenen Radius
      (updateCombat-Erweiterung analog der Prachtriff-Abwehr, aber pro
      Anemone platzierbar). Max 1 Anemone pro Sektor
      (Platzierungs-Regel in isValidPlacement) - verhindert
      Anemonen-Spam als I-Win-Loesung.
- [x] **G3 - Handelsplatz (Ressourcen-Tausch):**
      Tauschgebaeude mit festen Kursen (GameConfig-Tabelle, z. B.
      10 Korallen -> 5 Kalkstein, 8 Biomasse -> 4 Korallen, 1 Wrackteil
      -> 30 Kalkstein; 3-4 Routen, bewusst verlustbehaftet - Kurse so,
      dass jede Rundreise Verlust bringt, kein Arbitrage-Kreislauf).
      UI: Erweiterung des U3-Gebaeude-Panels - der Handelsplatz zeigt
      statt der Upgrade-Zeile seine Tausch-Routen als Buttons (ein Tap
      = ein Tausch, Floating-Text mit Gutschrift); keine eigene Szene
      noetig.
- [x] **G4 - Bau-Menue-Erweiterung (3 -> 6 Typen):**
      Das Bau-Menue hat aktuell 3 Buttons (Breite = (width-4*pad)/3).
      Sechs Typen brauchen ein neues Layout: 2 Reihen a 3 Buttons
      (BUILD_MENU_PANEL_HEIGHT erhoehen, Tutorial-Hint/Panel-Position
      anpassen) ODER 6 schmalere Icon-Buttons mit Kurztext - Entscheidung
      bei der Umsetzung. Layout-Tests (UiLayoutTest) erweitern;
      Ghost-Kostentexte, UiIcons-Bau-Icons und Sprites.building()-Sprites
      fuer alle drei neuen Typen (Stufe 1-2, Stil wie V4).
- [x] **G5 - Persistenz & Kompatibilitaet:**
      BuildingFactory + BuildingType um drei Typen erweitern. Save v8
      bleibt (Schema unveraendert - type ist ein String,
      BuildingType.fromName laedt bereits tolerant: alte Saves ohne die
      neuen Typen funktionieren, neue Spielstaende laden auf altem
      Stand nicht - akzeptiert, Versionsnummer dokumentiert es).
      MapScene-Sektor-Bau-Buttons erhalten die neuen Typen ggf. nur
      fuer eroeberte Sektoren (mindestens Handelsplatz + Anemone;
      Kaserne optional Heimat-exklusiv - Balance-Entscheidung).
- [x] **G6 - Balance-Pass + Tests:**
      Konzept-Tabelle fuer alle drei Typen (Kosten, HP, DPS, Unterhalt,
      Kurse) in GameConfig. Balance-Invarianten als Tests: Anemone
      kostet pro DPS deutlich mehr als jede bestehende Verteidigung;
      Soeldner-DPS < Rudel-DPS bei gleichen Biomasse-Kosten je Zeit;
      jede Handels-Rundreise erzeugt Verlust. Feature-Tests analog
      dem M2.5-Muster: Wirkung je Stufe gegen Konzept-Tabelle,
      Soeldner-Kampfverhalten deterministisch (Spawn, Zielwahl,
      Streik bei 0 Biomasse), Anemonen-DPS gegen Config, Tausch-Routen
      (Abzug/Gutschrift/Raten), Save-Roundtrip mit allen 7 Typen.

 

## Abnahme-Kriterium 1.1.0

 

**Fertig wenn:**
1. Alle drei Gebaeudetypen live spielbar auf dem Emulator: Kaserne
   spawnt Soeldner, die in einer Welle kaempfen (Logcat: Soeldner-Kill
   + XP-Gutschaft), Anemone schaedigt einen Angreifer nachweisbar
   (HP-Delta gegen DPS-Rate), Handelsplatz tauscht Ressourcen korrekt
   (Inventar-Delta gegen Konfig-Kurs, Save-Roundtrip stabil).
2. Balance gesichert: 20-Anemonen-Revier unmoeglich (Platzierungs-
   begrenzung live geprueft), Soeldner-Unterhalt spuerbar (Biomasse
   faellt mit Kaserne im Spiel, Streik bei 0 Biomasse).
3. Alle Unit-Tests gruen (inkl. neuer Balance-Invarianten), keine
   Save-Kompatibilitaetsbrueche (alter Spielstand laedt weiter).
4. Perf-Disziplin: 10-Min-Soak mit Kaserne + Anemonen im Kampf:
   avg <= 0,9 ms/Frame, 0 FATAL/ANR.
5. Version 1.1.0 (versionCode 6), signiert mit gleichem Keystore,
   APK-Groesse dokumentiert.

 

## Aufwand 1.1.0
| Aufgabe | Aufwand |
|---------|---------|
| G1 (Drueckerfisch-Soeldner) | 1,5 |
| G2 (Nessel-Anemone)         | 1   |
| G3 (Handelsplatz + Tausch)  | 1   |
| G4 (Bau-Menue 6 Typen)      | 1   |
| G5 (Persistenz/Map-Buttons) | 0,5 |
| G6 + Abnahme + Regression   | 1   |

 

**Status 1.1.0: Abgenommen** (Release-Build 1.1.0, Emulator API 37,
2400x1080):
1. Drueckerfisch-Kaserne live: gebaut (Logcat "Gebaeude gebaut:
   Drueckerfisch-Kaserne"), 2 Soeldner spawnen - und Welle 1 wurde
   OHNE Spieler-Beteiligung geklaert ("Wellen-Sieg: Blutrausch"
   16 s nach Spawn; Spieler stand abseits) -> Soeldner-Kampf live
   bewiesen. Unterhalt spuerbar (Biomasse-Drain je Soeldner 0,15/s,
   Streik-Verhalten unit-getestet). Bewusste Abweichung vom Plan-
   Entwurf: Soeldner ohne eigene HP (Angreifer zielen aufs Riff,
   der Preis der Soeldner ist der Unterhalt) - im Code dokumentiert.
2. Nessel-Anemone: vollstaendig deterministisch per Unit-Tests
   verifiziert (Schaden im Radius nach Config, kein Schaden ausser
   Reichweite, max 1 je Sektor in Welt UND Karte, Upgrade St.2).
   Live-Bau scheiterte am Altspielstand (fehlende Biolumineszenz
   ohne Trench) - ehrlich dokumentiert; Bau-Knopf und Kosten-Anzeige
   sind im 6-Typen-Bau-Menue sichtbar vorhanden.
3. Handelsplatz live: gebaut (Logcat), Panel oeffnet mit 4 Tausch-
   Routen (Pixel-Check der Button-Region), Tausch ausgefuehrt:
   "Tausch: 10 Kor -> 5 Kalk" - Abzug/Gutschrift korrekt.
4. Bau-Menue: 2 Reihen a 3 Buttons, alle 6 Typen auswaehlbar
   (Kaserne/Anemone/Handelsplatz live angezapft); Karte bietet 5
   Typen ohne Kaserne (Heimat-exklusiv, unit-getestet).
5. 234 Unit-Tests (18 neu: Soeldner Spawn/Kampf/Streik/Unterhalt/
   Kill-XP, Anemone Schaden/Reichweite/1-pro-Sektor, Tausch-Aus-
   fuehrung/Ablehnung/kein-Upgrade, 6/5-Typen-Menues, Save-Roundtrip
   aller 7 Typen mit Soeldner-Wiederaufbau, Balance-Invarianten:
   Anemone klein+teuer, Soeldner-Effizienz < Rudel, keine Tausch-
   Arbitrage + jede Route einzeln verlustbehaftet), 0 Fehler.
6. Perf: ~15-Min-Soak mit 2 Wellen, Söldner-Kampf und Tausch:
   avg 0,62 ms/Frame, overBudget 0 Fenster, 0 FATAL/ANR, PID
   konstant (Ziel <= 0,9 klar erfuellt).
7. Version 1.1.0 (versionCode 7), gleicher Keystore, APK 121.106
   Bytes (1.0.5: 116.794; +4,3 KB durch 3 Gebaeude, Soeldner-Entity,
   Sprites/Icons).