Skip to content

andrepadez/vimazing-vimaze

Repository files navigation

Vimazing — a vim-motion maze game

vimazing.pastilhas.eu

Practice vim motions by escaping randomly-generated mazes — fast.

Vimazing logo

Built for speedrunners, learners, and everyone who loves hjkl.

screenshot-2025-10-08_19-27-15

🎮 What is this?

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.


✨ Features

  • 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.

🕹 How to play

  • 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.

🧮 Scoring (high-level)

  • 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


🚀 Quick start (local)

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.


⚙️ Configuration

  • 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 to ws://localhost:9000).

🧠 Architecture (high-level)

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

Vimaze App Structure

  • 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.


🧪 Development notes

  • 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}"].

🗺️ Roadmap / Next up

  • 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.

🙏 Acknowledgements


📜 License

MIT © You can do whatever the heck you want with this.


💬 Contributing

PRs and ideas are welcome!
File an issue, or open a discussion with suggestions for motions, scoring, or UI.


📷 Screenshots

  • make a pull request with a screenrecording (GIF) of your best run and we'll feature it here

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages