From 5d11d7730cfca2fa2040bbb4943cd3aaf4d33b52 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sun, 31 May 2026 23:00:15 +0200 Subject: [PATCH] docs: spec for light & darkness (model B, blocking) Room.dark + Item.light flags, a Light helper (isLit/carryingLight), and command gating: can't enter a dark room without a lit light source; look/take/examine obscured in the dark; HUD light field wired. Entry-gate prevents soft-locks. Demo: dark dungeon needs the lit lamp. Fuel/timed light out of scope. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../specs/2026-05-31-light-darkness-design.md | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Semesterprojekt/docs/superpowers/specs/2026-05-31-light-darkness-design.md diff --git a/Semesterprojekt/docs/superpowers/specs/2026-05-31-light-darkness-design.md b/Semesterprojekt/docs/superpowers/specs/2026-05-31-light-darkness-design.md new file mode 100644 index 0000000..04977a8 --- /dev/null +++ b/Semesterprojekt/docs/superpowers/specs/2026-05-31-light-darkness-design.md @@ -0,0 +1,87 @@ +# Spec: Licht & Dunkelheit (Mechanik-Erweiterung) + +Stand: 2026-05-31. Kleine Mechanik aus dem Spine (#3 der Mechanik-Liste), die das +Fundament (Flags/Items) nutzt. Strenge: **Modell B** (Dunkelheit blockiert). + +## 1. Kontext & Ziel + +Dunkle Räume sollen den schaltbaren `lamp` sinnvoll machen: Ohne aktive +Lichtquelle kann man einen dunklen Raum **nicht betreten**, nichts sehen +(`look`), und nichts aufnehmen/untersuchen. Die HUD-Zeile `light: on/off` wird +endlich verdrahtet. + +## 2. Scope + +**In Scope:** +- `Room.dark` (Bool, optional), `Item.light` (Bool, optional). +- `Light`-Helper: `isLit`, `carryingLight`. +- Command-Gating: `go` (Eintritt), `look`, `take`, `examine`; HUD-`lightOn`. +- Demo: Dungeon dunkel → Lampe nötig. + +**Out of Scope:** Lampen-Brennstoff/zeitlich begrenztes Licht; Lichtradius über +Räume hinweg; Zufall. + +## 3. Daten (rückwärtskompatibel) + +- **`Room.dark`**: `@Setter`-Feld (default `false`), **kein** Konstruktor-Argument → + keine Test-Brüche. Vom `RoomFactory` aus `RoomDto.dark` gesetzt. YAML: `dark: true`. +- **`Item.light`**: `boolean` am abstrakten `Item` (via `@SuperBuilder`), default + `false`. Vom `ItemFactory` aus `ItemDto.light` gesetzt. YAML: `light: true`. +- **Aktive Lichtquelle** = `item.light` **und** (kein Switchable **oder** + `SwitchableItem.isOn()`). Die `lamp` leuchtet also nur eingeschaltet. + +## 4. Helper `Light` (game) + +```java +static boolean isLit(GameContext ctx, Room room) { + if (!room.isDark()) return true; + return hasActiveLight(player-inventory) || hasActiveLight(room-items); +} +static boolean carryingLight(GameContext ctx); // aktive Lichtquelle im Inventar +``` +`hasActiveLight(items)` iteriert; `isActiveLight(item)` = `item.isLight()` && +(`!(item instanceof SwitchableItem s)` || `s.isOn()`). + +Räume gelten als beleuchtet, wenn sie nicht dunkel sind **oder** eine aktive +Lichtquelle getragen wird **oder** im Raum liegt. + +## 5. Command-Gating (Modell B) + +| Command | Verhalten bei dunklem, unbeleuchtetem Zielraum/aktuellem Raum | +|---|---| +| `GoCommand` | **Eintritt blockiert**, wenn `!isLit(ctx, target)`: Hinweis-Text, kein Wechsel. (Lichträume bleiben immer betretbar → **kein Soft-Lock**, Rückzug stets möglich.) | +| `LookCommand` | `!isLit(ctx, current)` → „It's pitch black; you can't make anything out." statt `RoomView` (Fall: Lampe ging im Raum aus). | +| `TakeCommand` | `!isLit(ctx, current)` → „It's too dark to see that." | +| `ExamineCommand` | `!isLit(ctx, current)` → „It's too dark to see that." | +| HUD | `lightOn` = `Light.carryingLight(ctx)` (in `Game.publishHud`). | + +Erlaubt im Dunkeln bleiben: `inventory`, `drop`, **`use`** (z. B. Lampe anzünden), +`quests`, `map`, `help`. So kann man eine getragene Lampe im Dunkeln anzünden. + +## 6. Fehlerbehandlung / Soft-Lock + +Eintrittssperre statt Innen-Sperre: Man betritt einen dunklen Raum nur **mit** +Licht. Geht das Licht drinnen aus, sind `look`/`take`/`examine` blockiert, aber der +Rückweg in einen hellen Raum bleibt (Zielraum hell → `isLit` true). Kein Soft-Lock. + +## 7. Demo + +- `lamp`: `light: true` (bereits schaltbar; `use lamp` → an). +- `dungeon`: `dark: true`; der Generator steht dort. Ablauf: + `take lamp` → `use lamp` (an) → `go south` (jetzt betretbar) → `use generator`. + HUD zeigt `light: on`, sobald die Lampe brennt. Gibt man die Lampe später dem + alten Mann, verliert man das Licht (thematisch). + +## 8. Testing + +- `Light.isLit`: nicht dunkel → hell; dunkel ohne Licht → dunkel; dunkel + getragene + brennende Lampe → hell; dunkel + Lampe **aus** → dunkel; dunkel + brennende Lampe + **im Raum** → hell. `carryingLight`. +- Command-Gates: `go` in dunklen Raum ohne Licht blockt, mit brennender Lampe ok; + `look`/`take` im dunklen Raum blockt. +- End-to-End (Konsole): `go south` ohne Licht blockt; `take lamp`/`use lamp`/`go south` + betritt; HUD `light: on`. + +## 9. Offene Detailfragen (in Implementierung) + +- Genauer Hinweis-Text der Eintrittssperre (nennt `use lamp`).