Games2026
500ç Card Game
Rummy-style card game with a heuristic AI and real-time online play.
A passion project: a fully rule-enforcing digital version of the rummy-style card game 500ç for two players: against a heuristic AI (Easy / Normal / Hard), pass-and-play on one device, or online with a 6-character invite code. It's a pnpm monorepo with a React 19 + Vite web app and an Expo mobile app, both built on one pure TypeScript rules engine.
The interesting part is that the same reduce(state, action) drives the UI, the
AI, the tests and an authoritative WebSocket server, so illegal moves can't be
made or forged, and each player only ever receives a redacted view of the game.
Architecture
- Engine:
@500c/core, a pure, isomorphic TypeScript package: one Immer-wrappedreduce(state, action)for dealing, the turn machine, round scoring and target escalation (500 → 750 → 1000), set/run validation with wild-2 placement, and a seedable mulberry32 RNG for deterministic tests. - AI: a heuristic opponent on three difficulty levels that opens with its first 25-point meld, searches for an exact-cover go-out, discards the least useful card and, on Hard, takes from the ground and avoids feeding the opponent; every move it makes goes through the engine.
- Server: Node +
wswith Zod-validated messages, in-memory rooms with unambiguous 6-character codes, token-based reconnection, an out-of-band chat relay, an origin allowlist and per-seatredactForsnapshots that never send the opponent's hand or the deck. - Clients: a React 19 + Vite + Tailwind web app and an Expo / React Native app sharing
@500c/client: a Zustand store with local and online transports, EN/SQ i18n and an interactive tutorial. - Infra: a single Docker image where one Node process serves the built web app and the WebSocket on one port, behind Nginx Proxy Manager with a
/healthcheck.
Tech stack
TypeScriptImmernanoidVitestReact 19ViteTailwind CSSFramer MotionZustandExpo SDK 56React Native 0.85Expo RouterReanimated 4Node.jswsZodtsupDocker