Dark Chess

Chess where you only see what your pieces have traveled.

Dark Chess is multiplayer web chess with a fog-of-war board: you always see your own army, but you only discover the rest of the board along paths your pieces have actually moved. Standard chess rules apply; the server is authoritative for legality and game state.

Credits

Charlie Bishop conceived Dark Chess—the original inspiration and the rules as played here. This site’s implementation was built in collaboration with Charlie; the software author refined the design, wrote the implementation prompts, and stayed in consultation with him throughout development.

How visibility works

The server keeps the true position. For each player it sends a masked view. Opponent moves do not reveal the board for you; enemy pieces appear only on squares you can see (including when they capture your piece).

  1. Your pieces — Every square occupied by your own army is always visible.
  2. Your traveled squares — Only squares on your moves’ paths (cumulative) become visible. Path rules per move:
    • Pawns — each step (including the middle square of a two-step advance).
    • Knights — you choose which valid L-shaped route the knight uses; every square on that L (including jumped intermediates) becomes visible.
    • Sliding pieces — every square along the ray from start to end, inclusive.
    • Kings — start and end; castling includes the full king and rook paths.
    • En passant — the captured pawn’s square is on your path when you take en passant.
  3. Captures against you — If the opponent captures your piece, the capture square is revealed so you can see what’s there afterward.
  4. Visible squares — If a square is empty, you see empty; if any piece is there, you see that piece (including an enemy only when that square is visible to you).
  5. Probes (wasted turns) — If you try to push a pawn into a blocked square, or make a diagonal “capture” onto an empty square (that isn’t en passant), you lose the turn without moving, but that destination square stays explored for you for the rest of the game.
  6. Sliders — If you aim a rook, bishop, or queen at a distant square and an enemy blocks the path, your move captures that first piece and stops there.
  7. Illegal move into check — Destinations that would leave your king in check still appear as normal highlights (you cannot infer a hidden pin from missing dots). If you attempt such a move, it fails without passing the turn or changing the clocks; fog does not clear; squares that would attack your king in that hypothetical position flash red.

Every square keeps a light cell border so the mesh stays visible in fog. After you select a piece, the server sends legal targets; the server validates every attempt.

Features

Lobby & vs computer

Pick a username, see who’s online, challenge players, or play a bot that uses the same fog rules.

Time controls

Fischer-style clocks (e.g. 10+0, 3+2): your time ticks on your turn; each completed move adds increment; flag loses.

Material & review

See captured-piece tallies during play. After the game, fog lifts—replay the full position history with a slider.

Full chess rules

Check, mate, stalemate, castling, en passant, promotion, draws—including resignation when you need to concede.

Architecture

The server keeps the authoritative chess state in memory; clients receive masked squares per player. Move validation uses chess.js on the server for every attempt.

ExpressServes static HTML/CSS/JS from public/.
Socket.IOLobby presence, challenges, game rooms, clocks, and move events.
server/dark.jsBuilds per-player visibility sets and masked payloads from full position + move history.
DeploySingle Node process (state in memory). For production behind nginx, proxy /darkchess/ and websocket path /darkchess/socket.io/.

Repository layout

darkchess/
├── server/
│   ├── index.js    # HTTP + Socket.IO
│   └── dark.js     # Fog / masking
├── public/
│   ├── index.html
│   ├── app.js
│   └── style.css
└── package.json

Run locally

git clone https://github.com/151henry151/darkchess.git
cd darkchess
npm install
npm start
# http://localhost:3333 — set PORT=… to change