# 15 — Progression und Level-up Type: grilling Status: resolved 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. ## 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.