NAME

Game::Durak::Table - the terminal's table, drawn as a grid of characters

VERSION

Version 0.01

SYNOPSIS

my $table  = Game::Durak::Table->new(width => 80, height => 24);
my $grid   = $table->screen($view, header => 'your move', footer => '1-6');
my $plain  = $table->lines($grid);      # for a test, or a dumb handle
my $shown  = $table->paint($grid);      # the same, with colour

DESCRIPTION

A table of cards drawn as a fixed grid: face up cards with an index in two corners, face down cards with a woven back, hands fanned so that every card's index is readable behind the one in front of it, and the bout laid out as an attack with its answer laid across it.

This module is the geometry and nothing else. It builds a grid and returns it; Game::Durak::Terminal is the only thing in the distribution that writes to a handle, and t/18-silent.t is the grep that keeps it that way.

Why a grid and not a list of lines

Colour is an escape sequence in the middle of a line, and a line with escapes in it has a length that is not its width. Anything that composes a screen out of coloured strings therefore gets its own arithmetic wrong the first time a card is red.

So the grid holds one character and one paint name per cell, and the colour is put on at the very end by paint. lines serialises the same grid without any colour at all, which is what a test reads: the whole screen can be asserted character by character with no terminal anywhere near it, and the assertion is about the layout rather than about the escapes.

A fan shows every index

A durak hand reaches eighteen cards after two big bouts are taken, and twenty in a measured deal. A player has to be able to read all of them to count, so a hand is fanned: each card but the last shows its leftmost columns and the last is drawn whole, and the pitch closes up if the hand is wider than the screen rather than running off the edge.

The index in a sliver is the rank ON ONE ROW AND THE SUIT ON THE NEXT, which is how a real card is printed and is not decoration here. A twenty card hand closes the pitch to three columns; an index written across the row would show a ten as 10 with its suit covered by the next card, and a hand with two tens in it would be unplayable. Down the rows it is readable at any pitch.

A card that cannot be played right now is drawn in grey and its number is drawn quiet; a card that can is drawn in its own ink with its number lit. The set comes from the view's legal, so the screen cannot disagree with the engine about what may be played. When nothing in the hand is playable, every card is drawn in its own ink rather than the whole hand going grey, because a hand greyed out end to end reads as a bug.

METHODS

width, height, ascii

The screen, and whether to draw it out of box drawing characters and suit glyphs or out of ASCII. Defaults are 80 by 24, which is a terminal nobody has resized.

blank

An empty grid: every cell a space, every cell painted baize.

put, band, lay

Write a string into the grid at a row and column, fill a whole row, and write a box of lines at a row and column. All three clip at the edges rather than growing the grid, because a screen that grows is a screen that scrolls.

card, back, fan_of, fan_back

One card face up, one face down, and the four column slivers of each for a fan. Each returns an arrayref of five strings.

fan

Lays a row of cards at a row and column and returns the column it ended at. face => 0 draws them backs up; lit is a hashref of the positions that are playable.

pitch_for

The number of columns between one fanned card and the next, given where the fan starts and how many cards are in it.

screen

The whole table for one seat's view: their hand face down and counted, the trump and the two counts, the talon with the turn up lying under it, the bout, your own hand numbered and fanned, and a bar at the top and the bottom for whatever the terminal wants to say.

It also says WHICH SIDE OF THE BOUT YOU ARE ON, over the table, and that is not decoration. Everything else on the screen is the same shape whether you are attacking or defending: the same cards in the same places, the same hand lit the same way. The one thing that changes is what playing a card MEANS, and a player who has lost track of that plays a card that beats nothing. The line comes from the view's phase and turn, so it says what the other seat is doing while it is their move rather than going blank.

lit_for

The positions in a hand that the view's legal can play, counting from zero.

lines, paint

The grid as plain strings, and the grid as strings with colour.

suit_glyph, ink_of, index_of

A suit as a glyph or a letter, the colour a card's suit is drawn in, and the two or three characters that go in a card's corner. The ten is 10 and never T: the engine spells it T because a card id there is two characters, and a person reading a table has never heard of that.

SEE ALSO

Game::Durak::Terminal, Game::Durak::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.