Brogue: Community Edition (BrogueCE)
What it is
Section titled “What it is”Brogue is a roguelike: descend a 26-level procedurally-generated dungeon to retrieve the Amulet of Yendor from level 26, fighting creatures, dodging traps, and managing a small inventory along the way. Brogue’s reputation rests on doing more with less — it is famous for being the roguelike that proved a minimal glyph set and a disciplined screen layout can carry a deep tactical game without tile art. Brogue: Community Edition (BrogueCE) is the maintained fork that carries the original forward, runs on Linux/Windows/macOS, ships graphical tiles you can toggle with G, and retains a full ncurses text-mode build for pure-terminal play.
For KN-86 this is the headline reference of the games cluster, because Brogue is the cleanest worked example of the exact problem KN-86 has to solve: rendering a color-coded ASCII game state on a single-color grid. Brogue’s full-color build leans hard on color (terrain hazards “dance,” item-identification status is color-cued, threat is color-cued), and yet the game is fully playable in monochrome ncurses — because the underlying design never lets color be the only channel carrying a piece of state. That discipline is precisely what KN-86’s amber-on-black grid demands. (Reference “CLAUDE.md Canonical Hardware Specification” for the grid; not restated here.)
UI / layout / interaction
Section titled “UI / layout / interaction”Brogue’s screen layout is a fixed-region terminal composition — directly portable to KN-86’s content area:
| Region | Brogue dimensions | Role |
|---|---|---|
| Sidebar (left) | STAT_BAR_WIDTH = 20 columns | Player stats, equipped items, nearby monster/item roster, health/threat readouts |
| Message log (top) | MESSAGE_LINES = 3 lines | Scrolling event log — combat results, pickups, environmental events |
| Map (center/right) | DCOLS × DROWS = (COLS − 20 − 1) × (ROWS − 3 − 2) | The dungeon level, one glyph per cell |
Total grid is COLS = 100 × ROWS = 34 (31 map + 3 message). The map is the bulk; the left sidebar is a persistent status/roster column, and the top message log is a rolling 3-line scrollback. This three-region split (map + sidebar + log) is the canonical roguelike IA and maps cleanly onto KN-86’s Rows 1–23 content band — a roguelike cart would carve the content area into a left status strip, a top message band, and a map field, with firmware Rows 0/24 untouched.
- Inventory management — single-key item interaction; the sidebar shows what’s relevant nearby; a full inventory pane opens on demand. Items carry an identification state (un-identified scrolls/potions/rings show as generic glyphs with descriptive labels until identified) — a state machine worth stealing for any KN-86 cart with collectible items.
- Look / examine mode — the player can move a cursor over any cell to get a description of what’s there, which is how a monochrome player recovers information that color would otherwise have carried at a glance.
Rendering — and the monochrome problem (headline)
Section titled “Rendering — and the monochrome problem (headline)”Brogue’s per-cell display model is a glyph plus two RGB colors:
typedef struct cellDisplayBuffer { enum displayGlyph character; char foreColorComponents[3]; /* foreground RGB */ char backColorComponents[3]; /* background RGB */ char opacity;} cellDisplayBuffer;The color model itself is unusually rich — Brogue colors carry random jitter components and a colorDances flag, so fire, water, and magical effects literally shimmer frame-to-frame:
typedef struct color { short red, green, blue; /* base */ short redRand, greenRand, blueRand; /* per-component random add */ short rand; /* scalar random add to all */ boolean colorDances; /* re-randomize every refresh */} color;Here is the decisive insight for KN-86. Brogue never lets color be the sole carrier of identity. Every entity already has a distinct glyph: the curses platform’s glyphToAscii() maps each internal displayGlyph to a specific ASCII character before drawing —
case G_FLOOR: return '.';case G_CHASM: return ':';case G_TRAP: return '%';case G_FOLIAGE: return '&';case G_SCROLL: return '?';case G_RING: return '=';case G_WEAPON: return '(';case G_GEM: return '+';/* monsters fall through to their letter (rat 'r', goblin 'g', etc.) */So in the ncurses text build, the glyph alone disambiguates entity type — @ is you, . is floor, r is a rat, ( is a weapon, ? is a scroll. Color is a redundant, secondary channel layered on top: it encodes status and intensity (how hot a fire is, whether a potion is identified, how dangerous a monster is, whether terrain is hazardous), never what the thing is. That is exactly why Brogue survives monochrome: kill the color and you lose the at-a-glance flavor but never the information needed to play.
The curses renderer proves the degradation path is real and shipped: curses_plotChar() takes the same RGB the SDL build uses, divides each component by 100, and hands it to whatever the terminal can do — on a limited-palette terminal it collapses toward the nearest available attribute, and the game stays winnable.
Single-color adaptation
Section titled “Single-color adaptation”This is the entry’s whole reason for existing. How does color-coded roguelike game state best survive a monochrome amber grid? Brogue answers it by example; here is the read-across for KN-86 (recommended ranking):
- Glyph is identity; never color. The first and biggest rule. Every entity type, terrain type, and item class gets a distinct character. If two things must be told apart, they must differ in glyph (or position/box), not in hue. Brogue already does this — KN-86 carts must adopt the same constraint as a hard rule, because amber-on-black has zero color channel to spare.
- Inversion (fg/bg swap) as the second channel. KN-86 has amber-on-black and its inverse (black-on-amber). Brogue uses background color to mark the player’s cell, targeting cursors, and hazard tiles; KN-86 maps that onto inversion — the selected/targeted/hazardous cell renders inverted. One bit, highly legible, costs no glyph.
- Glyph density / weight for intensity. Where Brogue ramps brightness or saturation to show “how much” (fire intensity, gas concentration, light level), KN-86 ramps CP437 shading glyphs —
░ ▒ ▓ █(light→dark) — to encode a scalar in a single cell. This is the monochrome substitute for a brightness gradient and it reads instantly. - Position / dedicated readout for what color used to whisper. Brogue’s sidebar spells out, in text, the threat roster that color-cues on the map. KN-86 leans harder on this: anything color alone conveyed in the full-color build (threat tier, identification state, status effects) gets an explicit sidebar glyph badge or a text token — e.g. a
!suffix on a monster’s roster line for “dangerous,” a?glyph for “un-identified.” - Animation/blink for the
colorDanceseffect. Brogue’s shimmering fire/water/magic (colorDances) can’t be done with hue on KN-86 — so port it to the time axis: cycle the glyph (░▒▓alternating) or blink inversion on the animated-redraw tick (the runtime already caps animation at 20 fps). Motion replaces shimmer.
The summary recommendation for KN-86 cart authors: treat color as if it were never available, then add inversion + shading-glyph + blink as your three “extra” channels. Brogue is the proof that a game designed this way is not a compromised game — it’s a famously good one.
Navigation / keybindings
Section titled “Navigation / keybindings”- Movement — arrow keys /
hjkl/ numpad for the eight directions; movement is the core verb. - Single-key item & action verbs — apply, equip, drop, throw, rest, search, travel-to.
- Look mode — cursor-driven cell inspection (the monochrome player’s information-recovery tool).
G— toggle graphical tiles vs ASCII at runtime (in the SDL build). The fact that the same game renders identically-playable in tiles and in ASCII is itself the proof-of-concept KN-86 wants.- Keybindings are remappable via a keymap file (
curses_remap/ amapsymbollinked list in the curses platform).
Architecture
Section titled “Architecture”Brogue’s structure is a clean game-core / platform-layer split that KN-86’s own two-target (emulator + device) architecture should study:
src/brogue/— all game logic, platform-agnostic (Architect, Combat, Monsters, Items, Light, Movement, Dijkstra pathfinding, the procedural Grid, RNG, save/recording). Renders into an in-memoryscreenDisplayBuffer(acellDisplayBuffer[COLS][ROWS]grid).src/platform/— abrogueConsolestruct of function pointers (plotChar, input poll, modifier query, …) that each platform fills in.sdl2-platform.c,curses-platform.c,web-platform.c, andnull-platform.care interchangeable backends behind that one vtable.
The game never knows whether it’s drawing to SDL or ncurses — it writes glyph+color into the buffer and a backend renders it. This is the same separation KN-86 has between the nOSh runtime’s logical 80×25 grid and its two render targets (SDL3 emulator / Pi device). Brogue validates that a single glyph+attribute buffer can drive both a rich graphical build and a pure-terminal build with no game-logic changes — which is the whole bet KN-86 is making.
Deckline feature inspiration
Section titled “Deckline feature inspiration”- Roguelike cart IA reference. Map + left status sidebar + top message log is the layout a KN-86 roguelike/dungeon cart should adopt wholesale, inside Rows 1–23.
- The 26-level procedural descent is a textbook depth-of-content-from-little-data model — directly relevant to KN-86’s cart generation-data approach (carts carry generation rules + behavior tables, not hand-authored levels). Cross-link the procedural-generation guidance in the cartridge authoring docs.
- Item-identification state machine — un-identified → identified is a cheap, deep mechanic that fits the amber grid (an un-identified item is just a generic glyph +
?until used). Good fit for any KN-86 cart with loot. colorDances→ motion-as-emphasis. Adopt the principle that “alive/dangerous/active” things move, even on a static amber grid, via the 20 fps animation tick.
- This is the central single-color problem flagged in the Batch 8 brief. The recommendation above (glyph=identity, inversion=selection/hazard, shading-glyphs=intensity, text/badge=status, blink=animation) is the deliverable.
- Cross-link the cartridge / gameplay docs:
docs/software/cartridges/authoring/screen-design-rules.md(the Row 0 / 1–23 / 24 layout contract that a roguelike cart must honor),docs/software/cartridges/authoring/ui-patterns.md(audio-as-data + reusable UI patterns), anddocs/software/cartridges/authoring/lisp-paradigm.md(cell-as-data model). Brogue’scellDisplayBufferis conceptually the same as KN-86’s per-cell glyph+attribute model. - Cross-link zork.md — the other deep game-history reference; Zork is the Lisp/bytecode-VM precedent, Brogue is the ASCII-rendering precedent.
- The platform-layer vtable pattern is worth a citation in any future ADR that formalizes the emulator/device render-target split.