chessai 1.0.1

High-performance Xiangqi (Chinese Chess) AI engine with u128 bitboards
Documentation

ChessAI

Crates.io docs.rs License: MIT

高性能中国象棋(Xiangqi)AI 引擎,基于 u128 位棋盘(bitboard)的纯 Rust 实现。

特性

  • 位棋盘表示:单个 u128 覆盖 10×9 的中国象棋棋盘,所有走法生成均为位运算。
  • Magic Bitboard 攻击表:车、炮的快速查表攻击生成;马、象、兵、士、将采用预生成表。
  • Alpha-Beta 搜索:迭代加深 + 换位表(Zobrist 键)+ 空着裁剪 + PVS + 静态搜索(QS)。
  • 走法排序:杀手启发、历史启发、反制走法、MVV-LVA、SEE 裁剪。
  • Lazy SMP 并行:多线程共享换位表,配合 depth-skip 模式分散搜索。
  • 开局库:内嵌 assets/BOOK.DAT,支持走法镜像。
  • FEN & ICCS:完整的 FEN 解析/生成,ICCS 坐标(b2-e2b2e2)双向转换。
  • 构建器 APIEngine::builder().hash_size(mb).threads(n).build(),零配置即可运行。

安装

[dependencies]
chessai = "1"

快速开始

use std::time::Duration;
use chessai::{Engine, Limits};

let mut engine = Engine::builder()
    .hash_size(128)   // 换位表 128 MB
    .threads(4)       // Lazy SMP 4 线程
    .build();

let info = engine.search(
    Limits::new()
        .depth(12)
        .time(Duration::from_millis(500)),
);

if let Some(mv) = info.best_move {
    println!("best={mv} score={} depth={} nodes={} nps={} score={}",
        info.score, info.depth, info.nodes, info.nps, info.score);
}

从任意 FEN 开始

use chessai::Engine;

let mut engine = Engine::builder().build();
engine.set_fen("rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w")?;
println!("fen: {}", engine.fen());
println!("legal moves: {}", engine.legal_moves().len());
# Ok::<(), chessai::ChessAIError>(())

走子与对弈循环

use chessai::{Engine, Limits, Move};
use std::time::Duration;

let mut engine = Engine::builder().build();
let mv = Move::from_iccs("b2-e2")?;
assert!(engine.make_move(mv));

let reply = engine.search(Limits::new().time(Duration::from_millis(200)));
println!("engine plays: {:?}", reply.best_move);
# Ok::<(), chessai::ChessAIError>(())

迭代回调

search_with 在每个完成的迭代深度触发一次回调,便于向 UI/日志流式输出:

use chessai::{Engine, Limits};
use std::time::Duration;

let mut engine = Engine::builder().threads(2).build();
engine.search_with(
    Limits::new().depth(14).time(Duration::from_secs(2)),
    |info| println!("d={} score={} pv={:?}", info.depth, info.score, info.pv),
);

跨线程停止

stop_handle() 返回一个 Arc<AtomicBool>,任意线程写 true 即可请求搜索尽早返回当前最佳结果。

use chessai::{Engine, Limits};
use std::sync::atomic::Ordering;
use std::time::Duration;

let mut engine = Engine::builder().build();
let stop = engine.stop_handle();

// 在其他线程按 GUI 按钮时:
// stop.store(true, Ordering::Relaxed);

let info = engine.search(Limits::new().time(Duration::from_secs(5)));
# let _ = (stop, info);

公共 API

类型 说明
Engine / EngineBuilder 引擎主入口,搜索与状态管理
Position 不可变棋局视图(通过 engine.position() 获取)
Move 16 位压缩走法,支持 ICCS from_iccs / to_iccs
Square 0..=89 的格子索引,支持 ICCS (a0..i9)
Piece / PieceType 带颜色的棋子与棋子种类
Color Red / Black
Limits 搜索限制(深度、时间、节点)
SearchInfo 搜索结果快照(best_move、pv、score、nodes、nps、time)
ChessAIError 统一错误类型(FEN / ICCS 解析错误)

Engine 常用方法

  • Engine::builder() -> EngineBuilderhash_size(mb)threads(n)use_book(bool)build()
  • engine.set_fen(&str) -> Result<(), ChessAIError> — 加载 FEN,自动清空 TT 与历史
  • engine.reset_to_startpos() — 复位到开局
  • engine.fen() -> String — 导出当前 FEN
  • engine.side_to_move() -> Color
  • engine.legal_moves() -> Vec<Move>
  • engine.make_move(Move) -> bool — 伪合法校验 + 将军校验
  • engine.book_move() -> Option<Move> — 探询开局库
  • engine.search(Limits) -> SearchInfo
  • engine.search_with(Limits, |&SearchInfo| …) -> SearchInfo
  • engine.stop_handle() -> Arc<AtomicBool>

项目结构

chessai/
├── Cargo.toml
├── README.md
├── LICENSE
├── assets/
│   └── BOOK.DAT          # 内嵌开局库
└── src/
    ├── lib.rs            # 公共导出
    ├── engine.rs         # Engine / EngineBuilder
    ├── position.rs       # 棋局状态、make/undo、Zobrist 增量更新
    ├── movegen.rs        # 伪合法走法 / captures / quiets 生成
    ├── attacks.rs        # 马、象、兵、士、将的攻击表
    ├── magic.rs          # 车、炮的 Magic Bitboard 查表
    ├── bitboard.rs       # u128 位棋盘原语与 90 格掩码
    ├── search.rs         # Alpha-Beta、QS、迭代加深、Lazy SMP
    ├── picker.rs         # 分阶段走法挑选器
    ├── see.rs            # 静态交换评估
    ├── eval.rs           # 物质 + PST 增量评估
    ├── tt.rs             # 换位表(Zobrist 键 + lock 校验)
    ├── zobrist.rs        # Zobrist 随机键
    ├── book.rs           # 开局库探询
    ├── fen.rs            # FEN 解析/生成
    ├── limits.rs         # 搜索限制
    ├── mv.rs             # 走法压缩表示
    ├── square.rs         # 格子索引与 ICCS
    ├── piece.rs / color.rs
    ├── util.rs           # SplitMix64 RNG
    └── error.rs          # ChessAIError

性能优化

  • 搜索:PVS、NMP(空着裁剪)、LMR(后续走法减少)、Futility、SEE 裁剪
  • 走法排序:TT 走法 → captures(MVV-LVA) → killers → countermove → history
  • 换位表:Zobrist u64 键 + 32 位 lock 校验;置换策略按深度/年龄择优
  • Lazy SMP:主线程 id=0 驱动回调,工作线程按 Stockfish 风格 SKIP_SIZE/SKIP_PHASE 错开深度
  • 增量评估make_move/undo_move 同步维护物质分与 PST 分,避免全盘重算

从源码构建

git clone https://github.com/atopx/chessai.git
cd chessai
cargo build --release