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