Vi-Fighter
vi motions meet a roguelike terminal shooter
About
Vi-Fighter is a real-time terminal game that combines Vim-style navigation and text operations with typing, shooting, procedural encounters, adaptive enemy movement, and generative audio.
It is written in Go around a custom Entity-Component-System, an event-settled fixed-step runtime, and TOML-authored hierarchical state machines. There is no application CGO requirement; terminal, TOML, color, and logging support come from separately maintained Go modules.
Movement, targeting, and editing use vi motions: hjkl, w/b/e, f/t,
counts, operators, registers, searches, and macros across Normal, Insert,
Visual, Search, Command, and Overlay modes. Play with the keyboard, mouse, or
both.
The application supports interactive play, caller-driven headless simulation, and terminal playback of recorded runs. The shipped interactive client uses one selected local cursor; the underlying event-driven cursor roster also provides a common path for replay, bots, and future remote producers.
Some encounters learn during the run. Route selection shifts using observed enemy fitness, while a streaming genetic engine evolves eye parameters from lifetime outcomes.
Screenshots














Gameplay
Play in the Browser
The constrained Go build runs in WebAssembly inside xterm.js. It opens in a new tab because the terminal captures keyboard and mouse input while the game has focus.
- Requires
- A modern browser with JavaScript and WebAssembly support. WebGL2 improves xterm.js rendering but is optional; the terminal falls back to its canvas renderer when the WebGL addon is unavailable.
- First load
- The WebAssembly binary and browser runtime assets are fetched on startup. Built-in TOML configuration and fallback content are embedded in the binary, so the game does not fetch scenario data after it starts.
- Audio
- Silent. The WebAssembly target disables the native process and device audio backends.
- Performance
- Usually below the native build. The Go WebAssembly runtime, game loop, and xterm.js renderer all execute within the browser environment.
- Rendering
- The WebGL addon is used when available. If initialization fails or its context is lost, xterm.js continues with the canvas renderer.
Under the Hood
ECS Runtime
Float64 Physics
float64 values; integer points and areas describe discrete grid cells. The
physics library provides bounce integration, steering, collision impulses,
orbital constraints, springs, and 3D helpers projected onto the terminal plane.
Manual-clock runs are reproducible for one build, but floating-point simulation
is not presented as a cross-platform lockstep contract.Adaptive Enemies
Terminal Compositor
Procedural Audio
Input and Replay
Technical Details
Runtime
- Platforms: Linux, FreeBSD, constrained WebAssembly, and experimental Windows
- Toolchain: Go 1.26.5
- Dependencies: separately maintained Go modules for terminal, TOML, color, and logging; no application CGO requirement
- Data: TOML-authored game phases, species, visuals, audio, and keymaps, with built-in fallback scenarios and content
- Modes: interactive play, manual-clock headless simulation, and journal replay
- Player model: FSM-owned 16-slot roster; the shipped client selects one local cursor
- Input: keyboard, mouse, or mixed
- Audio: starts muted; press
Ctrl-Sto cycle music and effects - License: BSD-3-Clause
Build
- Clone
git clone https://github.com/lixenwraith/vi-fighter --depth 1- Build
cd vi-fighter && make release- Run
./bin/vif