2 unstable releases
0.2.0 | Oct 17, 2024 |
---|---|
0.1.0 | Oct 3, 2024 |
#312 in Game dev
331 downloads per month
84KB
1.5K
SLoC
A Universal Chess Interface (UCI) Parser
This crate contains types and functions for communicating with chess engines and chess GUIs through the Universal Chess Interface (UCI) protocol.
Overview
The primary function of this crate is to provide well-typed representations for every message/command described in the UCI protocol, along with an easy-to-use API for converting between these well-typed representations and strings.
Examples
The simplest use case is parsing commands like uci
, which is as easy as it sounds:
use uci_parser::UciCommand;
let cmd = UciCommand::new("uci").unwrap();
assert_eq!(cmd, UciCommand::Uci);
Commands implement FromStr
, so you can call .parse()
:
use uci_parser::UciCommand;
// Arbitrary whitespace is handled appropriately
let cmd = "setoption name \n Threads value \t 16".parse::<UciCommand>();
assert!(cmd.is_ok());
assert_eq!(
cmd.unwrap(),
UciCommand::SetOption {
name: "Threads".to_string(),
value: Some("16".to_string())
}
);
Commands that have many optional arguments, like go
, implement Default
so they can be parsed cleanly:
use std::time::Duration;
use uci_parser::{UciCommand, UciSearchOptions};
let cmd = "go movetime 42".parse::<UciCommand>();
assert!(cmd.is_ok());
assert_eq!(
cmd.unwrap(),
UciCommand::Go(UciSearchOptions {
// Times are provided as Durations
movetime: Some(Duration::from_millis(42)),
..Default::default()
})
);
Crate Features
How edge cases should be handled is a delicate subject and the correct answer depends on the needs of your engine. Rather than enforce my own opinion on handling those edge cases, I've marked them as crate features.
-
parse-go-perft
: Adds support for parsingperft <depth>
as an argument to thego
command.- This is not part of the UCI protocol, but is common among engines.
-
parse-bench
: Adds support for parsing the stringbench
intoUciCommand::Bench
.- This is not part of the UCI protocol, but is common among engines and very useful for engine development.
- The arguments to
bench
are the same as the arguments togo
, since both commands involve running searches.
-
parse-position-kiwipete
: Adds support to parsekiwipete
as a special argument toposition
(similar tostartpos
).- The "kiwipete" position is useful for debugging engines, as it is a messy position with many possible moves available.
- If enabled,
position kiwipete
will be equivalent to parsingposition fen r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1
, so thefen
field ofPosition
will beSome(<kiwipete fen>)
.
-
validate-promotion-moves
: Restricts the grammar when parsing moves in UCI notation to ensure that promotions are valid:- By default, moves are parsed with the grammar
[a-h][1-8][a-h][1-8][pnbrqk]
, which will parsee2e4p
successfully, even though it doesn't "make sense" in-game. With this feature enabled, the grammar restricts to:[a-h][1-8][a-h][1-8] | [a-h]7[a-h]8[qnrb] | [a-h]2[a-h]1[qnrb]
. This means that only moves from the penultimate ranks to the final ranks will be parsed as promotions, and the only valid pieces for a promotion are a Queen, Knight, Rook, or Bishop.
- By default, moves are parsed with the grammar
-
clamp-negatives
: Clamps negative numbers to0
when parsing.- By default, all numbers are assumed to be positive, and the parser will fail on strings like
go wtime -80
. This is normally not a problem, - All numeric values within the UCI protocol should be positive. That said, there have been instances where some GUIs send negative move times, which could mean any variety of things. If this feature is enabled, all numeric values are clamped to at least 0. That is, if a GUI sent
go movetime -42
, this crate will parse that as aDuration
of0
milliseconds. It is up to your engine to determine how to respond to these situations.
- By default, all numbers are assumed to be positive, and the parser will fail on strings like
-
err-on-unused-input
: Causes the parser to fail if the input text was not fully consumed during parsing.- As per the protocol, unknown tokens encountered before a command are ignored (
joho debug on
parses todebug on
). Unknown tokens encountered while parsing a specific command will generate errors (debug joho on
fails). Unknown tokens after a command are, by default, ignored (debug on joho
parses todebug on
). If this feature is enabled, the parser will fail if all tokens were not consumed during parsing (debug on joho
will fail).
- As per the protocol, unknown tokens encountered before a command are ignored (
-
types
: Exposes several well-typed representations of UCI components, such as moves.- By default, commands like
position startpos moves e2e4
will yield a list ofString
s for all parsedmoves
, leaving you to have to re-parse them in your engine later. If this feature is enabled, anyString
that is parsed as a move will be converted toUciMove
, which contains types representing the files, ranks, squares, and pieces involved in each move. - See the
types
module for more information.
- By default, commands like
Dependencies
~1–1.7MB
~35K SLoC