#chess #uci #parser-serializer #parser #chess-engine #parse-input

吸血鬼-uci

通用棋类接口(UCI)协议解析器和序列化器。Vampirc 棋类套件的一部分。

12 个版本 (6 个破坏性更新)

0.11.1 2022年3月27日
0.11.0 2020年9月17日
0.10.1 2020年5月16日
0.8.3 2019年12月21日
0.8.0 2019年3月29日

#532 in 解析器实现

Download history 59/week @ 2024-03-11 62/week @ 2024-03-18 77/week @ 2024-03-25 88/week @ 2024-04-01 36/week @ 2024-04-08 35/week @ 2024-04-15 49/week @ 2024-04-22 44/week @ 2024-04-29 38/week @ 2024-05-06 52/week @ 2024-05-13 29/week @ 2024-05-20 45/week @ 2024-05-27 32/week @ 2024-06-03 23/week @ 2024-06-10 47/week @ 2024-06-17 47/week @ 2024-06-24

每月157次 下载
用于 吸血鬼-io

Apache-2.0

170KB
3.5K SLoC

吸血鬼-uci 文档状态

吸血鬼 UCI 是一个 通用棋类接口(UCI)协议 解析器和序列化器。

UCI 协议是棋类引擎与棋盘图形用户界面(如 Cute Chess)通信的一种方式。

Vampirc 项目 是一个用 Rust 编写的棋类引擎和棋类库套件,以斯洛文尼亚特级大师 Vasja Pirc 的名字命名,以及,我想,吸血鬼?我不知道。

吸血鬼 UCI 使用 PEST 解析器 来解析 UCI 消息。如果您想构建自己对该协议的抽象,相应的 PEG 语法可以在 这里 获取。

安装库

要使用此包,请在您的 Cargo.toml 文件中声明对其的依赖项

[dependencies]
vampirc-uci = "0.11"

然后,在您的包根目录中引用 vampirc_uci

extern crate vampirc_uci;

使用方法

  1. 选择并导入一个 parse.. 函数。请参阅 选择解析函数
use vampirc_uci::parse;
  1. 一些其他有用的导入(用于消息表示)
use vampirc_uci::{UciMessage, MessageList, UciTimeControl, Serializable};
  1. 解析一些输入
let messages: MessageList = parse("uci\nposition startpos moves e2e4 e7e5\ngo ponder\n");
  1. 对解析后的消息进行一些操作
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. 输出消息
    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. 或者,按行解析并处理输入,例如从 stdin
use std::io::{self, BufRead};
use vampirc_uci::{UciMessage, parse_one};

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

选择解析函数

根据您的需求和用例,有几个解析函数可用。它们在返回值和如何处理未识别输入方面有所不同。以下表格可能有助于选择解析函数

函数 返回值 是否跳过终止换行符 在未识别输入时...
parse MessageList(一个VecUciMessage 在最后一条命令上 忽略它
parse_strict MessageList(一个VecUciMessage 在最后一条命令上 抛出pest::ParseError
parse_with_unknown MessageList(一个VecUciMessage 在最后一条命令上 将其包裹在UciMessage::Unknown变体中
parse_one UciMessage 将其包裹在UciMessage::Unknown变体中

根据我的经验,如果你字符串可以包含多个命令,我建议使用parse_with_unknown,否则如果你是逐行解析,请使用parse_one。这样,你的棋引擎或工具至少可以记录未识别的输入,可以从UciMessage::Unknown(String, Error)变体中获取。

与 chess crate 的集成(自 0.9.0 版起)

此库(可选)与chess crate集成。首先,使用chess功能将vampirc-uci crate包含到你的项目中

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

这将导致vampirc_uci对走法、棋子和棋盘的内部表示被替换为chess crate对这些概念的解释。完整的表格如下

vampirc_uci 的表示 chess 的表示
vampirc_uci::UciSquare chess::Square
vampirc_uci::UciPiece chess::Piece
vampirc_uci::UciMove chess::ChessMove

警告

chess是一个相当重的crate,有一些重依赖,所以可能只有在您使用它构建自己的棋引擎或工具时才使用集成功能。


API

完整的API文档可在docs.rs找到。

新功能 0.11.1

  • 改进了parse_with_unknown(&str),以便尽可能正确地识别输入。例如,之前输入uci\ndebug on\nucinewgame\nabc\nstop\nquit会返回一个单独的Uci::Unknown消息,改进的语法支持将返回六个独立的消息,其中五个将是正确的UCI消息,而将'abc'包裹在Uci::Unknown中。
  • btime参数错误序列化的修复,感谢@analog_hors
  • 支持 chess crate v. 3.2.0。

新功能 0.11.0

  • 支持负时间,例如剩余时间减少和时间增量,如vampirc-uci 不识别负时间 #16中讨论的那样。为了支持负持续时间,基于毫秒的时间数量表示从Rust标准库的std::time::Duration切换到chrono crate的 chrono::Duration文档)。这是一个API破坏性更改,因此版本号增加。
  • 修复了vampric-uci-19,一个有时会错误解析的go消息。

新功能 0.10.1

  • 由于发布不当,重新发布为0.10.1

新功能 0.10.0

  • 添加了 parse_one(&str) 方法,用于解析并返回单个命令,可在从 stdin 或其他 BufReader 读取的循环中使用。参见上面的示例。
  • 将时间参数的内部表示从 u64 改为 std::time::Duration(破坏性变更)。
  • 放宽了语法规则,现在允许发送给 parse() 或其相关方法的最後一条命令不必以换行符结尾。这允许解析,例如,从 stdin::io::stdin().lock().lines() 读取的单个命令,该命令会移除末尾的换行符 - 请参阅 vampirc-uci-14
  • UciMessage::direction(&self) 方法标记为公共。

0.9.0 中的新功能

  • (可选)与 chess crate 集成(见上文)。
  • 移除了显式的 Safe 和 Sync 实现。

0.8.3 中的新功能

0.8.2 中的新功能

  • 添加了 ByteVecUciMessage,作为 UciMessage 封装器,将消息的序列化形式作为字节向量保存在结构体中。如果您需要将相同的消息序列化多次或支持 AsRef<[u8]> trait 以将消息传递到 futures::Sink 或类似的结构,这非常有用。
  • 对与基于异步 async-stdvampirc-io 集成进行的修改。

0.8.1 中的新功能

  • 添加了 parse_with_unknown() 方法,该方法在忽略未知消息(如 parse)或引发错误(如 parse_strict)时,将它们作为 UciMessage::Unknown 变体返回。

0.8.0 中的新功能

  • 支持解析 info 消息,其中 UciAttributeInfo 枚举表示 UCI 文档中描述的所有 17 种消息类型,以及通过 Any 变体 的任何其他信息消息。

0.7.5 中的新功能

  • 支持解析 option 消息。
  • <empty>setoption 中对 option 字符串进行适当的支持。

vampirc-io

本节曾推荐使用 vampirc-io 包将基于 UCI 的棋引擎连接到 GUI,但说实话,随着 Rust 异步栈支持的最新进展,您可能自己使用,例如 async-std 库 来完成它可能会更简单。

限制和 1.0 版本

库功能完善 - 它支持解析和序列化 UCI 规范中描述的所有消息。然而,在发布 1.0 版本之前,这个库需要更多地进行实战测试,特别是在即将到来的 Vampirc 棋引擎 中。

此外,由于我相对较新于 Rust,我想在发布 1.0 版本之前确保这个协议解析器的实现是 Rust-idiomatic。因此,直到发布 1.0,API 都不应被认为是完全稳定的。

此外,一些性能测试也不会错。

支持引擎端消息(100%)

  • uci
  • debug
  • isready
  • register
  • position
  • setoption
  • ucinewgame
  • stop
  • ponderhit
  • quit
  • go

支持 GUI 端消息(100%)

  • id
  • uciok
  • readyok
  • bestmove
  • copyprotection
  • registration
  • option
  • info

依赖关系

~3–4MB
~77K SLoC