#棋盘 # #棋盘 #人工智能 #桌面游戏

无需 std 程序+库 chess-engine

一个无需依赖即可在任何地方运行的独立棋引擎库

3 个版本

0.1.2 2021 年 9 月 27 日
0.1.1 2021 年 9 月 27 日
0.1.0 2021 年 1 月 27 日

158游戏

每月 38 次下载
dune 中使用

MIT 许可证

2MB
2K SLoC

包含 (WOFF 字体, 99KB) fontawesome-webfont.woff, (WOFF 字体, 78KB) fontawesome-webfont.woff2, (WOFF 字体, 45KB) open-sans-v17-all-charsets-300.woff2, (WOFF 字体, 41KB) open-sans-v17-all-charsets-300italic.woff2, (WOFF 字体, 45KB) open-sans-v17-all-charsets-600.woff2, (WOFF 字体, 43KB) open-sans-v17-all-charsets-600italic.woff2更多.

♔棋引擎♚

一个无需依赖即可在任何地方运行的独立棋引擎库。

Donate Open Source

演示 | 文档 | 联系我

用 Rust🦀💖 编写

为什么编写一个棋引擎?

首先,Tom7 的这个视频 是这个项目的灵感来源。他非常出色,我强烈建议您观看他的内容。

我非常喜欢棋。它绝对是我最喜欢的游戏之一。然而,当我尝试编写数字下棋的程序(尤其是在编译型语言中)时,我总是感到失望。尽管存在几个惊人的引擎,但几乎找不到一个整洁的库来用于棋类编程,并且能在所有设备上运行。

chess-engine 是我对这个问题的解决方案。如果您需要一个可以在嵌入式设备、终端、桌面(带图形界面)网络 上运行的棋引擎,这可能就是您的最佳选择。

它是如何工作的?

这个特定的 AI(以及大多数其他棋类 AI)使用 Minimax 算法,并结合 Alpha-Beta 剪枝 进行优化。

现在,让我们来分解一下。

Minimax 算法本质上会递归地遍历所有可能的走法,并在走法执行后评估所有棋盘。如果一个棋盘更倾向于积极,它将 鼓励 执行其父节点走法,但如果一个棋盘倾向于消极,它将 反对 执行给定的走法。

Minimax

此外,当AI试图看到除了当前棋盘之外的棋局时,它将假设人类玩家总是做出最佳走法。因此,电脑几乎从不犯错。这使得电脑几乎总是比玩家做出更客观的走法。

嵌入网页

因为它没有依赖项,所以使用wasm将其嵌入网页浏览器非常简单。试试自己玩吧!

平均AI设置

Try playing it yourself!

用法

Board结构有几个不同的方法,允许用户从给定位置生成走法,包括get_best_next_moveget_worst_next_moveget_legal_moves。这些方法特别适用于编写与AI对战的棋类AI。

fn main() {
    let board = Board::default();

    // Get the best move with 4 moves of lookahead
    let best_move = board.get_best_next_move(4);
    // Get the worst move with 3 moves of lookahead
    let worst_move = board.get_worst_next_move(3);

    // Get all of the possible legal moves for the given player
    let legal_moves = board.get_legal_moves();
    // Print the board
    println!("{}", board);

    print!("CPU chose to ");
    match best_move {
        Move::Piece(from, to) => println!("move {} to {}", from, to),
        Move::KingSideCastle => println!("castle kingside"),
        Move::QueenSideCastle => println!("castle queenside"),
        Move::Resign => println!("resign")
    }
}

为了增加变化或更高级的玩法,可以考虑编写一个AI,它首先使用已知的开局来构建更好的位置,然后再使用get_best_next_move方法!

自定义棋盘

此外,用户可以创建自己的自定义Board对象,而不仅仅是默认对象。这是通过使用BoardBuilder结构来完成的。BoardBuilder结构支持启用和禁用王车易位,放置行和列的棋子,以及放置单个棋子。

请注意,在使用BoardBuilder时,王车易位默认是禁用的!

玩群体象棋变体

Play the Horde Chess Variant
fn main() {
    // `BoardBuilder::new()` returns an empty board
    // with castling disabled.
    // Creating a board builder from another board
    // structure will preserve
    // all settings from the board (such as castling
    // and the last en-passant move).

    // This BoardBuilder constructs the "Horde" chess variant!
    let board = BoardBuilder::from(Board::default())
            .row(Piece::Pawn(WHITE, A1))
            .row(Piece::Pawn(WHITE, A2))
            .row(Piece::Pawn(WHITE, A3))
            .row(Piece::Pawn(WHITE, A4))
            .piece(Piece::Pawn(WHITE, F5))
            .piece(Piece::Pawn(WHITE, G5))
            .piece(Piece::Pawn(WHITE, B5))
            .piece(Piece::Pawn(WHITE, C5))
            .build();

    // The CPU can also play variants!
    let cpu_move = board.get_best_next_move(3);
    
    match board.play_move(cpu_move) {
        GameResult::Continuing(next_board) => {
            println!("{}", next_board);
        }

        GameResult::Victory(winner) => {
            // You can use the ! operator on a player's
            // color to invert.
            println!("{} loses. {} is victorious.",
              !winner, winner
            );
        }

        GameResult::IllegalMove(x) => {
            eprintln!("{} is an illegal move.", x);
        }

        GameResult::Stalemate => {
            println!("Drawn game.");
        }
    }
}

关于作者

网站 | 博客 | GitHub

我是一名大学生,主要在课间30分钟的空闲时间做这样的副项目。如果您喜欢我的项目,请考虑通过为我买咖啡来支持我!

Buy Me A Coffee

无运行时依赖