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