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.
3.0 KiB
3.0 KiB
NPCs
Nicht-Spieler-Figuren — optionaler Bonusteil laut Aufgabenstellung. Hier mit Talk- und Give-Interaktion modelliert.
Domain-Modell
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
reactionsistHashMap<String, NpcReaction>mit dem Trigger-Item-id als Key. O(1) Nachschlagen beimgib X an Y.
Interaktionen
talk <npc>
- Sucht NPC im aktuellen Raum.
- Wirft
greeting-Text aus. - Mutiert nichts.
gib <item> an <npc>
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
- 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:
private final LinkedHashMap<String, Npc> npcs = new LinkedHashMap<>();
LinkedHashMapweil O(1)-Lookup beimtalk <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, hier explizit pro NPC:
ideindeutig innpcs.yamlgreetingnicht leer (sonst sinnloses NPC)- Jede
onReceive-id existiert initems.yaml - Jede
gives-id existiert initems.yaml - Jede
consumes-id existiert initems.yaml - Innerhalb eines NPCs ist
onReceiveeindeutig (keine zwei Reaktionen auf dasselbe Item)