The docs had drifted from the code and described things that never existed. - architecture.md documented a QuitCommand class (quit/exit are aliases on MenuCommand) and a GameIO interface of read()/write(String); the real one is readLine() plus print(StyledText) with presentation hooks. Both corrected, along with the package diagram and the game-loop sketch. - conventions.md listed a package tree missing save, menu, io.text and command.impl. Updated, including why MapLayout lives in game. - data-structures.md claimed LinkedList was deliberately avoided (Pathfinder uses one for O(1) addFirst during path reconstruction), named the wrong queue for the Swing bridge, and listed an input history that was never built. - Removed enhancement-ideas.md and implementation-status.md: a backlog and a phase tracker, neither of which documents the delivered project. Also stop tracking the built jars. They still ship in the submission, but a 22 MB binary that changes on every build does not belong in git history.
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.
Die Spielwelt ist vollständig datengetrieben – Räume, Gegenstände und NPCs werden aus YAML-Dateien geladen, nicht im Code festverdrahtet.
Features
- 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
- Java 21+ (LTS). Gebaut wird gegen
maven.compiler.release=21; das neueste genutzte Sprachfeature istList.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.
Schnellstart ohne Maven
Im Ordner release/ liegen zwei fertig gebaute, eigenständige
JARs mit allen Abhängigkeiten – je eine pro Frontend. Sie brauchen nur Java 21+:
java -jar release/HauntedManor-Console.jar # Konsolen-Version (~5 MB, ohne Audio)
java -jar release/HauntedManor-GUI.jar # Swing-GUI (~17 MB, mit Musik)
Die Konsolen-JAR enthält weder die Musikdateien noch die OGG-Bibliotheken – der Textmodus spielt keine Musik, daher werden sie dort weggelassen.
Bauen und Testen
Mit dem Wrapper (empfohlen, keine Maven-Installation nötig) – unter Windows
mvnw.cmd statt ./mvnw:
./mvnw clean test # alle Tests ausführen (259 Tests)
./mvnw clean package # baut beide JARs nach release/ (Console + GUI)
Ein systemweit installiertes mvn funktioniert identisch (mvn clean test …).
Spielen
Über die im pom.xml konfigurierten Run-Profile des exec-maven-plugin:
./mvnw exec:java@run # Konsolen-Version (thb.jeanluc.adventure.App)
./mvnw exec:java@gui # Swing-GUI (thb.jeanluc.adventure.AppGui)
./mvnw exec:java ohne Profil startet ebenfalls die Konsolen-Version.
Alternativ direkt aus der gebauten JAR (siehe Schnellstart).
Befehle im Spiel
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).
| Befehl | Aliase | Deutsch | Wirkung |
|---|---|---|---|
go <richtung> |
move, walk |
gehe, geh |
In eine Himmelsrichtung gehen |
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 |
inventory |
inv, i |
inventar |
Inventar anzeigen |
take <item> |
pick, get |
nimm, nehme |
Gegenstand aufnehmen |
drop <item> |
put |
lege, ablegen |
Gegenstand ablegen |
use <item> |
benutze |
Gegenstand benutzen / schalten | |
use <a> on <b> |
Zwei Gegenstände kombinieren | ||
read <item> |
lies, lese |
Lesbaren Gegenstand lesen | |
examine <item> |
x, inspect |
untersuche |
Gegenstand genauer ansehen |
talk <npc> |
speak |
rede, sprich |
Mit einem NPC sprechen |
give <item> <npc> |
gib |
NPC einen Gegenstand geben | |
help |
? |
hilfe |
Befehlsübersicht anzeigen |
quit |
exit |
beenden |
Spiel beenden |
Wo die Aufgabenstellung umgesetzt ist
Kurzwegweiser zu den geforderten Punkten:
| Anforderung | Wo | Details |
|---|---|---|
| Raum-Klasse + Navigation, mind. 4 Räume | model/Room.java, model/Direction.java |
14 Räume. Room hält direkte Referenzen auf Nachbarräume in einer EnumMap<Direction, Room> – ein echter Objektgraph, keine String-IDs. |
gehen-Befehl (Tipp: switch/if-else/HashMap) |
command/CommandRegistry.java, command/impl/GoCommand.java |
Dispatch über HashMap<String, Command> (O(1), Aliase = mehrere Keys auf dieselbe Instanz). Richtung dann O(1) per EnumMap-Lookup. |
| Gegenstände + Inventar, mind. 3 Items | model/Player.java, model/item/ |
19 Items. Inventar = LinkedHashMap<String, Item>. Item-Hierarchie: PlainItem, ReadableItem, SwitchableItem. |
| Aufnehmen / Ablegen / Benutzen / Lesen | command/impl/ |
TakeCommand, DropCommand, UseCommand, ReadCommand – inkl. letter („Brief") und shovel („Schaufel") aus den Beispielen. |
| Datenstrukturwahl (bewertungsrelevant) | docs/data-structures.md |
Begründung je Anwendungsfall + Tabelle „Bewusst NICHT gewählt". |
| NPCs (Bonus) | model/Npc.java |
3 NPCs, die auf Spielerzustand reagieren (talk, give). |
| Swing-GUI (Bonus) | io/SwingIO.java |
JTextField für die Eingabe (s. Hinweis unten). |
| Javadoc | überall | 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.
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)
├── 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
Technologie-Stack
- Java 21 (LTS)
- Jackson (YAML) für das Laden der Spielwelt
- Lombok zur Reduktion von Boilerplate
- JUnit 5 + AssertJ + Mockito für Tests
- SLF4J + Logback für Logging
- Swing für die GUI (Bonus)
Dokumentation
Ausführliche Design- und Architekturdokumentation liegt unter
docs/: Package-Struktur, Datenstrukturen, Item-Modell,
YAML-Schemas, Lade-Ablauf, Befehle und NPC-Modell.