1 个不稳定版本
0.1.0 | 2023年10月31日 |
---|
#290 在 游戏 中
150KB
3K SLoC
AyaPoker
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版,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
- zlib许可证 (LICENSE-ZLIB 或 https://opensource.org/license/zlib/)
。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您提交的任何有意包含在作品中的贡献都将如上所述多许可,没有任何额外的条款或条件。
依赖关系
~0–9.5MB
~51K SLoC