Here is a crude script for you to tweak... This can be applied to ptbsearch outputs to filter out matches.
, also for persist gens.
Code: Select all
# Check if a target pattern pops out.
# The first layer should be empty.
# Currently:
# Stops at gen 500 or if pop is constant; no quiescence test.
# Can specify:
# min gens for the target pattern to persist
# max pop of the junk excluding the catalysts and the target
import golly as g
from collections import defaultdict, deque
g.setrule('LifeHistory')
g.autoupdate(True)
statedict = defaultdict(lambda: 1, {'.': 0, 'z': 1, '*': 3})
# Directories
ptbdir = '/home/scorbie/Apps/ptbsearch'
ptbdumppath = g.opendialog("Choose ptbsearch dump file", "*", ptbdir)
# Pattern alignment
patx, paty, inc = 0, 0, 80
curpatrow, patrows = 0, 10
# Filter settings
persist = 10
maxjunkpop = 30
# keystr is the target pattern to match
# and kx, ky is the relative coordinate of any nonempty cell.
kx, ky= 2, 2
keystr = (
'......!'
'......!'
'..aa..!'
'..aa..!'
'......!'
'......')
keypop = keystr.count('a')
samestatedict = [(0,2), (1,), (0,2), (3,), (4,), (5,)]
gliderstr = (
'.....!'
'.aa..!'
'..aa.!'
'.a...!'
'.....!',
'.....!'
'..a..!'
'.aa..!'
'.a.a.!'
'.....!',
'.....!'
'...a.!'
'.aa..!'
'..aa.!'
'.....!',
'.....!'
'.a.a.!'
'..aa.!'
'..a..!'
'.....!',
'.....!'
'..a..!'
'..aa.!'
'.a.a.!'
'.....!',
'.....!'
'..aa.!'
'.aa..!'
'...a.!'
'.....!',
'.....!'
'.a.a.!'
'.aa..!'
'..a..!'
'.....!',
'.....!'
'.a...!'
'..aa.!'
'.aa..!'
'.....!',
'.....!'
'.aaa.!'
'...a.!'
'..a..!'
'.....!',
'.....!'
'.aa..!'
'.a.a.!'
'.a...!'
'.....!',
'.....!'
'..a..!'
'.a...!'
'.aaa.!'
'.....!',
'.....!'
'...a.!'
'.a.a.!'
'..aa.!'
'.....!',
'.....!'
'..aa.!'
'.a.a.!'
'...a.!'
'.....!',
'.....!'
'.aaa.!'
'.a...!'
'..a..!'
'.....!',
'.....!'
'.a...!'
'.a.a.!'
'.aa..!'
'.....!',
'.....!'
'..a..!'
'...a.!'
'.aaa.!'
'.....!')
#assert len(gliders) == 16
def parse(patstr, kx=0, ky=0):
return {(x-kx, y-ky): samestatedict[statedict[char]]
for y, row in enumerate(keystr.split('!'))
for x, char in enumerate(row)}
key = parse(keystr, kx, ky)
gliders = [parse(gl, 3, 3) for gl in gliderstr]
# Main
try:
g.addlayer()
g.setlayer(0)
with open(ptbdumppath) as ptbdumpfile:
lines = sum(1 for line in ptbdumpfile)
with open(ptbdumppath) as ptbdumpfile:
for lineno, line in enumerate(ptbdumpfile):
# Initialize
g.new('')
g.setoption('autofit', True)
g.setmag(2)
g.show('{}/{}'.format(lineno+1, lines))
pattern = line.split()[0]
catpop = pattern.count('*') + pattern.count('z')
rows = pattern.split('!')
for y, row in enumerate(rows):
for x, char in enumerate(row):
g.setcell(x, y, statedict[char])
initpat = g.getcells(g.getrect())
recentmatches = deque([], persist)
recentjunkpop = deque([], persist)
# Run the pattern and check for matches
assert g.getoption('autofit')
while int(g.getgen()) < 500:
g.run(1)
curpat = g.getcells(g.getrect())
# Dictionary of (coordinate: cell state)s:
celldict = {(x, y): c for x, y, c in zip(*([iter(curpat)]*3))}
celldict = defaultdict(lambda: 0, celldict)
# Abort if any catalyst is damaged.
if 4 in celldict.values():
break
# Live cell population; g.getpop() counts state 2 cells...
matches, glidermatches = set(), set()
oncells = {coord for coord in celldict.keys() if coord}
for vx, vy in oncells:
if all(celldict[(x+vx, y+vy)] in cs
for (x, y), cs in key.iteritems()):
matches.add((vx, vy))
# Glider detection... Disabled until there's a faster way.
'''
for gl in gliders:
if all(celldict[(x+vx, y+vy)] in cs
for (x, y), cs in gl.iteritems()):
glidermatches.add((vx, vy))
'''
curpop = sum(c in [1, 3, 5] for c in celldict.values())
junkpop = (curpop - catpop - keypop
- 5 * len(glidermatches))
#g.show('curpop: {}, catpop: {}, keys: {}*{}, gliders: 5*{}, junkpop: {}'
# .format(curpop, catpop, keypop, len(matches), len(glidermatches), junkpop))
#g.show('{}/{}, junkpop={}'.format(lineno, lines, junkpop))
recentmatches.append(matches)
recentjunkpop.append(junkpop)
#g.show(str(recentmatches)); import time; time.sleep(0.5)
if (len(recentmatches) == persist and
all(junkpop <= maxjunkpop for junkpop in recentjunkpop) and
set.intersection(*recentmatches)):
g.setlayer(1)
g.putcells(initpat, patx, paty)
curpatrow += 1
if curpatrow < patrows:
patx += inc
else:
patx, paty, curpatrow = 0, paty+inc, 0
g.setlayer(0)
break
# See if population doesn't change for 10 gens
if (len(recentmatches) == persist and
all(junkpop == recentjunkpop[0]
for junkpop in list(recentjunkpop)[-10:])):
break
except:
g.dellayer()
if not ptbdumppath:
g.exit("No file specified; aborting.")
else:
raise