#德州扑克 #纸牌 #无标准库

无标准库 aya_poker

支持大多数流行扑克变种的快速扑克牌面评估

1 个不稳定版本

0.1.0 2023年10月31日

#290游戏

Zlib OR Apache-2.0 OR MIT

150KB
3K SLoC

AyaPoker

Latest Release Documentation Minimum Supported Rust Version 1.64

AyaPoker 是一个基于 OMPEval C++ 手牌评估器(https://github.com/zekyll/OMPEval)的 Rust 库,支持大多数流行的扑克变体。

功能

  • 可用于对标准扑克、五点低牌、七点低牌、六或更好(短牌)、奥马哈、奥马哈高低、Badugi 或 Baduci 的手牌进行排名。
  • 可评估 0 到 7 张牌的手牌,缺失的牌计为最差的踢子,允许在 Stud 游戏中使用。
  • 使用编译时生成的完美哈希函数查找表,以实现出色的运行时性能和快速初始化。
  • 拥有全面的测试套件,以确保每个变体的手牌排名规则的正确实现。

标志

此 crate 具有以下 Cargo 功能

  • std:默认情况下,aya_poker 是一个 !#[no_std] crate,但可以通过 std 功能进行编译,以允许使用系统生成的随机种子初始化 Deck
  • colored:使用 colored 以颜色显示牌和手牌。
  • colored-4color:与 colored 相同,但使用四色牌组。

示例

use std::cmp::Ordering;

use aya_poker::{base::*, deck::Deck, poker_rank};

const SEED: u64 = 42;
const SAMPLE_SIZE: usize = 100_000;

fn main() -> Result<(), ParseError> {
    // We can initialize cards by specifying the rank and suit,
    // and then use collect to combine the cards into a Hand
    let player = [
        Card::new(Rank::King, Suit::Hearts),
        Card::new(Rank::King, Suit::Clubs),
    ]
    .iter()
    .collect();

    // Or, first parse the cards from strings
    let opponent = ["Js".parse::<Card>(), "Qs".parse::<Card>()]
        .iter()
        .copied()
        .collect::<Result<Hand, ParseError>>()?;

    // Or, parse a space-separated string of cards as a Hand
    let board = "Ah 5s Ts".parse()?;

    let equity = equity_calculator(&player, &opponent, &board);
    println!(
        "{} has {:.1}% equity on {} against {}.",
        player,
        100.0 * equity,
        board,
        opponent
    );

    Ok(())

}

fn equity_calculator(
    player: &Hand,
    opponent: &Hand,
    board: &Hand,
) -> f64 {
    // To simulate board run-outs, we begin by preparing a deck
    // that doesn't contain the already dealt-out cards
    let available_cards = CARDS
        .iter()
        .filter(|c| !player.contains(c))
        .filter(|c| !opponent.contains(c))
        .filter(|c| !board.contains(c));
    let mut deck = Deck::with_seed(available_cards, SEED);

    let mut pots_won = 0.0;
    for _ in 0..SAMPLE_SIZE {
        // Then, for each run we draw cards to complete the board
        deck.reset();
        let missing = 5 - board.len();
        let complete_board = board
            .iter()
            .chain(deck.deal(missing).unwrap().iter())
            .collect::<Hand>();

        // Evaluate the player's hand given the completed board
        let mut player_hand = *player;
        player_hand.extend(complete_board.iter());
        let player_rank = poker_rank(&player_hand);

        // Evaluate the opponent's hand
        let mut opponent_hand = *opponent;
        opponent_hand.extend(complete_board.iter());
        let opponent_rank = poker_rank(&opponent_hand);

        // And record the player's share of the pot for the run
        match player_rank.cmp(&opponent_rank) {
            Ordering::Greater => pots_won += 1.0,
            Ordering::Less => {}
            Ordering::Equal => pots_won += 0.5,
        };
    }

    pots_won / SAMPLE_SIZE as f64
}

性能

以下所有基准测试都在 AMD Ryzen 5 2600 上运行,并使用 lto = "thin" 编译。

标准 / 五点低牌 / 七点低牌 / 六加

标准扑克、五点低牌和六或更好的(短牌)扑克是最快的,因为它们代表了查找表方法的理想场景:它们只需要计算 Hand 值,然后使用它进行单次查找。

七点低牌由于必须遍历非同花牌组合,对于超过 5 张牌的情况速度略慢。

Badugi / Baduci

由于目前 AyaPoker 只具有非重叠花色的等级组合的查找表,因此 Badugi / Baduci 的评估速度要慢得多,需要对每种牌的组合进行多次查找。

奥马哈

AyaPoker不包含任何奥马哈牌型的查找表,因为它们在编译时计算过于庞大,但由于标准牌型和五低牌型查找表的出色性能,仍然能够通过遍历所有五张牌组合来实现奥马哈牌型的可接受性能。

许可证

根据您的选择,受以下任何一种许可证的许可:

贡献

除非您明确声明,否则根据Apache-2.0许可证定义,您提交的任何有意包含在作品中的贡献都将如上所述多许可,没有任何额外的条款或条件。

依赖关系

~0–9.5MB
~51K SLoC