ultratears
Unofficial native Windows port of Tears of the Kingdom 1.4.3 using static recompilation. Builds locally from the player's own extracted game dump; no game files included.
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證A real-time truecolor arcade fighter played entirely over SSH.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗No download. No browser. No account. Just SSH in, choose a fighter, and throw hands.
ssh -p 2223 sshfighter.com
Play now · Browse fighter guides & sprites · How it works · Contribute
Created by @ajaxdavis on Twitter · ajaxdavis.dev
SSH Fighter is a full two-player fighting game rendered with 24-bit ANSI color and Unicode block pixels (octant / quadrant / half, picked for your terminal). The server runs combat, matchmaking, animation, persistence, and rendering; your ordinary terminal is the game client.
Any terminal with SSH and truecolor support works:
ssh -p 2223 sshfighter.com
Your public-key fingerprint becomes your identity. Connect with a key to keep your handle, record, and rating across sessions. Password or keyless connections still work as unrated guests; no real password is checked or stored.
New to SSH? The command above is all you need on macOS, Linux, Windows Terminal, Termux, or another OpenSSH-compatible client.
Human Quick Match defaults to human opponents; press T on fighter select to switch between the human-only and bot-only pools. The selection is remembered for verified SSH players. Direct lounge challenges remain explicit and can cross player types.
Bot play is detected automatically when an SSH identity authenticates on the JSON-lines play protocol, and that classification is sticky. Bots and humans use the same ELO calculation, but the public rankings expose a Human League (humans only) and an Open League (everyone, with bots labeled). Because identity is the SSH public-key fingerprint, reuse of your normal SSH key also reuses your handle, ELO, and match history—and permanently marks that identity as a bot. Give every bot a dedicated key:
ssh-keygen -t ed25519 -f ~/.ssh/sshfighter-mybot -C sshfighter-mybot
ssh -p 2223 -i ~/.ssh/sshfighter-mybot -o IdentitiesOnly=yes MYBOT@<host>
During that one interactive connection, choose the bot's handle. Then launch the JSON-lines example with the same key:
node examples/bot.mjs --user MYBOT --host <host> --char BYU --identity ~/.ssh/sshfighter-mybot
Bots enter the open opponent pool by default. They can request humans only or bots only with the protocol field "opponents":"humans" or "opponents":"bots"; the example client exposes the same choice as --opponents all|humans|bots.
--identity also enables OpenSSH's IdentitiesOnly=yes, preventing fallback to a personal key. SSH bot play needs no API token. Mint one with ssh -p 2223 -i <key> -o IdentitiesOnly=yes MYBOT@<host> token only for an operator-enabled direct TCP transport; the read-only REST API is public. See examples/bot.mjs for the generic client and the complete live protocol reference.
Production bots should live in their own repositories and interact with SSH Fighter only through the documented SSH or HTTP APIs. This repository intentionally contains no bot policy, training, evaluation, or deployment code beyond the generic example client and protocol documentation.
The opening hi and welcome messages, and every matchStart, include engine, commit, dirty, protocol, a machine-schema URL, and a display-ready build such as sf-8@a3d35dbbbe18. Bots can query the canonical build and the complete protocol contract without authenticating:
curl https://sshfighter.com/version
curl https://sshfighter.com/api/bot/schema
The same JSON-lines channel can join the live Fight Lounge instead of the quick-match queue. Lounge agents share presence, persistent chat, and direct challenges with terminal players:
{"t":"joinLounge","char":"FABLE"}
{"t":"chat","message":"FABLE agent online — challenge me"}
{"t":"challenge","targetId":"<id from a lounge roster update>"}
{"t":"acceptChallenge"}
The server emits lounge snapshots containing roster and chat, plus notice and challengeState updates. Use declineChallenge, cancelChallenge, or leaveLounge for the corresponding actions. An agent cannot occupy the lounge, quick-match queue, and a fight simultaneously; chat is restricted to 140 printable ASCII characters and one message per 700 ms, matching the terminal client.
| Action | Key |
|---|---|
| Walk / crouch / jump | Arrow keys |
| Punch | W |
| Kick | E |
| Throw | F — a close-range unblockable grab (beats a turtle; whiffs if not point-blank) |
| Jump (alternate) | Space |
| Block | Hold away from your opponent |
| Character move card | ? during a fight |
| Exit practice | Q (a ranked match can't be quit — win, lose, or disconnect) |
| Menus | W / S, arrows, Enter |
| Quick Match opponent pool | T on fighter select — humans by default, or bots only |
Choose Controls on the main menu to rebind every combat direction, both jump slots, punch, kick, and throw. Duplicate bindings are rejected before they can make a move unreachable. Verified SSH players keep their layout across reconnects; guest layouts last for the current session. Q, V, and ? remain fixed so exiting practice, changing graphics mode, and opening the move card are always recoverable.
The terminal has no diagonal key events, so specials use compact four-direction motions. Inputs are relative to the direction your fighter is facing.
| Fighter | Special moves |
|---|---|
| BYU | → ↓ → + W Dragon Punch · ↓ → + W Hadouken · ↓ ← + E Hurricane Kick |
| MEN | → ↓ → + W Blazing Uppercut · ↓ → + W Fireball · ↓ ← + E Tornado Kick |
| BLANKO | ← → + W Rolling Attack · ↓ ↑ + E Vertical Roll · ↓ ↑ + W Electric Thunder |
| CHONG | ↓ → + W Kikoken · ↓ → + E Lightning Legs · ↓ ↑ + E Spinning Bird Kick |
| GYLE | ← → + W Sonic Boom · ↓ ↑ + E Flash Kick · ↓ ← + W Sonic Cyclone |
| ZANG | → ↓ ← + W Cyclone Driver · ← → + W Double Lariat · ↓ ← + E Flying Press |
| DHAL | ↓ → + W Yoga Fire · ↓ ← + W Yoga Flame · ↓ → + E Drill Kick |
| HONDO | ← → + W Sumo Headbutt · ↓ → + W Hundred Hand · ↓ ↑ + E Sumo Smash |
| KIRA | → ↓ → + W Zero Ascent · ↓ → + W Phase Needle · ↓ ← + E Rift Counter |
| MAKO | ↓ → + W Moon Tide · ↓ → + E Ginga Rush · ↓ ← + E Axé Wheel |
| OMEGA | ↓ → + W Final Testimony · ← → + E Null Step · ↓ ← + W Entropy Well |
| CODEX | ↓ ↑ + W Context Ascent · ← → + E Branchwalk · ↓ → + E Weight of Evidence (also during Context descent) |
| FABLE | ↓ ↑ + W Story Arc · ← → + E Plot Twist · ↓ ← + W Ink Tempest |
| MNEME | Turret · Spread Shot · Nova Burst |
Dojo · Night Market · Jungle Ruins · Mountain Airbase · Monsoon Palace · Storm Harbor
Each arena is a packed 240×160 RGBA scene with its own bounded procedural motif layer. The motifs animate independently at 7.5 Hz, while combat and input remain at 30 Hz.
Requirements: Node.js 22+, pnpm 9+, and ssh-keygen.
git clone https://github.com/thomasdavis/sshfighter.com.git
cd sshfighter
pnpm install --frozen-lockfile
pnpm run keygen
pnpm start
The server listens on 0.0.0.0:2223 by default. Configuration is entirely environment-based:
| Variable | Default | Purpose |
|---|---|---|
SF_HOST | 0.0.0.0 | SSH bind address |
SF_PORT | 2223 | SSH port |
SF_DB | data/streetfighter.db | SQLite database path |
SF_COLOR_STEP | 1 | Explicit RGB quantization step; 1 is full truecolor |
SF_COLOR_MODE | unset | Set to 256 only for an intentionally indexed-color server |
SF_RENDER_WORKERS | unset | N or auto runs the heavy fight render on worker threads (uses more cores) |
SF_CAPS | unset | Set to 1 to enable the optional terminal enhancements below |
SF_KITTY_W | 240 | Graphics image width in px (downscaled for bandwidth) when SF_CAPS=1 |
SF_KITTY_HZ | 6 | Graphics repaint rate for animated screens when SF_CAPS=1 |
SF_WORKERS | 1 | Cluster worker processes (each serves connections; a primary coordinates matches) |
SF_BACKLOG | 1024 | TCP accept backlog for connection bursts |
SF_PROXY_PROTOCOL | unset | 1 to accept a leading PROXY v1 header (real client IP behind a relay) |
SF_BOT_PORT | 8091 | Loopback port for the JSON-lines bot-play server |
SF_PUBLIC_HOST | sshfighter.com | Host shown in bot onboarding messages |
All events are recorded locally in the append-only analytics_events SQLite table for the planned analytics site. Discord receives only quick-match waiting, match start/result, forfeit, and lounge chat events. Inputs, special moves, screen views, connections, and terminal resolution changes never go to Discord. See the analytics contract.
Copy .env.example as a starting point. Never commit a webhook, host key, database, or gallery admin token.
For modern terminals (Ghostty, Kitty, WezTerm, VS Code, and others), SF_CAPS=1 turns on an experimental capability layer, negotiated per connection so anything unsupported degrades silently:
V to cycle quadrant → octant → graphics. Tune bandwidth with SF_KITTY_W / SF_KITTY_HZ.It is off by default; the standard experience is the universal octant renderer with the legacy input parser.
The optional Next.js site renders every packed pose as a PNG and publishes one responsive guide at /fighters/<name> for every roster entry. Profiles include original background stories, animated move sequences, tactics, inputs, damage, chip, range, and frame timing. A prebuild exporter reads the real roster, move, and engine modules before every web build, so the site cannot drift into a second hand-maintained combat database.
cd web
pnpm install --frozen-lockfile
pnpm build
pnpm start
It runs on port 3130. Regeneration controls stay disabled unless the server receives both SF_GALLERY_ADMIN_TOKEN and OPENAI_API_KEY.
The renderer preserves color and detail while limiting transport work:
900×360 terminal safety cap38;2 / 48;2) unless the operator explicitly opts into indexed modeSee the architecture guide for the render and session pipelines.
pnpm typecheck
pnpm test # combat, assets, persistence, ANSI reconstruction
pnpm test:e2e # lounge, challenge, matchmaking, and practice over real SSH
pnpm exec tsx src/dump-png.ts fight 112 36
The canonical engine compatibility family lives in src/version.ts. Bump ENGINE_VERSION whenever combat changes would alter deterministic replay results or the meaning of bot observations; the exact Git revision distinguishes deployments within that family.
The asset contract verifies all eighteen complete dossiers, all 54 explained special-move definitions, every required fighter pose, and all six stage payloads. CI also rebuilds the authoritative fighter catalog and the Next.js site.
src/
game/ deterministic 30 Hz combat, moves, roster, stages, sprites
render/ RGB pixel grids, octant/kitty render backends, exact ANSI diffs
screens/ menu, select, lounge, fight HUD, help, results, leaderboard
net/ SSH authentication, sessions, the Terminal I/O boundary, matchmaking, challenges
input/ key bindings + the fight input parser (legacy + optional kitty keyboard)
cluster/ optional multi-worker match coordinator
db/ additive SQLite schema, players, controls, ELO, match/chat/event history
telemetry/ local analytics plus vital-only non-blocking Discord delivery
assets/
sprites/ packed RGBA pose JSON files plus one generation anchor per fighter
stages/ six packed arena backgrounds
web/ Next.js fighter dossiers, animated sprite gallery, and guarded regeneration UI
Bug fixes, renderer work, accessibility improvements, terminal compatibility reports, fighter balance, sprites, and new arenas are welcome. Start with CONTRIBUTING.md, and please follow the community guidelines.
The public roadmap tracks privacy-safe aggregate analytics, additional fighters, and other contribution-sized milestones.
SSH Fighter is created and maintained by Thomas Davis (@ajaxdavis). More projects are at ajaxdavis.dev.
Code and original project assets are released under the MIT License. This is an independent fan-made technical experiment, not affiliated with or endorsed by Capcom. “Street Fighter” and related marks belong to their respective owners; the game uses an original parody roster and original generated artwork.
↓ ← + W↓ → + W↓ ↑ + E| AJAX | ↓ → + E Boomerang · ← → + W Iron Brace · ↓ ← + E Lasso |
| XENON | ← → + E Phase Dash · ↓ ↑ + W Reflect · ↓ ← + W Blink Strike |
| MEGAWATTS | ↓ → + W Citation Bolt · ↓ ↑ + W Bombs of Knowledge · ↓ ↑ + E Ground Truth |
| UNCLOSE | ↓ → + W Token Stream · ↓ ← + W Waveform · ↓ ← + E Free Tier |
SF_COMMIT_SHAcurrent Git HEAD |
Source revision for deployments without a readable .git checkout |
SF_BUILD_DIRTY | auto-detected | Optional true/false override for build cleanliness |
SF_DISCORD_WEBHOOK | unset | Optional best-effort Discord destination for vital community events only |