docs: ticket 01 (effekt-vokabular) aufloesen, glossar anlegen, tickets 14 und 15 graduieren

This commit is contained in:
2026-08-11 16:08:00 +02:00
parent c8cde87db1
commit 4e86a37d2f
5 changed files with 205 additions and 4 deletions

View File

@@ -1,7 +1,7 @@
# 01 — Effekt-Vokabular # 01 — Effekt-Vokabular
Type: grilling Type: grilling
Status: open Status: resolved
Blocked by: — Blocked by: —
## Question ## Question
@@ -19,3 +19,81 @@ Zu klären:
- Wie sieht die TOML-Repräsentation aus, und bleibt sie lesbar genug für Modder ohne Doku? - Wie sieht die TOML-Repräsentation aus, und bleibt sie lesbar genug für Modder ohne Doku?
Ergebnis: eine Liste der Effekt-Varianten mit TOML-Beispiel je Variante. Ergebnis: eine Liste der Effekt-Varianten mit TOML-Beispiel je Variante.
## Answer
Begriffe sind im [Glossar](../../../CONTEXT.md) festgehalten.
### Zwei Begriffe, nicht einer
**Modifikator** rechnet ein Attribut um, solange er existiert — er wird nie ausgeführt, sondern beim
Auslesen aufsummiert. **Aktion** ändert Zustand einmalig. Getrennte Maschinen, getrennte TOML-Arrays.
Ein gemeinsamer Oberbegriff „Effekt" ist ausdrücklich *kein* kanonischer Begriff mehr.
### Attributkatalog (Engine-Vokabular, ohne Namensraum)
`strength` · `dexterity` · `constitution` · `charisma` · `luck` · `level` · `max_health` ·
`max_stamina` · `damage` · `hit_chance` · `critical_chance` · `critical_factor` ·
`resistance` (typ-indiziert) · `shop_price` · `carry_capacity`
`max_health` ist ein Attribut und wird von Modifikatoren umgerechnet. Der aktuelle Lebensstand ist
**kein** Attribut, sondern Zustand — den ändern Aktionen. Diese Trennung muss scharf bleiben.
### Modifikator
```toml
modifiers = [
{ attribute = "damage", flat = 5 },
{ attribute = "strength", flat = 2, percent = 5 },
{ attribute = "critical_chance", percent = 10, duration = "turns", turns = 3,
target = "all_enemies", symbol = "curse", name = "Verflucht" },
]
```
- `flat` und `percent` beide optional, mindestens eines Pflicht.
- `duration`: `permanent` · `while_equipped` · `turns` · `until_floor_end`.
- `target`: `self` · `target` · `all_enemies`. Der Modifikator wohnt **immer beim Träger** und wird
beim Auslesen des Ziels eingesammelt — stirbt der Träger, verschwindet die Aura von selbst.
- `symbol` und `name` nur bei befristeten Zuständen; Item-Boni erben beides vom Item.
`symbol` ist ein Schlüssel, keine Farbe — die Zuordnung macht `ui/theme.rs`.
### Aktion
```toml
actions = [
{ action = "damage", amount = 12, damage_type = "fire", target = "target" },
{ action = "change_attribute", attribute = "health", amount = 20, target = "self" },
{ action = "apply_modifier", modifier = "core:poisoned", target = "target" },
{ action = "remove_modifier", modifier = "core:poisoned", target = "self" },
{ action = "give_item", item = "core:gold", count = 50, target = "self" },
{ action = "remove_item", item = "core:torch", count = 1, target = "self" },
]
```
Sechs Aktionen. `damage` bleibt eigenständig statt `change_attribute health -12`, weil Schaden durch
eine Kette läuft (Resistenz mindert, Krit vervielfacht, Bedingungen greifen) und „bei erlittenem
Schaden" ein Event ist. Flache Liste, keine verschachtelten Aktionen — Ketten laufen über das
Event-System.
### Regeln
| | |
|---|---|
| Stapeln | `(Basis + Σ flach) × (1 + Σ prozentual)`, intern `f32`, gerundet an genau einer Stelle |
| Uhr | Ein Zug. Ein Feld gehen = ein Zug, eine Kampfaktion = ein Zug. Debuffs ticken auch beim Laufen |
| Schadenstypen | `fire` `ice` `poison` `shock` `holy` `slash` `blunt` — fest, Engine-Vokabular |
| Minderung | Ein Mechanismus: `resistance` je Typ. `armor` am Item ist Kurzschreibweise für Resistenz gegen `slash` und `blunt` |
| Namensraum | Doppelpunkt = Modder-Inhalt (`core:poisoned`). Ohne = Engine-Vokabular (`strength`, `fire`) |
| Tags | Freie namespaced Strings am Wesen, Grundlage für Bedingungen |
| Sprache | Schadenstyp `poison` ≠ Modifikator `core:poisoned` („Vergiftet") |
### Bewusst nicht entschieden
Das **Bedingungsvokabular** für `condition`. Es kommt aus Ticket 08, damit Quests und Modifikatoren
dieselbe Grammatik benutzen statt zweier, die sich subtil unterscheiden. Ticket 01 fordert es nur an.
### Folgen für bestehenden Code
`ItemArmor.armor` fällt weg und wird ein Modifikator auf `resistance`. `Stats` trennt Attribute von
Zustand. Der Attributkatalog braucht abgeleitete Größen, die es heute gar nicht gibt (`hit_chance`,
`carry_capacity`).

View File

@@ -0,0 +1,27 @@
# 14 — Kampfformeln und Rundenablauf
Type: grilling
Status: open
Blocked by: 01
## Question
Wie läuft ein Kampf ab, und mit welchen Formeln?
Der Attributkatalog aus 01 liefert die Zutaten (`damage`, `hit_chance`, `critical_chance`,
`critical_factor`, `resistance`, `dexterity`, `luck`). Wie sie zusammenwirken, ist offen:
- **Reihenfolge**: Was bestimmt, wer zuerst handelt — `dexterity`, ein Initiativwurf, oder immer der
Spieler zuerst? Ändert sich das während des Kampfes?
- **Trefferformel**: Wie berechnet sich, ob ein Angriff trifft? Ist `hit_chance` gegen Ausweichen
gerechnet, oder trifft immer und `dexterity` mindert nur den Schaden?
- **Schadensformel**: In welcher Reihenfolge greifen Waffe, `damage`-Modifikatoren, Krit und
`resistance`? Ist Resistenz prozentual oder flach, und gibt es eine Ober- oder Untergrenze?
- **Kritische Treffer**: Wie speist `luck` in `critical_chance`? Multipliziert `critical_factor` den
Rohschaden oder den geminderten?
- **Aktionen pro Zug**: Genau eine, oder gibt es Ausdauer als Budget? Wozu dient `max_stamina` sonst?
- **Flucht**: Möglich, mit welcher Chance, mit welchen Kosten?
- **Zufall**: Schadensstreuung ja oder nein, und woher kommt der Zufallsgenerator — braucht es einen
Seed im Speicherstand?
Ergebnis: die Formeln als Pseudocode plus der Ablauf eines Zuges von Eingabe bis Ergebnis.

View File

@@ -0,0 +1,25 @@
# 15 — Progression und Level-up
Type: grilling
Status: open
Blocked by: 02
## Question
Was passiert beim Aufstieg, und wie sieht die Kurve aus?
`Player` hat bereits `current_exp` und `next_level_exp`, `Stats::level_up()` deckelt bei 50. Der
Attributkatalog aus 01 steht. Offen ist, was ein Level überhaupt gibt:
- **Was gewährt ein Aufstieg?** Feste Modifikatoren aus der Klasse, frei verteilbare Attributpunkte,
oder beides? Freie Punkte heißen Zuweisungs-UI und die Gefahr, sich den Charakter zu verbauen.
- **Ist die Kurve Daten oder Formel?** Eine Tabelle je Level in TOML (moddbar, explizit) oder eine
Formel mit Parametern (kompakt, weniger schraubbar)?
- **Bleibt die Obergrenze bei 50**, wenn 1.0 aus fünf Etagen besteht? Passt das zusammen?
- **Woher kommt Erfahrung?** Nur Tötungen, auch Quests, auch erstmaliges Betreten einer Etage?
- **Skaliert Rasse oder Klasse mit?** „+2 Konstitution je Level" ist ein Modifikator mit Level-Bezug —
kann das Vokabular aus 01 das ausdrücken, oder braucht es dafür etwas Neues?
- **Werden Leben und Ausdauer beim Aufstieg aufgefüllt?** Das ist eine Balancing-Entscheidung mit
Folgen für die Etagen-Länge.
Ergebnis: Aufstiegsregel, Kurvenform (Daten oder Formel), Erfahrungsquellen und die Obergrenze.

View File

@@ -14,7 +14,8 @@ dort als Konvention im Body. Zuordnung Ticket → Gitea-Issue:
| 04 Fehlerstrategie | [#5](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/5) | 09 Save-Schema | [#10](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/10) | | 04 Fehlerstrategie | [#5](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/5) | 09 Save-Schema | [#10](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/10) |
| 05 Research Script-Engine | [#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6) | 10 Raum-Prefab-Format | [#11](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/11) | | 05 Research Script-Engine | [#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6) | 10 Raum-Prefab-Format | [#11](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/11) |
| 11 UI-Gerüst | [#12](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/12) | 12 Prototyp ratatui | [#13](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/13) | | 11 UI-Gerüst | [#12](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/12) | 12 Prototyp ratatui | [#13](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/13) |
| 13 Script-Engine wählen | [#14](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/14) | | | | 13 Script-Engine wählen | [#14](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/14) | 14 Kampfformeln | [#15](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/15) |
| 15 Progression | [#16](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/16) | | |
## Destination ## Destination
@@ -26,6 +27,9 @@ Inventar und Ausrüstung, Quests, NPCs, Handel, Speichern/Laden, Mod-Support auf
Domain: Rust-Terminal-Roguelike, moddbar. Repo: `MDietermann/rustkeep`. Domain: Rust-Terminal-Roguelike, moddbar. Repo: `MDietermann/rustkeep`.
Das Glossar liegt in [`CONTEXT.md`](../../CONTEXT.md) im Repo-Wurzelverzeichnis — kanonische Begriffe,
keine Implementierung. Jede Session, die einen Begriff schärft, schreibt ihn dort fest.
Jede Session konsultiert: `ponytail` (dauerhaft aktiv), `/grilling` und `/domain-modeling` für Jede Session konsultiert: `ponytail` (dauerhaft aktiv), `/grilling` und `/domain-modeling` für
Grilling-Tickets, `/research` für Research-Tickets, `/prototype` für Prototype-Tickets. Grilling-Tickets, `/research` für Research-Tickets, `/prototype` für Prototype-Tickets.
@@ -55,14 +59,13 @@ auch über Ticket 13.
<!-- eine Zeile pro geschlossenem Ticket --> <!-- eine Zeile pro geschlossenem Ticket -->
- [01 — Effekt-Vokabular](issues/01-effekt-vokabular.md) ([#2](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/2)) — **Zwei Begriffe statt einem**: Modifikator (rechnet ein Attribut um, solange er existiert) und Aktion (ändert Zustand einmalig), getrennte Maschinen und getrennte TOML-Arrays. Fester Attributkatalog ohne Namensraum; `max_health` ist Attribut, der Lebensstand ist Zustand. Sechs Aktionen, `damage` eigenständig wegen der Minderungskette. Stapeln `(Basis + Σ flach) × (1 + Σ prozentual)`. Eine Uhr: der Zug. Sieben feste Schadenstypen, ein Minderungsmechanismus (`resistance`), `armor` nur Kurzschreibweise. Auren wohnen beim Träger. Bedingungsvokabular bewusst an Ticket 08 delegiert. Begriffe im [Glossar](../../CONTEXT.md).
- [05 — Research: Script-Engine](issues/05-research-script-engine.md) ([#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6)) — Empfehlung Rhai wegen Fehlermeldungen mit Zeile und Spalte, billiger Typ-Brücke, AST-Hot-Reload und Build ohne `cc`. Gemessen: mlua liest unter `StdLib::ALL_SAFE` per `io.open` echte Dateien — „safe" heißt dort speichersicher, nicht fähigkeitsbeschränkt. Lua gewinnt bei der Modder-Vertrautheit; WASM scheidet für 1.0 aus. **Kernfolge: reden Scripts nur über das Effekt-Vokabular, ist die Engine-Wahl umkehrbar.** Entscheidung offen in Ticket 13. - [05 — Research: Script-Engine](issues/05-research-script-engine.md) ([#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6)) — Empfehlung Rhai wegen Fehlermeldungen mit Zeile und Spalte, billiger Typ-Brücke, AST-Hot-Reload und Build ohne `cc`. Gemessen: mlua liest unter `StdLib::ALL_SAFE` per `io.open` echte Dateien — „safe" heißt dort speichersicher, nicht fähigkeitsbeschränkt. Lua gewinnt bei der Modder-Vertrautheit; WASM scheidet für 1.0 aus. **Kernfolge: reden Scripts nur über das Effekt-Vokabular, ist die Engine-Wahl umkehrbar.** Entscheidung offen in Ticket 13.
- [06 — Research: ratatui-App-Architektur](issues/06-research-ratatui-architektur.md) ([#7](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/7)) — Screen-Stack über zentralem `Game`-State statt Elm oder Component-Trait; `game/` bleibt ratatui-frei; Popups per `Clear` auf Sub-`Rect` statt Widget-Stack; blockierendes `event::read()` ohne Tick; Dungeon-Grid ist Eigenbau, es gibt kein Widget dafür; ratatui 0.30.2 mit MSRV 1.88; `KeyEventKind::Press`-Filter unter Windows Pflicht. Voller Bericht in [research/06](research/06-ratatui-architektur.md). - [06 — Research: ratatui-App-Architektur](issues/06-research-ratatui-architektur.md) ([#7](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/7)) — Screen-Stack über zentralem `Game`-State statt Elm oder Component-Trait; `game/` bleibt ratatui-frei; Popups per `Clear` auf Sub-`Rect` statt Widget-Stack; blockierendes `event::read()` ohne Tick; Dungeon-Grid ist Eigenbau, es gibt kein Widget dafür; ratatui 0.30.2 mit MSRV 1.88; `KeyEventKind::Press`-Filter unter Windows Pflicht. Voller Bericht in [research/06](research/06-ratatui-architektur.md).
## Not yet specified ## Not yet specified
- **Kampfmechanik im Detail** — Initiative, Aktionen pro Runde, Trefferformel, Krit, Flucht. Wartet auf das Effekt-Vokabular (01), weil Angriffe und Fähigkeiten Effekte sind.
- **Loot-Tabellen** — wie Drops definiert und gewichtet werden, wie `luck` einwirkt. Wartet auf die Typ-Registry (02). - **Loot-Tabellen** — wie Drops definiert und gewichtet werden, wie `luck` einwirkt. Wartet auf die Typ-Registry (02).
- **XP-Kurve und Progression** — was Level-ups geben, wie Rasse/Klasse mitskalieren. Wartet auf 01.
- **Boss-Design** — ob Bosse nur Gegner mit besseren Werten sind oder eigene Mechanik brauchen (Phasen, Skripte). Berührt Stufe (c) des Mod-Supports. - **Boss-Design** — ob Bosse nur Gegner mit besseren Werten sind oder eigene Mechanik brauchen (Phasen, Skripte). Berührt Stufe (c) des Mod-Supports.
- **NPC- und Handelsmodell** — Warenbestand, Preisbildung über `charisma`, Dialogdaten. Wartet auf das Event-System (08). - **NPC- und Handelsmodell** — Warenbestand, Preisbildung über `charisma`, Dialogdaten. Wartet auf das Event-System (08).
- **Inventar-UX** — Slots, Gewicht oder Kapazität, Sortierung, Vergleichsansicht. Wartet jetzt auf das Screen-Modell (11), nicht mehr auf 06. - **Inventar-UX** — Slots, Gewicht oder Kapazität, Sortierung, Vergleichsansicht. Wartet jetzt auf das Screen-Modell (11), nicht mehr auf 06.

68
CONTEXT.md Normal file
View File

@@ -0,0 +1,68 @@
# Glossar
Kanonische Begriffe für rustkeep. Nur Sprache, keine Implementierung.
## Attribut
Eine benannte, veränderbare Größe an einem Wesen. Der Katalog ist fest und wird von der Engine
vorgegeben — er umfasst die Grundwerte (Stärke, Geschicklichkeit, Konstitution, Charisma, Glück,
Leben, Ausdauer, Level) *und* die abgeleiteten Kampfgrößen (Schaden, Rüstung, Trefferchance,
Kritische Chance, Kritischer Faktor, Shop-Preis, Tragfähigkeit).
Ein Attribut ist kein Inhalt, den ein Mod anlegt: Ein Modifikator auf ein Attribut, das keine
Spiellogik ausliest, hätte keine Wirkung. Der Katalog darf wachsen — aber durch die Engine,
nicht durch eine TOML-Datei.
## Modifikator
Eine Umrechnung eines [Attributs](#attribut), die gilt, solange eine Bedingung erfüllt ist.
Er wird nie ausgeführt, sondern beim Auslesen des Attributs aufsummiert. Quellen sind Rasse,
Klasse, ausgerüstete Gegenstände und befristete Zustände.
Beispiele: „Zwerg: +2 Konstitution", „Eisenschwert: +5 Schaden", „Segen: +10 % Kritische Chance".
## Aktion
Eine einmalige Zustandsänderung. Sie feuert, wirkt, ist vorbei. Quellen sind Angriffe,
Verbrauchsgegenstände, Questbelohnungen und Fallen.
Beispiele: „12 Schaden zufügen", „20 Leben heilen", „50 Gold geben", „Gift anwenden".
Eine Aktion kann einen befristeten [Modifikator](#modifikator) erzeugen — so hängen die beiden
Begriffe zusammen, ohne dasselbe zu sein.
## Zustand
Der veränderliche Istwert eines Wesens — aktuelles Leben, aktuelle Ausdauer, getragene Gegenstände,
aktive befristete [Modifikatoren](#modifikator). Kein [Attribut](#attribut) und nicht von
Modifikatoren umrechenbar: Ein Modifikator wirkt auf `max_health`, eine [Aktion](#aktion) ändert den
Lebensstand. Die Trennung muss scharf bleiben, sonst heilt ein Ring beim Anlegen.
## Schadenstyp
Eine von sieben festen Kennzeichnungen, wie Schaden gemindert wird: `fire`, `ice`, `poison`, `shock`,
`holy`, `slash`, `blunt`. Engine-Vokabular ohne Namensraum. Zu jedem Typ gehört eine Resistenz, und
Resistenz ist der *einzige* Minderungsmechanismus — Rüstung ist Kurzschreibweise für Resistenz gegen
`slash` und `blunt`, kein eigenes Konzept.
Der Schadenstyp `poison` ist **nicht** der Modifikator `core:poisoned` („Vergiftet"). Der Typ sagt,
wie gemindert wird; der Modifikator ist ein Zustand, der über Züge tickt.
## Tag
Eine freie, namespaced Kennzeichnung an einem Wesen (`core:undead`, `meinmod:aquatisch`). Reiner
Inhalt: Die Engine kennt keine Tags, sie vergleicht nur Zeichenketten. Grundlage für Bedingungen
wie „+5 Schaden gegen Untote". Gegenpol zum [Attribut](#attribut) — der Doppelpunkt zeigt dem Modder,
auf welcher Seite er steht.
## Zug
Die einzige Zeiteinheit des Spiels. Ein Feld weitergehen ist ein Zug, eine Kampfaktion ist ein Zug.
Es gibt keine getrennte Kampfrunden-Uhr: Befristete [Modifikatoren](#modifikator) ticken auch beim
Erkunden, damit „ich warte den Debuff draußen ab" eine Entscheidung mit Kosten bleibt.
## Effekt
**Kein kanonischer Begriff.** Wird umgangssprachlich für [Modifikator](#modifikator) *und*
[Aktion](#aktion) benutzt; in Code, TOML und Doku ist stattdessen immer der genaue Begriff zu
verwenden. Das Wort überlebt nur noch in „Effekt-Vokabular" als Sammelname für beide zusammen.