12 — Prototyp: ratatui-Durchstich #13

Closed
opened 2026-08-11 13:37:54 +00:00 by RDietermann · 1 comment
Owner

Teil der Map #1 · Type: wayfinder:prototype · Blocked by: #12 · graduiert aus #7

Traegt das Screen-Modell aus #12, bevor sieben Bildschirme darauf gebaut werden? Billiger Durchstich mit Hauptmenue + Dungeon-Grid + einem Popup. Kein Kampf, kein Inventar, keine Mods.

Volle Fragestellung (kanonisch): .scratch/rustkeep-1.0/issues/12-prototyp-ratatui-durchstich.md

Teil der Map #1 · **Type: `wayfinder:prototype`** · **Blocked by: #12** · graduiert aus #7 Traegt das Screen-Modell aus #12, bevor sieben Bildschirme darauf gebaut werden? Billiger Durchstich mit Hauptmenue + Dungeon-Grid + einem Popup. Kein Kampf, kein Inventar, keine Mods. Volle Fragestellung (kanonisch): `.scratch/rustkeep-1.0/issues/12-prototyp-ratatui-durchstich.md`
RDietermann added the wayfinder:prototype label 2026-08-11 13:37:54 +00:00
Author
Owner

Urteil: Das Modell aus #12 traegt. Aufgeloest in 88195d3.

Primaerquelle ist der Wegwerf-Branch prototyp/12-ratatui-durchstich (examples/durchstich.rs, 342 Zeilen). Start mit cargo run --example durchstich. Er bleibt dort und kommt nicht nach main.

Die fuenf Zusagen

Zusage Befund
mod game bleibt ratatui-frei haelt — null Treffer, ohne dass jemand aufpassen musste
Grid als eigenes impl Widget traegt — buf[(x,y)].set_symbol(…) ist der ganze Trick
Vec<Screen> fuer Screens und Popups traegt — das Overlay-Flag entscheidet Rendern und Auto-Schliessen
Response statt Stack-Mutation traegt — kein Borrow-Konflikt, der Screen sieht den Stack nie
KeyEventKind::Press-Filter gemessen statt geglaubt, siehe unten

Popup ueber Grid, x dann j: der Zug zaehlt hoch und das Popup schliesst sich in derselben Iteration. Die Regel "ein Response::Command schliesst alle Overlays" kostet die eine Zeile, die in #12 dafuer veranschlagt war.

Der Windows-Fallstrick ist jetzt eine Zahl

#7 fuehrte ihn als Faktum, aber ungemessen. Der Prototyp zaehlt Tasten-Events ungefiltert und gefiltert mit. Unter Windows 11:

Tasten 14 → Press 7 → Zuege 7

Jeder Tastendruck erzeugt zwei Event::Key (Press und Release). Ohne den Filter kostete jeder Schritt zwei Zuege — und weil ein Zug befristete Modifikatoren tickt, waere das kein kosmetischer Fehler, sondern doppelte Spielzeit.

Zwei Korrekturen, beide beim Spielen gefunden

  • #12 (11): "alle Commands kosten einen Zug" wird zu "alle ausgefuehrten". Gegen eine Wand zu laufen liess den Zugzaehler hochlaufen, obwohl sich nichts bewegte. Jetzt Outcome { TurnPassed, Rejected(&'static str) } — der Zug endet nur bei TurnPassed, der Grund reist mit zurueck in die Statuszeile. Betrifft weit mehr als Waende: kaufen ohne Gold, Faehigkeit ohne Ausdauer, absteigen ohne Treppe. Overlays schliessen sich trotzdem auch bei Rejected — die Rueckfrage wurde beantwortet.
  • #12 (11): Command muss Clone sein, sonst kommt es nicht aus Confirm { on_yes } heraus.

Ebenfalls bestaetigt (Nachtrag an #7)

ratatui::run, Clear auf ein Sub-Rect fuer Popups, und dass ratatui die Crate crossterm re-exportiert — ein eigener Cargo.toml-Eintrag ist tatsaechlich unnoetig. Gebaut gegen ratatui 0.30.2 mit Rust 1.96.

Was der Durchstich nicht beantwortet

Kampf, Inventar, Shop, Speichern, Mods — bewusst ausgelassen. Ungetestet blieb auch Registries neben Game aus #8: Der Durchstich laedt keine Registries, und der Borrow-Konflikt, den die Entscheidung vermeiden soll, tritt erst auf, wenn Game::execute beides gleichzeitig braucht. Das prueft erst die Implementierung.

**Urteil: Das Modell aus #12 traegt.** Aufgeloest in 88195d3. Primaerquelle ist der Wegwerf-Branch **`prototyp/12-ratatui-durchstich`** (`examples/durchstich.rs`, 342 Zeilen). Start mit `cargo run --example durchstich`. Er bleibt dort und kommt nicht nach `main`. ### Die fuenf Zusagen | Zusage | Befund | |---|---| | `mod game` bleibt ratatui-frei | **haelt** — null Treffer, ohne dass jemand aufpassen musste | | Grid als eigenes `impl Widget` | **traegt** — `buf[(x,y)].set_symbol(…)` ist der ganze Trick | | `Vec<Screen>` fuer Screens *und* Popups | **traegt** — das Overlay-Flag entscheidet Rendern *und* Auto-Schliessen | | `Response` statt Stack-Mutation | **traegt** — kein Borrow-Konflikt, der Screen sieht den Stack nie | | `KeyEventKind::Press`-Filter | **gemessen statt geglaubt**, siehe unten | Popup ueber Grid, `x` dann `j`: der Zug zaehlt hoch und das Popup schliesst sich in derselben Iteration. Die Regel "ein `Response::Command` schliesst alle Overlays" kostet die eine Zeile, die in #12 dafuer veranschlagt war. ### Der Windows-Fallstrick ist jetzt eine Zahl #7 fuehrte ihn als Faktum, aber ungemessen. Der Prototyp zaehlt Tasten-Events ungefiltert **und** gefiltert mit. Unter Windows 11: ``` Tasten 14 → Press 7 → Zuege 7 ``` Jeder Tastendruck erzeugt zwei `Event::Key` (Press und Release). **Ohne den Filter kostete jeder Schritt zwei Zuege** — und weil ein Zug befristete Modifikatoren tickt, waere das kein kosmetischer Fehler, sondern doppelte Spielzeit. ### Zwei Korrekturen, beide beim Spielen gefunden - **#12 (11)**: "alle Commands kosten einen Zug" wird zu **"alle ausgefuehrten"**. Gegen eine Wand zu laufen liess den Zugzaehler hochlaufen, obwohl sich nichts bewegte. Jetzt `Outcome { TurnPassed, Rejected(&'static str) }` — der Zug endet nur bei `TurnPassed`, der Grund reist mit zurueck in die Statuszeile. Betrifft weit mehr als Waende: kaufen ohne Gold, Faehigkeit ohne Ausdauer, absteigen ohne Treppe. Overlays schliessen sich trotzdem auch bei `Rejected` — die Rueckfrage *wurde* beantwortet. - **#12 (11)**: `Command` muss `Clone` sein, sonst kommt es nicht aus `Confirm { on_yes }` heraus. ### Ebenfalls bestaetigt (Nachtrag an #7) `ratatui::run`, `Clear` auf ein Sub-`Rect` fuer Popups, und dass `ratatui` die Crate `crossterm` re-exportiert — ein eigener `Cargo.toml`-Eintrag ist tatsaechlich unnoetig. Gebaut gegen ratatui 0.30.2 mit Rust 1.96. ### Was der Durchstich *nicht* beantwortet Kampf, Inventar, Shop, Speichern, Mods — bewusst ausgelassen. Ungetestet blieb auch **`Registries` neben `Game`** aus #8: Der Durchstich laedt keine Registries, und der Borrow-Konflikt, den die Entscheidung vermeiden soll, tritt erst auf, wenn `Game::execute` beides gleichzeitig braucht. Das prueft erst die Implementierung.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RDietermann/rustkeep#13