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.
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;
parse(..)
method or the parse_strict(..)
method. The difference between them is that parse_strict(..)
will return a pest::error::Error
if any of the input is unrecognized or violates the rules of the PEG grammar, whereas parse
will simply ignore any such input. The latter is the approach recommended by the protocol specification. The third option is
parse_with_unknown(..)
, which will pack unrecognized input into an UciMessage::Unknown
variant.rust
use vampirc_uci::parse;
rust
use vampirc_uci::{UciMessage, MessageList, UciTimeControl, Serializable};
rust
let messages: MessageList = parse("uci\nposition startpos moves e2e4 e7e5\ngo ponder\n");
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)
}
_ => {...}
}
}
}
_ => {...}
}
}
```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"
```
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.
The full API documentation is available at docs.rs.
u64
into std::time::Duration
(breaking
change, hence the version increase).UciMessage::direction(&self)
method as public.UciMessage::info_string()
utility function.go
command (see Parser cannot parse "go\n").ByteVecUciMessage
as a UciMessage
wrapper that keeps the serialized form of the message in the struct as a byte Vector. Useful if
you need to serialize the same message multiple types or support AsRef<[u8]>
trait for funnelling the messages into a futures::Sink
or
something.parse_with_unknown()
method that instead of ignoring unknown messages (like parse
) or throwing an error (like parse_strict
) returns
them as a UciMessage::Unknown
variant.info
message, with the UciAttributeInfo
enum representing all 17 types of messages described by the UCI documentation, as well as any other info message via the
Any variant.option
message.<empty>
strings in option
and setoption
.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.
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.
uci
debug
isready
register
position
setoption
ucinewgame
stop
ponderhit
quit
go
id
uciok
readyok
bestmove
copyprotection
registration
option
info