Here's a splitter, though it's maybe not in the direction you hoped for:
Code: Select all
x = 3, y = 8, rule = B34nq5ce6in7c8/S23-e4cqz5e6in7e8
o$b2o$2o4$2o$2o!
This is the awful script I used to find it, an ugly hack of Rulesrc. (I had designed it hoping to find a spaceship like the tlife puffer, but it works here):
Code: Select all
# Glidersrc.py
#
# Arie Paap, Aug 2017
# Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
# Updated by: Peter, NASZVADI (), June 2017.
# Grafted by Rhombic, Aug 2017.
# Ruined by toroidalet, Sep 2021, Sep 2023.
import golly as g
import itertools
import random
# Search parameters
# Stop if pattern is a ship with this minimum period
minShipP = 1
# Stop if pattern is an oscillator with this minimum period
minP = 3
# Maximum period to test the pattern for
maxGen = 1000
# Maximum population in any phase
maxPop = 300
# Allow search for oscillators
bOsc = False
import golly as g
from glife import validint
from string import replace
Hensel = [
['0'],
['1c', '1e'],
['2a', '2c', '2e', '2i', '2k', '2n'],
['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
['6a', '6c', '6e', '6i', '6k', '6n'],
['7c', '7e'],
['8']
]
if g.numlayers() == g.maxlayers():
g.exit("no layers")
# Python versions < 2.4 don't have "sorted" built-in
try:
sorted
except NameError:
def sorted(inlist):
outlist = list(inlist)
outlist.sort()
return outlist
# --------------------------------------------------------------------
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i+n]
# --------------------------------------------------------------------
def rulestringopt(a):
result = ''
context = ''
lastnum = ''
lastcontext = ''
for i in a:
if i in 'BS':
context = i
result += i
elif i in '012345678':
if (i == lastnum) and (lastcontext == context):
pass
else:
lastcontext = context
lastnum = i
result += i
else:
result += i
result = replace(result, '4aceijknqrtwyz', '4')
result = replace(result, '3aceijknqry', '3')
result = replace(result, '5aceijknqry', '5')
result = replace(result, '2aceikn', '2')
result = replace(result, '6aceikn', '6')
result = replace(result, '1ce', '1')
result = replace(result, '7ce', '7')
return result
clist = []
rule = g.getrule().split(':')[0]
fuzzer = rule + '9'
oldrule = rule
rule = ''
context = ''
deletefrom = []
for i in fuzzer:
if i == '-':
deletefrom = [x[1] for x in Hensel[int(context)]]
elif i in '0123456789/S':
if deletefrom:
rule += ''.join(deletefrom)
deletefrom = []
context = i
if len(deletefrom) == 0:
rule += i
elif i in deletefrom:
deletefrom.remove(i)
rule = rule.strip('9')
if not (rule[0] == 'B' and '/S' in rule):
g.exit('Please set Golly to a Life-like rule.')
if g.empty():
g.exit('The pattern is empty.')
s = g.getstring('How many generations to remain unchanged:', '', 'Rules calculator')
if not validint(s):
g.exit('Bad number: %s' % s)
w = g.getstring('final population', g.getpop(), '')
if not validint(w):
g.exit('Bad number: %s' % s)
n = g.getstring('Number of results', "1", '')
if not validint(n):
g.exit('Bad number: %s' % s)
numsteps = int(s)
if numsteps < 1:
g.exit('Period must be at least 1.')
nresults=int(n)
results=[]
g.select(g.getrect())
g.copy()
s = int(s)
for i in range(0,s):
g.run(1)
clist.append(list(chunks(g.getcells(g.getrect()), 2)))
mcc = min(clist[i])
clist[i] = [[x[0] - mcc[0], x[1] - mcc[1]] for x in clist[i]]
g.show('Processing...')
ruleArr = rule.split('/')
ruleArr[0] = ruleArr[0].lstrip('B')
ruleArr[1] = ruleArr[1].lstrip('S')
b_need = []
b_OK = []
s_need = []
s_OK = []
context = ''
fuzzed = ruleArr[0] + '9'
for i in fuzzed:
if i in '0123456789':
if len(context) == 1:
b_need += Hensel[int(context)]
b_OK += Hensel[int(context)]
context = i
elif context != '':
b_need.append(context[0] + i)
b_OK.append(context[0] + i)
context += context[0]
context = ''
fuzzed = ruleArr[1] + '9'
for i in fuzzed:
if i in '0123456789':
if len(context) == 1:
s_need += Hensel[int(context)]
s_OK += Hensel[int(context)]
context = i
elif context != '':
s_need.append(context[0] + i)
s_OK.append(context[0] + i)
context += context[0]
for i in [iter2 for iter1 in Hensel for iter2 in iter1]:
if not i in b_OK:
b_OK.append(i)
execfor = 1
# B0 and nontotalistic rulestrings are mutually exclusive
try:
g.setrule(rulestringopt('B' + ''.join(b_OK) + '/S' + ruleArr[1]))
except:
b_OK.remove(i)
execfor = 0
for j in range(0, s * execfor):
g.run(1)
try:
dlist = list(chunks(g.getcells(g.getrect()), 2))
mcc = min(dlist)
dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
if not(clist[j] == dlist):
b_OK.remove(i)
break
except:
b_OK.remove(i)
break
g.new('')
g.paste(0, 0, 'or')
g.select(g.getrect())
b_OK.sort()
if not i in s_OK:
s_OK.append(i)
execfor = 1
# B0 and nontotalistic rulestrings are mutually exclusive
try:
g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_OK)))
except:
s_OK.remove(i)
execfor = 0
for j in range(0, s * execfor):
g.run(1)
try:
dlist = list(chunks(g.getcells(g.getrect()), 2))
mcc = min(dlist)
dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
if not(clist[j] == dlist):
s_OK.remove(i)
break
except:
s_OK.remove(i)
break
g.new('')
g.paste(0, 0, 'or')
g.select(g.getrect())
s_OK.sort()
if i in b_need:
b_need.remove(i)
g.setrule(rulestringopt('B' + ''.join(b_need) + '/S' + ruleArr[1]))
for j in range(0, s):
g.run(1)
try:
dlist = list(chunks(g.getcells(g.getrect()), 2))
mcc = min(dlist)
dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
if not(clist[j] == dlist):
b_need.append(i)
break
except:
b_need.append(i)
break
g.new('')
g.paste(0, 0, 'or')
g.select(g.getrect())
b_need.sort()
if i in s_need:
s_need.remove(i)
g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_need)))
for j in range(0, s):
g.run(1)
try:
dlist = list(chunks(g.getcells(g.getrect()), 2))
mcc = min(dlist)
dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
if not(clist[j] == dlist):
s_need.append(i)
break
except:
s_need.append(i)
break
g.new('')
g.paste(0, 0, 'or')
g.select(g.getrect())
s_need.sort()
g.setrule(oldrule)
ruleres = 'B' + ''.join(sorted(b_need)) + '/S' + ''.join(sorted(s_need)) + \
' - B' + ''.join(sorted(b_OK)) + '/S' + ''.join(sorted(s_OK))
g.show(rulestringopt(ruleres))
ruleB="B"+''.join(sorted(b_need))
ruleS="S"+''.join(sorted(s_need))
isotropiclistB = sorted(b_OK)
isotropiclistS = sorted(s_OK)
# Remove B0 and B1 conditions
for wrongvalues in ["0","1c","1e"]:
if wrongvalues in isotropiclistB:
isotropiclistB.remove(wrongvalues)
# Generate a random isotropic rule which is likely to allow spaceships to exist
def randIsoRule():
# Birth conditions
prob = random.random()*0.55+0.05 # Random number between 0.05 and 0.6
rulestr = ruleB
for elem in isotropiclistB:
if random.random()<prob: rulestr+=elem
# Ensure rule has a chance of supporting ships
if len(rulestr) == 1:
# Add a random rule element
rulestr+=random.choice(isotropiclistB)
if not rulestr[1] in '23':
# Add two random 2x or 3x rule elements
rulestr+=random.choice(isotropiclistB[:16])
rulestr+=random.choice(isotropiclistB[:16])
# Survival conditions (force S0 for dot survival)
prob = random.random()*0.55+0.05 # Random number between 0.05 and 0.6
rulestr+='/'+ruleS
for elem in isotropiclistS:
if random.random()<prob: rulestr+=elem
return(rulestr)
# ----------------------------------------------------------
# Return the minimum and maximum of the absolute value of a list of numbers
def minmaxofabs(v):
v = map(abs, v)
return min(v), max(v)
# Test a pattern in the given rule to determine if it reappears
def testRule(rulestr):
r = g.getrect()
if r:
g.select(r)
g.clear(0)
g.putcells(testPatt)
g.setrule(rulestr)
for ii in xrange(maxGen):
g.run(1)
pop = int(g.getpop())
if (pop < minPop or pop > maxPop):
break
elif (pop == testPop):
w=g.getrect()
for b in xrange(20):
g.run(1)
if (int(g.getpop()) == testPop):
k=1
else:
k=0
break
if k==1:
if (g.getrect() == w):
k=0
else:
w=g.getrect()
g.run(8)
if w != g.getrect():
rule=g.getrule()
if len(results)==0 or rule!=results[-1]:
results.append(g.getrule())
if len(results)==nresults:
return "p"
return ()
# Set up the search with the current pattern
testRect = g.getrect()
testPop = int(w)
testPatt = g.transform(g.getcells(testRect),-testRect[0],-testRect[1])
if bOsc: minPop = 2 # Patterns with 0, or 1 cells can not be oscillators
else: minPop = 3 # Patterns with 0, 1, or 2 cells can not be ships
g.new('spRulesrc')
for ii in itertools.count(0,1):
if bOsc==False:
while 1:
j=randIsoRule()
if "2a" in j: break
if "2c" in j: break
if "3i" in j: break
else:
j=randIsoRule()
result = testRule(j)
if result:
# Interesting pattern found
break
if (ii % 1000 == 0):
g.select([])
g.show('%d candidate rules tested for interesting patterns' % (ii))
g.update()
g.new("")
g.new('Search result')
if result:
g.putcells(testPatt)
if (len(result) == 1):
# Pattern is an oscillator
description = ""
g.getstring("Rules",str(results),"")
elif (len(result) == 3):
dx, dy, period = result
dy, dx = minmaxofabs( (dx, dy) )
if dy == 0:
description = 'Found orthogonal spaceship with speed = %dc/%d' % (dx, period)
elif dy == dx:
description = 'Found diagonal spaceship with speed = %dc/%d' % (dx, period)
else:
description = 'Found knightship with speed = (%d, %d)c/%d' % (dx, dy, period)
else:
g.exit('Unrecognised pattern')
g.show(description)
else:
g.show('No results found')
Plug in a given number of generations to match, a target population and the number of results to find, and it looks for expanding patterns that stabilize at that constant population. You need to have space for one layer.
I used 20 generations and 5 results. The target population was 14.
It can generate a lot of false positives, which, in this case, were mainly (glider+blinker+beehive) and (different block+2 gliders). Just for fun, here is the best one:
Code: Select all
x = 3, y = 8, rule = B34cenq5ce8/S23-e4q5e6in
o$b2o$2o4$2o$2o!
EDIT: A better splitter, but still in the worst direction:
Code: Select all
x = 3, y = 8, rule = B34enq5ce7c8/S234q6i
bo$2bo$3o4$2o$2o!
It has enough clearance that you can send another one after it:
Code: Select all
x = 31, y = 47, rule = B34enq5ce7c8/S234q6i
3b2o$3b2o10$bo$2bo$3o26$29bo$30bo$28b3o4$28b2o$28b2o!
90° reflector!
Code: Select all
x = 3, y = 8, rule = B34enq6i8/S023-e4ceqz5e7e
bo$2bo$3o4$2o$2o!
Any sufficiently advanced software is indistinguishable from malice.