NAME

Games::SGF - A general SGF parser

VERSION

Version 0.03 Third Alpha Release

SYNOPSIS

use Games::SGF;

my $sgf = new Games::SGF();

$sgf->setStoneRead( sub { "something useful"} );
$sgf->setMoveRead( sub { "something useful"} );
$sgf->setPointRead( sub { "something useful"} );

$sgf->addTag('KM', $sgf->T_GAME_INFO, $sgf->V_REAL );
$sgf->parseFile("015-01.sgf");

DISCRIPTION

Games::SGF is a general Smart Game Format Parser. It parses the file, and checks the properties against the file format 4 standard. No game specific features are implemented.

It is designed so that the user can tell it how to handle new tags. It also allows the user to set callbacks to parse Stone, Point, and Move types. These are types are game specific.

SGF file contains 1 or more game trees. Each game tree consists of a sequence of nodes followed by a sequence of branches. Each branch also consists a sequence of nodes followed by a sequence of branches.

Each node contains a set of properties. Each property has a "Type", "Value Type", "Flags", and an Attribute. The Type specifies where and when an attribute may bew used. A Value Type says what type of value it contains. Flags are used to specify variuos properties, such as being a list, or if the field is empty. Attributes specify other behavior.

Also see: http://www.red-bean.com/sgf

METHODS

new

new Games::SGF();

Creates a SGF object, there may be options defined latter, but as of right now takes no paramaters.

readText

$sgf->readText($text);

This takes in a SGF formated string and parses it.

readFile

$sgf->readFile($file);

This will open the passed file, read it in then parse it.

writeText

$sgf->writeText;

Will return the current collection in SGF form;

writeFile

$sgf->writeFile($filename);

Will write the current game collection to $filename.

addTag

$sgf->addTag($tagname, $type, $value_type, $flags, $attribute);

This add a new tag to the parsing engine. This needs to called before the read or write commands are called. This tag will not override the FF[4] standard properties, or already defined properties.

The $tagname is the name of the tag which will be read in, thus if you want to be able to read AAA[...] from an SGF file the tagname needs to be "AAA".

The $type needs to be choosen from the "Type" list below. Defaults to T_NONE.

The $value_type needs to be choosen from the "Type" list below. Defaults to V_TEXT.

The $flags are from the "Flags" List. Defaults to VF_EMPTY | VF_LIST.

The $attribute is from the "Attribute" List. Defaults to A_NONE.

setPointRead

setMoveRead

setStoneRead

$sgf->setPointRead(\&coderef);
$sgf->setMoveRead(\&coderef);
$sgf->setStoneRead(\&coderef);

These call backs are called when a properties value needs to be parsed. It takes in a string, and returns a structure of some type. Here is a possible example for a Go point callback:

sub parsepoint {
   my $value = shift;
   my( $x, $y) = split //, $value;
   return [ ord($x) - ord('a'), ord($y) - ord('a') ];
}
# then somewhere else
$sgf->setPointParse( \&parsepoint );

Note: that you should do more then this in practice, but it gets the across.

If the value is an empty string and VF_RMPTY is set then the call back will not be called but return an empty string.

setPointCheck

setMoveCheck

setStoneCheck

$sgf->setPointCheck(\&coderef);
$sgf->setMoveCheck(\&coderef);
$sgf->setStoneCheck(\&coderef);

This callback is called when a parameter is stored. The callback takes the structure passed to setProperty, or component if composed, and returns true if it is a valid structure.

An Example of a stone check for go is as follows:

sub stoneCheck {
   my $stone = shift;
   if( ref $stone eq 'ARRAY' and @$stone == 2
          and $stone->[0] > 0 and $stone->[1] > 0 ) {
       return 1;
   } else {
       return 0;
   }
}

If the value is an empty string it will be passed to the check callback only if VF_EMPTY is not set.

setPointWrite

setMoveWrite

setStoneWrite

$sgf->setPointWrite(\&coderef);
$sgf->setMoveWrite(\&coderef);
$sgf->setStoneWrite(\&coderef);

This callback is called when a parameter is written in text format. The callback takes the structure passed to setProperty, or component if composed, and returns the text string which will be stored.

An Example of a stone check for go is as follows:

sub stoneWrite {
   my $stone = shift;
   my @list = ('a'..'Z','A'..'Z');
   return $list[$stone->[0] - 1] . $list[$stone->[1] - 1];
}

If the tag value is an empty string it will not be sent to the write callback, but immedeitely be returned as an empty string.

nextGame

$sgf->nextGame;

Sets the node pointer to the next game in the Collection. If the current game is the last game then returns 0 otherwise 1.

prevGame;

$sgf->prevGame;

Sets the node pointer to the prevoius game in the Collection. If the current game is the first game then returns 0 otherwise 1.

addGame

$self->addGame;

This will add a new game to the collection with the root node added. The current node pointer will be set to the root node of the new game.

Returns true on success.

next

$sgf->next;

Moves the node pointer ahead one node.

Returns 0 if it is the last node in the branch, otherwise 1

prev

$sgf->prev;

Moves the node pointer back one node.

Returns 0 if first node in the branch and 1 otherwise

variations

$sgf->variations;

Returns the number of variations on this branch.

gotoVariation

$sgf->gotoVariation($n);

Goes to the first node of the specified Variation. If it returns 4 that means that there is variations 0..3,

Returns 1 on success and 0 on Failure.

gotoParent

$sgf->gotoParent;

Will move the node pointer to the last node of the parent branch. This will fail if you already on the root branch for the current game.

Returns 1 on success or 0 on failure.

addNode

$sgf->addNode;

Adds node end of the current branch. It will fail if there is any variations on this branch.

Returns 1 on success and 0 on Failure.

addVariation

$sgf->addVariation;

Adds a new variation onto this branch. The current branch will be changed to this new variation. It will then add the first node for this variation.

Returns 1 on sucess 0 on Failure.

removeNode

$sgf->removeNode;

Removes last node from the current Branch, will fail if there is any variations on this branch

Returns 1 on success and 0 on Failure.

removeVariation

$sgf->removeVariation($n);

This will remove the $n variation from the branch. If you have variations 0..4 and ask it to remove variation 1 then the indexs will be 0..3.

Returns 1 on sucess 0 on Failure.

splitBranch

$sgf->splitBranch($n);

This will split the current branch into 2 branches, so that the last part of the branch will be a variation of the first portion. $n will be the first node in the next variation.

Your node pointer will be the last node first branch. For Example say the branch you are on has nodes 0..9 and you want to split it on node 5 will give the first branch having nodes 0..4 having one variation containing nodes 5..9 and the variations of the original branch. Your node pointer will point to node 4

This is used for adding a variation of move $n:

$sgf->splitBranch($n);
$sgf->addVariation;
$sgf->addNode;
# set some node properties

The above code will add a variation on the a node in the middle of a node sequence in a branch.

Returns 1 on success and 0 on Failure.

property

my $array_ref = $sgf->property( $value );
my $didSave = $sgf->property( $value , @values );

This is used to read and set properties on the current node. Will prevent T_MOVE and T_SETUP types from mixing. Will prevent writing T_ROOT tags to any location other then the root node. Will Lists from being stored in non list tags. Will prevent invalid structures from being stored.

getProperty

my $array_ref = $sgf->getProperty($tag);
if( $array_ref ) {
    # sucess
    foreach my $value( @$array_ref ) {
        # do something
    }
} else {
    # failure
}

Will fetch the the $tag value stored in the current node.

setProperty

fail() unless $sgf->setProperty($tag,@values);

Sets the the $tag value of the current node to @values. This method does a series of sanity checks before attempting to write. It will fail if any of the following are true:

@values > 0 and is not a list
$tag is of type T_ROOT but the current node is not the root node
$tag is a T_MOVE or T_SETUP and the other type is already present in the node
@values are invalid type values
unseting a value that is not set.

If @values is not passed then it will remove the property from the node. This is not the same as setting to a empty value.

$sgf->setProperty($tag); # will unset the $tag
$sgf->setProperty($tag, "" ); # will set to an empty value

compose

($pt1, $pt2) = $sgf->compose($compose);
$compose = $sgf->compose($pt1,$pt2);

Used for creating and breaking apart composed values. If you will be setting or fetching a composed value you will be needing this function to breack it apart.

isComposed

if( $sgf->isComposed($compose) ) {
   ($val1, $val2) = $sgf->compose($compose);
}

This returns true if the value passed in is a composed value, otherwise false.

err

if( $sgf->err ) {
   print $sgf->err;
   return 0;
}

# This is for extending modules and internal use
$sgf->err( "Will set error message");

Sets and fetchs the current error message.

CONSTANTS

Type

These are the defined property types. They tell the engine where the tag is allowed to be.

T_MOVE

This is used for properties discribing a move. T_MOVE and T_SETUP tags may not be present in the same node.

T_SETUP

These properties are used for setting up a position on the board. Such as placing stones on the board.

T_ROOT

These properties must be in the root node. This is the root of the collection, not the root of a variation tree.

T_GAME_INFO

These are used for discribing the game. They should be on the earliest node, that the game is evident. For example if the SGF file is a fuseki, the Game_info should be when the game becomes unique in the collection.

T_NONE

There is no placement restrictions placed on tags of this type.

These can be in any node. There is no resrictions placed on these nodes.

Value Type

These discribe the types of data contained in a tag.

V_NONE

These properties have no tag content.

V_NUMBER

This is a number which satifisies the regex: [+-]?[0-9]+

V_REAL

This is a number which satifisies the regex: [+-]?[0-9]+(\.[0-9]+)?

V_DOUBLE

This is used for emphasies. For example GB move the good for black property. GB[1] would mean "Good for Black" GB[2] would mean "Very Good for Black."

DBL_NORM

Used for normal emphasis. When 1 is passed into a V_DOUBLE.

DBL_EMPH

Used for emphasis. When 2 is passed into a V_DOUBLE.

V_COLOR

This is used to specify a color, such as which color starts.

C_BLACK

Used when B is passed into a V_COLOR tag.

C_WHITE

Used when W is passed into a V_COLOR tag.

V_TEXT

Can take pretty much any text.

V_SIMPLE_TEXT

Same as V_TEXT except all spaces are reduced down to a single space.

V_POINT

This is used to specify a point on the board. Used for marking positions. This is a Game Specific property type and will be handled as V_TEXT unless a parsing callback is specified.

V_STONE

This is used to specify a stone or placement of a stone on the board on the board. Used for stone placement. This is a Game Specific property type and will be handled as V_TEXT unless a parsing callback is specified.

V_MOVE

This is used to specify a move on the board. Used making moves on the board. This is a Game Specific property type and will be handled as V_TEXT unless a parsing callback is specified.

Flags

These are various flags that can be given to a property tag. Since these are bit flags, in order to set more then one flag use the bitwise | operator. For example to set both the VF_EMPTY and VF_LIST flag use VF_EMPTY | VF_LIST.

VF_EMPTY

This also's the property to the tag to be empty. For Example MA uses this flag:

MA[]

or

MA[ff][gg]
VF_LIST

This allows you to list properties together. The second example above demstrates this behavior. Used in conjunction with VF_EMPTY allows you to have a empty list, otherwise it must have at least one property given.

VF_OPT_COMPOSE

This tag allows a property to be composed with itself. For example in the specification any List of Points can be used as a List of Point composed with point, in order to specify a rectangular region of points. As an Example:

MA[aa][ab][ba][bb]

is equavalent to:

MA[aa:bb]

Attribute

A_NONE

Used to specify no Attribute is set.

A_INHERIT

Currently the only Attribute defined in the specs. This property value will be passed down to all subsequient nodes, untill a new value is set.

ASSUMPTIONS

All Inherited properties are T_NONE

This holds true for standard FF4 and I believe it would cause conflict if it was not true.

TODO and KNOWN Problems

Write Test Code
Add methods for auto detecting gamemode, and FF[4]

Could change the inheritance method to registering a class with a game mode.

index Node names

ALSO SEE

http://www.red-bean.com/sgf

Games::Goban

Games::Go::SGF

AUTHOR

David Whitcomb, <whitcode at gmail.com>

BUGS

Please report any bugs or feature requests to bug-games-sgf at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Games-SGF. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.