Rust poker hand evaluator for Texas Hold'em and Omaha with Python bindings via PyO3.
Ported from the C poker-eval library.
- Texas Hold'em — evaluate best 5-card hand from 2 hole + 0–5 board cards
- Omaha — evaluate best hand using exactly 2 hole + 3 board cards (4, 5, or 6 hole cards supported)
- Returns a comparable
u32hand value (higher = better) - Supports all standard hand types: NoPair, OnePair, TwoPair, Trips, Straight, Flush, FullHouse, Quads, StraightFlush
- Equity calculator — enumerate all board runouts to compute win/tie percentages for 2+ hands
- PyO3 Python bindings
import poker_eval_rs as pe
# Evaluate a hand
result = pe.evaluate_holdem(
hole_cards=["Ah", "Kh"],
board_cards=["Qh", "Jh", "Th", "2c", "3d"]
)
print(result.hand_type) # "StraightFlush"
print(result.description) # "StraightFlush (A)"
# Equity on the flop
results = pe.calc_equity_holdem(
hands=[["As", "Ah"], ["Ks", "Kh"]],
board=["2c", "5d", "9s"]
)
for i, r in enumerate(results):
print(f"Hand {i+1}: win={r.win_pct:.1f}%")
# Hand 1: win=91.6% Hand 2: win=8.4%
# Preflop equity
results = pe.calc_equity_holdem(
hands=[["As", "Ah"], ["7s", "8s"]],
board=[]
)
# Hand 1: win=77.9% Hand 2: win=21.6%import poker_eval_rs as pe
# Evaluate a hand (4 hole cards)
result = pe.evaluate_omaha(
hole_cards=["Ah", "Kh", "Qs", "Jc"],
board_cards=["Ts", "9h", "8d"]
)
print(result.hand_type) # "Straight"
print(result.description) # "Straight (Q)"
# Equity on the flop (supports 4, 5, or 6 hole cards)
results = pe.calc_equity(
hands=[["As", "Ah", "Ks", "Kh"], ["Qs", "Qd", "Js", "Jh"]],
board=["2c", "3d", "4s"]
)
# Hand 1: win=83.2% Hand 2: win=16.8%Compare hand values to determine the winner — value is a plain integer where higher beats lower:
import poker_eval_rs as pe
board = ["Ts", "9h", "8d", "4c", "2s"]
h1 = pe.evaluate_omaha(["Ah", "Kh", "Qs", "Jc"], board)
h2 = pe.evaluate_omaha(["9d", "8c", "7h", "6d"], board)
if h1.value > h2.value:
print(f"Hand 1 wins: {h1.description}")
elif h2.value > h1.value:
print(f"Hand 2 wins: {h2.description}")
else:
print("Split pot")The board parameter accepts 0 (preflop), 3 (flop), 4 (turn), or 5 (river) cards. For incomplete boards, all possible runouts are enumerated. The returned EquityResult has win_pct, tie_pct, and (for complete boards) hand_type, description, and value.
use poker_eval_rs::card::parse_card;
use poker_eval_rs::omaha::evaluate_omaha;
use poker_eval_rs::holdem::evaluate_holdem;
// Omaha
let hole: Vec<u8> = ["Ah", "Kh", "Qs", "Jc"]
.iter().map(|c| parse_card(c).unwrap()).collect();
let board: Vec<u8> = ["Ts", "9h", "8d"]
.iter().map(|c| parse_card(c).unwrap()).collect();
let hand_value = evaluate_omaha(&hole, &board).unwrap();
// Hold'em
let hole: Vec<u8> = ["Ah", "Kh"]
.iter().map(|c| parse_card(c).unwrap()).collect();
let board: Vec<u8> = ["Qh", "Jh", "Th"]
.iter().map(|c| parse_card(c).unwrap()).collect();
let hand_value = evaluate_holdem(&hole, &board).unwrap();# Rust tests
cargo test
# Python wheel (requires maturin)
uv venv .venv
uv pip install --python .venv/bin/python maturin
.venv/bin/maturin develop --releaseCards are strings in the format <rank><suit>:
| Rank | 2 3 4 5 6 7 8 9 T J Q K A |
|---|---|
| Suit | h d c s (hearts, diamonds, clubs, spades) |
Examples: Ah = Ace of hearts, Tc = Ten of clubs, 2s = Two of spades.
| Module | Description |
|---|---|
src/lookup.rs |
Const lookup tables (8192 entries for 13-bit rank masks) |
src/card.rs |
Card representation (u8 0–51) and string parsing |
src/hand_value.rs |
Hand value encoding and description |
src/eval.rs |
Core 5-card hand evaluator |
src/omaha.rs |
Omaha evaluator: enumerates C(hole,2) × C(board,3) |
src/holdem.rs |
Hold'em evaluator and equity calculator |
src/equity.rs |
Omaha equity calculator: enumerates board completions |
src/lib.rs |
PyO3 bindings and module entry point |
GPL-3.0 (matching the original poker-eval license).