NAME
Game::Xiangqi::Notation - ICCS coordinates, and WXF for the reader
SYNOPSIS
use Game::Xiangqi::Notation;
my $N = 'Game::Xiangqi::Notation';
$N->iccs_of($mv); # 'h2e2'
$N->move_of_iccs('h2e2'); # the packed move back
$N->wxf_of($board, $mv); # 'C2.5'
THE LOG STORES ICCS AND CARRIES WXF BESIDE IT
ICCS coordinates are what play takes and what a replay walks. A file letter a to i from Red's left and a rank digit 0 to 9 from Red's own side, so a move is four characters and means the same thing to both players and to a reader six months later.
WXF notation is what the reader sees, and it is never parsed back. There is deliberately no move_of_wxf in this module, and its absence is the point.
WXF is relative to the side that wrote it
Files run 1 to 9 from the mover's own right, so Red counts right to left across the board and Black counts left to right. The same string means two different moves depending on who played it: C2.5 is a Red cannon going from the h file to the e file, and it is equally a Black cannon going from the b file to the e file.
That is why every call here takes the board: the colour comes from the piece, and there is no way to spell a WXF move without knowing whose it is.
And it is why the parser is missing. A log that stored only WXF would be unreplayable the day its reader forgot which side wrote a line, and the reader is a person six months later looking at /games/:id/log. Chess made the same split for the same reason: it stores UCI and carries SAN for the reader.
Which pieces carry a distance and which carry a file
After + or -, the chariot, the cannon, the general and the soldier carry how many ranks they moved, and the advisor, the elephant and the horse carry the destination file, because their rank change is implied by the piece. After . every piece carries the destination file. Getting this backwards produces strings that look right and name the wrong square.
Two on a file, and three
Two identical pieces on one file take + for the front one and - for the rear instead of the file number, which could not tell them apart. Three or more are numbered from the front. Five soldiers on one file is legal and rare, and the general case is implemented rather than the common one.
Front means nearer the enemy, so the order reverses with the colour.
METHODS
iccs_of
Game::Xiangqi::Notation->iccs_of($move); # 'h2e2'
A packed move as ICCS coordinates: the from point then the to point, file letter a to i and rank digit 0 to 9, always from Red's left and Red's end. This is what the log stores.
move_of_iccs
my $move = Game::Xiangqi::Notation->move_of_iccs('h2e2');
The reverse. Returns undef for anything that is not four characters naming two points on the board, and judges nothing else: a well-formed move that is illegal in the position still parses, because deciding that is the board's job and not the parser's.
wxf_of
Game::Xiangqi::Notation->wxf_of($position, $move); # 'C2.5'
The move in WXF notation, which needs the position because WXF names a piece and a file rather than two points, and because two pieces of one kind on one file are written as the front one and the back one.
Returns undef if the move's from point holds nothing.
wxf_file
Game::Xiangqi::Notation->wxf_file($file_index, $colour);
The WXF file number for a board file, which is not the same number for the two sides: files are counted one to nine from the mover's own right, so Red's file 1 and Black's file 1 are opposite ends of the board.