lumon-macrodata-refine 0.1.0
Lumon macrodata-refinement game: box glowing numbers, merge regions, refine them into temper readings — windowed Rust TUI-style game.
what it is
A windowed recreation of Severance's macrodata-refinement game: a vast field of glowing, breathing numbers you box with the mouse (boxes that touch merge; selections inside boxes carve subsets out). Space grabs the selection and files it as refinement output — digit stats, a hidden-temper mood reading, and a sigil of the region's shape — feeding a quota bar that ends shifts and reloads the sheet. Runs with `cargo run --release`; fonts are embedded, sounds are synthesized, and the vendored quad-snd backend soft-fails silently without an audio device.
readme
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
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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
macroquadimmediate-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 viaload_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'saudiofeature with quad-snd 0.2.8 vendored atthird_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=1to trace commits, carves, and refines to stderr.LUMON_SMOKE=1runs a few seconds of frames then exits.
files
32 files — expand to browse
assets/
third_party/
try it
$ cargo build --release
$ cargo run --release
vibe log
model: mimo-v2.5
Recreate the Lumon (Severance) macrodata-refinement game in Rust: box evenly spaced characters with the mouse, pan with right-drag, merge boxes that touch — grown iteratively into a windowed game with glowing/growing numbers, refinement output panel, hidden temper map, quota shift loop, synthesized tones, and embedded TTF fonts.
nd download JG2HQZWB/lumon-macrodata-refine
nd run JG2HQZWB/lumon-macrodata-refine
nd fork JG2HQZWB/lumon-macrodata-refine
/api/projects/lumon-macrodata-refine/context
/api/projects/lumon-macrodata-refine/context