NAME

Game::Sternhalma - star halma, the race across a six-pointed star known as Chinese checkers

VERSION

Version 0.01

SYNOPSIS

use Game::Sternhalma;

my $game = Game::Sternhalma->new(seats => 3);

until ($game->over) {
    my @moves = $game->legal;
    my $flag  = $game->play($moves[0]{text});
    die Game::Sternhalma->reason($flag) if defined $flag;
    last if $game->ply >= 6;
}

print $game->position, "\n";
my $again = Game::Sternhalma->replay($game->log);
print $again->key eq $game->key ? "the same game\n" : "a different game\n";

DESCRIPTION

Sternhalma is played on a star of 121 holes by two, three, four or six, each with ten pieces starting in one point of the star and racing them into the point opposite. A piece steps to a neighbouring empty hole, or hops over one neighbouring piece, anyone's, into the empty hole straight beyond it, and may go on hopping as long as it likes and stop when it likes. Nothing is taken. The first seat home wins, and the others play on for second and third place.

It is the engine behind the Sternhalma at https://peer2peergames.com.

WHOSE RULES THESE ARE

The board, the moves and the winner are the game's own, from the English and German Wikipedia articles ("Chinese checkers", "Halma"). These are this distribution's, because those say nothing:

  • A parked piece cannot stop you. A seat is home when every hole of its home holds a piece and at least one of them is its own, so a rival who never moves a piece out of your home does not keep you out, and a rival who fills your last hole moves you home.

  • A piece may stop in any hole, the points nobody plays from or to as well.

  • A seat with no move passes, and when every seat still racing has passed in a row, the game ends.

  • A game ends at a cap of moves and passes, 1,000 a seat unless asked otherwise. At the cap, or when nobody can move, seats still racing are placed by how far their pieces are from home.

  • A seat that resigns is placed behind every seat that finished or is still racing. Its pieces stay on the board.

No game here can be shorter than George I. Bell's proofs allow ("The shortest game of Chinese Checkers and related problems", INTEGERS 9, 2009): 27 moves for one seat crossing alone, 30 for two seats.

CONSTRUCTOR

new

Game::Sternhalma->new(seats => 2, pieces => 10, first => 0, cap => 2000)
Game::Sternhalma->new(position => $string)

seats is 2 (the default), 3, 4 or 6. pieces is 10 (the default), or 15 for two or three seats. first is the seat that moves first. cap is the ply the game ends at if it has not ended before.

With position, the game starts from a position string (see Game::Sternhalma::Notation), which carries its own seats, pieces, seat to move and game so far; first cannot be given with it.

Dies with a Game::Sternhalma::Error when no game can be made of what it was given.

PLAYING

my @moves = $game->legal;

What the seat to move may do, each a hash: { kind => 'move', from, to, path, text }, where path is every hole the move goes through and text is how it is written; or the one { kind => 'pass' } when it has no move. Empty when the game is over.

play

my $flag = $game->play('e5:g5:g7');

Makes a move for the seat to move: text (a step e5-f5, a chain e5:g5:g7 or just its ends e5-g7, pass, resign 2), or a hash { from, to } of hole numbers or names, or { kind => 'pass' }. Returns undef when the move was made, and otherwise a flag naming why not: bad_string, no_such_hole, no_piece, not_your_piece, must_pass, occupied, not_reachable, pass_not_allowed, no_such_seat, seat_finished, seat_resigned or game_over. It never dies.

resign

my $flag = $game->resign($seat);

A seat still racing gives up, on its turn or not. The same flags as "play".

undo

Takes back the last move, pass or resignation. Returns 1, or 0 when there is nothing to take back.

reason

Game::Sternhalma->reason($flag)

A flag in words.

THE GAME

to_move

The seat whose turn it is.

over

True when the game has ended.

how

home, cap, deadlock or resign once it has; undef before.

result

A Game::Sternhalma::Result once the game is over; undef before.

finished

The seats home, in the order they got there.

places

Every seat's place, in seat order; 0 for a seat not yet placed.

distance_left

$game->distance_left($seat)

How far a seat's pieces are from home: 0 when it is home.

at

$game->at('i5')

The seat whose piece is in a hole, by name or number, or undef.

ply

Moves and passes made.

cap

The ply the game ends at.

seats

pieces

first

The seat that moved first, or undef for a game started from a position.

start

The position a game was started from, or undef for one started from its set-up.

solo

What the game was made with.

position

The position as a string (see Game::Sternhalma::Notation).

key

Sixteen hex digits naming the position.

board

A copy of the board, a Game::Sternhalma::Engine, to look at as closely as you like.

THE LOG

moves

Every move made, as text, in order.

history

$game->history($seat)

Every arrangement a seat's pieces have had, as "own_key" in Game::Sternhalma::Engines, the start first; the seat to move's when no seat is given. The bot reads it, so as never to put its pieces back as they were.

log

The game as text: the seats, pieces, cap and first seat (or the position it started from), then the moves.

replay

my $game = Game::Sternhalma->replay($text);

The game a log describes, replayed. Dies with a Game::Sternhalma::Error for a log that is not a game, or a move in it that cannot be made.

AUTHOR

LNATION <email@lnation.org>

BUGS

Please report any bugs or feature requests to bug-game-sternhalma at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Game-Sternhalma. 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::Sternhalma

You can also look for information at:

ACKNOWLEDGEMENTS

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)