From d7f91c2e47d23c07b9a2bbde8a7666ed1a5cb76b Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Tue, 14 Jul 2026 12:55:19 +0200 Subject: [PATCH] docs(readme): restructure around the two ways to run the game The README buried the "just run it" path below the Maven section and left out several commands the game actually supports. - Split the quick start into Weg A (prebuilt jars, Java only, works offline) and Weg B (Maven wrapper: test, package, exec:java@run / @gui) - State the Java 21 prerequisite up front, with how to check it - Note that the console version runs headless while the GUI needs a desktop, and where saves/ is written - Document the missing commands: 'go to ', 'save'/'speichern', and the skippable tutorial - Add the scope up front (14 rooms, 19 items, 3 NPCs, 259 tests) All commands and links in the file were executed/resolved before committing. --- Semesterprojekt/README.md | 184 +++++++++++++++++++++----------------- 1 file changed, 102 insertions(+), 82 deletions(-) diff --git a/Semesterprojekt/README.md b/Semesterprojekt/README.md index 9d4328e..3f3d85b 100644 --- a/Semesterprojekt/README.md +++ b/Semesterprojekt/README.md @@ -1,78 +1,89 @@ # Haunted Manor – Textadventure -Semesterprojekt im Modul Programmierung 2 (Algorithmen und Datenstrukturen, -2. Semester). Ein textbasiertes Adventure in Java: Der Spieler navigiert durch -Räume eines Spukhauses, sammelt Gegenstände, interagiert mit NPCs und löst so -das Spiel. +Semesterprojekt im Modul Algorithmen und Datenstrukturen (2. Semester). +Ein textbasiertes Adventure in Java: Der Spieler navigiert durch die Räume eines +Spukhauses, sammelt Gegenstände, spricht mit NPCs, löst Rätsel und findet einen +Weg hinaus. -Die Spielwelt ist vollständig datengetrieben – Räume, Gegenstände und NPCs -werden aus YAML-Dateien geladen, nicht im Code festverdrahtet. +Die Spielwelt ist vollständig datengetrieben – Räume, Gegenstände, NPCs, Quests +und Enden werden aus YAML-Dateien geladen, nicht im Code festverdrahtet. -## Features +**Umfang:** 14 Räume, 19 Gegenstände, 3 NPCs, 259 Tests. -- **Navigation** durch beliebig viele Räume in den Himmelsrichtungen -- **Inventar** mit Aufnehmen (`take`) und Ablegen (`drop`) von Gegenständen -- **Item-Hierarchie**: einfache, lesbare (`read`) und schaltbare (`use`) Gegenstände -- **NPCs** mit Gesprächen (`talk`) und Geschenk-Reaktionen (`give`) -- **Zwei Frontends**: klassische Konsole und Swing-GUI (Bonus) -- **Datengetriebene Welt** aus YAML inkl. Referenzauflösung und Validierung beim Laden +--- -## Voraussetzungen +## Schnellstart -- **Java 21+** (LTS). Gebaut wird gegen `maven.compiler.release=21`; das neueste - genutzte Sprachfeature ist `List.getFirst()` (SequencedCollection, Java 21). - Neuere JDKs (22–25) funktionieren ebenfalls. -- Maven 3.9+ **oder** der mitgelieferte Maven Wrapper (`./mvnw`) – damit ist - keine separate Maven-Installation nötig; der Wrapper lädt die passende - Maven-Version beim ersten Aufruf selbst herunter. +Es gibt **zwei Wege**, das Spiel zu starten. Wenn Sie nur spielen wollen, nehmen +Sie Weg A – dafür wird kein Maven benötigt. -## Schnellstart ohne Maven +### Voraussetzung -Im Ordner [`release/`](release/) liegen zwei fertig gebaute, eigenständige -JARs mit allen Abhängigkeiten – je eine pro Frontend. Sie brauchen nur Java 21+: +**Java 21 oder neuer** (LTS). Gebaut wird gegen `maven.compiler.release=21`; +das neueste genutzte Sprachfeature ist `List.getFirst()` (SequencedCollection, +Java 21). Neuere JDKs (22–25) funktionieren ebenfalls. + +Prüfen mit: ```bash -java -jar release/HauntedManor-Console.jar # Konsolen-Version (~5 MB, ohne Audio) -java -jar release/HauntedManor-GUI.jar # Swing-GUI (~17 MB, mit Musik) +java -version ``` -Die Konsolen-JAR enthält weder die Musikdateien noch die OGG-Bibliotheken – -der Textmodus spielt keine Musik, daher werden sie dort weggelassen. +### Weg A – fertige JARs starten (ohne Maven) -## Bauen und Testen - -Mit dem Wrapper (empfohlen, keine Maven-Installation nötig) – unter Windows -`mvnw.cmd` statt `./mvnw`: +Im Ordner [`release/`](release/) liegen zwei eigenständige JARs, die alle +Abhängigkeiten bereits enthalten. Es wird **nur Java** gebraucht, kein Maven, +keine Internetverbindung: ```bash -./mvnw clean test # alle Tests ausführen (259 Tests) -./mvnw clean package # baut beide JARs nach release/ (Console + GUI) +java -jar release/HauntedManor-Console.jar # Konsolen-Version (~5 MB) +java -jar release/HauntedManor-GUI.jar # Swing-GUI (~17 MB) ``` -Ein systemweit installiertes `mvn` funktioniert identisch (`mvn clean test` …). +- Die **Konsolen-Version** läuft in jedem Terminal, auch ohne grafische + Oberfläche. +- Die **GUI-Version** (Bonus) braucht einen Desktop und spielt zusätzlich + Hintergrundmusik. Die Konsolen-JAR enthält weder die Musikdateien noch die + OGG-Bibliotheken – im Textmodus gibt es keine Musik, daher sind sie dort + weggelassen. -## Spielen +### Weg B – mit Maven bauen und starten -Über die im `pom.xml` konfigurierten Run-Profile des `exec-maven-plugin`: +Der mitgelieferte **Maven Wrapper** (`./mvnw`) lädt die passende Maven-Version +beim ersten Aufruf selbst herunter – eine separate Maven-Installation ist nicht +nötig. Unter Windows `mvnw.cmd` statt `./mvnw` verwenden. Ein systemweit +installiertes `mvn` funktioniert identisch. ```bash -./mvnw exec:java@run # Konsolen-Version (thb.jeanluc.adventure.App) -./mvnw exec:java@gui # Swing-GUI (thb.jeanluc.adventure.AppGui) +./mvnw clean test # alle 259 Tests ausführen +./mvnw clean package # baut beide JARs neu nach release/ + +./mvnw exec:java@run # Konsolen-Version starten (thb.jeanluc.adventure.App) +./mvnw exec:java@gui # Swing-GUI starten (thb.jeanluc.adventure.AppGui) ``` `./mvnw exec:java` ohne Profil startet ebenfalls die Konsolen-Version. -Alternativ direkt aus der gebauten JAR (siehe [Schnellstart](#schnellstart-ohne-maven)). -### Befehle im Spiel +> **Hinweis:** Der erste Maven-Aufruf lädt die Abhängigkeiten (Jackson, Lombok, +> JUnit, Logback) aus dem Internet. Wer offline ist, nimmt Weg A. -Befehle funktionieren auf **Englisch und Deutsch** – die deutschen Beispiele der -Aufgabenstellung (`Gehe nach Norden`, `Nimm Brief`, `Lies Brief`, -`Benutze Schaufel`) laufen also direkt. Item-IDs bleiben englisch (`letter`, -`shovel`), Himmelsrichtungen verstehen beide Sprachen (`north` / `norden`). +Speicherstände und Einstellungen legt das Spiel in einem Ordner `saves/` neben +dem Arbeitsverzeichnis an, aus dem es gestartet wurde. + +--- + +## Befehle im Spiel + +Befehle funktionieren auf **Englisch und Deutsch** – die deutschen Beispiele aus +der Aufgabenstellung (`Gehe nach Norden`, `Nimm Brief`, `Lies Brief`, +`Benutze Schaufel`) laufen also direkt. Gegenstands-IDs bleiben englisch +(`letter`, `shovel`), Himmelsrichtungen verstehen beide Sprachen +(`north` / `norden`). | Befehl | Aliase | Deutsch | Wirkung | |---|---|---|---| | `go ` | `move`, `walk` | `gehe`, `geh` | In eine Himmelsrichtung gehen | +| `go to ` | | | Automatisch zu einem bekannten Raum laufen | | `look` | `l` | `schau`, `umsehen` | Aktuellen Raum beschreiben | | `map` | `m` | `karte` | Karte der erkundeten Räume anzeigen | | `quests` | `log`, `journal` | `aufgaben` | Aktive und erledigte Quests anzeigen | @@ -85,54 +96,63 @@ Aufgabenstellung (`Gehe nach Norden`, `Nimm Brief`, `Lies Brief`, | `examine ` | `x`, `inspect` | `untersuche` | Gegenstand genauer ansehen | | `talk ` | `speak` | `rede`, `sprich` | Mit einem NPC sprechen | | `give ` | | `gib` | NPC einen Gegenstand geben | +| `save` | | `speichern` | Spielstand speichern | | `help` | `?` | `hilfe` | Befehlsübersicht anzeigen | -| `quit` | `exit` | `beenden` | Spiel beenden | +| `quit` | `exit` | `beenden` | Speichern und zurück ins Hauptmenü | + +Zu Beginn führt ein kurzes, überspringbares Tutorial (`skip`) durch die +wichtigsten Befehle. + +--- ## Wo die Aufgabenstellung umgesetzt ist -Kurzwegweiser zu den geforderten Punkten: - -| Anforderung | Wo | Details | +| Anforderung | Wo im Code | Umsetzung | |---|---|---| -| **Raum-Klasse + Navigation**, mind. 4 Räume | [`model/Room.java`](src/main/java/thb/jeanluc/adventure/model/Room.java), [`model/Direction.java`](src/main/java/thb/jeanluc/adventure/model/Direction.java) | **14 Räume**. `Room` hält direkte Referenzen auf Nachbarräume in einer `EnumMap` – ein echter Objektgraph, keine String-IDs. | -| **`gehen`-Befehl** (Tipp: switch/if-else/HashMap) | [`command/CommandRegistry.java`](src/main/java/thb/jeanluc/adventure/command/CommandRegistry.java), [`command/impl/GoCommand.java`](src/main/java/thb/jeanluc/adventure/command/impl/GoCommand.java) | Dispatch über `HashMap` (O(1), Aliase = mehrere Keys auf dieselbe Instanz). Richtung dann O(1) per `EnumMap`-Lookup. | -| **Gegenstände + Inventar**, mind. 3 Items | [`model/Player.java`](src/main/java/thb/jeanluc/adventure/model/Player.java), [`model/item/`](src/main/java/thb/jeanluc/adventure/model/item/) | **19 Items**. Inventar = `LinkedHashMap`. Item-Hierarchie: `PlainItem`, `ReadableItem`, `SwitchableItem`. | -| **Aufnehmen / Ablegen / Benutzen / Lesen** | [`command/impl/`](src/main/java/thb/jeanluc/adventure/command/impl/) | `TakeCommand`, `DropCommand`, `UseCommand`, `ReadCommand` – inkl. `letter` („Brief") und `shovel` („Schaufel") aus den Beispielen. | -| **Datenstrukturwahl** (bewertungsrelevant) | [`docs/data-structures.md`](docs/data-structures.md) | Begründung je Anwendungsfall + Tabelle „Bewusst NICHT gewählt". | -| **NPCs** (Bonus) | [`model/Npc.java`](src/main/java/thb/jeanluc/adventure/model/Npc.java) | 3 NPCs, die auf Spielerzustand **reagieren** (`talk`, `give`). | -| **Swing-GUI** (Bonus) | [`io/SwingIO.java`](src/main/java/thb/jeanluc/adventure/io/SwingIO.java) | `JTextField` für die Eingabe (s. Hinweis unten). | -| **Javadoc** | überall | An Klassen, Methoden und Instanzvariablen. | +| **Raum-Klasse + Navigation**, mind. 4 Räume | [`model/Room.java`](src/main/java/thb/jeanluc/adventure/model/Room.java), [`model/Direction.java`](src/main/java/thb/jeanluc/adventure/model/Direction.java) | **14 Räume.** `Room` hält direkte Referenzen auf seine Nachbarräume in einer `EnumMap` – ein echter Objektgraph, keine String-IDs. | +| **`gehen`-Befehl** (Tipp: switch / if-else / HashMap) | [`command/CommandRegistry.java`](src/main/java/thb/jeanluc/adventure/command/CommandRegistry.java), [`command/impl/GoCommand.java`](src/main/java/thb/jeanluc/adventure/command/impl/GoCommand.java) | Dispatch über `HashMap` (O(1); Aliase = mehrere Keys auf dieselbe Instanz, statt eines wachsenden `switch`). Die Richtung danach O(1) per `EnumMap`-Lookup. | +| **Gegenstände + Inventar**, mind. 3 Items | [`model/Player.java`](src/main/java/thb/jeanluc/adventure/model/Player.java), [`model/item/`](src/main/java/thb/jeanluc/adventure/model/item/) | **19 Gegenstände.** Inventar = `LinkedHashMap` (O(1)-Zugriff *und* stabile Anzeigereihenfolge). Hierarchie: `PlainItem`, `ReadableItem`, `SwitchableItem`. | +| **Aufnehmen / Ablegen / Benutzen / Lesen** | [`command/impl/`](src/main/java/thb/jeanluc/adventure/command/impl/) | `TakeCommand`, `DropCommand`, `UseCommand`, `ReadCommand` – inklusive `letter` („Brief") und `shovel` („Schaufel") aus den Beispielen der Aufgabenstellung. | +| **Wahl der Datenstrukturen** | [`docs/data-structures.md`](docs/data-structures.md) | Begründung je Anwendungsfall, plus Tabelle „Bewusst NICHT gewählt". | +| **NPCs** (Bonus) | [`model/Npc.java`](src/main/java/thb/jeanluc/adventure/model/Npc.java) | 3 NPCs, die auf den Spielerzustand **reagieren** (`talk`, `give`). | +| **Swing-GUI** (Bonus) | [`io/SwingIO.java`](src/main/java/thb/jeanluc/adventure/io/SwingIO.java) | `JTextField` für die Eingabe (siehe Hinweis unten). | +| **Javadoc** | gesamtes `src/main/java` | An Klassen, Methoden und Instanzvariablen. | -**Hinweis zur GUI:** Die Aufgabe nennt `JTextField` + `JTextArea`. Die Eingabe ist ein -`JTextField` wie gefordert; für die **Ausgabe** wird bewusst ein `JTextPane` statt einer -`JTextArea` verwendet. Grund: `JTextArea` kann nur unformatierten Text darstellen, während -das Spiel farbige/gestylte Ausgabe (`StyledText` → `StyledDocument`) rendert – Raumnamen, -Items und Hinweise sind farblich unterschieden. `JTextPane` ist dafür die passende -Swing-Komponente und funktional eine Obermenge von `JTextArea`. +**Hinweis zur GUI:** Die Aufgabe nennt `JTextField` **und** `JTextArea`. Die +Eingabe ist wie gefordert ein `JTextField`. Für die **Ausgabe** wird bewusst ein +`JTextPane` statt einer `JTextArea` verwendet: `JTextArea` kann ausschließlich +unformatierten Text darstellen, das Spiel rendert aber farbig gestylte Ausgabe +(`StyledText` → `StyledDocument`), damit Raumnamen, Gegenstände und Hinweise +optisch unterscheidbar sind. `JTextPane` ist dafür die passende Swing-Komponente +und funktional eine Obermenge von `JTextArea`. + +--- ## Projektstruktur ``` Semesterprojekt/ ├── src/main/java/thb/jeanluc/adventure/ -│ ├── App.java - Einstiegspunkt Konsole -│ ├── AppGui.java - Einstiegspunkt Swing-GUI -│ ├── command/ - Befehlsparser, Registry + impl/ (15 Kommandos) -│ ├── game/ - Spielschleife, Engines, Light, Pathfinder, MapLayout -│ ├── io/ - GameIO-Abstraktion: ConsoleIO, SwingIO + text/ (Styling) -│ ├── loader/ - YAML-Laden: dto/, Factories, Resolver, Validator -│ ├── menu/ - Hauptmenü und Einstellungen -│ ├── model/ - Domänenmodell: Room, World, Player, Npc, item/ -│ └── save/ - Speicherstände und Settings (JSON) +│ ├── App.java – Einstiegspunkt Konsole +│ ├── AppGui.java – Einstiegspunkt Swing-GUI +│ ├── model/ – Domänenmodell: Room, Player, Npc, item/ … +│ ├── command/ – Parser, Registry + impl/ (15 Kommandos) +│ ├── game/ – Spielschleife, Engines, Light, Pathfinder, MapLayout +│ ├── io/ – GameIO-Abstraktion: ConsoleIO, SwingIO + text/ +│ ├── loader/ – YAML-Laden: dto/, Factories, Resolver, Validator +│ ├── save/ – Speicherstände und Einstellungen (JSON) +│ └── menu/ – Hauptmenü und Einstellungen ├── src/main/resources/world/ -│ ├── game.yaml - Metadaten (Titel, Startraum, Begrüßung) -│ ├── rooms.yaml - Räume mit Ausgängen, Items, NPCs -│ ├── items.yaml - Gegenstände -│ ├── npcs.yaml - NPCs und ihre Reaktionen -│ ├── quests.yaml - Quests und Stages -│ ├── endings.yaml - Spielenden -│ └── combinations.yaml - Item-Kombinationen (`use X on Y`) -└── docs/ - Design- und Architekturdokumentation +│ ├── game.yaml – Metadaten (Titel, Startraum, Begrüßung) +│ ├── rooms.yaml – Räume mit Ausgängen, Gegenständen, NPCs +│ ├── items.yaml – Gegenstände +│ ├── npcs.yaml – NPCs und ihre Reaktionen +│ ├── quests.yaml – Quests und ihre Stufen +│ ├── endings.yaml – Spielenden +│ └── combinations.yaml – Gegenstands-Kombinationen (`use X on Y`) +├── src/test/java/ – 259 Tests (JUnit 5 + AssertJ) +├── release/ – fertig gebaute JARs (Console + GUI) +└── docs/ – Design- und Architekturdokumentation ``` ## Technologie-Stack @@ -140,12 +160,12 @@ Semesterprojekt/ - **Java 21 (LTS)** - **Jackson** (YAML) für das Laden der Spielwelt - **Lombok** zur Reduktion von Boilerplate -- **JUnit 5 + AssertJ + Mockito** für Tests +- **JUnit 5 + AssertJ + Mockito** für die Tests - **SLF4J + Logback** für Logging - **Swing** für die GUI (Bonus) ## Dokumentation Ausführliche Design- und Architekturdokumentation liegt unter -[`docs/`](docs/README.md): Package-Struktur, Datenstrukturen, Item-Modell, -YAML-Schemas, Lade-Ablauf, Befehle und NPC-Modell. +[`docs/`](docs/README.md): Package-Struktur, Wahl der Datenstrukturen, +Item-Modell, Befehle, NPC-Modell, YAML-Schemas und Lade-Ablauf.