Skip to content

Repository files navigation

ChessMap

ChessMap is a remote chess training app built around a human-like adaptive rival. A player can enter Practice with only a profile name, or join a host-created match with a six-character code. Maia-3 runs on the server GPU, the room server validates every move and clock, and a transparent opponent map changes how the AI plays across games. An anonymized combined memory also retrieves similar positions and outcomes from every completed ChessMap game.

What Works

  • Practice mode: enter the same name on every visit; no room code is needed.
  • Selectable challenge: practice targets range from 1700 to 2500 in 100-point steps, with independent 1+0, 3+0, 5+0, and 10+0 clocks.
  • Live match mode: a host watches while a remote human joins by code or QR.
  • Human interaction: tap a piece to see legal moves, tap a destination, or drag.
  • Human-like AI: Maia-3 79M predicts plausible moves at a configured Elo instead of searching for a perfect engine move at every turn. Delivery pacing varies by rating, time control, game phase, candidate ambiguity, and clock pressure.
  • Mistake recovery: active rooms warn before navigation and resume after an accidental refresh through a private browser-held reconnect token.
  • Adaptive rival: profile confidence, estimated Elo, aggression, tactical risk, and clock behavior influence candidate selection and AI time usage.
  • Combined memory: a local position graph and deterministic piece-square vectors aggregate anonymized move/outcome evidence across all completed games.
  • Post-game coach: Maia replays up to eight representative decisions, identifies top-two human choices, suggests alternatives, and references the player's strongest stored prior game.
  • Local-first history: PGN, move times, profile changes, and coaching summaries persist outside Git.

Modes

Practice

  1. Open the app.
  2. Enter a profile name.
  3. Choose a Maia target from 1700 to 2500 and a practice clock.
  4. Select Practice against your AI. The default is 1700 at 5+0.

A profile name is currently an identifier, not a secure account. The same spelling loads the same history. Authentication is intentionally left for the persistent cloud phase.

Hosted Match

  1. The host selects Create match to watch.
  2. The app creates a room code and remote QR.
  3. The human enters a name and room code from another device.
  4. Both sides receive authoritative clock and board updates through Socket.IO.

How The AI Works

flowchart LR
    A[Human move] --> B[chess.js legal validation]
    B --> C[Authoritative room and clock]
    C --> D[Maia-3 79M on PyTorch]
    D --> E[Five human candidate moves and WDL]
    E --> F[Private opponent-map adaptation]
    E --> M[Combined position-memory recall]
    F --> G[Bounded candidate re-ranking]
    M --> G
    G --> J[AI move over Socket.IO]
    J --> H[Finished-game Maia review]
    H --> I[Persistent profile and PGN]
    H --> K[Anonymized graph indexing]
Loading

Maia-3 is a Chessformer model trained to predict human chess decisions across skill levels. ChessMap runs it as one persistent UCI subprocess so the model stays warm on the GPU. For each AI turn it receives move history, AI Elo, and estimated opponent Elo, then returns likely human moves and predicted win/draw/loss outcomes.

The base model weights remain frozen. ChessMap performs online profile adaptation, not unsupported per-game neural fine-tuning:

  • Low-confidence profiles mostly preserve Maia's normal human move distribution.
  • Higher confidence gradually gives predicted outcome more weight while retaining a penalty for moves that are unlikely human choices.
  • AI move timing follows a separate transparent human pacing model; Maia inference latency itself is not presented as thinking time.
  • The estimated player rating is sent to Maia on every AI turn.

Maia4All research describes few-game personal embeddings, but its official prototype-enriched implementation and weights are not publicly released. This repo does not claim to reproduce it.

The current system has a real combined retrieval memory, but not a combined neural model. It stores exact position nodes, move-transition edges, aggregate outcomes, and deterministic 780-dimensional piece-square vectors for cosine similarity. It does not use a vector database, learned embeddings, or Maia weight updates. One frozen Maia model is shared by all rooms, private profiles remain isolated, and collective records contain no player names. See Architecture And Memory Model for current architecture, live sequence, coaching, storage, privacy boundaries, and future learned-memory options.

Opponent Map

The map is updated after completed games:

Signal Current evidence
Aggression Captures, checks, advanced pawns, and castling behavior
Tactical risk Checks, queen activity, and capture frequency
Time pressure Average human think time
Rating Result update against the actual AI Elo for that game
Confidence Saturating function of completed games, capped at 95%

Profiles are keyed by normalized player name in data/opponents.json. Completed games are appended to data/games.jsonl with PGN, move times, result, map snapshot, and coaching summary. A resignation queues the partial PGN and profile write before the server acknowledges it. The entire data/ directory is gitignored.

Combined Memory

data/combined-memory.json is built automatically from existing PGNs on startup and updated after each new game's review. It contains:

  • canonical four-field FEN position nodes;
  • directed move-transition edges and counts;
  • per-move play counts and side-to-move outcome sums;
  • up to three anonymized reference examples per move;
  • SHA-256-derived game IDs for idempotent indexing;
  • deterministic 780-dimensional piece-square/castling/en-passant vectors computed in memory for similar-position cosine retrieval.

During an AI turn, ChessMap queries only positions with the same side to move, keeps the eight most similar nodes above 0.82 similarity, and checks evidence for Maia's top five candidates. Historical evidence contributes at most 0.18 bounded weight; without supported candidates it contributes exactly zero. Memory can re-rank Maia candidates but cannot introduce an illegal or out-of-policy move.

Post-Game Coaching

After the game ends, the room immediately enters an analysis state. Maia replays up to eight evenly sampled human decisions at the player's estimated level:

  • A played move ranked first or second becomes a What worked item.
  • A move outside the top two becomes a Try next time item with Maia's leading human candidate and expected-score context.
  • The review compares the game with the strongest prior reviewed game for the same profile. The first game becomes the baseline.
  • Combined memory reports anonymized support counts and stored-game provenance for similar positions. The current game is indexed only after review, preventing self-reference.

This is Maia-based behavioral coaching, not a Stockfish proof that a move is objectively best. That distinction is deliberate: the product is teaching a human through realistic human candidates.

Human-Play Calibration

Maia-3 supplies skill-aware move choice through its documented SelfElo and OppoElo options with one-node inference. ChessMap adds timing separately from a measured sample of the CC0 Lichess open database. The committed calibration/lichess-human-pacing-centered.json artifact contains only aggregate quantiles and style rates, never usernames or games. It is stratified by:

  • exact 1+0, 3+0, 5+0, and 10+0 controls;
  • nearest-100 rating bands centered on each target from 1700 through 2500;
  • opening, middlegame, and endgame phase;
  • normal, low, critical, and scramble clock pressure.

The artifact records its archive URL, actual sample byte count, byte-range request, SHA-256, parser method, and deterministic reservoir seed. Likely tournament berserk games are excluded when first observed clocks do not match the nominal control. Regenerate it with the pinned dependencies in scripts/requirements-calibration.txt and scripts/calibrate_lichess_pacing.py. Raw compressed samples belong under the gitignored data/research/ directory. If the artifact is missing or invalid, ChessMap safely falls back to tested built-in pacing constants. ChessMap also records both human and AI move times for future local recalibration without changing Maia's frozen weights.

Local Setup

Requirements

  • Windows 10/11
  • Node.js 20 or newer
  • Python 3.10-3.12
  • NVIDIA GPU recommended; CPU inference is supported by Maia but much slower

Install JavaScript dependencies:

npm install

Create a Python environment and install CUDA PyTorch appropriate for the machine, then install the pinned Maia-3 source revision:

conda create -n chessmap python=3.11 -y
conda activate chessmap
pip install torch --index-url https://download.pytorch.org/whl/cu121
pip install git+https://github.com/CSSLab/maia3.git@1e13597
python -m maia3.cache --model maia3-79m

Set MAIA_PYTHON to that environment's interpreter. See .env.example. The app reads environment variables from the launching shell; it does not load the example file automatically.

Run locally:

npm run dev

Share Across The Internet

npm run share

On Windows, the first run downloads the official cloudflared.exe release into the gitignored tools/ directory, builds the production app, creates a temporary HTTPS Quick Tunnel, and starts ChessMap with the public hostname embedded in room QR codes. Keep the terminal and PC running. The random URL changes after every restart and has no uptime guarantee.

For a stable hostname, use a named Cloudflare Tunnel and set PUBLIC_ORIGIN. Deployment tradeoffs and the recommended cloud migration are documented in docs/DEPLOYMENT.md.

Does Shutdown Lose Data?

No. A normal shutdown stops the website and Maia, but data/opponents.json, data/games.jsonl, data/combined-memory.json, and the cached Maia checkpoint remain on disk. The temporary public URL stops working and will change on the next npm run share. Disk failure, manual deletion, or an unsynced machine can still lose local history, so back up the data/ directory or migrate it to a hosted database.

Commands

npm test                         # maps, graph/vector memory, policy, and coaching
npm run lint                     # ESLint
npm run build                    # optimized Next.js build and TypeScript
npm run dev                      # local development server
npm run share                    # build + temporary public tunnel + production server
node scripts/room_smoke.mjs      # host/join/AI integration check
node scripts/practice_smoke.mjs  # no-code practice/AI integration check

Project Structure

src/app/                 Next.js interface and responsive chessboard
server.mjs               Socket.IO rooms, clocks, persistence, review orchestration
lib/maia-engine.mjs      Serialized persistent UCI bridge to Maia-3
lib/opponent-map.mjs     Profile extraction and adaptive candidate policy
lib/combined-memory.mjs  Anonymized position graph and vector retrieval
lib/coach.mjs            Review-position selection and coaching summary
scripts/                 Tunnel setup, public launcher, and smoke tests
tests/                   Deterministic Node test suite
data/                    Local private profiles and games (gitignored)

Privacy And Security

  • Game/profile data remains on the ChessMap host unless a cloud database is added.
  • Combined memory omits names/profile keys and stores hashed game IDs, dates, openings, results, positions, moves, and outcomes. PGNs still remain private in games.jsonl.
  • Room codes are convenience identifiers, not authentication or authorization.
  • Profile names are not accounts; do not use sensitive personal information.
  • Quick Tunnels are intended for development and personal testing, not production.
  • Model checkpoints, local data, Python environments, and tunnel binaries are not committed to Git.

Upstream Technology

Architecture Documentation

Review upstream licenses before distributing a hosted derivative. This repository does not currently declare its own license.

About

Human-like adaptive chess rival with practice mode, Maia-3 coaching, and persistent opponent maps

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages