#usi #shogi

haitaka-usi

Universal Shogi Interface (USI) library

1 unstable release

Uses new Rust 2024

new 0.1.0 May 4, 2025

#437 in Debugging

MIT license

96KB
2K SLoC

haitaka-usi ハイタカ-usi

Haitaka-usi is a Universal Shogi Interface (USI) protocol parser and serializer.

The USI protocol is a simple, 7-bit-ascii-text-based protocol for Shogi clients and engines to communicate with each other. The protocol is based on the UCI (Universal Chess Interface) protocol with modifications to support Shogi.

The parser code in this repo uses a PEG/PEST grammar to define the protocol syntax. The grammar file, usi.pest, was originally inspired by the uci.pest file of Vampirc UCI, which was a great help in getting up to speed with PEST. But apart from making the required modifications to support Shogi, I also made some other pretty significant changes. In particular, I unified the top-level entry points (the start rule) which should make it easier to use and verify the grammar. I also clearly separated GUI messages from Engine messages, and I made a few other, smaller modifications to conform more closely to the spec. See comments in the usi.pest file for details.

This library implements serialization and deserialization for both the client (GUI) and server (engine) side. This makes it possible to use as a bridge between a server (Shogi engine frontend) and a client (GUI backend). It differs in this regard from the usi-rs crate which is an alternative implementation and an excellent GUI client, but which only supports deserialization of GUI commands and parsing of Engine commands.

Installation

Add haitaka-usi to your Cargo.toml:

[dependencies]
haitaka-usi = "0.1.0"   # or use the latest version on crates.io

Usage

Deserialization

use haitaka_types::*;
use haitaka_usi::*;

// parse a multi-line sequence of messages
let input = "\
    id name haitaka-shogi
    id author tofutofu
    option name Style type combo default Normal var Solid var Normal var Wild
    option name USI_Hash type spin default 256
    option name USI_Ponder type check default false
    usiok
";
for msg in EngineMessageStream::new(input) {
    println!("{msg:?}");
    println!("{msg}");
}

// parse one line
let input = "bestmove 2g2f ponder 8c8d\n";
let bestmove = Move::BoardMove { from: Square::G2, to: Square::F2, promotion: false };
let ponder = Some(Move::BoardMove { from: Square::C8, to: Square::D8, promotion: false });

let msg = EngineMessage::parse(input).unwrap();
assert_eq!(
    msg, 
    EngineMessage::BestMove(BestMoveParams::BestMove { bestmove, ponder })
);

// parse one line, skipping junk tokens
let input = "yo taka usiok\n";
let msg = EngineMessage::parse_first_valid(input).unwrap();
assert_eq!(msg, EngineMessage::UsiOk);

// parse a gui message multi-line input string
let input = "\
    usinewgame
    position startpos moves 7g7f 3c3d
    go btime 300000 wtime 300000 byoyomi 10000
";
for msg in GuiMessageStream::new(input) {
    println!("{msg:?}");
    println!("{msg}");
}

// parse one line
let input = "usinewgame\n";
let msg = GuiMessage::parse(input).unwrap();
assert_eq!(msg, GuiMessage::UsiNewGame);

Serialization

use haitaka_types::*;
use haitaka_usi::*;

let params = EngineParams::new().btime(300000).wtime(300000).byoyomi(10000);
let msg = GuiMessage::Go(params);

assert_eq!(format!("{msg}\n"), "go btime 300000 wtime 300000 byoyomi 10000\n"); 

let bestmove = Move::BoardMove { from: Square::G2, to: Square::F2, promotion: false };
let ponder = Some(Move::BoardMove { from: Square::C8, to: Square::D8, promotion: false });
let msg = EngineMessage::BestMove(BestMoveParams::BestMove { bestmove, ponder });

assert_eq!(format!("{msg}\n"), "bestmove 2g2f ponder 8c8d\n");

More examples can be found in the unit tests.

API

The API docs will be available at docs.rs/haitaka-usi.

Current limitations

The main limitation is that the current library does not support a real streaming protocol. All parser functions require a complete input string. GuiMessageStream and EngineMessageStream can convert a given input string into a sequence of message objects, but also require the input to be fully given.

Supported Protocol Messages

GuiToEngine

    usi
    usinewgame
    isready
    debug
    setoption
    register
    ponderhit
    position 
    go
    stop
    quit
    gameover

EngineToGui

    id
    usiok
    copyprotection
    registration 
    option
    readyok
    bestmove
    info

Contributing

Contributions are very welcome! Please open an issue or submit a pull request on GitHub. Also, feel free to contact me on the Discord Shogi Harbour channel (@tofutofu).

License

haitaka-usi is licensed under the MIT license.

References

Dependencies

~2.1–2.9MB
~57K SLoC