CoOp:Anything
게임을 검색해 협동 플레이 가능한 모드·단계·품질·커뮤니티 평점을 확인합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A real-time, two-player arena battler where your deck is whatever you can describe. Point at the arena, say what the troop is, and AI turns your words into a fighting unit with stats, quirks, a price and artwork. Say something that isn't a creature and it becomes a spell.
Built at Cal Hacks 13.0 (Oct 23–25, 2026) with Claude, Cartesia and SpacetimeDB.
| Path | What |
|---|---|
shared/ | Plain TypeScript used everywhere: sim.ts (the combat step()), troop.ts (stat schema, clamps, price()), anchors.ts (the 15 reference troops: 10 plain, 5 with quirks), spell.ts (the 12 spell effects), arena.ts (board and match constants), prompt.ts (the troop-designer prompt). |
server/ | SpacetimeDB module: rooms, deploys, and the 20 Hz tick that runs step(). |
client/ | Vite + TypeScript browser game: lobby, 3D arena (Three.js), MediaPipe hand tracking, touch, keyboard / mouse / text input, Cartesia STT, the Pavilion. |
api/ | Key proxy: one Vercel function per route, with the shared code in api/_lib/ and a local server in api/_dev.ts. POST /api/troop turns a description into a priced troop with Claude, POST /api/voice-token mints a 60 s Cartesia token for the browser's sockets, POST /api/sprite draws a troop with fal and serves it at /api/sprite/<id>.png, /api/pose draws its attack-pose frame (both kept in .cache/ locally, Vercel Blob when deployed). |
sim/ | Headless balance sim: generated troops against the anchors, value per elixir. |
bench/ | Designer benchmark (npm run bench, below). |
meta/ | Spec, progress log and aesthetic vision. |
Needs Node 22+ and the SpacetimeDB CLI.
npm start (or ./run.sh) does all of the below in one terminal: installs dependencies if missing, creates .env if missing, starts and publishes SpacetimeDB (skipped if the CLI isn't installed, leaving only Play vs Bot), then runs the API and the game. Ctrl-C stops everything. To run the pieces separately:
npm install && (cd server && npm install)
cp .env.example .env # add ANTHROPIC_API_KEY, CARTESIA_API_KEY, FAL_KEY (all optional, see below)
npm run db:start # terminal 1: local SpacetimeDB on :3000
npm run db:publish # once, and after every server/ change
npm run api # terminal 2: key proxy on :8787
npm run dev # terminal 3: game on http://localhost:5173
Every key is optional and the game still runs without it: no ANTHROPIC_API_KEY uses the offline designer, no CARTESIA_API_KEY falls back to the browser's speech recognition, no FAL_KEY keeps the emoji placeholder tokens. npm run api prints which of them it found.
Open http://localhost:5173 in two tabs (each tab is its own player), create a room in one and join it from the other, or both press Join DEMO. From a second laptop on the same network, open http://<this-laptop-ip>:5173.
To run a second copy beside the first (another worktree, say), give it its own ports: API_PORT=8790 npm run api and API_PORT=8790 npm run dev -- --port 5190 (Vite's /api proxy follows API_PORT), and ?db=<name> for its own database.
After changing tables or reducers in server/, run npm run db:publish then npm run db:generate to refresh client/src/module_bindings. If a schema change is refused, npm run db:reset republishes and wipes the data.
To use Maincloud instead of a local server: spacetime login, spacetime publish --module-path server --server maincloud <db-name> -y, then open http://localhost:5173/?host=https://maincloud.spacetimedb.com&db=<db-name>.
The repo is linked to the Vercel project calhacks-2026: every push to main deploys to production, other branches get preview URLs. Vercel builds client/ (npm run build) and serves api/*.ts as functions; their API keys (ANTHROPIC_API_KEY, CARTESIA_API_KEY, FAL_KEY) are Vercel environment variables, not .env. The deployed site plays online against the Maincloud database calhacks-arena, so after changing server/ run spacetime publish --module-path server --server maincloud calhacks-arena -y. New columns get defaults so that publish keeps the play logs; one without a default makes it ask for --delete-data, which wipes them.
Generated sprites and pose frames need a Vercel Blob store. Each function instance has its own temp dir, so without one a GET for /api/sprite/<id>.png that lands on another instance than the one that drew it 404s. Create the store once in the Vercel project (Storage → Create → Blob, public access, connected to calhacks-2026), which adds BLOB_READ_WRITE_TOKEN to its environment variables, then redeploy so the functions pick it up. With the token set, the api writes each PNG to Blob under sprites/<id>.png or poses/<id>.png and serves it from there at the same short /api/... URL; without it (local dev) art stays in .cache/ as before (api/_lib/art_store.ts).
The same store keeps gameplay recordings. Every match on the deployed site is recorded from its two board canvases plus the game audio (no permission prompt, so the HTML HUD isn't in it) and uploaded when it ends to recordings/<date>/<time>-<suffix>.webm, straight from the browser with a token from /api/recording (client/src/recorder.ts). List them with vercel blob list --prefix recordings/. Off in local dev.
npm start (or npm run api next to npm run dev); the api should print voice: Cartesia. Turn the mic on (setup screen, or the camera button top right; Mic top left at /dev; no camera needed), start a match, point the mouse at your half, hold Space or the mouse button, say the troop ("a fire dragon"), let go. Your words show at the spot as you talk and the troop deploys there. A hint under the text box says the same during a match. Without the api or a Cartesia key, or when Cartesia refuses it (out of credit, say), the browser's recogniser is used instead, which Chrome has and Arc and Brave don't (theirs fails every time). Where that doesn't work either (Arc, Brave, Firefox), a speech model runs on the player's own machine: Moonshine base through transformers.js, in a worker, on the GPU (WebGPU) or else the CPU (client/src/input/localstt.ts). It's a one-time download of about 60 MB that the browser caches (setup's mic step shows the progress), and it hears whole clips rather than a stream, so your words show when you let go of the pinch (or stop talking, without the camera), about 0.2–0.3 s later. When nothing works, setup's mic step, a notice and the hint under the text box say why ("no Cartesia key on the server, and this browser's speech recognition can't reach its service") and point to typing, and the first summon switches to typing. A watchdog catches the quiet failures too: three utterances heard with no words ever coming back counts as no speech./#pavilion).client/src/onboard.ts). Without a camera it teaches saying (or typing) a troop and clicking instead. After that the camera and mic come back on by themselves each visit (the ⋯ menu has Run setup again, first summon and all). Your first three matches with the camera coach you with a line when you look stuck: a hand up but never pinching, talking without pinching, a hand that keeps leaving the frame or sits badly placed (). Left idle, the home screen shows how it works on a loop.npm run bench compares troop-designer backends on the same descriptions: cold start, p50/p90 latency, valid-JSON rate and 12 judgement checks from the prompt's rules (size words, abuse, consistency, element as the default on-hit effect), plus the average answer size and every wish the designer made. It runs every provider that has a key in .env (ANTHROPIC_API_KEY, GEMINI_API_KEY, CEREBRAS_API_KEY, GROQ_API_KEY). With Claude plus another provider, it also reports cost agreement with Claude and what racing the two would give. Options: --n 40, --providers claude,cerebras, --dry (offline designer only), --n 0 (checks only). Set DESIGNER=gemini|cerebras|groq in .env to play with another backend; the default is Claude.
Every round is logged to private SpacetimeDB tables that only the database owner can read: match_log (one row per round, online or vs Bot), generation (one per deploy attempt: transcript, description, design before and after clamping, designer source and timings, when the art arrived, outcome), utterance (every finished speech segment, including words said between deploys), troop_log (what each troop did in the fight) and event (setup, camera and mic, speech errors, mismatch flags). Players flag a troop that isn't what they asked for by saying "that's wrong" or pressing X.
npm run logs prints the last rounds as timelines (each deploy next to what the player said after it) plus a summary: input mix, outcomes and cancel reasons, design wait p50/p90, art on time, mismatch rate, damage per elixir. npm run logs -- --jsonl > attempts.jsonl writes one joined line per attempt for tuning the prompt and the art. npm run logs -- --funnel shows how far first-time players got through setup and the first summon, step by step with the time between steps, where they skipped or were sent back, and how often the coach spoke and the pinch refitted itself. npm run logs -- --wishes lists what the designer wished the lists had (the design's wish, logged on generation), counted by times and distinct players with sample descriptions, and mismatch flags per on_hit, trait and element value. Options: --last 20, --server maincloud --db <name>.
Open DevTools → Console: each pipeline stage logs as [MIC], [STT], [HAND], [DESIGN], [ART], [DB], [DEPLOY], warnings and errors always, step-by-step detail with ?debug in the URL or localStorage.debug = 1; run __diag() for the last 20 drops and the startup health check, and GET /api/health for which api keys are set (booleans) plus a 1-token Anthropic check.
npm test # sim, pricing, bot, deploy and input logic tests
npm run typecheck # client, api and server
client/src/coach.ts/dev; opt-in): aim with the point halfway between your index and thumb tips. Pinch your thumb to any finger to pick a troop up, say it while you hold (with the camera on, only words said during the pinch count), move to aim, and open your hand to place it. Thumbs down cancels a troop still being summoned (refunded), or before that clears the words said so far. On menus, letting go of a pinch clicks. The middle of the camera frame maps to the whole screen, like a touchpad. An arc closes round the cursor as your thumb nears the finger, and fills when the pinch counts. The pinch fits itself to your hand as you play, from how far your thumb comes in on each try (client/src/input/autofit.ts), so a hand the default threshold misses still gets there; the ⋯ menu has Fit pinch to my hand to fit it by hand instead, which autofit then leaves alone. Space and Esc always stand in for the hand.ink-2 (the panel says "listening (Cartesia)"); without a Cartesia key, or if it can't connect, the browser's speech recognition takes over.T (or ?timings in the URL) shows how long each step took; release → stats is the one that must beat the 2.5 s delay.elixir in code), is refused with what it would have cost./#pavilion): every troop anyone has summoned.? reopens the how-to card, M mutes all sound, music included.