vampirc-uci Build Status Documentation Status

Vampirc UCI is a Universal Chess Interface (UCI) protocol parser and serializer.

The UCI protocol is a way for a chess engine to communicate with a chessboard GUI, such as Scid vs. PC.

The Vampirc Project is a chess engine and chess library suite, written in Rust. It is named for the Slovenian grandmaster Vasja Pirc, and, I guess, vampires? I dunno.

Vampirc UCI uses the PEST parser to parse the UCI messages. If you want to build your own abstractions of the protocol, the corresponding PEG grammar is available here.

Installing the library

To use the crate, declare a dependency on it in your Cargo.toml file:

toml [dependencies] vampirc-uci = "0.10"

Then reference the vampirc_uci crate in your crate root: rust extern crate vampirc_uci;

Usage

  1. Choose and import one of the parse.. functions. See Choosing the parsing function.

rust use vampirc_uci::parse;

  1. Some other useful imports (for message representation):

rust use vampirc_uci::{UciMessage, MessageList, UciTimeControl, Serializable};

  1. Parse some input:

rust let messages: MessageList = parse("uci\nposition startpos moves e2e4 e7e5\ngo ponder\n");

  1. Do something with the parsed messages:

rust for m in messages { match m { UciMessage::Uci => { // Initialize the UCI mode of the chess engine. } UciMessage::Position { startpos, fen, moves } => { // Set up the starting position in the engine and play the moves e2-e4 and e7-e5 } UciMessage::Go { time_control, search_control } { if let Some(tc) = time_control { match tc { UciTimeControl::Ponder => { // Put the engine into ponder mode ("think" on opponent's time) } _ => {...} } } } _ => {...} } }

  1. Outputting the messages

```rust let message = UciMessage::Option(UciOptionConfig::Spin { name: "Selectivity".to_string(), default: Some(2), min: Some(0), max: Some(4), });

println!(message); // Outputs "option name Selectivity type spin default 2 min 0 max 4"

```

  1. Or, parse and handle input line by line, from, for example, stdin: ```rust use std::io::{self, BufRead}; use vampircuci::{UciMessage, parseone};

for line in io::stdin().lock().lines() { let msg: UciMessage = parse_one(&line.unwrap()); println!("Received message: {}", msg); } ```

Choosing the parsing function

There are several parsing functions available, depending on your need and use case. They differ in what they return and how they handle unrecognized input. The following table may be of assistance in selecting the parsing function:

| Function | Returns | Can skip terminating newline | On unrecognised input... | | -------------------- | ----------------------------------------|------------------------------|---------------------------------------------| | parse | MessageList (a Vec of UciMessage) | On last command | Ignores it | | parse_strict | MessageList (a Vec of UciMessage) | On last command | Throws a pest::ParseError | | parse_with_unknown | MessageList (a Vec of UciMessage) | On last command | Wraps it in a UciMessage::Unknown variant | | parse_one | UciMessage | Yes | Wraps it in a UciMessage::Unknown variant |

From my own experience, I recommend using either parse_with_unknown if your string can contain multiple commands, or else parse_one if you're doing line by line parsing. That way, your chess engine or tooling can at least log unrecognised input, available from UciMessage::Unknown(String, Error) variant.

Integration with the chess crate (since 0.9.0)

This library (optionally) integrates with the chess crate. First, include the vampirc-uci crate into your project with the chess feature:

toml [dependencies] vampirc-uci = {version = "0.10", features = ["chess"]}

This will cause the vampirc_uci's internal representation of moves, squares and pieces to be replaced with chess crate's representation of those concepts. Full table below:

| vampirc_uci 's representation | chess' representation | | ----------------------------- | --------------------- | | vampirc_uci::UciSquare | chess::Square | | vampirc_uci::UciPiece | chess::Piece | | vampirc_uci::UciMove | chess::ChessMove |


WARNING

chess is a fairly heavy create with some heavy dependencies, so probably only use the integration feature if you're building your own chess engine or tooling with it.


API

The full API documentation is available at docs.rs.

New in 0.10.1

New in 0.10.0

New in 0.9.0

New in 0.8.3

New in 0.8.2

New in 0.8.1

New in 0.8.0

New in 0.7.5

vampirc-io

This crate goes together well with the vampirc-io crate, a library for non-blocking communication over standard input and output (which is how UCI communication is usually conducted), based on the async-std framework.

Limitations and 1.0

The library is functionally complete – it supports the parsing and serialization to string of all the messages described by the UCI specification. Before the 1.0 version can be released, though, this library needs to be battle tested more, especially in the upcoming Vampirc chess engine.

Furthermore, as I am fairly new to Rust, I want to make sure the implementation of this protocol parser is Rust-idiomatic before releasing 1.0. For this reason, the API should not be considered completely stable until 1.0 is released.

Additionally, some performance testing would also not go amiss.

Supported engine-bound messages (100%)

Supported GUI-bound messages (100%)