WorldValidator only checked id syntax, startRoom and NPC greetings. Quests, endings and combinations were never even passed to it, so a broken world could load "successfully" and then fail during play: - A room without a 'name' loaded cleanly and threw an NPE in ConsoleIO.frameTop the moment the player walked in. - A typo'd item id in a quest condition silently evaluated to false forever, leaving the stage uncompletable with no diagnostic. The validator now receives quests, endings and combinations, and resolves every item and quest id used in conditions, effects and recipes. Rooms and items must carry a non-blank name and description. All problems are collected and reported together instead of one per run.
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.