`viberogue` is a ZZT-inspired game-making system written in Rust (edition 2024). The goal is a system where players can create games using a scripting language, similar to the classic DOS game ZZT. It uses **Rhai** for scripting (WASM-compatible, sandboxed, pure Rust).
- Add `///` rustdoc comments to every `pub` type, field, and function. The user reads rustdoc in their IDE to understand the code while making changes.
- Add inline `//` comments inside non-trivial function bodies to explain the *why* of each logical step — especially in `update` loops, rendering math, and conversion logic.
- Keep comments accurate: update them when the code they describe changes.
cargo test <name> # run a single test by name (substring match)
cargo clippy # lint
cargo fmt # format
```
## Architecture
The game is a single Rust binary using **eframe 0.33 / egui 0.33** for the GUI. eframe drives a retained-mode UI: the `App::update` method is called every frame and is responsible for both drawing and responding to input.
`update` is structured in two panels:
-`egui::TopBottomPanel::top` — menu bar (File → Exit)
-`Glyph` (`Copy`) — per-cell visual: `ch: char`, `fg/bg: Color32`. `Glyph::player()` is the only constructor used at runtime (colors for board tiles come from the map file).
- Board is centered in the CentralPanel when the window is larger than minimum
-`draw_glyph(painter, origin, x, y, glyph)` draws one cell: filled rect (bg) + monospace char (fg)
- Player is rendered on top of the board using `Glyph::player()`
- Arrow key input handled via `ctx.input(|i| ...)` before panel rendering
### Map file format (`maps/*.toml`)
XPM-inspired: a `[palette]` maps single characters to `(Glyph, Element)` definitions; `[grid] content` is a TOML multi-line string where each character indexes the palette.
[[objects]]# optional; parsed but not yet runtime-wired
x=10
y=5
script="""
on_touch(|| { send_message("open"); });
"""
[[portals]]# optional; parsed but not yet runtime-wired
x=59
y=12
target_map="cave"
target_entry="west_door"
```
Colors are `"#RRGGBB"` hex strings. `player_start` is a header field — the player is not a board cell. The grid multi-line string's leading newline is trimmed by TOML; trailing newline is handled correctly by `str::lines()`.
### Key design decisions
- **`cells: Vec<(Glyph, usize)>`** — the `usize` element index is intentionally an anonymous tuple field; it only has meaning relative to a specific `Board`'s `elements` palette and cannot be misused as a standalone value.
- **`Board` is the complete unit** — grid, player, objects, and portals all live on `Board`, matching how ZZT treats a "board". No separate wrapper struct.
- **Glyph (visual) and Element (behavior) are decoupled** — each cell has its own `Glyph` (so colors can vary per-cell, e.g. fire flickering) but shares `Element` definitions from the palette.
- **File loading happens in `main()`** before the window is created, so board dimensions are available for window sizing.