NAME
Game::Terminal::Kit::Steer - move a cursor the way the key points
VERSION
Version 0.05
SYNOPSIS
use Game::Terminal::Kit::Steer;
# a row or a list: an index and a step
$at = Game::Terminal::Kit::Steer::ring(scalar @drawn, $at, +1);
# a board: where each thing is on the screen, and a direction
my @points = map { [ $_->column, $_->row ] } @drawn;
my $next = Game::Terminal::Kit::Steer::nearest(
\@points, $at, Game::Terminal::Kit::Steer::way($key),
);
$at = $next if defined $next;
DESCRIPTION
A cursor has to go where the arrow key points on the screen. It stops doing so the moment it walks one list while the screen draws another: a hand held in the order it was dealt and drawn sorted into suits, a set of legal moves in the order the rules found them and drawn where they are on the board. Every item is still reachable, so nothing fails; right has just stopped meaning right.
Every function here therefore takes what was drawn, in the order or at the place it was drawn. Build the list the cursor walks from the same function the screen is drawn from, and hand that list over.
Indexes and points
For a row or a column of things, the cursor is an index into the drawn list and "ring" or "clamp" moves it.
For things scattered over a board, each has a point, [$x, $y], in columns and rows counted from the top left as the screen counts them, so down is a greater y. The cursor is still an index, into the list of points, and "nearest" or "axis" moves it. A direction is two numbers, the change in x and in y; "way" gives them for an arrow key, and a game with diagonals gives its own.
FUNCTIONS
None is exported.
ring
$at = Game::Terminal::Kit::Steer::ring($count, $at, $delta, $skip);
The index $delta on from $at among $count, going round at the ends. $skip, when given, is called with an index and returns true for one the cursor may not rest on; it is stepped over in the direction of travel. When every index is skipped the cursor stays where it is.
clamp
$at = Game::Terminal::Kit::Steer::clamp($count, $at, $delta, $skip);
The same, stopping at the ends. A cursor that would have to pass the end to find somewhere to rest stays where it is.
nearest
my $next = Game::Terminal::Kit::Steer::nearest(\@points, $at, $dx, $dy, %option);
The index of the point that is nearest in the direction given, or undef when nothing lies that way, in which case the cursor should stay. Nearest is the least distance along the direction plus twice the distance across it, so a thing straight ahead is preferred to a closer thing off to one side; between two that cost the same, the one less far across wins, and after that the one drawn first.
The options are cone, which when true leaves out a point further across than it is along, so that right never picks something that is mostly up; and skip, as for "ring".
axis
$at = Game::Terminal::Kit::Steer::axis(\@points, $at, $dx, $dy);
For a few things on a track: the points are put in order along the axis of the direction, left to right or top to bottom, and the cursor goes to the next or the one before. It stops at the ends.
rest
my $at = Game::Terminal::Kit::Steer::rest(\@items, sub { $_[0]{loose} });
Where a cursor should start: the first item the code reference accepts, else the first at all. It is called with the item and its index. An item that is a hash reference with a true skip is never chosen. A cursor that starts on the item the player usually means saves a key every turn.
way
my ($dx, $dy) = Game::Terminal::Kit::Steer::way('left'); # (-1, 0)
The direction of up, down, left or right; an empty list for any other key.
SEE ALSO
Game::Terminal::Kit, Game::Terminal::Kit::Keys.
AUTHOR
LNATION, <email at lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)