
Vimazing is a browser game where you move a hero through a maze using pure vim motions. It supports numeric counts (e.g. 10j
), line anchors (^
, $
), relative line/column numbers, and a score system tuned for both step-optimal routes and raw speed.
- Vim motions:
h j k l
(+ uppercase) with counts:12j
,3k
, etc. - Hard “all-or-nothing” moves: counted/anchor moves must be fully traversable or they fail (no partial).
- Anchors:
^
— jump to the start of the current corridor only if the path to the left border is clear.$
— jump to the end (right border) only if the path is clear.
- Relative numbering: vim-style row/column numbers around the board; current line/column highlighted.
- Fast multi-step animation (visual only; scoring uses logic-time).
- Scoring built for speedruns:
- 100/100 at par time → 10,000
- Faster 100/100 → asymptotes to 50,000
- Fewer-than-optimal steps + speed → asymptotes to 100,000
See the full math in SCORING.MD.
- Online status (WebSocket ping + user count).
- Deterministic maze internals; consistent DOM mapping with
data-r
/data-c
attributes. - Accessible defaults: rem-based sizing and high-contrast theme.
- Press
i
to start a new run. - Move with
h j k l
. - Use numeric counts:
10j
,3l
, etc. If any tile in the path is blocked, the move is invalid (hero doesn’t move). - Anchors:
^
to the left border,$
to the right border — only if the corridor is clear end-to-end. - Press
Esc
to leave a run. - Numbers around the maze are relative to your hero’s position; the active row/column is highlighted.
- Par time =
optimalSteps × 250ms
. - 10,000 for 100/100 at par.
- Up to 50,000 for 100/100 faster-than-par (saturating curve).
- Up to 100,000 (asymptotic) for routes that use fewer steps than optimal and are fast.
- Scoring uses logic time (timestamps on accepted moves), not animation duration.
Full details & formulas: SCORING.MD
Prereqs: Bun (v1+). Install from https://bun.sh
# install deps
bun install
# dev server (vimaze)
bun run dev:vimaze
# dev server (API)
bun run dev:api
# build
bun run build:vimaze
Open the dev server URL that Vite prints (usually http://localhost:5173
).
Note: This is now a monorepo. See WORKSPACES.md for architecture details.
- Maze size: URL query params (user-facing counts, not internal grid):
?cols=64&rows=48
→ renders the same maze as the old 32×24 internal grid, with vim-style numbering around.
- Cell & font size:
src/App.css
:root { --cell-size: 24px; /* maze cell & number cell size */ --number-font-size: 10px; /* digits around the maze */ }
- WebSocket server: set
VITE_WS_URL
(defaults tows://localhost:9000
).
This is a monorepo with multiple apps and servers:
- apps/vimaze – The maze game (React + Vite)
- servers/api – WebSocket multiplayer server (Bun + Hono)
- workspaces/types – Shared TypeScript types
apps/vimaze/src/lib/MazeBuilder.ts
– maze generation, DOM rendering, shortest paths, helpers.apps/vimaze/src/hooks/useGame/*
– orchestration (maze, player, status, hero render, keybindings).apps/vimaze/src/hooks/useKeyBindings.ts
– vim motions, numeric counts, and key logging.apps/vimaze/src/hooks/useGame/usePlayer.ts
– movement logic, all-or-nothing counted moves, anchors (^
,$
), fast RAF animation, DOM effects (trail).apps/vimaze/src/hooks/useScore/*
– timer, optimal distances, logic-time, player step counting, final score.apps/vimaze/src/App.tsx
– UI composition (scoreboard, multiplayer status, overlay).
See WORKSPACES.md for full architecture documentation.
- Invalid move feedback: a red “mist” class is applied around the hero for failed moves.
- Logic time: emitted via a
maze-logic-tick
CustomEvent
; all scoring uses these timestamps. - Player steps: counted from position deltas, so counted motions & animations are measured correctly.
- DOM mapping: cells are addressable via
.maze-row > div[data-r="{row}"][data-c="{col}"]
.
- More vim motions (e.g. word-wise,
gg/G
,[{
/}]
style corridor jumps). - Seeded mazes & weekly challenges.
- Ghost replays & leaderboards.
- Audio ticks / haptic feedback (optional).
- Accessibility & mobile touch helpers.
- The Art of Web and their Random maze generator
MIT © You can do whatever the heck you want with this.
PRs and ideas are welcome!
File an issue, or open a discussion with suggestions for motions, scoring, or UI.
- make a pull request with a screenrecording (GIF) of your best run and we'll feature it here