NAME

Game::Merrills::Notation - moves, positions and whole games as text

VERSION

Version 0.03

SYNOPSIS

use Game::Merrills::Notation;

my $move = Game::Merrills::Notation::parse_move('d2-d3xa1');
# { from => 19, to => 16, remove => 21 }

Game::Merrills::Notation::format_move($move);      # 'd2-d3xa1'

my $position = Game::Merrills::Notation::parse_position(
	'W..........B............ w 8 8 0 2'
);

my $moves = Game::Merrills::Notation::parse_record("1. d2 f4\n2. d6");

DESCRIPTION

Three things are written down: a move, a position, and a game.

A move

Points are named by their coordinates, a1 to g7, as in Game::Merrills::Points.

d2            a man is placed on d2
d2-d3         the man on d2 moves to d3
d2xa1         a man is placed on d2, closes a mill and takes the man on a1
d2-d3xa1      the man on d2 moves to d3, closes a mill and takes a1

Case does not matter when reading, and spaces around the - and the x are forgiven. What is written is always lower case with no spaces.

A flying move is written like any other move. Whether a man flew is plain from the two points.

A position

One line of six fields, separated by spaces:

W..........B............ w 8 8 0 2
  1. The 24 points in point order, W for a white man, B for a black one and . for an empty point.

  2. The side to move, w or b.

  3. The men white has yet to place.

  4. The men black has yet to place.

  5. The plies played since a mill was last closed, which a draw is counted from.

  6. The plies played in the game so far.

A position holds no history. A game begun from one has no earlier positions to repeat, so a count of repeated positions starts again from nothing.

A game

The moves in order, numbered in pairs, white's move and then black's:

1. d2 f4
2. d6 b4
3. d7

Reading takes the moves in the order they come and ignores the numbers and the line breaks.

A game that did not begin from the empty board says where it began, on a line of its own before the moves:

position WWW.BB..B..W....B..W.B.. w 4 4 0 10
1. d2 f4

A game played without flying says so on a line of its own before the moves, and a game with a draw offer standing, or ended by a resignation, a timeout or an agreed draw, says so on lines of their own after them. Each of the three is written only when it is so:

flying no
1. d2 f4
offer black
result white resign

The result names the winner, or draw, and the reason. Only the endings the moves cannot show are written; the rest come back from playing the moves.

A line that begins with # is a note and is passed over when reading.

FUNCTIONS

None is exported.

parse_move

Reads a move. Returns a hashref with to, and with from and remove when the move has them, each a point number. Returns undef for anything that is not a move, and never dies, so it can be handed whatever a player typed.

A move that names the same point twice is not a move. Whether a move is legal is not asked here.

my $move = Game::Merrills::Notation::parse_move('D2 - D3');

format_move

Writes a move from a hashref of from, to and remove. Dies when there is no to.

Game::Merrills::Notation::format_move({ to => 19 });     # 'd2'

format_position

Writes a position from a hashref of cells, turn, hand, no_mill and ply, the shape "parse_position" returns. The hand and the two counts are taken as 0 when left out. Dies when what it is given could not be a position.

my $text = Game::Merrills::Notation::format_position({
	cells => \@cells,
	turn => 'white',
	hand => { white => 9, black => 9 },
});

parse_position

Reads a position. Returns a hashref of cells (24 values, 1 for white, -1 for black, 0 for empty), turn (white or black), hand (a hashref keyed by side), no_mill and ply. Dies, saying what is wrong, when the text is not a position or gives a side more than nine men.

my $position = Game::Merrills::Notation::parse_position($text);

format_record

Writes a game from an arrayref of moves. Each may be a string, a hashref as "parse_move" returns, or a Game::Merrills::Move. Dies, naming the move, when one of them is not a move. Give position for a game that began somewhere other than the empty board, flying as 0 for a game played without it, offer as the side whose draw offer stands, and result as an arrayref of the winner (undef for a draw) and the reason for a game ended by resign, timeout or agreement. Dies when one of those is not so.

my $text = Game::Merrills::Notation::format_record(\@moves);
my $text = Game::Merrills::Notation::format_record(\@moves, position => $start);

parse_record

Reads a game. Returns an arrayref of moves as "parse_move" returns them. A position line is passed over; "record_position" reads it. The flying, offer and result lines are passed over too; "record_state" reads them. Dies, naming the move by its place in the game, when one cannot be read.

my $moves = Game::Merrills::Notation::parse_record($text);

record_position

The position a written game began from, or undef when it names none and so began from the empty board. Dies when the position line is not a position.

my $position = Game::Merrills::Notation::record_position($text);

record_state

What a written game says beside its moves and its start, as a hashref with flying (1 or 0) when the game names it, offer (a side) when a draw offer stands, and result (an arrayref of the winner, undef for a draw, and the reason) when the game was resigned, timed out or agreed drawn. Dies, saying what is wrong, when one of those lines cannot be read or comes twice.

my $state = Game::Merrills::Notation::record_state($text);

PACKAGE VARIABLES

%CELL, %GLYPH

The cell value of each board character, and the character of each value.

%TURN, %LETTER

The side of each side letter, and the letter of each side.

%SIDE

The two sides, white and black, each true.

AUTHOR

LNATION, <email at lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)