In case it might be useful to anyone, here is an almost complete Python implementation for Golly which I hacked up years ago. Unless there are other issues, the only thing missing is representing spaceships in the standard form according to the spec for direction traveled. It encodes the pattern in the current layer rather than converting rle and copies the sof representation of the pattern to the clipboard. If you want an rle converter it should be just a matter of inserting a few lines to place the pattern in a new layer.

Code: Select all

```
# Canonical small object format representation
# Representation for CGoL objects devised by Heinrich Koenig
# Format description at http://conwaylife.com/wiki/SOF
# Further information at http://www.pentadecathlon.com/objects/definitions/definitions.php
# Determine the canonical small object format representation of the current
# pattern using the comparison rules. Special case rules for spaceships are
# not yet implemented.
#
# By Arie Paap
# Oct. 2014
import golly as g
# Obtains a canonical representation of the current pattern
# Uses algorithm by Adam P. Goucher
def sof_canonise(duration):
sof = ""
# We need to compare each phase to find the one used to determine the
# pattern's standard form:
for t in xrange(duration):
if (duration > 1):
g.run(1)
rect = g.getrect()
if (len(rect) == 0):
return "0"
ox = rect[0]
oy = rect[1]
x_length = rect[2]
y_breadth = rect[3]
# Choose the orientation which comes first according to sof comparison rules:
sof = sof_representation(x_length, y_breadth, ox, oy, 1, 0, 0, 1)
sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox+x_length-1, oy, -1, 0, 0, 1)) # flip_x
sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox, oy+y_breadth-1, 1, 0, 0, -1)) # flip_y
sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox+x_length-1, oy+y_breadth-1, -1, 0, 0, -1)) # 180
sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy, 0, 1, 1, 0)) # swap_xy
sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox+x_length-1, oy, 0, -1, 1, 0)) # cw 90
sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy+y_breadth-1, 0, 1, -1, 0)) # ccw 90
sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox+x_length-1, oy+y_breadth-1, 0, -1, -1, 0)) # swap_xy_flip
return sof
# Determine sof for current pattern in specified orientation:
def sof_representation(length, breadth, ox, oy, a, b, c, d):
sof = ""
for v in xrange(breadth):
value = 1
run = 0
blank = True
if (v != 0):
sof += "-"
for u in xrange(length+1):
x = ox + a*u + b*v
y = oy + c*u + d*v
if (g.getcell(x,y) == value):
# Continue the run
run += 1
else:
# Encode the run, unless a run of zeros reaches the boundary
if (u < length or value == 1):
while (run > 78):
run -= 78
sof += "~0"
sof += chr(run + ord('0'))
run = 1
value = 1 - value # Toggle value
if (value==1):
blank = False
if (blank == True):
# Remove unnecessary '0'
sof = sof[:-2] + '-'
sof += "."
return sof
# Compares two sof patterns according to sof comparison rules.
def sof_compare(a, b):
alines = str.split(a, '-')
blines = str.split(b, '-')
aline = ''
bline = ''
# Find first line with different cell
for line in xrange(0, len(a)):
aline = alines[line]
bline = blines[line]
if not (aline == bline):
break
# Find first difference
value = 1
ii = 0
for ii in xrange(0, min(len(aline), len(bline))):
if not (aline[ii] == bline[ii]):
break
value = 1 - value
if (value == 1):
if int(aline[ii]) > int(bline[ii]):
return a
else:
return b
else:
if int(aline[ii]) > int(bline[ii]):
return b
else:
return a
g.warn("Did not compare")
return '#'
p = int(g.getstring("Enter period of pattern", "1"))
canonPatt = sof_canonise(p)
g.setclipstr(canonPatt)
g.show("SOF representation of pattern is: " + canonPatt + " (copied to clipboard).")
```