NAME
Game::Gin::Terminal - gin rummy at a prompt
VERSION
Version 0.01
SYNOPSIS
my $ui = Game::Gin::Terminal->new(mode => 'bot', level => 2, seat => 'p1');
$ui->play;
# or with no terminal at all, which is how it is tested
open my $in, '<', \$script;
open my $out, '>', \my $shown;
Game::Gin::Terminal->new(in => $in, out => $out, mode => 'watch')->play(seed => $seed);
DESCRIPTION
Every read and every print in this distribution is in this class. Nothing under Game::Gin:: touches a handle, which is what lets the engine be loaded by a web application, and that is only true because there is exactly one place where it stops being true.
in and out are attributes
So a whole game can be played with no terminal, which is what t/14-terminal.t does. An interface that can only be driven by a human is one that silently rots.
The cards
stock 24 upcard 7♥
┌─────────┐ ┌─────────┐
│░░░░░░░░░│ │7 │
│░░░░░░░░░│ │♥ │
...
┌───┌───┌───┌───┌───┌───┌───┌───┌───┌─────────┐
│7 │7 │7 │3 │4 │5 │A │K │2 │10 │
│♠ │♦ │♣ │♠ │♠ │♠ │♠ │♥ │♦ │♣ │
...
└───set────┘└───run────┘└──────loose 23───────┘
Eleven columns by nine rows, the rank and the suit in opposite corners and a pip in the middle, which is the same card Game::Cribbage deals.
The corner is what makes a hand fannable. Ten cards drawn in full are a hundred and ten columns; ten cards fanned are forty-seven, because a covered card only has to show the corner you would read it by, which is also how a hand is held. Under the fan a bracket marks each meld and says whether it is a set or a run, and what the rest of the hand is costing: grouping a hand by eye is the one chore a screen can take away.
The stock is drawn face down and the upcard face up, because choosing between those two piles is the first half of every turn. A pile with nothing in it is an empty space rather than a gap, so the table does not appear to end there.
"ascii" draws the suits as S H D C in a +-| frame for a terminal without the box characters, and colour is on when out is a terminal and NO_COLOR is unset.
METHODS
play
$ui->play(seed => $bytes, dealer => 'p1', limit => 20_000);
Plays a match to the end and returns the Game::Gin. With no seed it makes one. Stops if input runs out rather than looping.
render
$ui->render($seat);
The lines shown to a seat, as an arrayref: the deal and the score, the stock and the upcard drawn as cards, the hand fanned with a bracket under each meld, and whether it may knock.
show
render, printed.
table_lines
$ui->table_lines($deal, $seat);
The stock and the upcard, drawn side by side under their labels.
hand_lines
$ui->hand_lines($melding);
A hand from "best" in Game::Gin::Deadwood, fanned, with the brackets under it.
card_art
$ui->card_art($id);
One card as nine rows of eleven columns.
card_back, card_space
A card face down, and the outline of where a card would be.
fan
$ui->fan([ @ids ]);
Cards overlapped so that every one shows its corner and the last shows all of itself.
fan_width
How wide a fan of that many cards is, which is what the brackets are drawn from.
pretty
$ui->pretty($id); # K♥
A card's name for reading. What is typed is still KH.
card_named
$ui->card_named('K♥'); # 26
The card somebody typed, or undef. KH is the engine's spelling, and the two that a drawn card invites are taken as well: the pip instead of the letter, and 10 instead of T.
paint
Wraps text in a colour, or returns it untouched when colour is off.
human_move
Asks the seat on turn for a move and returns it, or undef when input runs out. A discard is named as a card; a knock is the same with ! after it.
bot_move
What Game::Gin::Bot would play for a seat.
is_human
Whether a seat is played from the keyboard, which depends on mode.
announce
One line for an outcome from the engine.
announce_result
The final score.
ask, say_to
The two places this distribution reads and writes.
game, in, out, mode, level, seat, ascii, colour
mode is bot (the default), hotseat or watch. seat is the seat a person plays when the mode is bot. ascii draws the cards without box characters or pips, and colour defaults to on for a terminal with NO_COLOR unset.
SEE ALSO
Game::Gin, and bin/gin.
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.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 437:
Non-ASCII character seen before =encoding in '7♥'. Assuming UTF-8