Fog-of-war chess with accounts, invites, random matchmaking, and a Datastar-powered web UI.
- Rust 1.85+
- SQLite
cargo run -p btch-serverServer listens on http://0.0.0.0:3100 by default.
Environment variables:
PORT— default3100DATABASE_URL— defaultsqlite:./battlechess.db?mode=rwc
docker compose up --build -dOpen http://localhost:3100. The SQLite database is stored in the named volume btch-data at /data/battlechess.db inside the container (survives restarts and image rebuilds).
# Logs
docker compose logs -f battlechess
# Stop
docker compose down
# Stop and remove the database volume (destructive)
docker compose down -vOverride the host port: PORT=8080 docker compose up --build -d (maps host 8080 → container 3100).
cargo test -p btch-core
cargo build -p btch-servercrates/btch-core— chess engine with fog visibility, awareness-gated check/en passant, dual-aware checkmate, player-chosen promotioncrates/btch-server— Axum HTTP server, SQLite persistence, session auth, SSR templates, Datastar SSE live updates
- Lobby —
data-on:load="@get('/lobby/events')"patches#invites,#games-list,#queue-msgwhen invites, games, or queue status change - Game —
data-on:load="@get('/games/{uuid}/events')"patches#game-status,#board,#move-areawhen the opponent moves or game ends - Moves — forms use
data-on:submit="@post(..., {contentType: 'form'})"so move fields are sent as form data; SSE patches update the board without a full reload - Live game view —
static/game-sse.jsopens/games/{uuid}/events(SSE) and applies board patches; moves submit via fetch and patch the DOM for both players
- New accounts start at 1500 ELO
- After each finished game with two human players, ratings update using standard Elo (K=32): win = 1, loss = 0
- The game-over overlay shows your change (e.g.
+16 ELO · rating now 1516); the lobby shows your current rating - Leaderboard —
/leaderboardlists players by ELO (top 100)
- Archive —
/archivelists all finished games (newest first, 20 per page). Any logged-in user can open a replay. - Replay —
/games/{uuid}/replaysteps through stored positions with First/Prev/Next/Last and arrow keys. - Fog modes — no fog, white POV, black POV, or active player at the current ply (overlay only; all pieces are shown).
- Access — players can replay in-progress games; spectators can replay finished games only.
- Entry: archive list, game-over Watch replay, or
/games/{uuid}/replay(starts at move 0; use transport controls or?step=lastfor the final position).
├── crates/btch-core/ # Chess engine
├── crates/btch-server/ # HTTP server + templates
├── migrations/ # SQLite schema
├── static/ # CSS and client scripts
├── Dockerfile # Container image
├── docker-compose.yml # Run with persistent DB volume
└── legacy/ # Original Python, Vue, and Cocos2d-x code (not used)
Older stacks live under legacy/ only; do not run them for the current game.
- Each player sees their pieces and adjacent squares (Moore neighborhood).
- Check restrictions apply only when the player is aware of the threat.
- En passant requires visibility of the capturing pawn, target square, and passed pawn.
- Checkmate ends the game when both players are aware; king capture always ends the game.
- Pawn promotion: choose queen, rook, bishop, or knight.