This week's post is a playable chess engine that runs in modern browsers that have support for websockets. The engine is my fork of the chess-at-nite engine which is written in C++. The engine is compiled with clang to LLVM byte code and then to asmjs with Emscripten. The engine runs in a web worker and the UI is built with a minimal amount of Javascript that makes use of the excellent chess.js and chessboard.js libraries.

Game is Drawn

New Game

Black Pieces
White Pieces
Position

To get started I compiled Emscripten, and the Emscripten forks of LLVM and clang as Enscripten currently prefers to use the "fastcomp" LLVM backend which is not the version I had previously installed with brew. After configuring my Emscripten to use the new clang I could run emcc which is pretty much a drop-in replacement for gcc.

I found the chess-at-nite randomly by googling for chess engine source code. I would have liked to have used the GNU Chess engine, but I have looked at the source previously and did not think it was a great codebase to adapt. Fortunately the chess-at-nite source compiles with gcc and looked like a pretty nice codebase to hack on.

When I initially tried to compile the code with Enscripten I got a heap of 'error: reference to 'move' is ambiguous' errors. Unfortunately many of the source files use 'using namespace std;' and apparently the Emscripten std namespace defines move. After updating all the usages to only include the referenced parts of the std namespace, it compiled and even printed the menu in the Emscripten generated web page! And then crashed my browser.

At this point I thought it would be awesome if I could compile it as a worker and have it automagically use postMessage and onmessage for stdin/stdout and console.error for stderr. I was disappointed, but this is a compiler option I would consider working on!

I also couldn't get all of the Worker API working for some reason I have not investigated yet. However, I could get enough of it working to hack together this post. I created a new entry point in the chess-at-nite code that exports a C style function suitable to be called using the Emscripten Worker API, this partly worked. I was unable to get the Worker API calling the worker, but noticed I could create and call the worker with normal Javascript, provided I posted and handled the internal message formats used by the Worker API.

For this post the worker takes a FEN game state and returns a new FEN string with an updated game state. Luckily chess.js and chessboard.js support FEN strings which made wiring up the UI quite straight forward. As FEN strings do not provide enough information about previous moves to detect threefold repetitions, the engine is quite susceptible to threefold repetition draws, as can be seen when it plays itself.

Ideally I would have liked to have the Chess engine running in the worker, comunicating with the xboard protocol using "standard" stdio over the web worker onmessage/postMessage interface. However I am pretty happy with the results and may have found a project I want to contribute too.

Comments