Skip to content

Latest commit

 

History

690 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Return to Dark Tower

Ultimate Dark Tower

A TypeScript ecosystem for Restoration Games' Return to Dark Tower — libraries, renderers, and apps for its real, motorized, Bluetooth-enabled tower.

CI license


Restoration Games' Return to Dark Tower ships with a motorized, Bluetooth-enabled tower — three rotating drums, 16 individually addressable LEDs, a 56mm speaker with 113 sound effects, and infrared skull sensors. This repo is a reverse-engineered TypeScript driver for that hardware, plus everything built on top of it: renderers, a scenario creator, a relay for sharing tower state across a network, and companion apps and AI agents that can drive a tower from a chat client.

Getting Started

pnpm install    # installs every workspace + builds native BLE deps and @udtc/engine
pnpm run ci     # validate:nodes → lint → format:check → build → typecheck → test

Requires Node ≥ 22.13 and pnpm ≥ 11 (packageManager pins pnpm 11.9.0) — pnpm 11 loads the built-in node:sqlite, so pnpm install fails outright on Node 20. Published libraries still target a Node ≥ 18 runtime.

No tower required to start — every app with a UI ships a browser-based 3D emulator, so you can explore the whole ecosystem without hardware. See docs/local-development.md for the full list of per-app dev commands and ports, or jump straight to the live demos.

From here:

  • Packages — the libraries, for building your own app on top of the tower.
  • Apps — the runnable companion apps, for playing or driving a tower directly.

Packages

Reusable libraries under packages/. Six are published to npm — a seventh, apps/mcp-server, publishes too, since npx is how an MCP server gets consumed:

Package npm What it is
packages/core ultimatedarktower BLE driver + core library for the physical tower
packages/display ultimatedarktowerdisplay Composable text / 2D / 3D renderers for tower state
packages/board ultimatedarktowerboard 2D game-board renderer, token layout, and Board3D plugin
packages/relay-shared ultimatedarktowerrelay-shared Shared relay protocol types, message factories, constants
packages/relay-core ultimatedarktowerrelay-core Headless relay engine (BLE tower-emulator peripheral + WebSocket)
packages/relay-client ultimatedarktowerrelay-client Framework-agnostic consumer SDK for the relay

Internal (private) Creator libraries: creator-schema (@udtc/schema), creator-engine (@udtc/engine), creator-adapters (@udtc/adapters), creator-card-render (@udtc/card-render), creator-theme (@udtc/theme).

Apps

Runnable leaf apps under apps/. All are private except apps/mcp-server, which publishes to npm. Publishing is a per-package private flag, not a property of the directory.

App Demo / npm What it is
apps/controller /controller/ Drive a real tower over BLE, plus a 3D emulator
apps/creator /creator/ Scenario creator — deck, dungeon & battle builder
apps/player /player/ Scenario player (masked-map play engine)
apps/digital /digital/ Solo digital play
apps/game /game/ The Tower's Challenge — an example web game
apps/seed /seed/ Seed / tower-state decoder
apps/codex /codex/ Game data + art reference — cards, foes, locations, tokens, audio
apps/sync /sync/ Browser client for the relay
apps/mcp-server mcp-server-return-to-dark-tower MCP server — drive the tower from Claude, ChatGPT, or any MCP client
apps/relay-cli Relay daemon (CLI)
apps/relay-electron BLE tower-emulator desktop console

AI Agents

Two AI coding agents for this ecosystem live in .github/agents/ and are documented in docs/agents/README.md:

Agent Platform Use when...
Ultimate Dark Tower VS Code (Copilot custom agent) Writing TypeScript/JS against packages/core (ultimatedarktower)
Return to Dark Tower Claude.ai / ChatGPT / web AI tools Controlling the physical tower via apps/mcp-server

See also the root AGENTS.md for ecosystem context auto-loaded by AGENTS.md-standard tools (Cursor, Aider, Zed, etc.).

Development

Day-to-day commands, once you've followed Getting Started. For the full breakdown of how the workspace is configured — TypeScript config families, the pnpm catalog, lint/test setup, CI/CD architecture, and known gotchas — see CONFIGURATION.md.

pnpm --filter <pkg> build        # build one package/app
pnpm --filter <pkg> test         # test one package/app
pnpm run format                  # prettier --write across the workspace
pnpm run lint                    # eslint across the workspace

ci builds before it typechecks on purpose: cross-package typechecks resolve workspace imports against each dependency's built dist/, so the graph has to exist first.

  • Workspace: pnpm-workspace.yaml — one TypeScript version via catalog:, nodeLinker: hoisted, and allowBuilds for the native BLE / esbuild / electron deps.
  • Tooling: one root eslint.config.js + .prettierrc, both covering the whole workspace. Don't add per-package eslint devDeps — a nested copy shadows the root flat config and crashes lint. Both lint and format:check are ci gates.
  • Docs: per-package docs live in each package; Creator/Relay/Sync guides are under docs/.

Publishing

Published packages use Changesets with independent versioning. Add a changeset with pnpm changeset when you change a published package. Pushing to main opens a "Version Packages" PR; merging it bumps versions and publishes from .github/workflows/release.yml.

What gets published is driven purely by each package's private flag — .changeset/config.json has an empty ignore list, so private: false opts a package in automatically.

Adding a newly published package? Add its name to the NPM_TOKEN secret's package allow-list on npmjs.com before merging its Version Packages PR. The token is a granular token scoped to named packages, and it does not learn about new ones — the publish fails, and Changesets reports the failure as an unrelated TypeError that hides npm's real error.

License

MIT © ChessMess — see LICENSE.

Questions or ideas? The community hangs out on the Ultimate Dark Tower Discord server.

About

A JS monorepo container 10 apps and 3 libraries designed to take the board game Return to Dark Tower to the next level

Topics

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages