NAME
Game::Checkers::Rules - move generation over a raw position
VERSION
Version 0.01
SYNOPSIS
use Game::Checkers::Rules;
my $moves = Game::Checkers::Rules::generate($position, 'black');
Game::Checkers::Rules::apply($position, $moves->[0]);
Game::Checkers::Rules::unapply($position, $moves->[0]);
DESCRIPTION
Functions over a position arrayref, not an object, and the only part of the engine the search talks to. Nothing here allocates a blessed object, because Game::Checkers::Bot calls generate, apply and unapply millions of times for one move. Game::Checkers is the interface for everybody else.
The rules implemented
English draughts, also called American checkers:
A man moves one square diagonally forward and a king one square diagonally in any direction, always to an empty square.
A jump passes over an adjacent enemy piece to the empty square beyond. A man jumps forward only, a king in any direction.
Capture is compulsory: when any jump exists, the legal list is jumps and nothing else. Which jump is a free choice, because English draughts has no maximum capture rule.
A jump sequence continues while the piece that jumped can jump again, and the whole sequence is one move. A piece already jumped may not be jumped again in that sequence, and it stays on the board until the move ends, so it still blocks a landing square.
A man reaching the far row is crowned and the turn ends there, even when the new king could jump again.
Deciding the game is over is Game::Checkers's: this module answers what can be played, and "has_move" answers whether anything can.
THE RAW MOVE
A generated move is an unblessed arrayref whose layout is documented in "THE RAW MOVE" in Game::Checkers::Move. The constants RM_FROM, RM_TO, RM_PROMOTED, RM_PATH, RM_CAPTURES, RM_CAPTURED and RM_KING are defined there and re-exported here under the same names, so a caller may use either spelling.
FUNCTIONS
generate
All the legal moves for a side, as an arrayref of raw moves, with the compulsory capture rule already applied. The order is deterministic: ascending starting square, then ascending destination, then by path, so a client may index into the list and get the same move twice. The search reorders its own copy.
my $moves = Game::Checkers::Rules::generate($position, 'white');
apply
Applies a raw move to a position, in place, crowning the piece when the move says so. Returns the raw move, which is also the record "unapply" wants.
Game::Checkers::Rules::apply($position, $raw);
unapply
Takes a move back, in place, restoring every captured piece with the value it had so a jumped king comes back a king, and taking the crown off a piece the move promoted.
Game::Checkers::Rules::unapply($position, $raw);
has_move
True when the side has any move at all. It stops at the first one it finds, so it is the cheap way to ask whether a player has lost.
Game::Checkers::Rules::has_move($position, 'black');
progress
True when a move is a capture or a man move, which is what resets the no progress counter that draws a game nobody is winning.
Game::Checkers::Rules::progress($raw);
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)