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.
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
Opening book file (book) is missing. <-- how to read book with .cpp
MAYBE no book, i have beat engine first game, Also with winboard.