NAME

Game::Gin - gin rummy as a reusable engine

VERSION

Version 0.01

SYNOPSIS

use Game::Gin;

my $game = Game::Gin->build(seed => $thirty_two_bytes, dealer => 'p1');

$game->turn;                 # 'p2', the non-dealer has the first say
$game->legal('p2');          # take or pass

my @out = $game->apply('p2', { kind => 'take' });
@out = $game->apply('p2', { kind => 'discard', card => $id, knock => 1 });

$game->scores;               # { p1 => 41, p2 => 12 }
$game->over;                 # 1 once somebody reaches the target
$game->result->{winner};

DESCRIPTION

Two-handed gin rummy, played over many deals to 100 points.

The engine does no input and no output: it never prints, never reads a handle and never calls rand. A match is a pure function of its seed and its moves, so a finished game can be replayed and checked by anybody once the seed is published. Game::Gin::Terminal is the only part of this distribution that touches a handle.

It is the engine behind the gin rummy at https://peer2peergames.com.

Which ruleset this is

The modern set, as Wikipedia states it: knock at ten, gin 25, undercut 25, big gin 31, box bonus 25 a hand, game bonus 100, target 100. The older published set, which Pagat gives and Wikipedia calls the early official rules, is gin 20 and undercut 10. They are two rulesets rather than two opinions, and taking a number from each would produce scoring no publication describes.

The player who reaches the target wins

The bonuses decide the margin, not the winner. A player who wins many small hands can finish with a higher total than the player who won the game, and still not have won it. See "match_result" in Game::Gin::Scoring.

The winner of a hand deals the next

Pagat's standard rule. Two variations exist and are not implemented: that the loser deals, and that the deal alternates. After a cancelled hand, which no source covers, the dealer deals again.

METHODS

build

Game::Gin->build(seed => $bytes, dealer => 'p1', target => 100);

Starts a match. Returns the game, or a Game::Gin::Error for a bad seed.

The moves a seat may make now, delegated to the current deal.

apply

$game->apply($seat, $move);

Applies a move. Returns the outcomes, or a Game::Gin::Error. When a deal ends, the outcomes carry a hand_end and then either a deal for the next one or a game_end.

scores

The running hand points, without bonuses. This is what decides when the match ends.

turn, over, result, deal, hands, number, dealer, seed, target

Where the match is. deal is the current Game::Gin::Deal, hands the results of the finished ones, and result the match result once it is over.

SEE ALSO

Game::Gin::Deal, Game::Gin::Scoring, Game::Gin::Deadwood, Game::Gin::Meld, Game::Gin::Deck, Game::Gin::Card.

AUTHOR

LNATION, <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under the Artistic License 2.0.