Expand description
§Gin Rummy Engine
Bots and strategy tooling for gin rummy, built on the gin-rummy mechanics crate. Where gin-rummy answers “what moves are legal?”, this crate answers “which move should I make?”
The design triangle:
Strategy: a decision procedure for one seat — take or pass the upcard, where to draw, what to shed, whether to knock, what to lay off.View: the information a seat may legally see. The underlyingRoundexposes both hands and the stock order; strategies never touch it. AViewshows only the seat’s own hand, the discard pile, the stock count, and what the opponent has revealed (cards taken from the pile, discards, declined upcards).Table: the driver. It owns theRound, tracks each seat’s knowledge, asks strategies for decisions, and applies them — so information hygiene holds by construction.
§Bots
HeuristicBot: deterministic and fast. Draws from the pile only when that strictly lowers deadwood, sheds the least useful card weighted by how dangerous it is to the opponent, knocks by a configurable threshold, and lays off greedily but never breaks its own melds.MonteCarloBot(featurerand): determinized Monte Carlo. At each decision it samples hidden worlds consistent with theView— opponent hands containing every known card, random stock orders over the unseen cards — rolls each out with the greedy policy, and picks the action with the best expected score.EaaiSimpleBot(featurerand): a port ofSimpleGinRummyPlayer, the baseline every entry of the EAAI-2021 Gin Rummy AI challenge was measured against. Deliberately weak and knob-free — it exists so that win rates against it are comparable across engines and papers.
§Benchmarks
EaaiSimpleBot is the yardstick: arena runs under --rules eaai (the
challenge’s round conditions), seats and the dealer alternating, seed 7.
Parenthesized ranges are 95% Wilson intervals, in percent, over 4000
rounds and over 500 (greedy) or 600 (mc:64) whole games.
| Bot vs baseline | Rounds won | Points/round | Games won |
|---|---|---|---|
greedy | 39.9% (38.4–41.4) | 9.17 vs 8.17 | 57.4% (53.0–61.7) |
mc:64 | 52.4% (50.8–53.9) | 9.51 vs 8.54 | 53.3% (49.3–57.3) |
mc:128 | 54.0% (52.4–55.5) | 10.19 vs 8.20 | — |
The default heuristic concedes rounds by design — it hunts gin while the
baseline knocks at the first opportunity — yet outscores it per round and
wins the matches, which is what its knobs are tuned for. For calibration,
EAAI-21 entries reported roughly 55–68% against this same baseline
(metrics vary by paper); comparisons stay approximate because this crate’s
match play rotates the deal to each round’s winner where the challenge
alternated dealers. Throughput in those same runs, single-threaded:
~8500 rounds/s for greedy vs the baseline, 5.8 rounds/s at mc:64, 3.4
at mc:128.
§Quick start
A bot-vs-bot round needs no features:
use gin_rummy::{Hand, Player, Round, Rules};
use gin_rummy_engine::{HeuristicBot, play_round};
let hands: [Hand; 2] = ["A23.456.789.T".parse()?, "TJQK.A23.456.".parse()?];
let (upcard, stock) = (rest[0], rest[1..].to_vec()); // the other 32 cards
let round = Round::from_deal(Rules::default(), Player::One, hands, upcard, stock)?;
let result = play_round(round, [&mut HeuristicBot::new(), &mut HeuristicBot::new()])?;
println!("{result:?}");With the (default) rand feature, deal and settle whole games:
use gin_rummy::{Game, Player, Rules};
use gin_rummy_engine::{HeuristicBot, MonteCarloBot, play_game};
let mut rules = Rules::default();
let mut game = Game::new(rules, Player::One);
let mut greedy = HeuristicBot::new();
let mut mc = MonteCarloBot::new(rand::rng()).samples(8);
let score = play_game(&mut game, [&mut greedy, &mut mc], &mut rand::rng())?;
println!("{} wins {} : {}", score.winner, score.totals[0], score.totals[1]);Writing your own bot is implementing Strategy’s four decisions against a
View; the driver handles all bookkeeping.
§Feature flags
rand(default): the Monte Carlo bot,Table::deal,play_game, and the examples. Disable it for a dependency-free heuristic-only build.parallel: Monte Carlo rollouts across the CPU cores via rayon. Decisions are bit-identical to the serial build, each just arrives faster; worthwhile at high sample counts. Off by default.
§Examples
play: play against a bot in the terminal —cargo run --example play(--bot mc,--rules classic, …)arena: bot-vs-bot tournaments with win-rate statistics —cargo run --release --example arena -- --rounds 1000 --p1 greedy --p2 mc:64
§Alternatives
No other open-source project ships gin rummy bots as a reusable library.
OpenSpiel and RLCard embed gin rummy environments for generic search
and reinforcement-learning algorithms (bring your own agent), and
gin-rummy-eaai is the EAAI-2021 challenge framework whose reference
baseline this crate ports as EaaiSimpleBot — precisely so the numbers
above stay comparable with the challenge literature.
Re-exports§
pub use gin_rummy;
Structs§
- Assessment
- One candidate action’s Monte Carlo assessment, for a solver or hint view
- Eaai
Simple Bot - The reference baseline of the EAAI-2021 Gin Rummy challenge
- Heuristic
Bot - A deterministic knowledge-based player
- Heuristic
Config - Tuning knobs for
HeuristicBot - Layoff
- One layoff onto the knocker’s spread
- Monte
Carlo Bot - A determinized Monte Carlo player
- Table
- A round in progress, with per-seat knowledge tracking
- View
- What one seat may legally see of a round
Enums§
- Draw
Action - Where to draw at the start of a normal turn
- Engine
Error - An error while driving a round
- Turn
Action - How to end a turn from an 11-card hand
- Upcard
Action - Response to the initial upcard offer
Traits§
- Strategy
- A decision procedure for one seat of gin rummy
Functions§
- play_
game - Deal and play rounds until the game is over, returning the settled score
- play_
round - Play one round to completion, one strategy per seat, indexed by
Player