# Implementierungsstand & Reihenfolge
Stand: alle Phasen 1–7 implementiert, 67 Tests grün, End-to-End-Smoke-Test des Walking-Skeletons + YAML-Load erfolgreich.
## Phasen-Überblick
```mermaid
flowchart TD
P1["Phase 1
Domain-Fundament"]
P2["Phase 2
Command-Schicht"]
P3["Phase 3
Walking Skeleton
(Konsole + handgebaute Welt)"]
P4["Phase 4
YAML-Loading + Validator"]
P5["Phase 5
Restliche Commands"]
P6["Phase 6
NPCs end-to-end"]
P7["Phase 7
Swing-GUI (Bonus)"]
P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7
```
## Checkliste Phase 1: Domain
- [x] `Direction` (`model.Direction`)
- [x] `Room` (`model.Room`)
- [x] `Item` abstract (`model.item.Item`) mit `abstract use(GameContext)`
- [x] `Npc` (`model.Npc`) inklusive `shell()`-Factory und `putReaction()`
- [x] `NpcReaction` (`model.NpcReaction`)
- [x] `GameIO` interface (`io.GameIO`)
- [x] `Player` (`model.Player`)
- [x] `World` (`model.World`)
- [x] `GameContext` (`game.GameContext`)
- [x] `ReadableItem` (`model.item.ReadableItem`)
- [x] `SwitchableItem` (`model.item.SwitchableItem`)
- [x] `PlainItem` (`model.item.PlainItem`)
## Checkliste Phase 2: Commands
- [x] `Command` interface (`command.Command`)
- [x] `ParsedCommand` (record)
- [x] `CommandRegistry` (`command.CommandRegistry`)
- [x] `CommandParser` (`command.CommandParser`) mit Filler-Words
- [x] `LookCommand`
- [x] `GoCommand`
- [x] `InventoryCommand`
## Checkliste Phase 3: Walking Skeleton
- [x] `ConsoleIO`
- [x] `Game` (Loop)
- [x] `App.main` (lädt sofort über YAML; der Walking-Skeleton-Zustand mit hartkodierter Welt wurde übersprungen, weil YAML-Load und Loop schon zusammen funktionieren)
- [x] Probelauf: `look`, `go north`, `inventory` (siehe `GameTest`, `LookCommandTest`)
## Checkliste Phase 4: YAML-Loading
- [x] DTOs: `GameDto`, `ItemDto`, `RoomDto`, `NpcDto`, `ReactionDto`
- [x] Test-Fixtures unter `src/test/resources/world/`
- [x] `WorldLoader` (Happy-Path)
- [x] `ReferenceResolver`
- [x] `WorldValidator` (eine Validierungsregel pro Test)
- [x] Echte Welt-YAMLs unter `src/main/resources/world/`
- [x] `App.main` läuft direkt gegen YAML-Load
## Checkliste Phase 5: Restliche Commands
- [x] `TakeCommand`
- [x] `DropCommand`
- [x] `UseCommand`
- [x] `ReadCommand`
- [x] `ExamineCommand`
- [x] `HelpCommand`
- [x] `QuitCommand`
## Checkliste Phase 6: NPCs
- [x] `Npc` voll ausgebaut (greeting, reactions)
- [x] `NpcReaction`
- [x] `TalkCommand`
- [x] `GiveCommand`
- [x] NPCs in `WorldLoader` integriert
- [x] End-to-End-Test: Lampe geben → Schlüssel bekommen (`TalkGiveCommandTest`)
## Checkliste Phase 7: Swing-GUI
- [x] `SwingIO` mit `LinkedBlockingQueue`-Brücke
- [x] `AppGui.main`
- [x] Game-Loop in Worker-Thread
## Build & Run
```sh
mvn test # 67 Tests
mvn -DskipTests exec:java -Dexec.mainClass=thb.jeanluc.adventure.App # Konsole
mvn -DskipTests exec:java -Dexec.mainClass=thb.jeanluc.adventure.AppGui # Swing
```
## Festgelegte Designentscheidungen
Nicht mehr offen, nicht nochmal diskutieren:
| Entscheidung | Wert |
|---|---|
| Item-Hierarchie | abstract Item + ReadableItem/SwitchableItem/PlainItem |
| Item-Package | `model.item` (Subpackage) |
| Switchable-State-Typ | `boolean` (kein Enum) |
| Switchable-Felder | nur `state` (Builder mappt YAML `initialState`); kein separates `initialState`-Feld am Domain-Objekt |
| use-Targets | argless `use X`, kein `use X on Y` |
| Item kennt Standort | nein, „dumme" Items |
| Hidden Items | nein |
| State→Raum-Beschreibung | nein im MVP |
| Room.description | `final`, immutable |
| Room.describe() | nicht auf Room, im LookCommand |
| Room.equals/hashCode | nicht überschreiben, Identity |
| Room-NPCs-Feld | von Anfang an drin |
| Bidirektionale Exits | manuell, kein Auto-Spiegeln |
| GameContext-Inhalt | minimal: World + Player + GameIO |
| IDs | lowercase snake_case slugs, kein UUID |
| ID-Regex | `^[a-z][a-z0-9_]*$` |
| YAML-Aufteilung | `game.yaml`, `items.yaml`, `rooms.yaml`, `npcs.yaml` |
| DTO ↔ Domain | getrennt, Resolver-Phase löst String-IDs zu Referenzen auf |
| Item-Type-Discriminator | YAML-Feld `type: plain|readable|switchable`, in `ItemFactory` als switch |
| Codebase-Sprache | Englisch (Identifier, YAML, User-Strings) |
| Doku-Sprache | Deutsch (Prose), Englisch (Code-Beispiele) |
| Diagramme | Mermaid |
| Lombok-Inheritance | `@SuperBuilder` |
| `@Data` | vermeiden, einzelne Annotations bevorzugen |
| Quit-Wiring | `QuitCommand.bind(Game)` nach Registry-Aufbau |
| Help-Quelle | `HelpCommand` zieht aus `CommandRegistry.distinctCommands()` |
| GameIO-Methodennamen | `readLine()` / `write(String)` (Java-üblich, konsistent) |
| Lombok-Version | 1.18.42 (1.18.36 ist nicht Java-26-kompatibel) |
## Offen / nicht im MVP
- **Win-Condition**: Spiel endet nur per `quit`. Optionale Erweiterung: Bedingung in `game.yaml` (`winRoom`, `requiredItem`).
- **Bedingte NPC-Reaktionen**, NPC-Memory, Quests — bewusst ausgelassen (siehe `npcs.md`).
- **Item-Aliases** (z.B. `lamp` ↔ `oil_lamp`) — YAGNI bis konkreter Bedarf.
- **Eingabehistorie** in der GUI — `ArrayDeque` ist vorgesehen, nicht umgesetzt.