stockfish

CRAN status Codecov test coverage R-CMD-check

Overview

{stockfish} is an R package that implements the UCI open communication protocol and ships with Stockfish, a very popular, open source, powerful chess engine written in C++.

Installation

Install the released version of {stockfish} from CRAN:

install.packages("stockfish")

Or install the development version from GitHub:

# install.packages("remotes")
remotes::install_github("curso-r/stockfish")

You can also find more (and more recent) versions of the Stockfish engine to use with {stockfish} at their download page.

Example

{stockfish} is as simple to use as any other UCI package. You should start the engine with fish$new() and send commands with its internal methods, only remembering to run quit() once you’re done.

library(stockfish)

# Start the engine
engine <- fish$new()

# Examine background process
engine$process
#> PROCESS 'stockfish', running, pid 51774.

# Search for best move
engine$go()
#> [1] "info depth 10 seldepth 10 multipv 1 score cp 69 nodes 42240 nps 276078 tbhits 0 time 153 pv e2e4 b8c6 d2d4 d7d5 e4e5 e7e6 g1f3 g8e7 b1c3 h7h6"

# Setup a game from FEN
engine$ucinewgame()
engine$position("6rk/2Q3p1/5qBp/5P2/8/7P/6PK/8 w - - 15 51")
engine$go()
#> [1] "info depth 15 seldepth 18 multipv 1 score cp 53 nodes 585935 nps 264053 hashfull 259 tbhits 0 time 2219 pv e2e4 e7e5 b1c3 g8f6 g1f3 b8c6 f1c4 f6e4 c3e4 d7d5 c4d3 d5e4 d3e4 f8c5 e1g1"

# Stop the engine
engine$quit()

Usage

fish, this package’s main class, represents a Stockfish engine, allowing the user to send commands and receive outputs according to the UCI protocol. In short, a fish object, when created, spawns a detached Stockfish process and pipes into its stdin and stdout.

For more information, see its full documentation by running ?fish.

Bundled Stockfish

This package comes bundled with Stockfish, a very popular, open source, powerful chess engine written in C++. It can achieve an ELO of 3544, runs on Windows, macOS, Linux, iOS and Android, and can be compiled in less than a minute.

When installing {stockfish} (lower case), Stockfish’s (upper case) source code is compiled and the resulting executable is stored with your R packages. This is not a system-wide installation! You don’t have to give it administrative privileges to run or even worry about any additional software.

But there are two main downsides:

  1. While the bundled version of the engine (Stockfish 14.1) is up-to-date as of March 2022, it isn’t able to update itself. This means that, if I’m not able to port an upcomming version of Stockfish, the package will stay behind. Luckly, you can always download the version of your choosing and pass the executable as an argument to fish$new().

  2. Since version 12, Stockfish supports NNUE evaluation, but this requires some pretty heavy binaries. In order to avoid bundling large files with {stockfish}, I have decided to disable NNUE in the source code. Again, you are free to download a NNUE-capable version and use it instead of the bundled executable.

UCI Protocol

UCI (Universal Chess Interface) is an open communication protocol that enables chess engines to communicate with user interfaces. Strictly speaking, the fish class implements the UCI protocol as publicized by Stefan-Meyer Kahlen, just with a focus on the Stockfish engine. This means that some methods are not implemented (see Common Gotchas) and that all tests are run on Stockfish, but everything else should work fine with other engines.

The quoted text at the end of the documentation of each method was extracted directly from the official UCI protocol, so you can see exactly what that command can do. In general, the commands are pretty self-explanatory, except for long algebraic notation (LAN), the move notation used by UCI. In this notation, moves are recorded using the starting and ending positions of each piece, e.g. e2e4, e7e5, e1g1 (white short castling), e7e8q (for promotion), 0000 (nullmove).

Implementation

All the heavy lifting of the fish class is done by the {processx} package. The Stockfish process is created with processx::process$new and IO is done with write_input() and read_output(). An important aspect of the communication protocol of any UCI engine is waiting for replies, and here this is done with a loop that queries the process with poll_io() and stops once the output comes back empty.

Before implementing the UCI protocol manually, this package used {bigchess}. It is a great package created by [@rosawojciech](https://github.com/rosawojciech), but it has some dependencies that are beyond the scope of this package and ultimately I wanted more control over the API (e.g. using {R6}).

Common Gotchas

The fish class has some specifics that the user should keep in mind when trying to communicate with Stockfish. Some of them are due to implementation choices, but others are related to the UCI protocol itself. This is by no means a comprehensive list (and you should probably read UCI’s documentation), but here are a few things to look out for:

Code of Conduct

Please note that the {stockfish} project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

The C++ code of the {stockfish} project is derived from Stockfish 14.1, and its main authors are listed as contributors in the DESCRIPTION file. For a full list of Stockfish 14.1’s authors, please see their AUTHORS list. Finally, as per Stockfish’s terms of use, {stockfish} is also licensed under the GPL 3 (or any later version at your option). Check out LICENSE.md for the full text.