NAME

Chess::PGN::Parse - reads and parses PGN (Portable Game Notation) Chess files

SYNOPSIS

	use Chess::PGN::Parse;
	my $pgnfile = "kk_2001.pgn";
	my $pgn = new Chess::PGN::Parse $pgnfile 
		or die "can't open $pgnfile\n";
	while ($pgn->read_game()) {
		print $pgn->white, ", " , $pgn->black, ", ", 
			$pgn->result, ", ",
			$pgn->game, "\n";
	}


	use Chess::PGN::Parse;
    my $text ="";
    {
        local $/ = undef;
        open PGN "< $pgnfile" or die;
        $text = <PGN>;
        close $text;
    }
    # reads from string instead of a file
	my $pgn = new Chess::PGN::Parse undef, $text; 
	while ($pgn->read_game()) {
		print $pgn->white, ", " , $pgn->black, ", ", 
			$pgn->result, ", ",
			$pgn->game, "\n";
	}

	use Chess::PGN::Parse;
	my $pgnfile = "kk_2001.pgn";
	my $pgn = new Chess::PGN::Parse $pgnfile 
		or die "can't open $pgnfile\n";
	my @games = $pgn->smart_read_all();

DESCRIPTION

Chess::PGN::Parse offers a range of methods to read and manipulate Portable Game Notation files. PGN files contain chess games produced by chess programs following a standard format (http://www.schachprobleme.de/chessml/faq/pgn/). It is among the preferred means of chess games distribution. Being a public, well established standard, PGN is understood by many chess archive programs. Parsing simple PGN files is not difficult. However, dealing with some of the intricacies of the Standard is less than trivial. This module offers a clean handle toward reading and parsing complex PGN files.

A PGN file has several tags, which are key/values pairs at the header of each game, in the format [key "value"]

After the header, the game follows. A string of numbered chess moves, optionally interrupted by braced comments and recursive parenthesized variants and comments. While dealing with simple braced comments is straightforward, parsing nested comments can give you more than a headache.

Chess::PGN::Parse most immediate methods are: read_game() reads one game, separating the tags and the game text.

parse_game() parse the current game, and stores the moves into an 
	array and optionally saves the comments into an array of hashes
	for furter usage. It can deal with nested comments and recursive
	variations.

quick_parse_game() Same as the above, but doesn't save the comments, 
	which are just stripped	from the text. It can't deal with nested
	comments. Should be the preferred method when we know that we are
	dealing with simple PGNs.

smart_parse_game() Best of the above methods. A  preliminary check
	will call parse_game() or quick_parse_game(), depending on the
	presence of nested comments in the game.

read_all(), quick_read_all(), smart_read_all() will read all the records
	in the current PGN file and return an array of hashes with all the
	parsed details from the games.

EXPORT

new, STR, read_game, tags, event, site, white, black, round, date, result, game , NAG, moves

DEPENDENCIES

FileHandle

Class methods

new()

Create a new Chess::PGN::Parse object (requires file name) my $pgn = Chess::PGN::Parse->new "filename.pgn" or die "no such file \n";

NAG() returns the corresponding Numeric Annotation Glyph
STR()

returns the Seven Tags Roster array

@array = $pgn->STR();
@array = PGNParser::STR();
event()

returns the Event tag

site()

returns the Site tag

date()

returns the Date tag

white()

returns the White tag

black()

returns the Black tag

result()

returns the result tag

round()

returns the Round tag

game()

returns the unparsed game moves

time()

returns the Time tag

eco()

returns the ECO tag

eventdate()

returns the EventDate tag

moves()

returns an array reference to the game moves (no numbers)

comments()

returns a hash reference to the game comments (the key is the move number and the value are the comments for such move)

errors()

returns a hash reference to the game errors (the key is the move number and the value are the errors for such move)

tags()

returns a hash reference to all the parsed tags

$hash_ref = $pgn->tags();
read_all()

Will read and parse all the games in the current file and return a reference to an array of hashes. Each hash item contains both the raw data and the parsed moves and comments

Same parameters as for parse_game(). Default : discard comments

my $games_ref = $pgn->read_all();
quick_read_all()

Will read and quick parse all the games in the current file and return a reference to an array of hashes. Each hash item contains both the raw data and the parsed moves Comments are discarded. Same parameters as for quick_parse_game().

my $games_ref = $pgn->quick_read_all();
smart_read_all()

Will read and quick parse all the games in the current file and return a reference to an array of hashes. Each hash item contains both the raw data and the parsed moves Comments are discarded. Calls smart_read_game() to decide which method is best to parse each given game.

my $games_ref = $pgn->smart_read_all();
read_game()

reads the next game from the given PGN file. Returns TRUE (1) if successful (= a game was read) or FALSE (0) if no more games are available or an unexpected EOF occurred before the end of parsing

while ($pgn->read_game()) {
	do_something_smart;
}
_get_tags() returns a list of tags depending on the parameters

_get_format() returns a format to be used when printing tags

_get_formatted_tag() returns a tag formatted according to the
given template.
standard_PGN()
returns a string containing all current PGN tags, including
the game.
Parameters are passed through a hash reference. None is
required.

tags => [tag list], # default is the Seven Tags Roster.
                    # You may specify only the tags you want to 
                    # print 
                    # tags => [qw(White Black Result)]

all_tags => 'no',   # default 'no'. If yes (or 1), it outputs all the tags
                    # if 'tags' and 'all_tags' are used, 'all_tags' 
                    # prevails

nl => '\n',         # default '\n'. Tag separator. Can be changed
                    # according to your needs.
                    # nl => '<br>\n' is a good candidate for HTML 
                    # output.

brackets => '[]',   # default '[]'. Output tags within brackets.
                    # Bracketing can be as creative as you want.
                    # If the left and rigth bracketing sequence are
                    # longer than one character, they must be separated
                    # by a pipe (|) symbol.
                    # '()', '(|)\t,'{|}\n' and '{}' are valid 
                    # sequences.
                    # 
                    # '<h1>|</h1>' will output HTML header 1
                    # '<b>{</b>|<b>}</b>\n' will enclose each tag
                    # between bold braces.

quotes => '"',      # default '"'. Quote tags values.
                    # As for brackets, quotes can be specified in
                    # pairs: '<>' and '<|>' are equivalent.
                    # If the quoting sequence is more than one char,
                    # the pipe symbol is needed to separate the left
                    # quote from the right one.
                    # '<i>|</i>' will produce HTML italicized text.
                    
game => 'yes',      # default 'yes'. Output the game text 
                    # If the game was parsed, returns a clean list
                    # of moves, else the unparsed text
smart_parse_game()

Parses the current game, returning the moves only. Uses by default quick_parse_game(), unless recursive comments are found in the source game.

quick_parse_game()

Parses the current game, returning the moves only. Comments are discarded. This function does FAIL on Recursive Annotated Variation or nested comments. Parameters (passed as a hash reference): check_moves = 'yes'|'no'. Default : no. If requested, each move is checked against a RegEx, to filter off possible unbraced comments.

parse_game()

Parses the current game (after read_game() was called). Accepts parameters as hash reference.

$pgn->parse_game(); # default save_comments => 'no'

$pgn->parse_game({save_comments => 'yes'});
$pgn->parse_game({save_comments => 'yes', log_errors = 'yes'});

parse_game() implements a finite state machine on two assumptions:

1. No moves or move numbers are truncated at the end of a line;
2. the possible states in a PGN game are:

	a. move number
	b. move
	c. braced comment
	d. EOL comment
	e. Numeric Annotation Glyph
	f. Recursive Annotated Variation
	g. Result
	h. unbraced comments (barewords, "!?+-=")

items from "a" to "g" are actively parsed and recognized. 
Anything unrecognized goes into the "h" state and discarded
(or stored, if log_errors was requested)
shrink_epd()

Given a EPD (Extended Position Description) string, shrink_epd() will convert it into a bit string, which reduces the original by about 50%. It can be restored to the original string by expand_epd()

expand_epd()

given a EPD bitstring created by shrink_epd(), expand_epd() will restore the original text.

AUTHOR

Giuseppe Maxia, gmax@karma.oltrelinux.com

THANKS

Thanks to - Hugh S. Myers for advice, support, testing and brainstorming; - Damian Conway for the recursive Regular Expressions used to parse comments; - all people at PerlMonks (www.perlmonks.org) for advice and good developing environment.

COPYRIGHT

The Chess::PGN::Parse module is Copyright (c) 2002 Giuseppe Maxia, Sardinia, Italy. All rights reserved.

You may distribute this software under the terms of either the GNU General Public License version 2 or the Artistic License, as specified in the Perl README file. The embedded and encosed documentation is released under the GNU FDL Free Documentation License 1.1