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.
legal
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.