# Lumon — Macrodata Refine A windowed recreation of the Lumon macrodata-refinement game: a vast field of glowing, breathing numbers. Box them in with the mouse, merge regions that touch, then **grab your selections and file them as refinement output**. ## Run ```sh cargo run --release ``` Built with `macroquad` — a real window (1280×800, resizable, hi-dpi), so mouse input is polled directly by the game every frame. ## Controls | Input | Action | |------------------------|-----------------------------------------------------| | **Left-click drag** | Draw a rectangular box around characters | | **Right-click drag** | Pan the view (free, not grid-snapped) | | **Scroll wheel** | Zoom (anchored at the cursor) | | **Space** | **Grab the selection -> refinement output** | | **,** (comma) | Settings panel (font, glow, scanlines, sound) | | **b** | Box-cursor mode (keyboard drawing fallback) | | **Arrows / WASD** | Pan (`Shift` = faster); move cursor in box mode | | **z** | Undo the last box | | **c** | Clear every box | | **Home** | Reset the view to the origin | | **q** / `Esc` | Quit (Esc first exits box-cursor mode / settings) | ## Settings Press **`,`** for the settings panel. Click a row or use arrows to change; settings save automatically to `lumongame.cfg`. - **FONT** — built-in pixel bitmap, or four embedded SIL-OFL monos: JetBrains Mono, Space Mono, IBM Plex Mono, Fira Mono. - **GLOW** — halo intensity behind glyphs: off / subtle / normal / bright. - **SCANLINES** — CRT overlay on/off. - **SOUND** — synthesized tones on/off (see below). Text is rasterized at integer pixel sizes (with only a sub-pixel scale residual) so it stays crisp at any font or zoom level. ## The refinement loop 1. **Draw a box** around numbers — left-drag from any corner to any other. The release position always defines the far corner, so selection is exact. 2. **Boxes that touch or overlap merge** into one region. Two exceptions carve instead: an **exact re-drag** of a box's rectangle toggles that box off, and a selection lying **entirely inside** existing boxes removes only those selected cells — the rest of the box stays, split into separate boxes if the cut disconnects it. 3. The last-drawn box is the **selection**: it stays highlighted in white, its border pulses between single and double lines, and the numbers inside glow hardest and grow largest. 4. **Press Space to grab it.** The selection's data is extracted — digit sum, digit/letter counts, the dominant character — and its **hidden temper** is read from an invisible cluster map seeded into the sheet. Enough tagged cells in the box and the output reports that temper (WOE / DREAD / MALICE / FROCLIC); otherwise a fallback signature is filed. Either way you get a calibration score and a cryptic line. 5. The result is filed in the **REFINEMENT OUTPUT** panel with a **sigil** — an 8×8 silhouette of the exact region you refined. Newest on top, hue accent from the source box. The box is stamped **R**, dims, and goes quiet — refined data is spent data. 6. **The quota bar fills.** Filed mass feeds it; each shift's target grows (400, 550, 700, …). Meet quota and the sheet **settles** — every number freezes mid-breath, the screen dims, SHIFT COMPLETE — then a fresh sheet loads with a new hidden temper map. The output log persists. **The trail**: refine a box that hit a temper cluster and its hidden siblings elsewhere on the sheet pulse faintly for a few seconds — a map to follow, never a translation. Nothing in the game ever spells out what the numbers mean; the meaning only ever emerges from what the output says about what you boxed. **Suspect numbers** (the flickering yellow digits) keep their yellow hue even inside a box — boxing one never repaints it. They cluster toward temper interiors, so the yellows are where the meaning lives. Everything is deterministic: the same selection on the same sheet always yields the same temper, score, sigil, and line. ## Feel - Numbers **glow** (one tight halo layer under a bright core that pushes toward white as luminance rises — adjustable in settings) and **grow/shrink** on independent per-cell phases; boxed data pulses bigger and brighter than the open field. - Suspect digits flicker yellow like failing bulbs; the open field only breathes subtly, so boxed regions pop. - Committing a box triggers a quick bright grow-pop across the selection. - Subtle CRT scanlines over a dark blue-charcoal background (toggleable). ## Sound Tones, not music — every effect is synthesized in code at startup (no asset files) and played through quad-snd's low-latency mixer: | Event | Tone | |--------------------------|---------------------------------------------------------| | Box drawn | soft blip | | Boxes merged | rising two-note chime | | Carve / remove | descending tone / low pop | | **Refine (Space)** | C-major arpeggio over a sustained fifth — the chime | | Quota met | warm detuned C-major chord swell | | New sheet | airy gliss with a sub thump | | Temper trail started | high bell ping | | Undo / clear / settings | descending blip / low thud / tiny tick | If no audio device is available the game runs silently instead of crashing (the vendored ALSA backend soft-fails; a warning prints to stderr). ## Implementation notes - `macroquad` immediate-mode rendering at 60 fps; glyph metrics are cached per character and font, and every visible cell is animated from a hash phase and a sine — no per-cell state. - Fonts are embedded with `include_bytes!` and loaded via `load_ttf_font_from_bytes`, so the binary is self-contained. - The hidden temper map is generated per sheet: 26 seeded clusters with distance falloff, suspects biased toward cluster interiors. Mood classification counts tags in the selection (≥4 tagged, ≥⅔ dominant); anything else falls back to the hash. - Quota mass = refined area; targets grow per shift; shift reloads derive sheet seeds from the base seed (xorshift64\* — non-zero-state only, so distinct seeds stay distinct). - Box outlines are derived per cell from exposed edges, so any union of cells (L-shapes, jags) renders as one correct shape, with a double-line echo border on the selection. - Merged regions are `HashSet<(row, col)>` cell sets; touching = 4-adjacency or overlap; carves split remainders via 4-connected components. - Input is polled every frame — no dependence on terminal mouse protocols. The drag preview exists only while the left button is physically held, so WM focus quirks can never leave a phantom selection on screen. - Headless logic tests (`cargo test`) cover the temper map, carve/split, reselect toggle, refinement classification, quota/shift cycle, sigils, and the WAV synthesis. - Audio: `macroquad`'s `audio` feature with **quad-snd 0.2.8 vendored** at `third_party/quad-snd/` (MIT/Apache-2.0, (c) quad-snd contributors) and patched so the ALSA backend returns silence instead of panicking when no device exists. Sound effects are synthesized PCM16 WAVs (`src/sfx.rs`). - Set `LUMON_DEBUG=1` to trace commits, carves, and refines to stderr. `LUMON_SMOKE=1` runs a few seconds of frames then exits.