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:
139
Semesterprojekt/docs/item-model.md
Normal file
139
Semesterprojekt/docs/item-model.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Item-Modell
|
||||
|
||||
Hierarchie aus abstraktem `Item` und drei konkreten Subtypen. Liegt im Subpackage `thb.jeanluc.adventure.model.item`.
|
||||
|
||||
## Hierarchie
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Item {
|
||||
<<abstract>>
|
||||
#String id
|
||||
#String name
|
||||
#String description
|
||||
+use(GameContext)* void
|
||||
}
|
||||
|
||||
class ReadableItem {
|
||||
-String readText
|
||||
+use(GameContext) void
|
||||
}
|
||||
|
||||
class SwitchableItem {
|
||||
-boolean state
|
||||
-boolean initialState
|
||||
-String onText
|
||||
-String offText
|
||||
+use(GameContext) void
|
||||
+isOn() boolean
|
||||
}
|
||||
|
||||
class PlainItem {
|
||||
+use(GameContext) void
|
||||
}
|
||||
|
||||
Item <|-- ReadableItem
|
||||
Item <|-- SwitchableItem
|
||||
Item <|-- PlainItem
|
||||
```
|
||||
|
||||
## Felder pro Klasse
|
||||
|
||||
### `Item` (abstract)
|
||||
|
||||
| Feld | Typ | Hinweis |
|
||||
|---|---|---|
|
||||
| `id` | `String` | unique slug, Lookup-Key |
|
||||
| `name` | `String` | Anzeigename |
|
||||
| `description` | `String` | `examine`-Output |
|
||||
|
||||
Abstrakte Methode: `public abstract void use(GameContext ctx)`
|
||||
|
||||
### `ReadableItem`
|
||||
|
||||
| Feld | Typ | Hinweis |
|
||||
|---|---|---|
|
||||
| `readText` | `String` | wird beim `read`/`use` ausgegeben |
|
||||
|
||||
`use()` schreibt `readText` über `ctx.io()`.
|
||||
|
||||
### `SwitchableItem`
|
||||
|
||||
| Feld | Typ | Hinweis |
|
||||
|---|---|---|
|
||||
| `state` | `boolean` | aktueller Zustand (mutable) |
|
||||
| `initialState` | `boolean` | aus YAML, im Konstruktor an `state` durchgereicht |
|
||||
| `onText` | `String` | Nachricht beim Einschalten |
|
||||
| `offText` | `String` | Nachricht beim Ausschalten |
|
||||
|
||||
`use()` toggelt `state` und schreibt den entsprechenden Text.
|
||||
|
||||
Bewusste Entscheidung: `boolean` statt `enum SwitchState`. Wenn später `BROKEN` o.ä. nötig wird, refactoren.
|
||||
|
||||
### `PlainItem`
|
||||
|
||||
Keine eigenen Felder. `use()` schreibt eine generische Nachricht („You can't use the X by itself."). Existiert, damit alle Items polymorph `use()` haben und das YAML einen konsistenten `type:`-Discriminator hat.
|
||||
|
||||
## Lombok-Setup
|
||||
|
||||
`@SuperBuilder` ist Pflicht, weil normales `@Builder` Vererbung nicht beherrscht.
|
||||
|
||||
```java
|
||||
@Getter
|
||||
@SuperBuilder
|
||||
@RequiredArgsConstructor
|
||||
public abstract class Item {
|
||||
protected final String id;
|
||||
protected final String name;
|
||||
protected final String description;
|
||||
|
||||
public abstract void use(GameContext ctx);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@SuperBuilder
|
||||
public class ReadableItem extends Item {
|
||||
private final String readText;
|
||||
|
||||
@Override
|
||||
public void use(GameContext ctx) {
|
||||
ctx.getIo().write(readText);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Konstruktion:
|
||||
```java
|
||||
ReadableItem.builder()
|
||||
.id("letter").name("Letter").description("A crumpled paper.")
|
||||
.readText("Meet me at midnight.")
|
||||
.build();
|
||||
```
|
||||
|
||||
## Jackson Polymorphism
|
||||
|
||||
```java
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = ReadableItem.class, name = "readable"),
|
||||
@JsonSubTypes.Type(value = SwitchableItem.class, name = "switchable"),
|
||||
@JsonSubTypes.Type(value = PlainItem.class, name = "plain")
|
||||
})
|
||||
public abstract class Item { ... }
|
||||
```
|
||||
|
||||
YAML-Pflichtfeld pro Item: `type: readable|switchable|plain`.
|
||||
|
||||
## Verworfen / bewusst nicht im MVP
|
||||
|
||||
- **`use X on Y`** (targeted use) — Items kennen ihren Kontext über `GameContext`, kein zweites Item als Parameter.
|
||||
- **Hidden Items** (sichtbar erst nach Aktion) — keine `visible`-Flag, alle Items sofort sichtbar.
|
||||
- **Item kennt seinen Standort** — Items sind „dumm", nur Room/Player wissen wer sie hält.
|
||||
- **Item-State beeinflusst Raumbeschreibung** (z.B. „Cellar dark unless lamp on") — wenn nötig, später per Conditions-System.
|
||||
- **`hasBeenRead`-Tracking** — Lesen bleibt idempotent.
|
||||
|
||||
## Player-Input-Matching
|
||||
|
||||
Player tippt `take lamp` → Match gegen `id`. Multi-Word-Items haben snake_case ids, also `take oil_lamp`.
|
||||
|
||||
Alias-Feld (`aliases: [lamp, oil]`) ist YAGNI bis ein konkreter Bedarf entsteht.
|
||||
Reference in New Issue
Block a user