- JavaScript 92.7%
- CSS 5.5%
- HTML 1.7%
| .github/workflows | ||
| client | ||
| docs | ||
| locales/stones-of-the-sea | ||
| server | ||
| .dockerignore | ||
| .editorconfig | ||
| .env.example | ||
| .git-blame-ignore-revs | ||
| .gitignore | ||
| .nvmrc | ||
| CLAUDE.md | ||
| Dockerfile | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
Gamagie
One self-hosted multiplayer lobby for Landlord's Game, Stones of the Sea, and other turn-based games.
Gamagie keeps accounts, open tables, spectators, chat, persistence, and computer-player orchestration in one shared framework. Each game contributes only its server logic, configuration, help, and client renderer. Landlord's Game remains the default table and adds its versioned rule laboratory inside that boundary.
This repository is based on LAN Games and preserves its MIT-licensed history.
Unit and integration suites · one self-hosted Node.js server
The waiting room repeats the exact versioned selection that was persisted when the table was created.
Start a table
Prerequisites: Node.js 24 LTS or newer and the native build tools required by better-sqlite3 and bcrypt.
git clone <repository-url> gamagie
cd gamagie
npm ci --prefix server
node -e "console.log('JWT_SECRET=' + require('crypto').randomBytes(48).toString('hex'))" > .env
npm start
Open http://localhost:3000. Before inviting LAN players, verify the host is connected to the intended trusted LAN or VPN; do not expose the server directly to the public internet.
The first table takes four steps:
- Each player registers a local username and password, or signs back in.
- The host names the table, chooses a preset, and optionally changes compatible switches. The explanation card updates immediately.
- Other players open
http://<host-ip>:3000and join from the lobby. NPC-ready games can fill seats with Chaos NPC or—when configured—the external n8n Director. Landlord tables additionally offer Prudent Steward; Stones tables offer Steady Navigator. - Everyone reviews the persisted explanation card in the waiting room; the host starts the game.
Windows, reset, and connection details are covered in Installation details.
The rule laboratory
There is one selectable extension—Monopolomics Laboratory v1—with a complete option matrix. Sets are convenience presets over that matrix, not separate engines or rule forks.
| Switch | What it changes |
|---|---|
| Kitchen table | Disables compulsory auctions, routes eligible payments to a pot, and permits one issue-backed rescue per player. |
| Prosperity | Collects site rent publicly, permits public infrastructure acquisition, and replaces last-player-standing with a shared cash target. |
| Issuer's ledger | Journals Bank-boundary flows and reconciles the table each full round. |
| Issuer rescue exercise | Enables the documented rescue loan/grant exercise. This switch requires the Issuer's ledger. |
| Missing column | Adds finite construction capacity plus verified retrofit, reversal, and repair claims. |
Bundled presets are Set 1 (rules as written), Set 2 (Kitchen table), Set 3 (Prosperity), Set 4 (Issuer's ledger), Set 5 (Missing column), Sets 3 + 4, and Sets 5 + 4. Presets remain editable before the table is created.
The Games
Every game supports save/resume, in-game chat, and spectator mode. Games with hidden information (Battleship, Risk, Life) enforce privacy server-side — each player sees only what they're allowed to.
Table of Contents
Start a table · Rule laboratory · The Games · Features · Installation details
In this README: Project Structure · Architecture · Security Notes · Development · Documentation · Roadmap
Standalone docs: How to Play · Configuration · Adding a New Game · API Reference · Socket.io Events
Features
Framework
- Multi-game — add any turn-based game by implementing one interface file; no framework changes required
- Real-time multiplayer — all clients sync instantly via Socket.io WebSockets
- Player accounts — register/login with username + password; JWT persisted in
localStorage - Lobby — create, browse, and join open games; game-type badge shown on every card
- Save & Resume — pause any in-progress game and continue it later from the lobby
- Auto-reconnect — disconnected players are marked AFK; their turn is auto-skipped after 30 s
- In-game chat — room-scoped, real-time, 300-character cap
- Spectator mode — anyone logged in can watch any game in progress (👁 Spectate button on every in-progress lobby card). Spectators see the full unfiltered state (including hidden information for games like Battleship, Risk, and Life), chat with players, and watch the action log; they cannot take actions. Players are notified when spectators join. See the "Spectator mode" section below.
- Configurable — content and tuning live in JSON; Landlord policy is a discoverable, versioned server-side extension
- Shared NPC controller — allowlisted, conformance-tested games offer local and authenticated n8n play without trusting a controller to invent moves; strategies see the same player-filtered state as a human seat
Landlord's Game
- One bundled Monopolomics Laboratory extension contains the whole rules experiment; Sets 1–5 and the documented combinations are presets, not separate engines
- Composable switches cover Kitchen Table, Prosperity, the Issuer's Ledger, issuer rescue, and the Missing Column; declared requirements such as issuer rescue → Issuer's Ledger are validated before play
- Live explanation cards show the selected preset, every switch, and the exact table settings in the create flow and waiting room
- Each open seat can be filled independently with a host-selected computer strategy. Faker gives every NPC a persisted fictional, locale-aware name plus randomly selected country and sex metadata; these cosmetics never affect play. Prudent Steward preserves liquidity, values income and complete groups, liquidates conservatively, and follows cooperative rule objectives; Chaos NPC samples the same server-approved action catalog randomly; the optional authenticated n8n Director lets a private workflow select only from pseudonymized, server-approved candidates and falls back locally on failure
- Exact extension version, preset, and complete validated option matrix are pinned per table, so saved games cannot change meaning after deployment
- Full property engine: dice, property buying, auctions, rent, color groups, even building, mortgages, cards, trades, and bankruptcy
- Canonical accounts, transaction journal, settlement phase, institutional ownership, full-round lifecycle, and extension-requested random facts keep composed rules auditable
- Visual CSS Grid board with color bands, player tokens, house/hotel indicators, and ownership dots
Connect Four
- Standard 7 × 6 board; drop pieces by clicking column buttons
- Win detection: horizontal, vertical, and both diagonals
- Draw detection when the board is full
Risk
- Classic 42-territory world map across 6 continents; 2–6 players
- Three-phase turns: reinforce → attack → fortify
- Auto-distributed initial setup; armies and territories dealt evenly to all players
- Dice combat: attacker rolls up to 3, defender auto-rolls up to 2; ties go to defender
- Continent bonuses (NA 5, SA 2, EU 5, AF 3, AS 7, AU 2) applied at the start of every reinforce phase
- 44-card deck (42 territory + 2 wild); valid sets (3 of a kind, 3 different, or any 2 + wild) traded for escalating bonus armies (4, 6, 8, 10, 12, 15, then +5 each)
- Player elimination transfers all cards to the conqueror; last player standing wins by world domination
- First game with hidden information — each player's hand is private, enforced server-side by the game's
getStateForPlayerfilter
Tic-Tac-Toe
- Classic 3 × 3 board; 2 players take turns marking cells with
✕and◯ - Win detection: rows, columns, both diagonals
- Draw detection when the board fills
- Supports shared local and n8n-directed NPC seats
Stones of the Sea
- Cooperative-competitive island stewardship across six changing seasons
- Shared reef, forest, and trust tracks; specialist lineages; voyages; gatherings; and community construction
- Public rai expeditions separate material stones, witnessed loss, provenance, and recognized title
- Supports shared local and n8n-directed NPC seats
- Steady Navigator protects food, gathering cadence, shared tracks, hosting, and rai-expedition progress instead of merely sampling legal moves
Other NPC-ready games
Yahtzee, Checkers, and The Game of Life use the reconciled descriptor adapter to materialize complete legal moves for Chaos NPC and the n8n Director. Risk, Battleship, and Connect Four remain fail-closed until their complete NPC-driving surfaces pass the same full-game conformance gate.
Yahtzee
- Standard 5-dice, 13-category, three-rolls-per-turn rules; 1–8 players (solo play supported)
- Up to 3 rolls per turn with arbitrary holds between rolls
- All 13 categories (six upper + three-/four-of-a-kind, full house, two straights, Yahtzee, chance)
- Upper-section bonus (+35 when subtotal ≥ 63); ties produce a shared-winner array
- Two-click commit on category selection prevents accidental score-locking
- First non-board game — UI is a shared score sheet (players as columns, categories as rows) plus a dice tray, all inside the renderer-owned board area
Battleship
- Classic 2-player, 10×10 grid; five ships per side (Carrier 5, Battleship 4, Cruiser 3, Submarine 3, Destroyer 2)
- Drag-and-drop ship placement with R-key rotation during drag
- Two-grid firing layout — your fleet on the left, opponent's waters on the right; fixed positions across turns with active/inactive treatment that flips
- Both fleets revealed at game over (winner and loser see the layout that beat them)
- First game with a simultaneous private setup phase — both players place ships in parallel; the phase transitions to firing on a barrier (both Ready) rather than via a turn. Modelled as
status='playing'+turnState.phase='setup'withcurrentPlayerIndex=null - First game with fully hidden state per player — opponents' ship positions are stripped by
getStateForPlayeron every emit, not masked
Checkers
- Classic American Checkers on an 8×8 board; 12 pieces per side, 2 players
- Diagonal movement with mandatory captures and multi-jump chain captures
- King coronation on reaching the back row (kings move forward and backward, one square at a time — not "flying" kings)
- Stalemate-as-loss: player with no legal move loses
- Click-driven move selection consuming server-supplied action descriptors — the renderer highlights only legal pieces and destinations
- Animated piece movement, capture fading, chain-capture sequencing, and king coronation visual
The Game of Life
- 64-square branching board with a start fork (Career vs College), main track, and two-path retirement choice (Countryside Acres vs Millionaire Estates)
- 1–10 spinner (no dice) — CSS-animated wheel that decelerates and settles on the result
- College path costs $40,000 in loans but unlocks degree-required careers; career path skips the loan but is locked out of degree careers
- Marriage adds a spouse peg and collects $5,000 from each other player as wedding gifts
- Children mechanic — single births (+$5k/player) and twins (+$10k/player); each child counts toward final scoring at $50k each
- Insurance — auto and life, optional out-of-band purchases that nullify the matching accident squares
- Stocks — pick a number 1–10; collect $10,000 whenever any player's spinner matches it (cross-turn payouts)
- House purchase — pick from 2–3 offered house cards (cost vs scoring value); contributes to final score
- Retirement is the strategic crux: Countryside Acres draws life tiles from a shrinking deck; Millionaire Estates is a cash gamble that resolves at game over
- First game with a branching, non-grid board — squares are graph nodes with explicit
next[]adjacency; the renderer places squares at hand-tuned grid coordinates with arrows showing direction - First game with deferred-resolution game over — ME retirees' win/loss is undetermined until the last player retires; documented in docs/renderer-contract.md
- First game with a "retired-but-still-in-game" pattern — retired players stay in
state.playersand turn rotation skips past them; the game ends when every player is retired - Life tiles are hidden information per player (count visible to opponents, values masked until game over); revealed with a per-tile flip animation during the final score reveal
Installation details
Prerequisites
- Node.js 24+ (Node 24 LTS recommended)
- C++ build toolchain —
better-sqlite3andbcryptare native modules compiled duringnpm install. If the build fails, install the toolchain for your OS:- Windows:
npm install -g windows-build-toolsor install the "Desktop development with C++" workload from Visual Studio Build Tools - macOS:
xcode-select --install - Linux (Debian/Ubuntu):
sudo apt install build-essential python3
- Windows:
- No external database — SQLite is embedded via
better-sqlite3
Install and run
npm ci --prefix server
node -e "console.log('JWT_SECRET=' + require('crypto').randomBytes(48).toString('hex'))" > .env
npm start
The server binds to 0.0.0.0:3000 by default — reachable on your entire LAN.
The root scripts use POSIX shell syntax. On Windows, run them from Git Bash or WSL, or set JWT_SECRET in the current shell and run npm --prefix server start directly.
Connect
| Who | URL |
|---|---|
| Host machine | http://localhost:3000 |
| LAN players | http://<host-ip>:3000 |
Find <host-ip> with ip addr (Linux), ipconfig getifaddr en0 (macOS), or ipconfig (Windows).
Spectator mode
Anyone logged in can watch any in-progress game without playing.
- In the lobby, every game in
playingstatus has a 👁 Spectate button next to the Join/Rejoin button. - A spectator sees the full unfiltered state — including hidden information like Battleship ship positions, Risk card hands, and Life tiles. (The point is to enjoy watching strategy unfold; spectators are watching, not playing.)
- Spectators can chat in the same room as players; their messages are prefixed with 👁 so players know which lines come from the gallery.
- Spectators see the action log, the player roster, and any in-progress modals.
- The action panel is hidden; the "You're spectating" banner persists at the top of the play area.
- Players are notified when a spectator joins (log entry). Leaves are silent.
- A spectator can leave any time via the ✕ Leave button (replacing the host's Save/Quit). Leaving has no effect on the game.
Spectators cannot take actions. The server enforces this (any game:action from a spectator is rejected with a game:error); the client gates click handlers as a UX layer so spectator clicks don't appear to do anything.
A user who is already a player in a game cannot also spectate it — the Spectate button is suppressed in that case, and the server rejects an explicit attempt with "You are already a player in this game".
Project Structure
The repository has three top-level directories: server/ (Node.js backend with game-logic modules under server/games/ and framework under server/src/), client/ (single-page application with per-game renderers under client/js/games/), and docs/ (design notes and reference documentation).
See docs/project-structure.md for the full annotated directory tree.
Architecture
The platform is a single Node.js server (Express + Socket.io) backed by embedded SQLite. Game logic lives in pure-function modules behind a small interface; the framework handles persistence, real-time sync, authentication, and the lobby. Each client renders its game type through a registry-dispatched renderer.
Landlord's Game adds a second boundary inside its property engine: a trusted, versioned extension owns switchable economic policy, while the engine owns shared board mechanics. Named sets are complete presets over one option matrix. The browser builds controls and explanation cards from server metadata and executes no extension code.
See docs/architecture.md for the component diagram, data-flow walkthrough, database schema, and common GameState shape.
Security Notes
LAN Games is designed for trusted local networks. Authentication uses JWT tokens (the server refuses to start without a JWT_SECRET) and bcrypt-hashed passwords. Every game action is validated server-side, and every state-bearing emission routes through getStateForPlayer to protect hidden information. A full state-emission audit documents the boundary.
The platform is offline by design — once installed, the server and client need zero internet connectivity. All assets are served locally, there are no CDN dependencies, no telemetry, and no outbound HTTP calls.
See docs/security.md for the complete security notes including JWT configuration, LAN binding warnings, and the offline-by-design inventory.
Development
Scripts
npm start # run the server
npm run dev # run with nodemon (auto-restart)
npm test # unit tests (778 across 20 suites)
npm run test:integration # integration tests (45 across 6 suites)
npm run lint # ESLint
npm run format:check # Prettier (verify)
npm run format:write # Prettier (auto-fix)
npm run reset-db # drop all tables and recreate schema
npm run reset-db:hard # delete the .db file entirely
npm run screenshot:rules # regenerate the rule-card and board screenshots
npm run screenshots # regenerate the complete game gallery
See docs/development.md for environment variables, port configuration, test details, hot-reloading, and the new-game checklist.
Documentation
Guides
- How to Play — rules and controls for the original eight games; Stones of the Sea also ships contextual help in its game module
- Adding a New Game — interface contract, state versioning, renderer registration
- Development — environment variables, scripts, testing, hot-reload, new-game checklist
Reference
- Configuration — every tunable setting, board layout, and card deck
- API Reference — REST endpoints for auth and game management
- Socket.io Events — real-time event protocol for gameplay
- Architecture — component diagram, data flow, database schema, GameState shape
- Project Structure — annotated repository layout
- Security Notes — security model, JWT, LAN binding, offline-by-design
- n8n NPC Director — optional private workflow orchestration, setup, and decision contract
Design Documents
- Action Descriptors — optional rich-action interface (5 of 8 games)
- Renderer Contract — client-side renderer interface design memo
- State-Emission Audit — security audit of every state-bearing emit
- Screenshot Generation — how the README rule, board, and gallery images are produced
Roadmap
- More games — Chess, Scrabble, Catan, Coup, Liar's Dice, …
- Action descriptor contract — implemented across six of the nine games (Battleship, Checkers, Risk, Yahtzee, The Game of Life, and Stones of the Sea). Connect Four and Tic-Tac-Toe deliberately keep their trivial action surfaces (
dropPiece,markCell) ongetValidActions. Seedocs/action-descriptors.mdfor the contract. - Turn timer UI — server emits absolute-deadline warnings via
game:turn_warning; the client-side countdown bar is implemented inclient/js/turn-warning.js. Spectator mode— shipped; see the Spectator mode section above- NPC tournament and rollout tools — benchmark Prudent Steward across rule matrices and add bounded Monte Carlo evaluation without moving authority out of the server
- Custom board themes — CSS variable overrides per game type
- Mobile optimisation — touch-friendly controls for handheld players
- HTTPS / mDNS — easier LAN discovery and secure transport without manual IP lookup








