docs: ticket 15 (progression) aufloesen, nachtraege an 01 07 11 14, erfahrung ins glossar

This commit is contained in:
2026-08-12 13:45:41 +02:00
parent 380400611e
commit 5faa5d6165
7 changed files with 170 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
# 15 — Progression und Level-up
Type: grilling
Status: open
Status: resolved
Blocked by: 02
## Question
@@ -23,3 +23,126 @@ Attributkatalog aus 01 steht. Offen ist, was ein Level überhaupt gibt:
Folgen für die Etagen-Länge.
Ergebnis: Aufstiegsregel, Kurvenform (Daten oder Formel), Erfahrungsquellen und die Obergrenze.
## Answer
Begriffe im [Glossar](../../../CONTEXT.md). Dieses Ticket entscheidet **Formen und Regeln** — die
konkreten Zahlen bleiben beim Balancing, das ein spielbares Spiel voraussetzt.
### Ein Aufstieg gibt genau einen Punkt
Frei verteilbar auf die **fünf Grundwerte**: `strength` · `dexterity` · `constitution` · `charisma` ·
`luck`. Abgeleitete Größen wie `damage` oder `hit_chance` bleiben ausgeschlossen — Punkte direkt
dorthin zu setzen umginge das ganze Modifikatorsystem aus 01.
**`current_exp` und `unspent_points` leben an `Game`, nicht am `Creature`.** Ticket 07 hatte die
Platzierung ausdrücklich hierher delegiert; `base.level` bleibt am Wesen (Gegner haben echte Level, die
Etagen-Skalierung liest sie), aber Erfahrung und unverteilte Punkte hat ausschließlich der Held. Ein
Feld, das für 99 % der Exemplare bedeutungslos ist, wäre ein Kommentar in Feldform — und der Save
schriebe es für jeden Gegner mit. Beide Werte werden ohnehin nur beim Aufstieg und in `AssignPoints`
angefasst, und beides läuft über `Game`.
Verteilt wird im `CharacterSheet` aus Ticket 11, kein zwölfter Screen. **Kein Umverteilen** — ein
Permadeath-Lauf ist kurz und endet endgültig, eine Respec-Mechanik löst ein Problem, das dabei gar
nicht entsteht.
`AssignPoints` ist **ein** Command mit allen Punkten auf einmal und kostet damit **einen** Zug. Ein
Command je Punkt hieße bei drei Stufen drei Züge, in denen ein Gift-Debuff tickt, während man ein Menü
bedient; eine Ausnahme von der Zugregel wollte Ticket 11 ausdrücklich vermeiden. Dasselbe Muster wie
`Buy(item, 10)`.
### Keine Obergrenze
`Stats::level_up()`s `clamp(1, 50)` fällt ersatzlos. Fünfzig Stufen über fünf Etagen wären
bedeutungslos, und eine harte Grenze wäre der einzige Teil der Progression, der einen späteren
**Endlosmodus** blockierte.
Die Kurve begrenzt sich selbst über steigende Kosten: `exp_base` und `exp_exponent` als zwei Felder in
`[balance]` aus Ticket 14 — zwei Zahlen statt fünfzig Tabellenzeilen. Eine Tabelle ließe einen Modder
Level 13 zum Sprung machen; falls das je gewünscht ist, ist sie der Ausbau.
### Erfahrung aus Tötungen und Quests
`exp_reward` als Feld an der `creatures`-Registry aus 14, plus **`give_exp` als zehnte Aktion** für
Questbelohnungen.
Das sind zwei Wege zum selben Ziel, gerechtfertigt nach demselben Muster, mit dem Ticket 01 `armor` als
Kurzschreibweise für Resistenz zugelassen hat: `exp_reward` ist die Kurzform für einen Todes-Trigger,
den sonst **jede einzelne** Gegnerdefinition mitschleppen müsste — samt einer `is_self`-Prüfung, die es
gar nicht gibt.
**Keine Erfahrung fürs Betreten einer Etage.** Das belohnte das Durchrennen; wer Räume auslässt, soll
schwächer ankommen — das ist die Spannung, von der ein Abstieg lebt.
Geprüft wird am Ende von `Game::execute`, nach dem Leerarbeiten der Warteschlange aus 08 — dann wirkt
eine Questbelohnung noch im selben Zug. Reicht die Erfahrung für mehrere Stufen, wird in einer
**Schleife** aufgestiegen; drei Stufen geben drei Punkte. Eine Stufe pro Ereignis erzeugte sonst die
Frage, wann der Rest nachgeholt wird, plus einen Zustand „aufstiegsbereit", den niemand bestellt hat.
### Die Zuwachs-Regel bleibt eng
Steigt `max_health` durch Progression um 10, steigt der Lebensstand um 10 mit — **aber nur durch
Progression.**
Ticket 01 hat davor ausdrücklich gewarnt: *„Ein Modifikator wirkt auf `max_health`, eine Aktion ändert
den Lebensstand. Die Trennung muss scharf bleiben, sonst heilt ein Ring beim Anlegen."* Eine allgemeine
Regel „max ändert sich → Stand ändert sich mit" bräche das sofort.
Genau **zwei** Stellen erhöhen den Stand um den Zuwachs, beide im Spielkern benannt statt aus einer
allgemeinen Regel gefolgert:
1. der Aufstieg,
2. `AssignPoints` — und das ist die unauffällige: `max_health` steigt erst, wenn `constitution`
tatsächlich erhöht wird, also beim Verteilen und nicht schon beim Aufstieg.
Ausrüstung nie. Der Unterschied ist die Dauerhaftigkeit: Ein Ring kommt und geht, ein Punkt in
Konstitution bleibt.
### Rasse und Klasse bleiben flach
Das beantwortet die Skalierungsfrage aus dem Ticketkörper mit „gar nicht": **`per_level` als Nachtrag
an 01 entfällt ersatzlos.** Charakteroptionen geben einen einmaligen, flachen Bonus.
Dass „Zwerg: +2 Konstitution" auf Level 30 nur noch Rauschen ist, ist gewollt. Was Charakteroptionen
dauerhaft trägt, sind **Fähigkeiten** — die veralten nicht. Ticket 02 hat sie als „Modifikatoren *und*
Fähigkeiten" definiert, und der interessante Teil ist die zweite Hälfte: Ein Magier bleibt ein Magier,
weil er zaubern kann, nicht weil er +2 auf etwas hat.
### `level` darf modifiziert werden
`Creature.base.level` steigt beim Aufstieg und ist die **einzige** Quelle für Punkte.
`attribute(wer, "level")` darf durch Modifikatoren höher ausfallen und wird von Bedingungen („Level ≥
3"), Formeln und Etagen-Skalierung gelesen.
Ein Ring mit `+1 level` macht den Helden also für alles, was Level *liest*, eine Stufe stärker — ohne
einen Punkt zu schenken. Dieselbe Trennung wie zwischen `max_health` und Lebensstand. Modifikatoren auf
`level` zu verbieten wäre die Bevormundung, die Ticket 02 abgeräumt hat, und nähme einem Modder ein
hübsches Item, das keinen Schaden anrichtet.
### Endlosrunner — neu aufgetaucht, bewusst hinter 1.0
In dieser Sitzung kam auf, dass das Fernziel ein **Endlosrunner** ist. Das berührt drei geschlossene
Entscheidungen: die Siegbedingung aus 10, `GameOver { outcome: Won }` aus 14, und die
`floors`-Registry, die einen Eintrag *je Nummer* hat — Etage 500 bräuchte eine Definition.
**1.0 bleibt endlich.** Die endliche Fassung ist vollständig durchentschieden, und ein Endlosmodus ist
additiv: ein Feld `repeat = true` an der letzten Etage plus eine Skalierungsformel. Umgekehrt hieße es,
10 und 16 gegen ein Zielbild zu bauen, das noch niemand gespielt hat.
Die fehlende Level-Obergrenze ist der Teil, der davon **jetzt schon** profitiert — sie wäre der einzige
Blocker gewesen.
### Vier Nachträge an geschlossene Tickets
| Ticket | Nachtrag |
|---|---|
| **01** | `give_exp` als **zehnte** Aktion |
| **07** | `current_exp` und `unspent_points: u32` an **`Game`**, nicht am `Creature` — die Platzierung, die 07 hierher delegiert hatte |
| **11** | `AssignPoints` als **dreizehnter** Command |
| **14** | `exp_base` und `exp_exponent` in `[balance]`, dazu `exp_reward` an der `creatures`-Registry |
### Auflage an Ticket 16
Die Beute-Skalierung darf **nicht gegen fünf feste Etagen fest verdrahtet** werden — der Endlosmodus
kommt später, und eine Skalierung, die nur bis Etage 5 denkt, wäre dann ein Umbau statt einer
Erweiterung.