The Turtle wrote:How can I search for an object by name?
If not, is there a pattern to "apgcode" converter?
Yes, well, speaking of feature requests... it would certainly be nice if the Object page in Catagolue could accept RLE or ASCII picture format, and/or a search-by-name as you mentioned. The apgcode representation is nice once you have it, but for anyone who is just discovering Catagolue and apgsearch/apgnano for the first time, there's no immediately obvious tool for producing apgcode from a pattern in Golly.
There are quite a few Python scripts floating around that can do the RLE-to-apgcode conversion. There's
flipper77's script that looks up soups on Catagolue that contain specific objects, for example, and
gameoflifeboy's patched versions which might be useful if you get errors (not sure if the problem was addressed in the original script.)
If you really just want to select an object and copy its apgcode to the clipboard, here's a script I mostly plagiarized directly from apgsearch code. Unlike flipper77's script, it doesn't support things like linear-growth patterns -- just nice simple still lifes, oscillators and spaceships:
standalone-canonise.py:
Code: Select all
import golly as g
# Differs from oscar.py in that it detects absolute cycles, not eventual cycles.
def bijoscar(maxsteps):
initpop = int(g.getpop())
initrect = g.getrect()
if (len(initrect) == 0):
return 0
inithash = g.hash(initrect)
for i in xrange(maxsteps):
g.run(1)
if (int(g.getpop()) == initpop):
prect = g.getrect()
phash = g.hash(prect)
if (phash == inithash):
period = i + 1
if (prect == initrect):
return period
else:
return -period
return -1
# Obtains a canonical representation of any oscillator/spaceship that (in
# some phase) fits within a 40-by-40 bounding box. This representation is
# alphanumeric and lowercase, and so much more compact than RLE. Compare:
#
# Common name: pentadecathlon
# Canonical representation: 4r4z4r4
# Equivalent RLE: 2bo4bo$2ob4ob2o$2bo4bo!
#
# It is a generalisation of a notation created by Allan Weschler in 1992.
def canonise(duration):
representation = "#"
# We need to compare each phase to find the one with the smallest
# description:
for t in xrange(duration):
rect = g.getrect()
if (len(rect) == 0):
return "0"
if ((rect[2] <= 40) & (rect[3] <= 40)):
# Fits within a 40-by-40 bounding box, so eligible to be canonised.
# Choose the orientation which results in the smallest description:
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1], -1, 0, 0, 1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1]+rect[3]-1, 1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1]+rect[3]-1, -1, 0, 0, -1))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1], 0, 1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1], 0, -1, 1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1]+rect[3]-1, 0, 1, -1, 0))
representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1]+rect[3]-1, 0, -1, -1, 0))
g.run(1)
return representation
# A subroutine used by canonise:
def canonise_orientation(length, breadth, ox, oy, a, b, c, d):
representation = ""
chars = "0123456789abcdefghijklmnopqrstuvwxyz"
for v in xrange(int((breadth-1)/5)+1):
zeroes = 0
if (v != 0):
representation += "z"
for u in xrange(length):
baudot = 0
for w in xrange(5):
x = ox + a*u + b*(5*v + w)
y = oy + c*u + d*(5*v + w)
baudot = (baudot >> 1) + 16*g.getcell(x, y)
if (baudot == 0):
zeroes += 1
else:
if (zeroes > 0):
if (zeroes == 1):
representation += "0"
elif (zeroes == 2):
representation += "w"
elif (zeroes == 3):
representation += "x"
else:
representation += "y"
representation += chars[zeroes - 4]
zeroes = 0
representation += chars[baudot]
return representation
# Compares strings first by length, then by lexicographical ordering.
# A hash character is worse than anything else.
def compare_representations(a, b):
if (a == "#"):
return b
elif (b == "#"):
return a
elif (len(a) < len(b)):
return a
elif (len(b) < len(a)):
return b
elif (a < b):
return a
else:
return b
r=g.getselrect()
if r==[]:
r=g.getrect()
if r==[]:
g.exit("No pattern to convert.")
cells=g.getcells(r)
if len(cells)==0:
g.exit("Select an object to get its apgcode representation.")
g.addlayer()
g.putcells(cells)
period = bijoscar(1000)
canonised = canonise(abs(period))
if (period < 0):
apgcode="xq"+str(0-period)+"_"+canonised
elif (period == 1):
apgcode="xs"+g.getpop()+"_"+canonised
else:
apgcode="xp"+str(period)+"_"+canonised
g.dellayer()
g.show(apgcode + " -- press 'c' to copy to clipboard, any other key to exit.")
c=""
while c=="": c=g.getevent()
if c[:5]=="key c":
g.setclipstr(apgcode)
g.show("Copied '"+apgcode+"' to clipboard.")
I added a small amount of error-checking code, and set it up so the script doesn't rudely modify your clipboard contents without warning -- you have to type 'c' if you want the apgcode copied to the clipboard.
There's a lot more that could be done in the error-checking department, though. In particular, if you try to encode a pattern that hasn't been run to stabilization, this script will cheerfully give you rather strange arbitrary results, which Catagolue probably won't recognize as valid apgcode.
I've used apgcode in a couple of scripting projects now, to produce a one-line ID for an arbitrary pattern (not necessarily stabilized.) That works fine if you just call canonise_orientation() and leave off the "x/y/z#_" prefix.
Unfortunately there's an awkward limitation to 40x40 patterns, which can't be easily patched. I've kludged it for my own purposes by adding uppercase characters to the string in line 74 -- but that makes the resulting codes much less HTML-compatible.
One of the design limitations in the current Catagolue is that very different objects that overflow 40x40 get piled indiscriminately into the "ov" category. Here's hoping that at some point Calcyman will decide on an official extension of the apgcode format to larger objects.