#poker #lookup-tables #monte-carlo #equity

bin+lib poker_eval

Texas Hold'em poker hand equity evaluator

1 unstable release

0.1.0 Feb 5, 2024

#376 in Games


Used in poker_server

MIT license

85KB
2K SLoC

Poker hand evaluator

This crate contains fast Texas hold'em poker hand equity evaluator.

Each of the 52 deck cards is attributed an integer key.
The 9 least significant bits encode the card suit, the others 23 the card face.

This encoding, based on keys precalculated by crate poker_keygen, in is such that it enables to uniquely identify a hand rank by a few simple operations (sums, bit mask, bit shift, and table lookups).

To use this crate as a server see poker_server.

Eval

Building the lookup is performed in sequence:

5-card hands

Build 5-card lookup tables: five::build_tables.
Which enables function get_rank_five.

use poker_eval::eval::five::{build_tables, get_rank_five};

// precalculate lookup tables
let t5 = build_tables(false);

// run the evaluation multiple times
let rank = get_rank_five(&t5, [31, 26, 50, 16, 49]);
assert_eq!(rank, 3971)

7-card hands

Build 7-card lookup tables: seven::build_tables using function eval:7️⃣:get_rank_seven built on eval:5️⃣:get_rank_five.
Which enables function get_rank.
This function is the entry point to evaluate a player hand.

use poker_eval::eval::seven::{build_tables, get_rank};

// precalculate lookup tables
let arc_t7 = build_tables(false);

// run the evaluation multiple times
let rank = get_rank(&arc_t7, [5, 4, 18, 31, 34, 48, 22]);
assert_eq!(rank, 1689)

Calc

From function get_rank, 2 calculation functions are implemented:

  • deterministic, ie. exhaustive
  • monte carlo

Deterministic

Function calc_equity_det:

  • Calculate the equity of all players hands through exhaustive simulation.
  • This requires all players cards to be known.
  • This is feasible because in all cases, the number of simulations is small - and the evaluator fast.
use poker_eval::eval::seven::build_tables;
use poker_eval::calc::equity_det::calc_equity_det;

// precalculate lookup tables
let arc_t7 = build_tables(true);

// then you can call calc_equity_det multiple times
let equity = calc_equity_det(
    // clone of Arc<TableSeven>
    arc_t7.clone(),  
    // players cards  
    vec![[7, 8], [22, 27]],  
    // table cards  
    vec![51, 30, 41],  
    // verbose  
    true
);
println!("equity = {:?}", equity);
//Ok([[0.23131312, 0.10707071], [0.55454546, 0.10707071]])

Monte carlo

Function calc_equity_mc:

  • Calculate the equity of the first player though monte carlo simulation.
  • This does not require all players to be known.
  • Because the number of cases is potentially massive, a number of simlations must be specified.
use poker_eval::eval::seven::build_tables;
use poker_eval::calc::equity_mc::calc_equity_monte_carlo;

// precalculate lookup tables
let arc_t7 = build_tables(true);

// then you can call calc_equity_monte_carlo multiple times
let equity = calc_equity_monte_carlo(
    // clone of Arc<TableSeven>
    arc_t7.clone(),
    // player cards
    vec![vec![8, 9], vec![11, 28], vec![]],
    // table cards
    vec![15, 47, 23, 33],
    // number of game
    100_000_000,
);
println!("equity = {:?}", equity);
// Ok(HandEquity { win: 0.3167, tie: 0.0 })

Dependencies

~0.8–1.4MB
~33K SLoC