Files
Jander_Semester2/Semesterprojekt/README.md
Jean-Luc Makiola d7f91c2e47 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 <raum>', '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.
2026-07-14 12:55:19 +02:00

172 lines
8.7 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 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, NPCs, Quests
und Enden werden aus YAML-Dateien geladen, nicht im Code festverdrahtet.
**Umfang:** 14 Räume, 19 Gegenstände, 3 NPCs, 259 Tests.
---
## Schnellstart
Es gibt **zwei Wege**, das Spiel zu starten. Wenn Sie nur spielen wollen, nehmen
Sie Weg A dafür wird kein Maven benötigt.
### Voraussetzung
**Java 21 oder neuer** (LTS). Gebaut wird gegen `maven.compiler.release=21`;
das neueste genutzte Sprachfeature ist `List.getFirst()` (SequencedCollection,
Java 21). Neuere JDKs (2225) funktionieren ebenfalls.
Prüfen mit:
```bash
java -version
```
### Weg A fertige JARs starten (ohne Maven)
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
java -jar release/HauntedManor-Console.jar # Konsolen-Version (~5 MB)
java -jar release/HauntedManor-GUI.jar # Swing-GUI (~17 MB)
```
- 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.
### Weg B mit Maven bauen und starten
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 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.
> **Hinweis:** Der erste Maven-Aufruf lädt die Abhängigkeiten (Jackson, Lombok,
> JUnit, Logback) aus dem Internet. Wer offline ist, nimmt Weg A.
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 <richtung>` | `move`, `walk` | `gehe`, `geh` | In eine Himmelsrichtung gehen |
| `go to <raum>` | | | 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 |
| `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 |
| `save` | | `speichern` | Spielstand speichern |
| `help` | `?` | `hilfe` | Befehlsübersicht anzeigen |
| `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
| 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 seine 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, 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<String, Item>` (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` **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
│ ├── 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, 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
- **Java 21 (LTS)**
- **Jackson** (YAML) für das Laden der Spielwelt
- **Lombok** zur Reduktion von Boilerplate
- **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, Wahl der Datenstrukturen,
Item-Modell, Befehle, NPC-Modell, YAML-Schemas und Lade-Ablauf.