36 个版本 (17 个稳定)
3.2.0 | 2021年3月12日 |
---|---|
3.1.1 | 2019年7月14日 |
3.1.0 | 2019年5月27日 |
3.0.1 | 2019年1月16日 |
0.2.0 | 2016年5月29日 |
在 游戏开发 中排名 80
每月下载量 1,331
在 10 crates 中使用
230KB
4.5K SLoC
Rust 中快速的国际象棋库
这个库处理棋引擎或棋盘用户界面中的移动生成过程。
该库遵循 MAJOR.MINOR.PATCH 格式的 semver 版本号。这意味着
- 任何破坏现有代码的 API 变更将涉及 MAJOR 版本号变更。
- 任何添加的功能或特性,只要不影响现有应用程序,将涉及 MINOR 版本号变更。
- 任何不影响用户的错误修复或性能改进将涉及 PATCH 版本变更。
需要 Rust 1.31 或更高版本
此库需要 rust 版本 1.27 或更高版本以在编译时检查 BMI2 指令集。此外,此构建与 rust 2018 兼容,我认为这需要 rust 1.31。
注意:由于在 AMD 架构上性能极差,已禁用 bmi2。我已选择公开两个相关函数,如果使用 bmi2 CPU。
示例
增量移动生成与捕获/非捕获排序
这里我们遍历所有移动,使用增量移动生成。下面的迭代器会在您遍历列表时生成移动,这在不是所有移动都将被查看的情况中很理想(例如,在引擎搜索函数中)。
use chess::MoveGen;
use chess::Board;
use chess::EMPTY;
// create a board with the initial position
let board = Board::default();
// create an iterable
let mut iterable = MoveGen::new_legal(&board);
// make sure .len() works.
assert_eq!(iterable.len(), 20); // the .len() function does *not* consume the iterator
// lets iterate over targets.
let targets = board.color_combined(!board.side_to_move());
iterable.set_iterator_mask(targets);
// count the number of targets
let mut count = 0;
for _ in &mut iterable {
count += 1;
// This move captures one of my opponents pieces (with the exception of en passant)
}
// now, iterate over the rest of the moves
iterable.set_iterator_mask(!EMPTY);
for _ in &mut iterable {
count += 1;
// This move does not capture anything
}
// make sure it works
assert_eq!(count, 20);
设置位置
Board
结构试图在所有时候保持位置合法。这在设置棋盘时可能会让人感到烦恼,例如通过用户输入。
为了解决这个问题,在 3.1.0 版本中引入了 BoardBuilder
结构。该 BoardBuilder
结构遵循非消耗性构建器模式,并且可以通过 Board::try_from(...)
或 board_builder.try_into()
转换为 Result<Board, Error>
。
use chess::{Board, BoardBuilder, Piece, Square, Color};
use std::convert::TryInto;
let mut board_builder = BoardBuilder::new();
board_builder.piece(Square::A1, Piece::King, Color::White)
.piece(Square::A8, Piece::Rook, Color::Black)
.piece(Square::D1, Piece::King, Color::Black);
let board: Board = board_builder.try_into()?;
进行走棋
在这里,我们在棋盘上走一步棋。棋盘是一个创建时复制的结构,这意味着每次走棋时,你都会创建一个新的棋盘。你可以使用 board.make_move()
来更新当前位置,但你不能撤销这步棋。棋盘结构经过优化以减小复制时间。
use chess::{Board, ChessMove, Square, Color};
let m = ChessMove::new(Square::D2, Square::D4, None);
let board = Board::default();
assert_eq!(board.make_move_new(m).side_to_move(), Color::Black);
表示完整游戏
棋类游戏不仅仅是棋盘上的内容。Game
对象跟踪游戏的历史,以便进行和棋提议、认输、50回合规则和棋、重复和棋等,总之,任何需要游戏历史的情况。
use chess::{Game, Square, ChessMove};
let b1c3 = ChessMove::new(Square::B1, Square::C3, None);
let c3b1 = ChessMove::new(Square::C3, Square::B1, None);
let b8c6 = ChessMove::new(Square::B8, Square::C6, None);
let c6b8 = ChessMove::new(Square::C6, Square::B8, None);
let mut game = Game::new();
assert_eq!(game.can_declare_draw(), false);
game.make_move(b1c3);
game.make_move(b8c6);
game.make_move(c3b1);
game.make_move(c6b8);
assert_eq!(game.can_declare_draw(), false); // position has shown up twice
game.make_move(b1c3);
game.make_move(b8c6);
game.make_move(c3b1);
game.make_move(c6b8);
assert_eq!(game.can_declare_draw(), true); // position has shown up three times
FEN 字符串
BoardBuilder
、Board
和 Game
都实现了 FromStr
,以便您可以将 FEN 字符串转换为对象。此外,BoardBuilder
和 Board
实现了 std::fmt::Display
,以便将它们转换为 FEN 字符串。
use chess::Board;
use std::str::FromStr;
assert_eq!(
Board::from_str("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
.expect("Valid Position"),
Board::default()
);
编译时选项
在编译时,我强烈建议使用 RUSTFLAGS="-C target-cpu=native",特别是为了获取几乎所有现代 CPU 都可用的 popcnt 和 ctzl 指令。这用于内部确定位图中有多少个棋子,以及棋子位于哪个位置。由于这里使用的类型系统,这些任务实际上只需要一条指令。此外,通过使用此标志,在具有指令的机器上启用了 BMI2。
BMI2
截至本库 1.0.3 版本,在支持它的机器上使用 BMI2 指令集。这以两种方式加快了逻辑的执行速度
- 它使用内置指令执行与魔幻位图相同的逻辑。
- 通过将走法存储在 u16 而不是 u64 中,减少了缓存负载,这可以通过单条指令解压缩为 u64。
在没有 BMI2 的目标上,该库回退到魔幻位图。这是在编译时检查的。
Shakmaty
另一个 Rust 棋类库是 'shakmaty' crate。这是一个非常好的库,比这个库有更多功能。它支持各种棋类变体以及 UCI 协议。然而,这些功能是有代价的,并且在这个库中,所有测试用例的性能都比我抛出的要快。为了比较这两个库,我已经在 'chess_perft' 应用程序中添加了对 'shakmaty' 的支持,并将许多基准测试移动到该 crate 中。您可以在 https://github.com/jordanbray/chess_perft 上查看结果。
它做什么
这个库允许您从 FEN 格式的字符串创建棋盘,列出棋盘的所有合法走法并执行走法。
这个库还允许您查看各种棋盘状态信息,例如王车易位权利。
这个库具有非常快速的走法生成(其存在的主要目的),将会进行更多的优化。所有使棋走法生成变得快速的技巧都被使用。
它不能做什么
这并不是一个棋引擎,只是一个走法生成器。这也不是一个棋盘界面,只是一个走法生成器。这也不是一个棋盘PGN解析器、数据库、UCI通信器、XBOARD/WinBoard协议、网站或大师。只是一个谦逊的走法生成器。
API 文档
...可在https://jordanbray.github.io/chess/chess/找到。
还有其他什么吗?
没有了。祝您玩得开心。
依赖项
约200KB