CoOp:Anything
게임을 검색해 협동 플레이 가능한 모드·단계·품질·커뮤니티 평점을 확인합니다
TypeScript 디지털 카탄, 규칙 엔진·봇·3D 보드·LAN 멀티플레이어, 브라우저에서 플레이
Digital Catan in TypeScript: deterministic rules engine, bots with difficulty levels, procedural 3D board and LAN multiplayer with an authoritative server. Playable in the browser.
게임GitHub @Juanjhenao온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A complete implementation of the Catan board game in TypeScript, with a procedurally drawn 3D board, bots at three difficulty levels and local-network multiplayer with an authoritative server.
No install needed: play against bots or hot-seat on the same device. Local-network multiplayer needs the server from this repo (npm run lan).
| Layer | Technology |
|---|---|
| Language | TypeScript 5 (strict), ES2022 |
| Build & dev server | Vite 5 |
| Rendering | Canvas 2D with a custom 3D projection, SVG |
| Audio | Web Audio API (oscillators and filtered noise) |
| Networking | WebSocket (ws) on the same HTTP port that serves the game |
| Testing | Vitest, jsdom, node-canvas, fuzzing with tsx |
| Deployment | GitHub Actions → GitHub Pages (tests gate every deploy) |
src/engine/ never touches the DOM, never calls Math.random and never reads the clock. Its interface is a reducer:
const state = createGame(players, { seed }); // deterministic match
const moves = getLegalActions(state, playerId); // everything they can do
const result = applyAction(state, moves[0]); // (state, action) -> state
Randomness lives inside the state (a seeded mulberry32 generator), so a whole match can be rebuilt from the seed plus the action list. That shape made bots and networking almost free: a bot is just a function that picks among legal actions, and the server re-validates every move with the same validate() the client uses — no duplicated logic. → src/engine/
Clients only propose moves. Before sending state to each player, the server strips what that player isn't allowed to see: other players' hands, other players' development cards, the deck order, and the RNG state, which would let anyone compute every future dice roll. Redacted fields are left empty rather than faked, and public counts travel separately. A test guards against any new secret field leaking. → src/net/redact.ts, server/room.ts
Instead of computing corners as floats and deciding with an epsilon whether two of them match, the board uses a doubled integer grid (X = 2q + r, Y = 3r): neighboring hexes produce literally the same pair for a shared corner, so vertex identity is plain integer equality. Harbors aren't hand-placed: the code walks the island's perimeter along single-hex edges and spaces them evenly, and the same code serves both board sizes. → src/engine/hex.ts, src/engine/board.ts
243 tests across 12 files. The most valuable ones aren't unit tests:
Requires Node.js 18+.
npm install
npm run dev # local match at http://localhost:5173
npm run lan # build and start the server for local-network play
npm test # 243 tests
npm run fuzz 500 # 500 bot matches checking invariants
npm run build # production build in dist/
Network scope: designed for a trusted network. Traffic is unencrypted and the only access control is the room code; don't expose it to the internet as-is.
src/
engine/ rules engine: pure TypeScript, no DOM, no external randomness
ai/ bot contract, random and heuristic bots, self-play loop
net/ protocol, state redaction and WebSocket client with reconnection
ui/ 3D scene, procedural art, sound and match controller
server/ HTTP + WebSocket on one port; rooms and the authoritative match
tools/ headless board-to-PNG rendering, fuzzer and bot tournaments
tests/ rules, board, bots, UI and networking
The full design document, covering every rules and UI decision, is in docs/DISENO.md.
Non-commercial personal project. Not affiliated with or endorsed by Catan GmbH; "Catan" is a trademark of its respective owners.