CLAUDE.md #
Project Overview #
DOOM-fire-zig is a terminal-based DOOM fire effect renderer written in Zig. It's a TTY stress test that pushes ~180KB per frame using ANSI escape codes and the half-block character (▀) for pixel rendering. Fork of https://github.com/const-void/DOOM-fire-zig.
Single source file: src/main.zig. No dependencies beyond libc.
Build & Run #
zig build run -Doptimize=ReleaseFast # build and run (recommended)
zig build # build only
zig build --global-cache-dir /tmp/claude/zig-cache # if global cache is read-only
The binary is output to zig-out/bin/DOOM-fire. Requires libc (link_libc = true in build.zig).
Exit: Ctrl+C (no graceful key polling yet). At pause prompts: q + Enter to quit, Enter to continue.
Zig Version #
Tracks latest Zig master (currently 0.17.0-dev.607+456b2ec07). Version is recorded in three places that must stay in sync:
.zigversionbuild.zig.zon.versionfieldbuild.zig.zon.minimum_zig_versionfield
Architecture #
Everything lives in src/main.zig. The program flow is:
main()->initTerm()->checkTermSz()->showTermCap()->showDoomFire()- initTerm: Sets up colors, terminal mode (ANSI escape sequences, Windows console API), terminal size, RNG
- checkTermSz: Warns if terminal is smaller than 120x22
- showTermCap: Renders color palette and scrolling marquee animation to verify terminal capabilities
- showDoomFire: The main fire simulation loop - updates fire buffer, renders to screen buffer, paints
Key Design Patterns #
- Cross-platform via compile-time branching:
if (builtin.os.tag == .windows)guards throughout. Windows uses kernel32 API; Linux/macOS uses libc + ANSI. - Never use
\ndirectly: On Windows, newlines are emulated via ANSI cursor movement (line_new). Usenlconstant everywhere. - Buffered rendering: Fire frames are built in
bs(buffer string) viadrawBuf(), then flushed in oneemit()call viapaintBuf()for performance. - emit() for all output: All terminal output goes through
emit()which usesstd.c.writeon Linux orWriteConsoleAon Windows. - Half-height pixels: Each character cell represents two vertical pixels using
▀with fg=top pixel color, bg=bottom pixel color.
Timing #
Uses std.c.clock_gettime(.MONOTONIC, ...) for both RNG seeding and FPS measurement. No std.time.Instant or std.time.Timer (removed from std in recent Zig versions).
Windows Support #
The win32 struct at the bottom of main.zig contains all Windows kernel32 FFI declarations. Windows uses UTF-16 via WriteConsoleW for wide chars but the project currently uses WriteConsoleA (ASCII) due to Zig's UTF-8 string model. Windows doesn't get fancy UTF-8 glyphs as a result.
Updating Zig Version #
When updating to a new Zig nightly:
- Update
.zigversion,build.zig.zon(version + minimum_zig_version) - Run
zig buildand fix any std library API breakage - Common breakage areas:
std.time,std.c,std.posixAPIs change frequently in Zig master - If the global zig cache is read-only, use
--global-cache-dir /tmp/claude/zig-cache - Clear
.zig-cache/if you see stale cache errors after a version change
License #
GPL-3.0. Copyright 2022-2025 const-void.