I am trying to interface a program I'm writing with an existing chess engine (stockfish
) in C++. To do this I'm using Boost but am having problems with processes. engine.exe
is the executable I'm trying to interface with but it seems to be terminating after the first command of uci
. By the time the program reaches the second while loop, sf.running()
returns false even though it was never terminated.
#include <iostream>
#include <string>
#include <algorithm>
#include <boost/process.hpp>
#include <boost/filesystem.hpp>
using namespace std;
namespace bp = boost::process;
int main()
{
boost::filesystem::path sfPath{ R"(engine.exe)" };
bp::ipstream is;
bp::opstream os;
bp::child sf(sfPath, "uci", bp::std_out > is, bp::std_in < os);
string line;
getline(is, line);
cout << line << endl;
while(sf.running()) {
getline(is, line);
cout << line << endl;
}
os << "position startpos moves d2d4 g8f6 g1f3\n";
os << "go\n";
while (sf.running()) {
getline(is, line);
cout << line << endl;
}
}
From a quick test with stockfish 8 on my machine, supplying a command on the CLI (like your
"uci"
) causes it to get executed and exit.Simple Test Client
I tried to make it work in synchronous mode first. For fun, I chose to connect two child processes, one for white and one for black. We can make them play a game:
Now I have two working implementations:
Synchronous Implementation
Though potentially wrought with the possibility of deadlocking on ful-duplex IO as documented (above), the code remains relatively simple:
A demo run on my system printed:
A win for white
Asynchronous Implementation
Just for completeness, I thought I'd try an asynchronous implementation. Using the default Asio callback style this could become unwieldy, so I thought to use Boost Coroutine for the stackful coroutines. That makes it so the implementation can be 99% similar to the synchronous version:
The most noticeable difference is the switch from iostream style IO to buffer-based IO. Another test run using this version:
A very dry, draw-out rook endgame, but black stumbles on the win in the end
REFERENCE LISTINGS
File
synchronous.cpp
File
asynchronous.cpp