Files
Jander_Semester2/Semesterprojekt/docs/npcs.md
Jean-Luc Makiola 83643a192f 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.
2026-05-25 21:37:59 +02:00

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
  • 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>

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<>();
  • 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, 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)