NAME
Game::Checkers - English draughts as an engine, with a terminal game on top
VERSION
Version 0.01
SYNOPSIS
use Game::Checkers;
my $game = Game::Checkers->new;
$game->turn; # 'black'
$game->legal_moves; # the seven opening moves
$game->move('11-15'); # a Game::Checkers::Move
my $bad = $game->move('11-15');
$bad->message if ref $bad eq 'Game::Checkers::Error';
$game->status; # 'active' until somebody wins
$game->result->stringify; # 'Black wins: White has no move'
DESCRIPTION
English draughts, also called American checkers: an eight by eight board, twelve pieces a side, men moving and capturing forward only, kings one square in any direction, capture compulsory, and the crown ending the turn. "The rules implemented" in Game::Checkers::Rules states them exactly.
It is the engine behind the checkers at https://peer2peergames.com.
The engine does no input and no output. It never prints, never reads a handle, never sleeps and never calls rand, so a game is a pure function of its moves and replays anywhere. The terminal game lives in Game::Checkers::Terminal and the checkers script, and nothing in the engine loads either.
A player's mistake is returned as a Game::Checkers::Error, never thrown. Only a programmer error dies: a square outside 1 to 32, a colour that is not black or white, a variant that is not English.
The modules
- Game::Checkers::Board
-
The 32 playing squares and what stands on them.
- Game::Checkers::Squares
-
The numbering, and the step and jump tables built from it.
- Game::Checkers::Piece
-
One man or king.
- Game::Checkers::Move
-
One move, with its whole jump path and everything it captured.
- Game::Checkers::Rules
-
Move generation over a raw position, and the interface the search uses.
- Game::Checkers::Notation
-
Moves, positions and games as text: numeric notation, FEN and PDN.
- Game::Checkers::Error, Game::Checkers::Result
-
Why a move was refused, and how a game ended.
- Game::Checkers::Bot
-
An opponent at five strengths, bounded by a node budget and never by a clock.
- Game::Checkers::Terminal
-
The game at a prompt, and the only module here that reads or writes a handle. The
checkersscript is a few lines of option parsing on top of it.
Draws
Three of them, and the first two are counted by the game object as it goes:
Threefold repetition. Every position the game has been in is counted by its FEN, which includes the side to move. The third occurrence ends the game.
No progress. Forty moves by each side, counted here as eighty plies, with no capture and no man moved. Any capture or man move resets it.
Agreement. "offer_draw" then "accept_draw" by the other side. An offer stands until the other side answers it with a move.
When a move both blocks the opponent and completes a draw counter, the block wins: a player with no move has lost.
PROPERTIES
board
Read and write Game::Checkers::Board. Pass one to start from a position without a FEN.
$game->board;
turn
Read and write string, black or white. Black moves first.
$game->turn;
variant
Read and write string. english is the only value, and anything else dies at construction. It is here so a later variant is an addition rather than a rewrite.
$game->variant;
fen
Read and write string: the position the game STARTED from, filled in at construction. Pass it to start from a position. The current position is "to_fen".
Game::Checkers->new(fen => 'W:WK5:BK28');
result
Read and write Game::Checkers::Result, undef while the game is active.
$game->result;
history
Read and write arrayref of the Game::Checkers::Move objects played, in order.
$game->history;
no_progress
Read and write integer: plies since the last capture or man move.
$game->no_progress;
repetition
Read and write hashref counting how often each position has occurred, keyed by FEN.
$game->repetition;
draw_offered_by
Read and write black, white or undef.
$game->draw_offered_by;
FUNCTIONS
status
active or finished.
$game->status;
ply
How many moves have been played.
$game->ply;
to_fen
The FEN of the current position, including the side to move.
$game->to_fen;
legal_moves
An arrayref of the Game::Checkers::Move objects the side to move may play, empty once the game is finished. The order is stable, so a client may show them numbered.
$game->legal_moves;
legal_moves_for
The legal moves starting on one square.
$game->legal_moves_for(11);
must_capture
True when a jump is available, which makes the legal list jumps only.
$game->must_capture;
move
Plays one move and returns it, or returns a Game::Checkers::Error saying why not. Accepts a Game::Checkers::Move, a notation string such as 11-15 or 23x14x7, the same move written as the squares on the board, f6-e5 and e3xc5xe7, or a hashref of from and to (or squares).
The short form of a jump is resolved against the legal list: 23x7 is one sequence in most positions, and where it is two the error is ambiguous rather than a guess. A multi jump stopped part way is not_legal, never completed on the player's behalf, because a position with two continuations would then be chosen for them.
my $played = $game->move('11-15');
undo
Takes back the last move and returns it, restoring the position exactly, including a crown the move gave and a king it captured. It also lifts a finish, so a resigned game can be taken back. Returns an error when nothing has been played.
$game->undo;
resign
Ends the game, the other side winning. Defaults to the side to move.
$game->resign('white');
offer_draw
Offers a draw on behalf of a side and returns it. The offer stands until the other side answers it with a move.
$game->offer_draw('black');
accept_draw
Accepts an offer made by the other side, ending the game as a draw by agreement.
$game->accept_draw('white');
decline_draw
Clears an offer made by the other side.
$game->decline_draw('white');
to_pdn
The game as PDN. Any arguments are tags, and a game that did not start from the opening position carries its FEN and SetUp tags automatically.
print $game->to_pdn(Event => 'Kitchen table', Black => 'Me');
from_pdn
Class method replaying a PDN game and returning it. Dies naming the move number when one of them is illegal, because a game record that does not replay is not a game record.
my $game = Game::Checkers->from_pdn($text);
clone
A copy of the whole game, position, history and counters, sharing nothing that matters.
my $copy = $game->clone;
CONSTANTS
NO_PROGRESS_PLIES is 80, the forty move rule counted in plies.
AUTHOR
LNATION, <email at lnation.org>
BUGS
Please report any bugs or feature requests to bug-game-checkers at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Game-Checkers. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Game::Checkers
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
Search CPAN
ACKNOWLEDGEMENTS
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)