Files
Jander_Semester2/Semesterprojekt/docs/superpowers/specs/2026-05-31-light-darkness-design.md
Jean-Luc Makiola 5d11d7730c 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) <noreply@anthropic.com>
2026-05-31 23:00:15 +02:00

88 lines
3.9 KiB
Markdown

# 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`).