NAME
Game::Fanorona::Terminal - fanorona in a terminal, by arrow key or by typed move
VERSION
Version 0.03
SYNOPSIS
use Game::Fanorona::Terminal;
exit Game::Fanorona::Terminal->new(human => 'black', level => 4)->start;
Most people want the program, fanorona, which is this with options.
DESCRIPTION
A game of Game::Fanorona played against Game::Fanorona::Bot, between two people at one keyboard, or by the program against itself.
It plays in one of two ways. On a terminal whose keys it can read one at a time, a move is built on the board with the arrow keys. Anywhere else, and whenever it is asked to, it reads a line at a time: a move written out, or a command. The second way needs nothing but two filehandles, so a whole game can be played through a pipe.
The board
5 X---X---X---X---X---X---X---X---X Black X 22 left taken 0
| \ | / | \ | / | \ | / | \ | / |
4 X---X---X---X---X---X---X---X---X
| / | \ | / | \ | / | \ | / | \ |
3 X---O---X---O---+---X---O---X---O
| \ | / | \ | / | \ | / | \ | / |
2 O---O---O---O---O---O---O---O---O
| / | \ | / | \ | / | \ | / | \ |
1 O---O---O---O---O---O---O---O---O White O 22 left taken 0
a b c d e f g h i
Every line a stone can step along is drawn. A point with a diagonal running into it is one a stone can leave diagonally; a point with none is not.
The two sides differ in shape as well as in colour: O and X in letters, a ring and a disc otherwise. A mark is a pair of brackets round the point, and with colour a ground behind it as well, so that no mark depends on colour:
[O] the cursor
<O> the stone that is moving
(+) a point it may step to
{*} a stone this move takes, shown where it stood
:O: the last move: where the stone went, and :*: what it took
{a} what a step would take by approach
{w} what the same step would take by withdrawal
Beside the board are the stones each side has left and has taken, and, once half the limit has gone by, how many moves running have taken nothing.
Choosing a move with the keys
The cursor walks over the stones that can move and over no others. The arrow keys move it to the nearest such stone that way; Tab goes round them in the order they are drawn. Enter picks the stone up.
With a stone picked up, the arrow keys move a second cursor over the points it may step to, and Enter steps it there. Every point is reached that way, the diagonal ones too: up and then right for the point up and to the right. A step can also be made with one key: y, b and n are up-left, down-left and down-right, and the numeric pad has all eight, 9 for up-right. The board then shows the position as it would be: the stone where it has got to and the stones it has taken gone, each marked where it stood. The counts beside the board are of that position too.
When one step could take either the row ahead of the stone or the row behind it, the board marks both rows and waits for a or w. Nothing is chosen for the player.
After a step that has taken, the stone may go on to take again. With the cursor on no point, Enter plays the move as it stands, which is how a player stops; a move is never played until that Enter is pressed, even when only one move is possible. Backspace takes the cursor off a point, and then takes back one step; Escape takes back all of them. The space bar does whatever Enter would. What the other side last played stays written above the board the whole time.
h shows the move the program would play, built on the board and waiting for Enter or Escape. ? lists the keys, R gives the rules, : takes a command and q stops.
u takes back your last move and the program's reply to it; between two people at one keyboard it takes back one move. r plays again what u took back, until another move is made. Both work on the board and once the game is over, where u takes back the move that ended it. With nothing to take back or play again, a line above the board says so and nothing changes; with the program playing both sides there is never anything. The line under the board names whichever of the two would do something.
Typed moves and commands
A move is the points the stone stands on, joined by hyphens, with A or W after each step that takes: d2-e3A, h3-g3W-h4W. The letter may be left off a move of one step when that step can take only one way.
moves the first step of every legal move, and what it would take
hint what the program would play
board draw the board again
undo take back your last move, and the reply to it
redo play again what undo took back
level N how hard the program plays, 1 to 5
side WHO white, black, both or neither
new another game; new telo and new dimy change the board
save FILE write the game to a file
load FILE read one back
draw offer a draw; accept and decline answer one
resign give the game up
rules the rules
help the keys and the commands
quit stop
METHODS
new
my $terminal = Game::Fanorona::Terminal->new(%options);
Every option is also an accessor of the same name.
- human
-
white(the default),black,bothorneither: the side or sides played from the keyboard. Anything else croaks. - level
-
1 to 5, 3 by default: which of "levels" in Game::Fanorona::Bot the program plays at. Anything else croaks.
- variant
-
What "new" in Game::Fanorona takes as
variant: a name such astelo, a hash of fields, or a Game::Fanorona::Variant. - game
-
A Game::Fanorona to carry on with, in place of a new one.
- in, out
-
The filehandles. Standard input and standard output by default.
- interactive
-
Whether
outis a screen to be redrawn. True by default wheninis a terminal. - colour
-
Whether to paint. On by default on a terminal, unless
NO_COLORis set. - unicode
-
Whether the stones are a ring and a disc, or the letters
OandX. It followscolourby default. - picking
-
Whether moves are chosen with the keys. On by default on a terminal, and turned off when the keys cannot be read one at a time, which needs Term::ReadKey.
-
Whether "start" first asks for the side, the level and the board. Off by default.
- width
-
The width of the window in columns. By default it is asked of the terminal each time the board is drawn. When the board does not fit, a line saying how wide it needs to be is drawn in its place, and no key but
qdoes anything until it fits. - pause
-
Whether to wait a moment between moves when the program plays both sides.
- keysource
-
A code reference called for each character in place of the keyboard, handed a true value when it should wait for one. It returns one character, or
undefat the end. This is how the tests press keys.
options
my $fields = Game::Fanorona::Terminal->options;
The options a person would set before a game, in the order a launcher shows them. Each is a hash reference with a name, a type and a help, and min and max or choices where the type has them. A new list is returned each time.
side-
One of
white,black,both,neither: your side; White moves first. level-
A whole number from 1 to 5: how hard the program plays.
variant-
One of
sivy,dimy,telo: the board: nine by five, five by five, or three by three.
run
exit Game::Fanorona::Terminal->run(@ARGV);
The whole command line program as a class method: parses the options the fanorona program documents, builds the terminal, plays, and returns the exit status rather than calling exit: 0 when the game was left in the ordinary way, 2 for a bad option, a stray word, a refused value or a file that could not be loaded, with the reason and the usage on STDERR. --help and --version print to STDOUT and return 0. Given none of --side, --level, --variant and --load, and a terminal whose keys it can read, it begins by asking for the three. Signal handlers are local to the call and the keyboard is given back on every way out, so a launcher such as Game::Terminal can call it in its own process and carry on afterwards. Colour is off under NO_COLOR as well as off a terminal.
start
my $status = $terminal->start;
Plays until the player stops or the input ends, and returns 0. The keyboard is given back as it was found, on the way out and when interrupted.
command
my $stop = $terminal->command('d2-e3A');
Does one line: a command, or else a move. Returns true when the line asks to stop.
load
$terminal->load('saved.txt') or die;
Replaces the game with the one in the file. Returns false, having said why, when the file cannot be read or is not a game.
pick
my $line = $terminal->pick;
Lets the player build one move with the keys and plays it. Returns an empty string once a move has been played, a command for "command" when the player asked for one, and undef when the keys ran out.
take_back
Takes back one step of "history", as u and undo do. Returns false, having said so, when there is none.
play_again
Plays one step again, as r and redo do. Returns false, having said so, when there is none.
swap
$terminal->swap($game);
Replaces the game, puts down a stone being stepped, and forgets the cursor, the last move and what was written above the board. The history is left as it is.
person_turn
Keeps the game in "history": called each time the move passes to a person, and once a game has ended with a person at the keys.
lit
The stones that can move, as an array reference of point names in the order they are drawn: the top row first, each row from the left.
steer
my $name = $terminal->steer('d3', 'up', \@names);
The nearest of the names in that direction from the point, or the point itself when there is none. The direction is one of the keys that steps a stone.
so_far
The move as built so far, written out, or an empty string when the stone has not stepped.
playable
Whether the move as built so far is a whole legal move.
marks
my ($mark, $stones, $sign) = $terminal->marks($mode);
What a drawing shows: the mark on each marked point, the side of the stone on each occupied point, and for a point that shows something other than its stone what it shows. The mode is plain, which while a stone is being chosen, where while one is being stepped, or ask while a step waits for a or w. In the last two the stones are those of the position the move would leave.
board_lines
my $lines = $terminal->board_lines($mode);
The board as lines of text, with the counts beside it.
screen
my $lines = $terminal->screen($mode);
A whole screen as lines of text. As well as the modes above there are ended, thinking, menu, help and rules.
show
Draws "screen" on out, over the last one when interactive is true.
render
Writes the board and whose turn it is, as typed play does before each prompt.
budget
The number of positions the program looks at for a move at the present level.
raw
Whether the keyboard is being read a key at a time.
notice
The lines written above the board, as an array reference: the last move, and what a command said. The newest eight are kept.
focus
The point the cursor is on.
chosen
The point the stone being stepped started from, or undef.
prefix
The steps taken so far by the stone being stepped, as "steps" in Game::Fanorona describes a step.
last
The last move played here, or after u or r the last move of the game then on the board, as a hash of side, move, the points the stone stood on and the points of the stones taken; undef before one has been.
history
The Game::Terminal::Kit::History the turns are kept in, as the game's text. A turn is kept each time the move passes to a person, and when a game ends with a person at the keys; with the program playing both sides nothing is kept. A new game, a loaded game, a board changed in the opening questions and "start" each begin it again.
TABLES
%GROUND, %INK, %GLYPH and %FRAME are package variables holding the colours, the stones and the brackets, so that a test can measure them. A colour is one of the 240 that every terminal with 256 agrees on, and never one of the first sixteen, which each terminal sets for itself.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)