Commit Graph

12 Commits

Author SHA1 Message Date
37b5820c5b feat(quests): Quests als Trigger mit Zaehler
Eine Quest IST ein Trigger mit count = N — kein zweiter Mechanismus.
Gezaehlt wird erst ab start_quest, erledigte bleiben mit done = true
stehen, und die Belohnung darf die naechste starten: das ist die Kette.

- fuenfzehnte Registry, Trigger per serde(flatten) eingebettet
- give_item als Aktion, damit eine Belohnung mehr als Erfahrung zahlt
- QuestLog auf q, Fortschritt im Speicherstand, unbekannte IDs verworfen
- eine Funktion entscheidet fuer alle Traeger, wann ein Trigger feuert

Befund: Die Ordnungszahlen im Aktionskatalog widersprechen sich — vier
Tickets zaehlten je vom eigenen Stand. Sie sind raus, CONTEXT.md fuehrt
die Liste.
2026-08-13 07:43:46 +02:00
d09fef7069 feat(save): Speicherstand als Game-Baum
Autosave beim Betreten einer Etage und beim Beenden, ein Slot, bei Tod
geloescht. Der Save ist der Baum selbst — keine eigenen Save-Structs, die
man zweimal pflegt.

- Kacheln als ASCII-Zeilen wie ein Prefab, nicht 3200 Enum-Eintraege
- atomar geschrieben: tmp plus rename, der einzige Stand ueberlebt einen
  Abbruch
- fremdes Schema wird abgelehnt, die Datei bleibt liegen
- fehlende Mods verwerfen Eintraege, nie den Lauf
- Confirm-Screen vor dem Spiel, wenn der Save Eintraege verloren hat

Fuenf Befunde: die Ereigniswarteschlange gehoert nicht in den Save, die
Feldreihenfolge ist Teil des TOML-Formats, Serialize fuer Floor muss von
Hand, Confirm braucht on_no, und die Rueckfrage galt zuerst auch fuer
Mod-Ladewarnungen.
2026-08-12 22:01:12 +02:00
6f91b44e50 fix(bogen): vorgemerkte Punkte beim Abschicken verbrauchen
Nach Enter stand unspent_points auf 0, waehrend der Screen den Punkt noch
vorgemerkt hielt — die Anzeige rechnete 0 - 1 auf u32 und stuerzte ab.

Der Screen leert sein Feld, waehrend er das Kommando uebergibt, dazu
saturating_sub an den zwei Lesestellen: unspent_points kann sich auch
unter dem offenen Screen aendern.

Erster UI-Test des Projekts. handle_key ist ohne Terminal aufrufbar, und
sobald ein Screen Zustand haelt, ist die Naht zum Spielzustand eine
Fehlerquelle wie jede andere.
2026-08-12 21:20:02 +02:00
b19492bb51 feat(progression): Erfahrung, Aufstieg und Punkteverteilung
Toeten gibt Erfahrung (exp_reward stand seit M3 ungelesen an jedem
Gegner), give_exp als zwoelfte Aktion fuer spaetere Quests. Aufstieg in
einer Schleife am Zugende, ein Punkt je Stufe, keine Obergrenze.

Verteilt wird im Charakterbogen — kein zwoelfter Screen. AssignPoints
nimmt alle Punkte auf einmal und kostet damit einen Zug.

luck wirkt jetzt: eine Chance auf einen Zusatzzug auf jeder Beutetabelle.

Drei Befunde:
- strength und constitution las niemand, zwei der fuenf verteilbaren
  Grundwerte waren Fallen. Zwei balance-Knoepfe rechnen sie beim
  Verteilen um.
- Rng::chance(0.0) verbrauchte eine Zahl und verschob den Zufallsstrom.
- Cheat::ClearRoom ging am Todesweg vorbei.
2026-08-12 21:15:25 +02:00
b072e5ade3 feat(kampf): Inventar im Kampf erreichbar
'i' oeffnet denselben Screen wie draussen. `rejects` hat `UseItem` im
Kampf nie verboten — es fehlte nur die Tuer in der UI.

Dabei: Ein Gegenstand traf `Enemy(0)`, auch wenn der schon tot war. Jetzt
der erste lebende. Dass er den Zielcursor ignoriert, steht als TODO — es
faellt erst mit dem ersten Wurfgegenstand auf.
2026-08-12 21:03:07 +02:00
26d9533a93 feat(debug): Werkbank auf F12
Gegenstandsliste mit Cursor, dazu heilen, absteigen und Raum leeren.
Laeuft ueber ein Kommando Debug(Cheat) statt am Spielkern vorbei — die
Zusage aus Ticket 11, dass Response::Command der einzige Weg nach game/
ist, gilt auch fuer Cheats.

ClearRoom toetet die Gegner, statt die Liste zu leeren: So laeuft der
normale Weg samt Todes-Triggern und "Der Raum ist geraeumt".
2026-08-12 20:58:35 +02:00
6014471c33 feat(kampf): verbindliche Gegner-Ansage und Zielcursor
Am Zugende legt jeder Gegner fest, was er im naechsten Zug tut; der
Kampf-Screen zeigt es unter dem Lebensbalken. Verbindlich statt Vorschau,
denn nur so entsteht ein Fenster: Wer dem Gegner zwischen Ansage und
Ausfuehrung die Ausdauer nimmt, kostet ihn den Zug.

Zielwahl bekommt einen eigenen Cursor, Tab schaltet zwischen Gegner- und
Faehigkeitsliste um — dieselbe Bedienung wie im Laden. Die Ziffern
springen nur noch aufs Ziel, ausgeloest wird mit Enter.
2026-08-12 20:49:24 +02:00
7ed15afaf9 feat(handel): NPC-Registry, Dialog, Laden und Stapelregel
Vierzehnte Registry: NPCs sind keine Wesen — kein Kampfzustand, keine
Initiative, keine Attribute. Ihre Antwortliste ist flach; was erst nach
einer Antwort erscheint, ist eine Option mit einer Bedingung.

- open_shop als elfte Aktion (game/ setzt eine Absicht, die UI schiebt)
- Talk/Choose/Buy/Sell, Talk wirkt auf das eigene Feld wie PickUp
- Preisspanne statt Goldkonto beim Haendler, Charisma in der Preisfunktion
- Warenkorb einmal bei der Etagenerzeugung gezogen
- Stapelregel aus Ticket 07 endlich gebaut: 50-120 Gold war 120 Eintraege
- Dialog- und Shop-Screen, NPC-Symbol im Grid
2026-08-12 20:31:35 +02:00
197f62ce33 feat: m4 teil 1 — beute, inventar und affixe
- data/: [[loot_tables]] und [[affixes]] als Registries; LootEntry mit
  guaranteed, nothing, table-in-table, count und affixes
- game/loot.rs: EINE Ziehmaschinerie fuer Gegenstaende und Affixe,
  Tiefendeckel gegen wechselseitigen Bezug
- PickUp zieht erst beim Aufheben (Ticket 16) — moeglich nur, weil alle
  Haufen dasselbe Symbol zeigen
- UseItem/Equip/Unequip/Drop, Inventar-Screen als Registry-Schleife
- Affixe im Attributpfad, in der Resistenz und in der Trigger-Suche;
  item_label stellt Affixnamen voran, item_price multipliziert Faktoren
- Room haelt eine loot_table (nicht je Haufen eine), Prefab-loot
  ueberschreibt die Etagentabelle

53 Tests. Offen aus M4: Handel.
2026-08-12 17:56:28 +02:00
217a7acbbc feat: m3 kampf, events und trigger
Der Dungeon hat jetzt Gegner, und man kann sterben.

- game/action.rs: sieben Schadenstypen, fuenf der zehn Aktionen, Target
- game/condition.rs: Bedingungsgrammatik (Liste = UND, not je Eintrag)
- game/event.rs: zwoelf Events, Trigger als vierte Wirkungsform
- game/combat.rs: Treffer- und Schadensformel mit drei Klemmbereichen
- Game::apply, drain_events (FIFO), Initiative, Rundenablauf aus Ticket 14
- data/: abilities-, creatures- und modifiers-Registry, [balance] feldweise
- ui/: Combat-Screen mit Faehigkeitsmenue und Sperrgrund

Drei Befunde:
- Die Trefferformel war toter Code — jeder Angriff traf. Nur der Compiler
  hat es gemeldet ('hit_chance is never used'). Test haelt sie am Leben.
- Die Warteschlange war ein Stack (pop statt pop_front), obwohl Ticket 08
  ausdruecklich 'haengt es hinten an' sagt. Jetzt VecDeque.
- Benannte Modifikatoren (core:poisoned) hatten keine Registry — Ticket 01
  laesst apply_modifier per ID referenzieren, aber keine der zwoelf
  definierte sie. Das ist die dreizehnte.

43 Tests.
2026-08-12 17:03:00 +02:00
f998e55210 feat: m2 etagengenerierung — prefabs, floors, korridore, abstieg und sieg
Der handgebaute Testraum ist weg; Etagen entstehen aus Daten.

- game/rng.rs: xorshift64*, Seed im Game (Ticket 14)
- game/generate.rs: freie Platzierung, Pflichtraeume zuerst, Kette
  i->i-1 fuer strukturelle Erreichbarkeit, acht Orientierungen
- data/: [[prefabs]] und [[floors]] als neunte und zehnte Registry,
  Ladepruefungen fuer rechteckige Layouts und Pflichtraum-Flaeche
- Descend plus Siegbedingung: keine [[floors]] mit der naechsten Nummer
  heisst gewonnen — die Zahl 5 steht nirgends im Code
- GameOver-Screen, mitlaufender Bildausschnitt im Grid

Befund: Korridore stanzten 2340 Loecher in gezeichnete Waende, weil sie
AUF der Tuer starteten. Erst Schritt nach aussen, dann L-Form, sonst
Wegsuche ueber den freien Raum — die kann eine Raumwand nicht beruehren.
Der Test zaehlt jetzt null.

21 Tests.
2026-08-12 16:14:23 +02:00
b39491916f feat: m1 vertikaler durchstich — mod-lader, registries, attributberechnung, screen-stack
Ersetzt src/ vollstaendig: print_box, include_str! und enum ItemType fallen,
wie Ticket 01-03 es vorgezeichnet haben.

- data/: Mod-Lader mit zwei Suchpfaden, selbstheilender load_order.toml,
  drei Phasen und zweistufiger Deserialisierung (03/04)
- game/: Attributkatalog, Creature, Game::attribute ueber mehrere Quellen,
  Command mit Outcome (01/07/11/12)
- ui/: Screen-Stack mit Response, Grid-Widget, Press-Filter (06/11/12)
- mods/core/: echte TOML-Dateien auf der Platte statt include_str!

10 Tests, darunter der Borrow-Beweis fuer Registries-neben-Game, den
Ticket 12 nicht fuehren konnte.
2026-08-12 15:39:17 +02:00