Skip to content
Trevoke edited this page Feb 21, 2013 · 5 revisions

First, apologies because I suck at writing documentation.

So… What is this gem? It’s a gem to parse the (Smart Game Format), a plain-text format to record board games such as Backgammon, Chess and Go/Weiqi/Baduk.

It works with Ruby >1.8.7 (ree, 1.9, etc).

It supports SGF format FF4 - the current format. If you have any files in a prior format (FF3 or FF1), you may want to look for a converter. I think it should work, but it is not guaranteed.

How would you use it? Well, you can use it with an SGF in String format, with a local path to an SGF file, or with a File handler: something like File.open(‘my.sgf).

require 'sgf'
parser = SGF::Parser.new
tree = parser.parse 'sgf_file'

Why is it a tree? Well, it’s actually a class that represents the entire file. SGF is basically a linked list of nodes, so in a way, this is a metaclass that holds high-level constructs. For instance:

tree.games # => yields an array of the games contained in the file.
game = tree.games.first # => yields a SGF::Game object, the first in the array, most likely what you care about.

There are many game-level properties that you may want to know about, and you can get to them with the following instance-level methods on the Game objects. Some are only available for some games, and these are optional anyway, so if they’re not available on your instance, you’ll get a SGF::NoIdentityError.

PROPERTIES = {"annotator"=>"AN",
              "black_octisquares"=>"BO", #Octi
              "black_rank"=>"BR",
              "black_team"=>"BT",
              "copyright"=>"CP",
              "date"=>"DT",
              "event"=>"EV",
              "game_content"=>"GC",
              "handicap"=>"HA", #Go
              "initial_position"=>"IP", #Lines of Action
              "invert_y_axis"=>"IY", #Lines of Action
              "komi"=>"KM", #Go
              "match_information"=>"MI", #Backgammon
              "name"=>"GN",
              "prongs"=>"NP", #Octi
              "reserve"=>"NR", #Octi
              "superprongs"=>"NS", #Octi
              "opening"=>"ON",
              "overtime"=>"OT",
              "black_player"=>"PB",
              "place"=>"PC",
              "puzzle"=>"PZ",
              "white_player"=>"PW",
              "result"=>"RE",
              "round"=>"RO",
              "rules"=>"RU",
              "setup_type"=>"SU", #Lines of Action
              "source"=>"SO",
              "time"=>"TM",
              "data_entry"=>"US",
              "white_octisquares"=>"WO", #Octi
              "white_rank"=>"WR",
              "white_team"=>"WT"}

You can navigate through the main branch fairly easily:

node = game.current_node # => returns the game's first node by default
node = game.next_node # => returns the next node in the current branch, and changes game.current_node to point to this node.

So… What can you do with nodes? Well, you can summon the basic properties like this: (I need to make them more human-friendly, refer to issue #18).

node.properties #=> returns a hash of the properties.

A single property can be called, like the comments, for instance, like so:

node.C #=> returns the comments for this node
node.pw #=> returns the value of PW (Player White) if it exists on this node
node["AW"] #=> same as node.aw or node.properties["AW"]
node[:AW] #=> same as the previous line
node.comments #=> syntactic sugar, only works for comments
node.comment #=> same as the previous line

When you’re done, I’m sure you’ll want to save the file:

tree.save 'destination_filename.sgf'

There’s also an executable to indent the SGF and makes it a little more readable:

$ sgf_indent source.sgf destination.sgf
Clone this wiki locally