semesterprojekt: implement full text adventure (phases 1-7)
Walking skeleton through Swing GUI: YAML-driven world (4 rooms, 4 items, 1 NPC), HashMap command dispatch with parser, three-tier item hierarchy (readable / switchable / plain), and end-to-end NPC give/receive flow. 67 tests green.
This commit is contained in:
119
Semesterprojekt/docs/npcs.md
Normal file
119
Semesterprojekt/docs/npcs.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# NPCs
|
||||
|
||||
Nicht-Spieler-Figuren — optionaler Bonusteil laut Aufgabenstellung. Hier mit Talk- und Give-Interaktion modelliert.
|
||||
|
||||
## Domain-Modell
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Npc {
|
||||
-String id
|
||||
-String name
|
||||
-String description
|
||||
-String greeting
|
||||
-Map~String, NpcReaction~ reactions
|
||||
+talk(GameContext) void
|
||||
+receive(Item, GameContext) boolean
|
||||
}
|
||||
|
||||
class NpcReaction {
|
||||
-Item consumes
|
||||
-Item gives
|
||||
-String response
|
||||
+apply(Player) void
|
||||
}
|
||||
|
||||
Npc "1" --> "*" NpcReaction : reactions
|
||||
```
|
||||
|
||||
- `reactions` ist `HashMap<String, NpcReaction>` mit dem Trigger-Item-id als Key. O(1) Nachschlagen beim `gib X an Y`.
|
||||
|
||||
## Interaktionen
|
||||
|
||||
### `talk <npc>`
|
||||
|
||||
- Sucht NPC im aktuellen Raum.
|
||||
- Wirft `greeting`-Text aus.
|
||||
- Mutiert nichts.
|
||||
|
||||
### `gib <item> an <npc>`
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor Spieler
|
||||
participant Cmd as GiveCommand
|
||||
participant P as Player
|
||||
participant N as Npc
|
||||
participant IO
|
||||
|
||||
Spieler->>Cmd: give lamp old_man
|
||||
Cmd->>P: hasItem("lamp")?
|
||||
P-->>Cmd: yes
|
||||
Cmd->>N: receive(lamp)
|
||||
N->>N: reactions.get("lamp")
|
||||
alt Reaktion existiert
|
||||
N->>P: inventory.remove(lamp)
|
||||
N->>P: inventory.add(key)
|
||||
N-->>Cmd: response text
|
||||
Cmd->>IO: write(response)
|
||||
else keine Reaktion
|
||||
N-->>Cmd: false
|
||||
Cmd->>IO: write("The NPC does not react.")
|
||||
end
|
||||
```
|
||||
|
||||
## YAML-Beispiel
|
||||
|
||||
```yaml
|
||||
- id: old_man
|
||||
name: Old Man
|
||||
description: A stooped old man with a grey beard.
|
||||
greeting: |
|
||||
"Hello traveller. If you bring me the lamp,
|
||||
I will show you the way to the cellar."
|
||||
reactions:
|
||||
- onReceive: lamp
|
||||
response: |
|
||||
"Thank you! Here, take this key."
|
||||
gives: key
|
||||
consumes: lamp
|
||||
```
|
||||
|
||||
Felder einer Reaktion:
|
||||
|
||||
| Feld | Pflicht | Bedeutung |
|
||||
|---|---|---|
|
||||
| `onReceive` | ja | Item-id, das ausgelöst werden muss |
|
||||
| `response` | ja | Antworttext nach erfolgreicher Übergabe |
|
||||
| `gives` | nein | Item-id, das der NPC zurückgibt |
|
||||
| `consumes` | nein | Item-id, das aus Spielerinventar entfernt wird (oft = `onReceive`) |
|
||||
|
||||
## Speichern in Räumen
|
||||
|
||||
Räume halten ihre NPCs analog zu Items:
|
||||
|
||||
```java
|
||||
private final LinkedHashMap<String, Npc> npcs = new LinkedHashMap<>();
|
||||
```
|
||||
|
||||
- `LinkedHashMap` weil O(1)-Lookup beim `talk <npc>` *und* stabile Reihenfolge in der Raumbeschreibung („Here is: Old Man, Innkeeper").
|
||||
|
||||
## Erweiterungen (bewusst nicht im MVP)
|
||||
|
||||
- Bedingte Dialoge („wenn Quest X erledigt, sag Y")
|
||||
- Kauf/Verkauf mit Gold
|
||||
- NPC bewegt sich zwischen Räumen
|
||||
- Mehrfache Reaktionsketten (NPC-Memory)
|
||||
|
||||
Diese würden ein eigenes Quest-/Event-System rechtfertigen. Für 3 Bonuspunkte überdimensioniert.
|
||||
|
||||
## Validierungsregeln
|
||||
|
||||
Wiederholung aus [yaml-schemas.md](yaml-schemas.md), hier explizit pro NPC:
|
||||
|
||||
1. `id` eindeutig in `npcs.yaml`
|
||||
2. `greeting` nicht leer (sonst sinnloses NPC)
|
||||
3. Jede `onReceive`-id existiert in `items.yaml`
|
||||
4. Jede `gives`-id existiert in `items.yaml`
|
||||
5. Jede `consumes`-id existiert in `items.yaml`
|
||||
6. Innerhalb eines NPCs ist `onReceive` eindeutig (keine zwei Reaktionen auf dasselbe Item)
|
||||
Reference in New Issue
Block a user