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

 
 
 

Contributors

Languages