feat(charakterbau): Rasse und Klasse werden gewaehlt

Der Held war seit M1 als Zwergenkrieger verdrahtet, waehrend zwei Rassen
und zwei Klassen ungenutzt in der Registry lagen. Der Charakterbau ist
eine Schleife ueber categories_ordered() und options_of() — ein Mod, der
"Talent" mit pick = 2 ergaenzt, bekommt eine dritte Spalte ohne Code.

- CharacterOption bekommt abilities und on_create (Ticket 02, TODO seit M3)
- abilities_of liest jetzt Rasse und Klasse: Krieger traegt Wuchtschlag,
  Dieb Hinterhalt, Zwerg Steinsinn
- on_create gibt die Startausruestung als gewoehnliche Aktionen —
  starting_hero() schrumpft auf Creature::new(name)
- MainMenu trennt "neuer Held" von "Lauf fortsetzen"

Befund: Das Feld abilities fehlte, obwohl Ticket 15 sein ganzes Argument
darauf stuetzt — eine Klasse konnte nur flache Modifikatoren geben.
This commit is contained in:
2026-08-13 08:03:19 +02:00
parent b721947a65
commit 69efa72d68
10 changed files with 403 additions and 23 deletions

View File

@@ -116,3 +116,28 @@ dessen leerer Liste die KI aus Ticket 14 sonst stünde.
`src/items/weapon.rs` und `src/items/armor.rs` werden gelöscht, `enum ItemType` entfällt,
`weapons.toml` und `armors.toml` verschmelzen zu einer gewöhnlichen Gegenstandsdatei, `items.rs`
schrumpft auf Laden plus Registry.
### Befunde aus M8
**`abilities` und `on_create` standen seit M3 als TODO — und `abilities` war eine echte Lücke.**
Ticket 15 hat später argumentiert: *„Was Charakteroptionen dauerhaft trägt, sind Fähigkeiten — ein
Magier bleibt ein Magier, weil er zaubern kann."* Genau das Feld, auf dem dieses Argument ruht, gab es
nicht; eine Klasse konnte bis M8 ausschließlich flache Modifikatoren geben, also genau die Hälfte, die
laut demselben Ticket auf Stufe 30 zu Rauschen wird. Beide Felder sind jetzt da, `abilities_of` liest
sie, und Krieger wie Dieb tragen eine eigene Fähigkeit.
**`on_create` hat sich als das erwiesen, was es sein sollte: keine Mechanik.** Startausrüstung kommt
über `give_item`, Startgold über dasselbe — die Engine kennt den Begriff nicht. `starting_hero()` in
`main.rs`, das seit M1 Schwert, Kappe und Trank von Hand anlegte, ist auf `Creature::new(name)`
geschrumpft. Das war der eigentliche Test der Entscheidung: Der hartcodierte Held *war* die
Startausrüstungs-Sonderregel, nur an einer Stelle, an der niemand sie so genannt hat.
**„Registry-Schleife statt gemauertem Layout" trägt.** Der Charakterbau liest `categories_ordered()`
und `options_of()`; ein Mod, der „Talent" mit `pick = 2` ergänzt, bekommt eine dritte Spalte, ohne dass
eine Zeile Code davon weiß. Geprüft wird `pick` in `rejects`, nicht im Screen — der Screen zählt gar
nicht mit.
**Der Startpunkt braucht ein Flag, keine Herleitung.** Naheliegend wäre gewesen, „Held ist noch nicht
gebaut" aus `player.options.is_empty()` zu folgern. Das ist falsch: Ein Speicherstand, dem der
Rassen-Mod fehlt, hat nach der Verwerf-Regel aus Ticket 09 ebenfalls keine Optionen — und würde neu
gebaut statt fortgesetzt. `MainMenu { neu }` weiß es stattdessen von `main`, das den Unterschied kennt.

View File

@@ -198,6 +198,27 @@ Ticket 08 nennt `start_quest` die „siebte", Ticket 14 `flee` die „achte", M4
gebaut sind neun Varianten. Jedes Ticket zählte von seinem eigenen Stand aus. Die Zahlen sind aus dem
Code raus, `CONTEXT.md` führt jetzt die Liste — die ist zählbar.
**M8 — Charaktererschaffung** (`feat/m8-charakterbau`, 72 Tests)
Nicht Scripting: **Ticket 13 hat Stufe (c) ausdrücklich hinter 1.0 gelegt**, und die Destination oben
sagt dasselbe. Der Vorschlag „M8 = Scripts" kam aus den TODO-Kommentaren im Code, nicht aus dem Ticket.
Offen für 1.0 war stattdessen „Solo-Held mit **Rasse und Klasse**" — gebaut war davon nichts.
| Zusage | Aus | Befund |
|---|---|---|
| Charakterbau ist eine **Registry-Schleife**, kein gemauertes Layout | 02/11 | **bestätigt** — „Talent" mit `pick = 2` bräuchte keine Zeile Code |
| `pick = N` an der Kategorie | 02 | **bestätigt**, geprüft in `rejects`, nicht im Screen |
| `on_create` ist **keine neue Mechanik** | 02 | **bestätigt** — der hartcodierte `starting_hero()` *war* die Sonderregel und ist ersatzlos weg |
| Was eine Option dauerhaft trägt, sind Fähigkeiten | 15 | **das Feld gab es nicht** — siehe unten |
| `core:attack`/`core:flee` implizit gewährt | 02/09 | **bestätigt** — ein Held ohne Klasse kann trotzdem angreifen |
Zwei Befunde nachgetragen: **02/15** (`CharacterOption.abilities` fehlte — das Argument „ein Magier
bleibt ein Magier, weil er zaubern kann" ruhte auf einem Feld, das nie gebaut wurde; eine Klasse konnte
nur flache Modifikatoren geben, also genau die Hälfte, die laut demselben Ticket veraltet) und **02/09**
(„Held ist noch nicht gebaut" darf **nicht** aus `options.is_empty()` gefolgert werden — ein
Speicherstand ohne Rassen-Mod hat nach der Verwerf-Regel ebenfalls keine Optionen und würde neu gebaut
statt fortgesetzt).
**Drei Befunde aus M1, die nur der Compiler liefern konnte** — alle in die Tickets zurückgetragen:
- **11**: Der Grenztest in seiner wörtlichen Fassung schlägt beim eigenen Doc-Kommentar an. Muss Kommentarzeilen ausnehmen.