NAME
Game::Oware::Terminal - a playable game on two filehandles
VERSION
Version 0.01
SYNOPSIS
use Game::Oware::Terminal;
my $terminal = Game::Oware::Terminal->new(level => 3, seat => 'p1');
my $result = $terminal->start;
DESCRIPTION
It is separate from the engine on purpose
Game::Cribbage is about a thousand lines of escape codes in its top level namespace module, so that only its ::Board was ever reusable by anything else. This is a consumer of the engine exactly as a web adapter would be, and the suite asserts that loading Game::Oware does not pull this in.
in and out are properties
Defaulting to STDIN and STDOUT. That is what makes a terminal testable: the suite drives a whole game in process against in-memory handles, with no pipe, no fork, and no subprocess writing into the TAP stream.
start returns, and never exits
A module that calls exit cannot be tested and cannot be embedded. The exit status belongs to bin/oware, which is the only part that knows it is a program.
Every option is validated in the constructor
An unknown variant, an unknown level or a seat that does not exist all die from BUILD, before a game is built and before anything is printed. Game::Reversi validated its variant three calls deeper and shipped a --variant draughts that died with a raw Perl message and an exit status of 255.
Counts, not glyphs
Oware is a game about numbers and a pile of dots is unreadable past four, so the board shows the seed count in each house. Two things follow.
The letters are the interface, so they are printed above and below the board and the prompt takes one, matching Game::Oware::Notation exactly. A terminal that invented its own numbering would give the distribution two notations.
And there is no alternative glyph set to write for --ascii, unlike the board games in this author's tree, because there are no glyphs. --ascii still picks the plain box drawing, and NO_COLOR still beats everything.
The board is turned round for whoever is looking
Your own six houses are always the bottom row, because the whole spatial vocabulary of this game is "your row" and "their row". The letters do not move: A to F is p1's side and a to f is p2's, in both views and in every line of narration, so two people looking at one game can never disagree about where a house is.
Four moments have to be said in words
Oware's failure mode on a terminal is that the board changes in ways the player cannot account for, so each of these gets a sentence rather than being left to be inferred:
a forfeited slam. A capturing move captures nothing. Unexplained, that is a bug report.
a sow of twelve or more, which skipped its own house on the way past, so the counts do not add up by eye and the player will count them again.
the feeding rule, when it has pruned the move list. The refusal message exists, but a player who never tries the illegal move never sees it.
the cycle ending, named as a house rule with the count that triggered it, because a game ending on a rule no book contains has to say so.
The failed-feed ending is a fifth: a seat that cannot move takes its own seeds, which reads backwards to anybody who knows chess.
PROPERTIES
in
The handle to read from. Defaults to STDIN.
out
The handle to write to. Defaults to STDOUT.
level
The bot's level, 1 to 5.
variant
abapa or awari.
seat
Which seat the human plays, p1 or p2.
seed
Passed to the game and, with a suffix, to the bot.
quiet
Suppress the narration and the banner.
ascii
Plain box drawing.
game
The Game::Oware being played. Built by BUILD unless one is supplied, which is how the suite starts from a constructed position.
bot
The Game::Oware::Bot playing the other seat.
METHODS
ansi
Whether to emit escapes. NO_COLOR wins over everything; an explicit ansi option beats the tty check; otherwise it follows whether out is a terminal.
Colour carries no information here: strip every escape and the board reads exactly the same.
rows_for
The house indices of the top and bottom rows, from a seat's point of view.
board_text
The board as a list of lines, from a seat's point of view.
command
One line of input as an instruction: quit, help, board, again for an empty line, or the text itself.
There is no single-letter shortcut for board. b and B are houses, and the first draft of this module accepted b as the command, so typing a perfectly ordinary move redrew the board instead of playing it. q and h are safe because no house is called either.
start
Plays the game and returns its Game::Oware::Result, or undef if the player quit.
SEE ALSO
Game::Oware, Game::Oware::Bot, Game::Oware::Notation
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.