A TypeScript engine and autonomous player for the card game 6 Nimmt! — built to play live on Board Game Arena and benchmark AI strategies against real humans.
6 Nimmt! is a deceptively simple card game: 104 cards, 4 rows on the table, everyone plays simultaneously. Your card goes to the nearest row tail lower than it — but if you land in the 6th slot, you take the whole row as penalty points. The lowest score wins.
The rules are fully deterministic. The interesting problem is predicting where opponents will play and avoiding the chaos.
This repo is a research project exploring that problem:
- 🎮 Play autonomously on BGA using Monte Carlo simulation with prior-based heuristics
- 📊 Benchmark strategies — random, Bayesian, MCS, MCS-Prior — against each other
- 📁 Collect game data in streaming JSONL for post-game analysis
- 🔬 Iterate fast — simulate 1000 games in seconds without touching a browser
npm install
# Simulate 1000 games: MCS-Prior vs 4 random players
npx tsx src/cli/index.ts simulate --strategies mcs-prior,random,random,random,random --games 1000
# Play live on BGA — log in and join a table in Chrome/Edge first, then:
npm run play -- --strategy mcs-prior --verbosesrc/
├── engine/ Pure TypeScript game engine — rules, state, strategies
├── cli/ Simulate and benchmark strategies offline
├── sim/ Game runner for batch simulations
├── player/ Headless Playwright player for live BGA games
└── mcp/ MCP server for Copilot agent integration
The game loop is 100% deterministic — no LLM in the play path. The engine calls a strategy directly in-process. The Playwright player polls BGA's DOM every 500ms, reads card values from CSS sprites, and clicks via el.click() (Playwright's visibility checks don't work on BGA's animated elements).
| Strategy | Description |
|---|---|
random |
Uniform random — the baseline |
dummy-min |
Always plays the lowest card in hand |
dummy-max |
Always plays the highest card in hand |
bayesian-simple |
Expected-penalty minimisation over unseen card distribution |
mcs |
Monte Carlo Simulation — simulates random game completions |
mcs-prior |
Strongest — MCS + prior-based heuristic + opponent modeling (~29% win rate vs mcs's ~24%) |
# Tune MCS-Prior options
npm run play -- --strategy mcs-prior:mcPerCard=200,timingWeight=0.3,trappedDiscount=0.3Results from a 1000-game competition tournament (3–6 players per game, random draws from pool). ELO: standard chess (initial=1500, K=32, D=400, normalized by N−1).
| Rank | Strategy | ELO | Win Rate | Avg Score |
|---|---|---|---|---|
| 🥇 | mcs:mcPerCard=100 |
1597 | 38.5% | 33.3 |
| 🥈 | mcs:mcPerCard=50 |
1558 | 36.1% | 36.6 |
| 🥉 | mcs-prior:mcPerCard=100 |
1500 | 34.3% | 37.5 |
| 4 | bayesian-simple |
1431 | 25.0% | 43.1 |
| 5 | dummy-max |
1367 | 16.0% | 48.2 |
| 6 | random |
1198 | 5.3% | 61.8 |
| 7 | dummy-min |
1083 | 3.2% | 66.0 |
| Doc | Description |
|---|---|
| Getting Started | Install, CLI, first live game |
| Strategies | All strategies, options, benchmarking |
| Headless Player | Live BGA player in depth |
| Simulator | Batch simulation and benchmarking |
| Data Capture | JSONL game log format |
| Game Rules | 6 Nimmt! rules reference |
| Contributing | Setup, adding strategies, code style |
npm test # Vitest test suite
npm run lint # ESLint
npm run build # tscMIT