These are the criteria a rule needs to satisfy to be a "Day and Knight" rule:
- It must be self-complementary, just like Day and Night
- It must have a (preferably natural) knightship or oblique ship.
- It must not be explosive, just like Day and Night
Day and Knight 1, found by Saka:
Code: Select all
x = 35, y = 37, rule = B2ci3aenry4ekrz5acinq6eik78/S2acn3ejkry4-cknz5cijkq6-ci78
35o$35o$35o$35o$35o$35o$35o$13o3b19o$13o2b20o$13o4b18o$13o4b18o$13o3b
19o$9o4b22o$9o4b22o$9o4b22o$9o4b22o$35o$35o$35o$35o$35o$3obob29o$2o2bo
2b28o$2o5b28o$2o5b28o$2o5b28o$2o5b28o$2o5b28o$35o$35o$29o3b3o$4ob11ob
12o2b4o$3o3b6ob3obobob8o3b3o$4ob6o3b4o2b9o2b4o$11ob6o3b8o3b3o$35o$35o!
Code: Select all
x = 46, y = 46, rule = B2-ak3acikr4cikrz5-ekny6-ac78/S2ac3ekny4-ekntz5ejnqy6ak78
bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo$b44o$46o$46o$b2o3b39o$b
2o2b3o3bob32o$18ob2o2b2o2b2ob8ob7o$10obob5o12b7obob6o$b11ob4o14b7ob6o$
b11ob4o14b5o2bo2b4o$18o6bobo3b8ob7o$4ob2o2b9o12b7obob6o$b2ob4ob8o7bobo
4b7ob6o$b16o4bo9b14o$18o3bo8b16o$10obob5o3bo8b16o$b3o3b10o4bo9b7ob6o$b
9obob4o14b7ob6o$18o12b8ob7o$18ob2o2b2o2b2ob6obobob5o$b37ob6o$b37ob6o$
38ob7o$29obob14o$b28obob13o$b28obob6ob6o$38ob7o$29obob6ob7o$b28obob6ob
6o$b28obob13o$46o$46o$b39o3b2o$b39obob2o$41ob4o$7ob38o$b4o3b37o$b5o3b
4o2b30o$6ob4o6b29o$12o4b24ob5o$b11ob2ob23o3b3o$b40ob3o$46o$46o$b44o$bo
2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo!
Code: Select all
x = 4, y = 3, rule = B2i3ain4ertyz5acn6ak7e/S01c2-ak3-acn4-cijnz5-ain6-i78
bo$3o$ob2o!
Code: Select all
x = 4, y = 3, rule = B3ai4knry5knr6ace8/S12ikn3-knr4-jknr5-ai678
bo$3o$ob2o!
Code: Select all
x = 60, y = 46, rule = B2k3aiy4cejnrty5ackqy6k7e/S01c2-k3eijnr4akqtwz5-aiy6-k78
15bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo$15b44o$14b46o$14b46o$
15b44o$15b6o2b36o$14b6o3b12ob4ob2ob16o$bo12b5o4b10o2b6o2b8ob8o$b2o12b
4o3bo3b5o4b6o2b8o2b6o$bo13b7o4b3o7b5o2b8ob7o$2bo11b8o3b5o5b5ob2ob8ob7o
$14b8o2b6ob29o$15b14o2b28o$15b44o$14b46o$14b37o3b6o$15b6o2b36o$15b8ob
7ob27o$14b6o2bob7ob28o$14b7o3b6o3b27o$15b7o2b6o3b26o$15b37o2b5o$14b37o
3b6o$14b37o2b7o$15b44o$15b44o$14b46o$14b46o$ob2o11b35obo2b5o$3o12b35o
3b6o$bo12b37ob8o$14b46o$15b44o$15b44o$14b46o$14b46o$15b34ob2ob6o$15b4o
b2ob25o2b2o2b5o$14b5ob2ob26ob2ob7o$14b5ob2ob37o$15b4ob2ob36o$15b44o$
14b46o$14b46o$15b44o$15bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo!
Code: Select all
x = 110, y = 47, rule = B3aeinq4jrtyz5aen6ak7e/S01c2-ak3-aen4-ijnyz5cjkry678
57bo2bobobobobobobobobobobobobobobobobobobobobobobobo2bo$58b51o$58b51o
$57b11ob36ob4o$58b46ob4o$57b30ob15ob6o$58b51o$57b53o$58b51o$57b53o$58b
51o$57b53o$58b51o$57b53o$58b51o$57b53o$58b3ob4ob2o2b38o$57b4ob3o2b2o3b
38o$58b3ob3ob4o2b37o$57b53o$58b51o$57b53o$58b51o$57b53o$58b51o$57b21ob
31o$58b2ob8ob7o4b22o3b3o$57b5ob6o2b5o6b21o3b4o$22bob2obo30b4ob14o4b24o
b3o$2bo11bo8b4o8bo4bo16b5ob7o2b7ob24ob5o$3bo9b3o5b8o5b3o2b3o8b3o5b6ob
6ob37o$2bobo7b2obo6b6o7bo4bo9b3o4b53o$o4bo29bob2obo11bo5b46ob4o$36bo2b
o11bo5b46o3b4o$58b44o2bob3o$57b27ob25o$58b51o$57b15ob7ob2ob7ob18o$58b
3o4b5ob11ob7o2b10ob6o$57b6o2b7o2b3ob5ob6o2b11ob6o$58b4obob7o3b11ob3o2b
10obob4o$57b7ob7o2b16o2b8ob4ob4o$58b24ob7ob18o$57b15ob37o$58b51o$58b
51o$57bo2bobobobobobobobobobobobobobobobobobobobobobobobo2bo!
This one is modified from wildmyron's searchRules.py:
Code: Select all
# searchRules.py Search for rules in which a given pattern is a spaceship
# Author: Arie Paap, Aug 2017
# Modified to only search self-complementary rules by Goldtiger997, Aug 2018
#
# Search for isotropic rules where a specified pattern is a spaceship or
# oscillator. Optimised to search rules which are most likely to contain small
# ships. Search ends when a ship is found.
import golly as g
import itertools
import random
# Search parameters
# Stop if pattern is a ship with this minimum period
minShipP = 4
# Stop if pattern is an oscillator with this minimum period
minP = 1
# Maximum period to test the pattern for
maxGen = 50
# Maximum population in any phase
maxPop = 300
# Allow search for oscillators
bOsc = False
# Force a search for oblique ships
bKnight = False
# Generate a random isotropic rule which is likely to allow spaceships to exist
# Adaptation of a script by Dave Green http://conwaylife.com/forums/viewtopic.php?p=43545#p43545
# ----------------------------------------------------------
isotropiclistB = ["0",
"1c", "1e",
"2c", "2e", "2k", "2a", "2i", "2n",
"3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
"4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z",
"5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
"6c", "6e", "6k", "6a", "6i", "6n",
"7c", "7e",
"8"]
isotropiclistS = ["0",
"1c", "1e",
"2c", "2e", "2k", "2a", "2i", "2n",
"3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
"5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
"6c", "6e", "6k", "6a", "6i", "6n",
"7c", "7e",
"8"]
fours = ["4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z"]
reversefours = ["4e", "4c", "4k", "4a", "4t", "4r", "4j", "4w", "4y", "4n", "4i", "4q", "4z"]
# Remove B0 and B1 conditions
isotropiclistB.remove("0")
isotropiclistB.remove("1c")
isotropiclistB.remove("1e")
# 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 = ""
for elem in isotropiclistB:
if random.random()<prob: rulestr+=elem
# Ensure rule has a chance of supporting ships
if len(rulestr) == 0:
# Add a random rule element
rulestr+=random.choice(isotropiclistB)
if not rulestr[0] 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+='/S'
# S0 is best used when the test pattern is sparse / has a low population
#if random.random()<0.5: rulestr+='0'
#for elem in isotropiclistS:
# if random.random()<prob: rulestr+=elem
inverse = ""
for trans in isotropiclistS:
if trans not in rulestr:
flipped = str(8-int(trans[0])) + trans[1:]
inverse += flipped
for i in range(0,len(fours)):
if fours[i] not in rulestr:
inverse += reversefours[i]
return("B" + rulestr + "/S" + inverse)
# ----------------------------------------------------------
# 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):
# Test for periodicity
r = g.getrect()
if testPatt == g.transform(g.getcells(r),-r[0],-r[1]):
period = ii+1
if (r[0] == 0 and r[1] == 0 ):
# Oscillator (reject if low period or bOsc is False)
if bOsc and period >= minP:
return (period, )
elif ( period >= minShipP and (bKnight == False or (abs(r[0]) != abs(r[1]) and r[0] != 0 and r[1] != 0))):
# Spaceship (reject if low period)
return (r[0], r[1], period)
break # Pattern is a low period oscillator or spaceship
return ()
# Set up the search with the current pattern
testRect = g.getrect()
testPop = int(g.getpop())
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('searchRules')
for ii in itertools.count(0,1):
result = testRule(randIsoRule())
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 = 'Found oscillator with period = %d' % result
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')
Code: Select all
# iterRulesrc.py
#
# This version of Rulesrc (available: ConwayLife.com) aims to improve search efficiency for productive patterns+conditions.
# The results get listed to iterRulesrc_results.txt and the search is cancelled by pressing any key.
# Arie Paap, Aug 2017
# Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
# Updated by: Peter, NASZVADI (), June 2017.
# Grafted by Rhombic, Aug 2017.
# Modified to only search self-complementary rules by Goldtiger997, Aug 2018
import golly as g
import itertools
from glife import validint
from string import replace
import random
if g.empty():
g.note("This program needs you to paste in a pattern to work.\nThen you can run the script",False)
g.setrule("B2ci3ai4c8/S02ae3eijkq4iz5ar6i7e")
g.putcells(g.parse("obo!"))
g.exit()
knight=g.getstring('Do you want to force knightships (y/n)?',"y")
if knight == "y":
bKnight = True
else:
bKnight = False
GENERATION_STRING=g.getstring('To stop this script, press any key at any point.\nHow many generations to remain unchanged:', '', 'Rules calculator')
birth_survival = g.getstring("Well actually for self-complementary rules you can't necessarily force the Generations to remain unchanged.\nSo this script supports keeping either the necessary birth conditions or the necessary survival conditions.\nWhich one would you like to keep (b/s)?","b")
if birth_survival == "b":
bs = "birth"
if birth_survival == "praisecalcyman":
g.setrule("b3/s23")
g.new("praisecalcyman")
g.putcells(g.parse("2bo$bobo$bobo$2ob3o$6bo$2ob3o$2obo!"))
g.exit("Praise Calcyman")
else:
bs = "survival"
def setminrule(RULE, DX, DY, PERIOD):
# Rule computation script for use with Golly.
# Author: Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
# Updated by: Peter, NASZVADI (), June 2017.
# Gives the maximal family of rules that a still life, oscillator, or spaceship
# works under. Must be called while the rule is set of one such family
# For example, to find out what rules a glider works in, first set the rule
# to Life or HighLife, not Seeds.
# Handles nontotalistic rules, too, so it needs Golly 2.8 or newer.
import golly as g
g.setrule(RULE)
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']
]
# 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 = PERIOD
numsteps = PERIOD
if numsteps < 1:
g.exit('Period must be at least 1.')
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))
ruleres = rulestringopt(ruleres)
g.setrule(ruleres)
RESULT = [ruleres, DX, DY, PERIOD]
return RESULT
def Rulesrc():
# 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']
]
# 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"""
return a
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 = GENERATION_STRING
if not validint(s):
g.exit('Bad number: %s' % s)
numsteps = int(s)
if numsteps < 1:
g.exit('Period must be at least 1.')
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)
isotropiclist = ["0",
"1c", "1e",
"2c", "2e", "2k", "2a", "2i", "2n",
"3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
"5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
"6c", "6e", "6k", "6a", "6i", "6n",
"7c", "7e",
"8"]
fours = ["4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z"]
reversefours = ["4e", "4c", "4k", "4a", "4t", "4r", "4j", "4w", "4y", "4n", "4i", "4q", "4z"]
# 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
if bs == "birth":
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])
inverse = ""
for trans in isotropiclist:
if trans not in rulestr:
flipped = str(8-int(trans[0])) + trans[1:]
inverse += flipped
for i in range(0,len(fours)):
if fours[i] not in rulestr:
inverse += reversefours[i]
return(rulestr + "/S" + inverse)
else:
rulestr = ruleS
for elem in isotropiclistS:
if random.random()<prob: rulestr+=elem
inverse = ""
for trans in isotropiclist:
if trans not in rulestr:
flipped = str(8-int(trans[0])) + trans[1:]
inverse += flipped
for i in range(0,len(fours)):
if fours[i] not in rulestr:
inverse += reversefours[i]
return("B" + inverse + 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)
# Stability check periodicity
stabCheckP = 24
# 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)
stabPatt = testPatt
stabPop = testPop
for ii in xrange(maxGen):
g.run(1)
pop = int(g.getpop())
if (pop < minPop or pop > maxPop):
break
elif (pop == testPop):
# Test for periodicity
r = g.getrect()
if testPatt == g.transform(g.getcells(r),-r[0],-r[1]):
period = ii+1
if (r[0] == 0 and r[1] == 0 ):
# Oscillator (reject if low period or bOsc is False)
if bOsc and period >= minP:
return (period, )
elif ( period >= minShipP and (bKnight == False or (abs(r[0]) != abs(r[1]) and r[0] != 0 and r[1] != 0))):
# Spaceship (reject if low period)
return (r[0], r[1], period)
break # Pattern is a low period oscillator or spaceship
# Stability check
if (ii % stabCheckP == 0):
r = g.getrect()
currPatt = g.transform(g.getcells(r),-r[0],-r[1])
if (pop == stabPop and currPatt == stabPatt):
# Pattern has stabilised
return ()
stabPop = pop
stabPatt = currPatt[:]
return ()
# Set up the search with the current pattern
testRect = g.getrect()
testPop = int(g.getpop())
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 = 'Found oscillator with period = %d' % result
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)
Spaceship = str(g.getrule()), dx, dy, period
return Spaceship
else:
g.show('No results found')
textfile=open("iterRulesrc_results.txt","w+")
g.select(g.getrect())
g.copy()
textfile.write("\n"+g.getclipstr()+"\n\n")
ListRules = set()
while 1:
newrule=Rulesrc()
event = g.getevent()
if event.startswith("key"):
break
if newrule[0] not in ListRules:
ListRules.add(newrule[0])
textfile.write(newrule[0]+"\t("+str(newrule[1])+","+str(newrule[2])+")/\t"+str(newrule[3])+"\n")
textfile.close()
g.exit("We have found %d results, found in your rule folder as iterRulesrc_results.txt. Thank you for your patience." % len(ListRules))
I hope you find this rule "group" interesting!