Hi everyone,
I ported Stockfish to an ICP canister, and you can play against it here:
Play: https://ne5l7-xiaaa-aaaaj-qsm3q-cai.icp0.io
Code (GPL-3, like Stockfish): https://github.com/kanodia/play-the-chain
Example game, replayed from the canister: https://ne5l7-xiaaa-aaaaj-qsm3q-cai.icp0.io/game/3
Canister on the IC dashboard: https://dashboard.internetcomputer.org/canister/ne5l7-xiaaa-aaaaj-qsm3q-cai
On X: https://x.com/abhi_kanodia803/status/2114213543235235884
What is Stockfish?
It’s the strongest open-source chess engine in the world, and has been the top computer chess engine for years. Grandmasters use it to analyse their games. It’s over 12,000 lines of heavily optimised C++, the kind of code you’d normally never expect to run inside a smart contract.
What runs on-chain
There’s no server and no frontend hosting. One canister does everything:
- serves the web page,
- referees the game (checks your move is legal, detects checkmate, stalemate, threefold repetition and the 50-move rule),
- thinks of its reply: a full Stockfish search, computed by all 13 nodes of the subnet and agreed on by consensus,
- writes every move to stable memory, so each game gets a permanent link anyone can replay (
/game/<id>), plus a raw JSON record (/api/game/<id>).
For each engine move the page shows a receipt: how many positions it searched, how many instructions that took, and roughly what it cost in cycles. The canister pays (reverse gas), so players don’t need a wallet.
How
- Stockfish 11 (the last version before neural nets), compiled to wasm with icpp-pro. Wasm is about 2.65 MB.
- The IC has no threads, so a small
SF_NO_THREADSpatch makes the search run synchronously inside a single update call. Apart from that the engine code is unchanged, and node counts match a native build exactly. - Cost is about 8–9.5k instructions per searched position. A depth-18 move takes around 12B instructions, which fits comfortably inside the 40B per-message limit, so each move is one update call. There’s no need for chunking or timers.
- All HTTP routes go through
http_request_update, so the responses are certified. - There’s a daily budget: moves are full strength up to a daily allowance, then lighter searches, then the canister politely says “come back tomorrow”. It’s funded by a small cycles balance, so please be gentle

Thanks
Big thanks to the @icpp and onicai. Porting a large real-world C++ codebase was much smoother than I expected, and I think it’s a great showcase of what C++ canisters can do.
Feedback welcome, and so is a game. Can anyone beat it?