Files
Jander_Semester2/Semesterprojekt/README.md
Jean-Luc Makiola e5c87015fa build: target Java 21 (LTS) instead of Java 25
maven.compiler.source/target were set to 25, but the newest language feature
actually used is List.getFirst() (SequencedCollection, Java 21). On a JDK 17 or
21 the project would not compile at all.

- Use maven.compiler.release=21 instead of the source/target pair
- README: update prerequisites, tech stack and test count
- .gitignore: ignore the Nextcloud sync file and release/*.jar
2026-07-14 12:37:45 +02:00

152 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 ist `List.getFirst()` (SequencedCollection, Java 21).
Neuere JDKs (2225) 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/`](release/) liegen zwei fertig gebaute, eigenständige
JARs mit allen Abhängigkeiten je eine pro Frontend. Sie brauchen nur Java 21+:
```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)
```
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`:
```bash
./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`:
```bash
./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](#schnellstart-ohne-maven)).
### 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`](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<Direction, Room>` 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<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`](src/main/java/thb/jeanluc/adventure/model/Player.java), [`model/item/`](src/main/java/thb/jeanluc/adventure/model/item/) | **19 Items**. Inventar = `LinkedHashMap<String, Item>`. 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. |
**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/`](docs/README.md): Package-Struktur, Datenstrukturen, Item-Modell,
YAML-Schemas, Lade-Ablauf, Befehle und NPC-Modell.