Skip to main content

Crate gin_rummy_engine

Crate gin_rummy_engine 

Source
Expand description

§Gin Rummy Engine

Crates.io Docs.rs Build Status

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 underlying Round exposes both hands and the stock order; strategies never touch it. A View shows 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 the Round, 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 (feature rand): determinized Monte Carlo. At each decision it samples hidden worlds consistent with the View — 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 (feature rand): a port of SimpleGinRummyPlayer, 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 baselineRounds wonPoints/roundGames won
greedy39.9% (38.4–41.4)9.17 vs 8.1757.4% (53.0–61.7)
mc:6452.4% (50.8–53.9)9.51 vs 8.5453.3% (49.3–57.3)
mc:12854.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
EaaiSimpleBot
The reference baseline of the EAAI-2021 Gin Rummy challenge
HeuristicBot
A deterministic knowledge-based player
HeuristicConfig
Tuning knobs for HeuristicBot
Layoff
One layoff onto the knocker’s spread
MonteCarloBot
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§

DrawAction
Where to draw at the start of a normal turn
EngineError
An error while driving a round
TurnAction
How to end a turn from an 11-card hand
UpcardAction
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