xiangqi

    中国象棋规则与搜索本地候选

    Download zip
    Version
    0.4.0
    License
    MIT
    Last updated
    4 hours ago
    Downloads
    1

    #可执行 API 示例

    增加同步 UCCI 命令核心:握手、准备、局面、走子、有限深度搜索及退出。这些例子调用公开 API,并随 moon test 执行。

    ///|
    test "UCCI ready position go quit session" {
    let e = @xiangqi.Engine::new()
    assert_true(e.command("ucci").has_suffix("ucciok"))
    assert_eq(e.command("isready"), "readyok")
    assert_eq(e.command("position startpos moves h2e2"), "")
    assert_true(e.command("go depth 1").has_prefix("bestmove "))
    assert_true(
    try {
    ignore(e.command("position startpos moves a0a9"))
    false
    } catch {
    _ => true
    },
    )
    assert_eq(e.command("quit"), "")
    assert_true(
    try {
    ignore(e.command("isready"))
    false
    } catch {
    _ => true
    },
    )
    }

    持续进程及异步停止见 node tools/engine.mjs。正式重复/长将/长捉裁决、开局库与专业棋力仍未完成。

    ChessError

    pub suberror ChessError {
    Invalid(String)
    } derive(
    Debug
    )

    Board

    pub struct Board {
    cells : Array[Int]
    red : Bool
    } derive(Eq,
    Debug
    )

    Board::best_move

    fn Board::best_move(self : Board, depth : Int, node_limit? : Int) -> Move? raise ChessError

    Board::fen

    fn Board::fen(self : Board) -> String

    Board::in_check

    fn Board::in_check(self : Board, red : Bool) -> Bool

    Board::legal_moves

    fn Board::legal_moves(self : Board) -> Array[Move]

    Board::perft

    fn Board::perft(self : Board, depth : Int) -> Int raise ChessError

    Board::play

    fn Board::play(self : Board, coordinate : String) -> Board raise ChessError

    Board::search

    fn Board::search(self : Board, depth : Int, node_limit? : Int, should_stop? : () -> Bool, on_iteration? : (SearchResult) -> Unit, history? : Array[String]) -> SearchResult raise ChessError

    Iterative alpha-beta with capture quiescence and a bounded move-order cache. Cancellation returns the last completed iteration (or a legal fallback). Repeated search-path positions score 0 as a heuristic, not tournament rules.

    Engine

    pub struct Engine {
    game : Game
    closed : Bool
    } derive(
    Debug
    )

    Synchronous, transport-independent UCCI command session.

    Engine::command

    fn Engine::command(self : Engine, line : String) -> String raise ChessError

    Engine::fen

    fn Engine::fen(self : Engine) -> String

    Engine::new

    fn Engine::new() -> Engine

    Engine::search

    fn Engine::search(self : Engine, depth : Int, node_limit? : Int, should_stop? : () -> Bool, on_iteration? : (SearchResult) -> Unit) -> SearchResult raise ChessError

    Engine::status

    fn Engine::status(self : Engine) -> String

    Game

    pub struct Game {
    positions : Array[Board]
    } derive(
    Debug
    )

    Bounded game history with simple threefold/perpetual-check adjudication. Long-chase and tournament-specific exceptions are outside this policy.

    Game::board

    fn Game::board(self : Game) -> Board

    Game::new

    fn Game::new(board : Board) -> Game

    Game::play

    fn Game::play(self : Game, coordinate : String) -> Unit raise ChessError

    Replay legal moves, including analysis lines beyond an earlier repetition.

    Game::search

    fn Game::search(self : Game, depth : Int, node_limit? : Int, should_stop? : () -> Bool, on_iteration? : (SearchResult) -> Unit) -> SearchResult raise ChessError

    Game::status

    fn Game::status(self : Game) -> String

    Move

    pub(all) struct Move {
    from : Int
    to : Int
    } derive(Eq,
    Debug
    )

    Move::coordinate

    fn Move::coordinate(self : Move) -> String

    SearchResult

    pub(all) struct SearchResult {
    best : Move?
    score : Int
    depth : Int
    nodes : Int
    stopped : Bool
    } derive(Eq,
    Debug
    )

    Last fully completed iteration; depth 0 is the legal fallback before any iteration completed. Scores are from the root side, in internal pawn units.

    initial

    fn initial() -> Board

    parse_fen

    fn parse_fen(fen : String) -> Board raise ChessError