def slideshow ():
   oldalgo = g.getalgo()
   oldrule = g.getrule()
   
   message = "Hit space to continue or escape to exit the slide show..."
   g.show(message)
   for root, dirs, files in os.walk(g.getdir("app") + "Patterns"):
      for name in files:
         if name.startswith("."):
            # ignore hidden files (like .DS_Store on Mac)
            pass
         else:
            fullname = join(root, name)
            g.open(fullname, False)       # don't add file to Open/Run Recent submenu
            g.update()
            if name.endswith(".pl") or name.endswith(".py"):
               # reshow message in case it was changed by script
               g.show(message)
            
            while True:
               event = g.getevent()
               if event == "key space none": break
               g.doevent(event)           # allow keyboard/mouse interaction
               sleep(0.01)                # avoid hogging cpu
      
      if "CVS" in dirs:
         dirs.remove("CVS")  # don't visit CVS directories
   
   # if all patterns have been displayed then restore original algo and rule
   # (don't do this if user hits escape in case they want to explore pattern)
   g.new("untitled")
   g.setalgo(oldalgo)
   g.setrule(oldrule)
Example #2
0
def canonise():

    p = bijoscar(1000)

    representation = "#"
    for i in range(abs(p)):
        rect = g.getrect()
        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)
    
    if (p<0):
        prefix = "q"+str(abs(p))
    elif (p==1):
        prefix = "s"+str(g.getpop())
    else:
        prefix = "p"+str(p)

    rule = str.replace(g.getrule(),"/","").lower()
    
    webbrowser.open_new("http://catagolue.appspot.com/object?apgcode=x"+prefix+"_"+representation+"&rule="+rule)
def slideshow():
    oldalgo = g.getalgo()
    oldrule = g.getrule()

    message = "Hit space to continue or escape to exit the slide show..."
    g.show(message)
    for root, dirs, files in os.walk(g.getdir("app") + "Patterns"):
        for name in files:
            if name.startswith("."):
                # ignore hidden files (like .DS_Store on Mac)
                pass
            else:
                g.new("")
                g.setalgo("QuickLife")  # nicer to start from this algo
                fullname = join(root, name)
                g.open(fullname,
                       False)  # don't add file to Open/Run Recent submenu
                g.update()
                if name.endswith(".lua") or name.endswith(".py"):
                    # reshow message in case it was changed by script
                    g.show(message)

                while True:
                    event = g.getevent()
                    if event == "key space none": break
                    g.doevent(event)  # allow keyboard/mouse interaction
                    sleep(0.01)  # avoid hogging cpu

    # if all patterns have been displayed then restore original algo and rule
    # (don't do this if user hits escape in case they want to explore pattern)
    g.new("untitled")
    g.setalgo(oldalgo)
    g.setrule(oldrule)
Example #4
0
def popcount(sel=0):
    dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]}
    live_cells = dict_lc[g.getrule().split(':')[0]]
    if not sel:
        clist = g.getcells(g.getrect())
    else:
        clist = g.getcells(g.getselrect())
    return sum(clist[2::3].count(x) for x in live_cells)
Example #5
0
def render(length, x, y, generation):
    g.setgen("0")
    g.setalgo("Generations")
    g.setrule(generate_rule(x, y, generation))

    pop, extinction = get_pop(length, x, y)
    if extinction < 4410:
        g.show("Rule {} extinct at generation {}.".format(
            g.getrule(), extinction))
        with open("snd/short_lived_rules", "a") as short_lived:
            short_lived.write(g.getrule() + "\n")
        return
    with open("snd/long_lived_rules", "a") as long_lived:
        long_lived.write(g.getrule() + "\n")

    filename = create_name("snd")
    write_wave(filename, pop)

    g.show("Wave saved to " + filename)
Example #6
0
def golly_main():

    bounding_box = g.getrect()

    g.show('Installing rule file...')
    src_rule = os.path.join(scriptdir, 'grills-examples', 'Grills.rule')
    dst_rule = os.path.join(g.getdir('rules'), 'Grills.rule')
    shutil.copyfile(src_rule, dst_rule)
    g.show('...installed.')

    if (len(bounding_box) == 0):
        g.setrule("Grills")
        g.exit("Please draw or load an input pattern.")
    elif (g.getrule() == "Grills"):
        golly_grills()
    elif (g.getrule() == "LifeHistory"):
        golly_lhistory()
    else:
        g.exit("Pattern has the incorrect rule: '%s' != '%s'" %
               (g.getrule(), 'Grills'))
Example #7
0
def popcount(sel=0):
    dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]}
    rule = g.getrule().split(':')[0]
    try:
        live_cells = dict_lc[rule]
    except:
        live_cells = range(1, g.numstates())
    if not sel:
        clist = g.getcells(g.getrect())
    else:
        clist = g.getcells(g.getselrect())
        return sum(clist[2::3].count(x) for x in live_cells)
Example #8
0
File: sss.py Project: apaap/sssss
def canon5Sship(ship, maxgen=2000):
    minpop, rulestr, dx, dy, period, shiprle = ship
    shipPatt = g.parse(shiprle)
    # Transform ship to canonical direction
    if abs(dx) >= abs(dy):
        a, b, c, d = sign(dx), 0, 0, sign(dy)
    else:
        a, b, c, d = 0, sign(dy), sign(dx), 0
    dy, dx = minmaxofabs((dx, dy))
    shipPatt = g.transform(shipPatt, 0, 0, a, b, c, d)
    # Clear the layer and place the ship
    r = g.getrect()
    if r:
        g.select(r)
        g.clear(0)
    g.putcells(shipPatt)
    shiprle = giveRLE(g.getcells(g.getrect()))
    g.setrule(rulestr)
    # Determine the minimal isotropic rule
    setminisorule(period)
    return minpop, g.getrule(), dx, dy, period, shiprle
Example #9
0
def get_pop(numsteps=44100, x=256, y=256):
    if numsteps < 1:
        g.exit("numsteps must be greater than 0.")

    randfill(x, y)

    poplist = [int(g.getpop())]
    extinction = sys.maxint

    rule = g.getrule()
    oldsecs = time.time()
    for i in xrange(numsteps - 1):
        if g.empty():
            extinction = int(g.getgen())
            break
        g.step()
        poplist.append(int(g.getpop()))
        newsecs = time.time()
        if newsecs - oldsecs >= 1.0:
            oldsecs = newsecs
            g.show("Rule {}, Step {} of {}".format(rule, i + 1, numsteps))

    return (poplist, extinction)
Example #10
0
  p = int(item[1:6])
  perioddict[p]=item

  if item.find("_fixed")>-1:
    # have to re-open original LifeHistory pattern to get the right bounding box
    g.open(os.path.join(fixedfolder,item.replace("_fixed","")))
    r=g.getrect()
    g.select(r)
    g.duplicate()
    g.setrule("LifeHistoryToLife")
    g.run(1)
    g.setrule("B3/S23")
    g.setgen("0")
    originalONcells = g.getcells(r)
    g.dellayer()
    if g.getrule()!="LifeHistory": g.exit("Uh-oh.") # should already be for this layer
    # The above assumes that fixed guns' LifeHistory envelopes are correct.
    # TODO: check this?
    # going to assume no bounding-box-marker sparks in the fixed guns
    gunpat = str(g.getcells(r))
    cycles=13 # we don't have any pseudoperiod guns with a factor more than 12, do we?
    while cycles>0:
      g.show("LifeHistorifizing period " + str(p) + ", trial #" + str(21-cycles))
      cycles-=1
      g.run(p)
      newgunpat = str(g.getcells(r))
      if gunpat == newgunpat: # this checks LifeHistory cells also
        break
    g.clear(1)
    g.setgen("0")    
    g.save(os.path.join(LHoutfolder,item),"rle")
Example #11
0
def oscillating():
    # return True if the pattern is empty, stable or oscillating

    # first get current pattern's bounding box
    csel = g.getselrect()
    g.shrink()
    prect = g.getselrect()
    g.select(csel)
    pbox = rect(prect)
    if pbox.empty:
        g.show("The pattern is empty.")
        return True

    # get current pattern and create hash of "normalized" version -- ie. shift
    # its top left corner to 0,0 -- so we can detect spaceships and knightships
    ## currpatt = pattern( g.getcells(prect) )
    ## h = hash( tuple( currpatt(-pbox.left, -pbox.top) ) )

    # use Golly's hash command (3 times faster than above code)
    h = g.hash(prect)

    # check if outer-totalistic rule has B0 but not S8
    rule = g.getrule().split(":")[0]
    hasB0notS8 = rule.startswith("B0") and (rule.find("/") >
                                            1) and not rule.endswith("8")

    # determine where to insert h into hashlist
    pos = 0
    listlen = len(hashlist)
    while pos < listlen:
        if h > hashlist[pos]:
            pos += 1
        elif h < hashlist[pos]:
            # shorten lists and append info below
            del hashlist[pos:listlen]
            del genlist[pos:listlen]
            del poplist[pos:listlen]
            del boxlist[pos:listlen]
            break
        else:
            # h == hashlist[pos] so pattern is probably oscillating, but just in
            # case this is a hash collision we also compare pop count and box size
            if (pbox.wd == boxlist[pos].wd) and \
               (pbox.ht == boxlist[pos].ht):
                # (int(g.getpop()) == poplist[pos])

                period = int(g.getgen()) - genlist[pos]

                if hasB0notS8 and (period % 2 > 0) and (pbox == boxlist[pos]):
                    # ignore this hash value because B0-and-not-S8 rules are
                    # emulated by using different rules for odd and even gens,
                    # so it's possible to have identical patterns at gen G and
                    # gen G+p if p is odd
                    return False

                if period == 1:
                    if pbox == boxlist[pos]:
                        g.show("The pattern is stable.")
                    else:
                        show_spaceship_speed(1, 0, 0)
                elif pbox == boxlist[pos]:
                    g.show("Oscillator detected (period = " + str(period) +
                           ")")
                else:
                    deltax = abs(boxlist[pos].x - pbox.x)
                    deltay = abs(boxlist[pos].y - pbox.y)
                    show_spaceship_speed(period, deltax, deltay)
                return True
            else:
                # look at next matching hash value or insert if no more
                pos += 1

    # store hash/gen/pop/box info at same position in various lists
    hashlist.insert(pos, h)
    genlist.insert(pos, int(g.getgen()))
    poplist.insert(pos, int(g.getpop()))
    boxlist.insert(pos, pbox)

    return False
Example #12
0
# save some info before we switch layers
stepsize = "%i^%i" % (g.getbase(), g.getstep())
pattname = g.getname()

# create population plot in separate layer
g.setoption("stacklayers", 0)
g.setoption("tilelayers", 0)
g.setoption("showlayerbar", 1)
if poplayer == -1:
    poplayer = g.addlayer()
else:
    g.setlayer(poplayer)
g.new(layername)

# use same rule but without any suffix (we don't want a bounded grid)
g.setrule(g.getrule().split(":")[0])

deadr, deadg, deadb = g.getcolor("deadcells")
if (deadr + deadg + deadb) / 3 > 128:
    # use black if light background
    g.setcolors([1,0,0,0])
else:
    # use white if dark background
    g.setcolors([1,255,255,255])

minpop = min(poplist)
maxpop = max(poplist)
if minpop == maxpop:
    # avoid division by zero
    minpop -= 1
popscale = float(maxpop - minpop) / float(ylen)
Example #13
0
import golly as g
import quiescentauton as q

soupfilepath = "/home/scorbie/Apps/ptbtest/random"
nsoups = int(g.getstring("How many soups?", "1000"))
soupsize = 10  # int(g.getstring('Soup size?', '10'))

if g.getrule() == "LifeHistory":
    g.setrule("B3/S23")
if g.numstates() > 2:
    g.exit("This script only works with two-state rules.")

soups = []
x, y, w, h = r = [0, 0, soupsize, soupsize]
cellchar = [".", "a"]
while len(soups) < nsoups:
    g.new("Generating Soups")
    g.select(r)
    g.randfill(40)
    g.run(250)
    # To avoid 'Empty Pattern!' messages in status bar.
    if int(g.getpop()) == 0:
        continue
    if not q.testquiescence(60):
        g.reset()
        soupstr = "!".join(
            "".join(cellchar[g.getcell(i, j)] for j in xrange(0, soupsize + 1)) for i in xrange(0, soupsize + 1)
        )
        soups.append(soupstr)
        g.show("Soup {}/{}".format(len(soups), nsoups))
with open(soupfilepath, "w") as soupfile:
Example #14
0
# Output an adjacency matrix for current selection to clipborad in a "Mathematica" list fomart 
# Use AdjacencyGraph[] in Mathematica for downstream processing.
# Author: Feng Geng([email protected]), May 2016.

import golly as g
from glife import *
import numpy as np
import hashlib

rule=g.getrule()
ruleB=rule.split('/')[0][1:]
ruleS=rule.split('/')[1][1:]
S=['S']
B=['B']
for i in range(9):
	if not str(i) in ruleB:
		S.append(str(8-int(i)))
	if not str(i) in ruleS:
		B.append(str(8-int(i)))

B=''.join(B)
S=''.join(S)
gen=int(g.getgen())
rules=['','']
invrule='/'.join([B,S])
if str(0) not in ruleB:
	tp=rule
	rule=invrule
	invrule=tp

rules[gen%2]=rule;
Example #15
0
# Use the current selection to create a toroidal universe.
# Author: Andrew Trevorrow ([email protected]), Sept 2010.

from glife import inside, outside
import golly as g

selrect = g.getselrect()
if len(selrect) == 0: g.exit("There is no selection.")
x =  selrect[0]
y =  selrect[1]
wd = selrect[2]
ht = selrect[3]

selcells = g.getcells(selrect)
if not g.empty():
    g.clear(inside)
    g.clear(outside)

# get current rule, remove any existing suffix, then add new suffix
rule = g.getrule().split(":")[0]
g.setrule(rule + ":T" + str(wd) + "," + str(ht))

newx = -int(wd/2)
newy = -int(ht/2)
selrect[0] = newx
selrect[1] = newy
g.select(selrect)
if len(selcells) > 0: g.putcells(selcells, newx - x, newy - y)
g.fitsel()
Example #16
0
# save some info before we switch layers
stepsize = "%i^%i" % (g.getbase(), g.getstep())
pattname = g.getname()

# create population plot in separate layer
g.setoption("stacklayers", 0)
g.setoption("tilelayers", 0)
g.setoption("showlayerbar", 1)
if poplayer == -1:
   poplayer = g.addlayer()
else:
   g.setlayer(poplayer)
g.new(layername)

# use same rule but without any suffix (we don't want a bounded grid)
g.setrule(g.getrule().split(":")[0])

deadr, deadg, deadb = g.getcolor("deadcells")
if (deadr + deadg + deadb) / 3 > 128:
   # use black if light background
   g.setcolors([1,0,0,0])
else:
   # use white if dark background
   g.setcolors([1,255,255,255])

minpop = min(poplist)
maxpop = max(poplist)
if minpop == maxpop:
   # avoid division by zero
   minpop -= 1
popscale = float(maxpop - minpop) / float(ylen)
Example #17
0
	if sel:
		clist=g.getcells(g.getselrect())		
	else:
		clist=g.getcells(g.getrect())

	return sum(clist[2::3].count(x) for x in live_cells)
	

dict_lc={'BDRainbow':[2,4],'BGRainbowR2':[2,4]}

input=(g.getstring('How many steps?/similarity distance?','2000/1'))
numsteps=int(input.split('/')[0])
dmax=int(input.split('/')[1])
sel=(g.getselrect()!=[])

rule=g.getrule().split(':')[0]
if rule in dict_lc:
	popfunc=lambda:popcount(sel)
else:
	popfunc=lambda:int(g.getpop())



poplist=[]
dpoplist=[]
hashlist=[int(g.hash(g.getrect()))]
popold=int(popfunc())

poplist.append(popold)
dpoplist.append(0)
for i in range(numsteps):
	def Main(self):
		
		g.show("left click on a pattern to change, 'h' for help")
		gollyMode = False
		
		while True:
		
			event = g.getevent()
			
			if ("key" in event and "return" in event) or (gollyMode and " a " in event):
				gollyMode = not gollyMode
				
				if gollyMode:
					g.show("In golly mode")
					g.update()

				else: 
					g.show("left click on a pattern, right click to finish")
					g.setrule("B3/S23")
					g.setalgo("HashLife")
					g.reset()
				
					g.update()
				
				continue 
				
			if gollyMode:
				
				if " delete " in event: 
					g.clear(0)
					
				if "click" in event and "ctrl" in event and g.getxy() != "":
					
					x, y = g.getxy().split()
					
					cell = g.getcell(int(x), int(y))
					
					if cell >= 0 and cell <= 1:
						g.setcell(int(x), int(y), 1 - cell)
					
					g.update()
				
				if " c " in event and "ctrl" in event and g.getselrect() != []:	
					g.copy()
				
				if " v " in event and "ctrl" in event and g.getxy() != "":
				
					x, y = g.getxy().split()
					
					g.paste(int(x), int(y), "or")
				
				if " space " in event:	
					if "ctrl" in event:
						g.run(10)
					else:
						g.run(1)
						
				g.doevent(event)
				continue 
				
			
			if "click" in event:
				
				if "left" in event:
					
					if self.ExistinCircuitHandler() == None:
						if self.SignalClickHandler(event) == None:
							g.show("left click on a pattern, h for help")
		
		
			elif "key" in event:
				if " space " in event:
					for i in xrange(0, 30):
						g.run(60)
						g.update()
						
					g.reset()
					g.update()		
					
				if " a " in event:
					
					if g.getrule() == "Perrier":
						g.setrule("B3/S23")
						g.setalgo("HashLife")
						g.update()
						
						
					else:
						g.setrule("Perrier")
						
						for key in self.smarCells:
							x, y = key.split(":")
							g.setcell(int(x), int(y),  self.smarCells[key] + 2)
						
						gollyMode = True
						g.show("In golly mode")
						g.update()
				
				if " s " in event:
					fname = os.path.join(g.getdir("data"), "MetadataManager.json")
					#self.Save(fname)
				
				if " h " in event:
					noteMessage = "Viewing and Selecting\n\n"
					noteMessage += "'left click' to chose gun or glider\n"
					noteMessage += "'a' to see in colors, a to go back \n"
					noteMessage += "'space' see ahead 1800 generations \n"
					noteMessage += "'enter' gollyMode, stays in the script \n"
					
					noteMessage += "\n Editing Gun \n\n"
					noteMessage += "'left click' to place\n"
					noteMessage += "'right click' to switch gun/orientation \n"
					noteMessage += "'delete' to delete the gun \n"
					noteMessage += "'left-right arrow' - one step adjustment\n"
					
					noteMessage += "\n In Golly Mode \n\n"
					noteMessage += "'delete' to clear selection\n"
					noteMessage += "'ctrl' + 'click' to draw \n"
					noteMessage += "'ctrl' + 'c' to copy selection \n"
					noteMessage += "'ctrl' + 'v' to paste in mouse location \n"
					noteMessage += "'space' + to run 1 generation \n"
					noteMessage += "'ctrl' +'space' to run 10 generations \n"
				
					g.note(noteMessage)
Example #19
0
# Use the current selection to create a toroidal universe.
# Author: Andrew Trevorrow ([email protected]), Sept 2010.

from glife import inside, outside
import golly as g

selrect = g.getselrect()
if len(selrect) == 0: g.exit("There is no selection.")
x = selrect[0]
y = selrect[1]
wd = selrect[2]
ht = selrect[3]

selcells = g.getcells(selrect)
if not g.empty():
    g.clear(inside)
    g.clear(outside)

# get current rule, remove any existing suffix, then add new suffix
rule = g.getrule().split(":")[0]
g.setrule(rule + ":T" + str(wd) + "," + str(ht))

newx = -int(wd / 2)
newy = -int(ht / 2)
selrect[0] = newx
selrect[1] = newy
g.select(selrect)
if len(selcells) > 0: g.putcells(selcells, newx - x, newy - y)
g.fitsel()
Example #20
0
# generate pattern for given number of steps


def popcount():
    clist = g.getcells(g.getrect())
    return sum(clist[2::3].count(x) for x in live_cells)


vars = g.getstring(
    "yVar/yxVar, \n pop=population,\n gen=generation,\n boxy=width of bounding box,\n boxx=height of bounding box,\n density=population/area of bindingbox ,\n area=area of bounding box",
    "pop/gen")

dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]}
try:
    live_cells = dict_lc[g.getrule().split(':')[0]]
except:
    live_cells = range(1, g.numstates())
dict_f = {'popc':popcount,'pop': g.getpop, 'gen': g.getgen,'boxx':lambda:boxdm(2) ,'boxy': lambda: boxdm(3),'area':area,'density':density, \
  'logpop':lambda:float(math.log(float(g.getpop()))/math.log(2)),'popi':lambda:int(1000000000/float(g.getpop())), 'areai':lambda:int(1000000000/float(int(boxdm(2))*int(boxdm(3))))}
dict_t={'popc':'Population','pop':'Population','gen':'Generation','boxx':'Box width','boxy':'Box height','area':'Box area','density':'Cell density (0.001)',\
  'logpop':'log(pop)','popi':'inverse of pop','areai':'inverse of area'}
yfunc = dict_f[vars.split("/")[0]]
xfunc = dict_f[vars.split("/")[1]]
ytitle = dict_t[vars.split("/")[0]]
xtitle = dict_t[vars.split("/")[1]]

poplist = [int(yfunc())]
genlist = [int(xfunc())]
xlimlist = [int(g.getrect()[1])]
oldsecs = time()
Example #21
0
import golly as g
stepmax = int(g.getstring('how many steps?', '500'))
rule1 = g.getstring('first rule', g.getrule())
rule2 = g.getstring('2nd rule', g.getrule())

step = 1
while step <= stepmax:
    g.setrule([rule1, rule2, rule2][int(g.getstep()) % 3])
    g.run(1)
    # execfile('shuffle.py')
    g.update()
    step = step + 1
Example #22
0
import golly as g

catdir = '/home/scorbie/Apps/ptbtest/cats'

r = g.getselrect()
if len(r)==0:
    r=g.getrect()
    if len(r)==0:
        g.exit('No pattern, nothing to do.')
sel = g.getcells(r)
if len(sel)==0:
    g.exit('Nothing in selection.')

if g.getrule() != 'LifeHistory':
    g.exit('The rule should be in LifeHistory.')

# Get catalyst in various positions
if g.getselrect() != []:
    g.shrink()
pattern = g.getcells(r)
patrlelist = []
translist =[(1,0,0,1), (1,0,0,-1), (-1,0,0,1), (-1,0,0,-1),
            (0,1,1,0), (0,-1,1,0), (0,1,-1,0), (0,-1,-1,0)]
# Get unique transformed patterns
for trans in translist:
    g.new('')
    g.putcells(g.transform(pattern, 0, 0, *trans))
    g.select(g.getrect())
    g.copy()
    patrle = ''.join(g.getclipstr().split('\n')[1:])
    if patrle not in patrlelist:
Example #23
0
status = 'Results file: %s.' % resultsFile
if bUniqueSpeeds:
    with open(resultsFile, 'a+') as rF:
        pass
    shipFiles.append(resultsFile)
    for F in shipFiles:
        if loadKnownSpeeds(F):
            g.exit('Failed to load known speeds from file: %s' % F)
    status += ' %d known speeds loaded.' % len(foundSpeeds)

# Set up the search with the current pattern
r = g.getrect()
origPop = int(g.getpop())
origPatt = g.transform(g.getcells(r), -r[0], -r[1])
origRule = g.getrule()

Nfound = 0
updateP = 1000
lastRule = ''

try:
    # Begin the search
    g.new('MatchPatt')
    g.putcells(origPatt)

    # Determine the rulespace to search
    B_need, S_need, B_OK, S_OK = sss.getRuleRangeElems(numgen)
    rulerange = sss.rulestringopt('B' + ''.join(sorted(B_need)) + '/S' + ''.join(sorted(S_need)) + \
            ' - B' + ''.join(sorted(B_OK)) + '/S' + ''.join(sorted(S_OK)))
    B_OK = [t for t in B_OK if t not in B_need]
Example #24
0
dict_fill = {'BGRainbowR2': [0, 2, 2, 4, 4, 5, 6], 'WireWorld': [0, 1, 2, 1]}


def randfill_mash(rectcoords, amt):
    newstate = g.getoption("drawingstate")
    for i in range(rectcoords[0], rectcoords[0] + rectcoords[2]):
        for j in range(rectcoords[1], rectcoords[1] + rectcoords[3]):
            if (100 * random.random() < amt):
                g.setcell(i, j, dict_fill[rule][g.getcell(i, j)])
            else:
                # g.setcell(i, j, 0)
                continue


dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]}
live_cells = dict_lc[g.getrule().split(':')[0]]


def popcount():
    clist = g.getcells(g.getrect())
    return sum(clist[2::3].count(x) for x in live_cells)


def list_reset():
    global hashlist, poplist, genlist, boxlist, densilist, longlist, timelist
    hashlist = []
    poplist = []
    genlist = []
    boxlist = []
    densilist = []
    longlist = []
Example #25
0
                lastcontext = context
                lastnum = i
                result += i
        else:
            result += i
    result = str.replace(result, '4aceijknqrtwyz', '4')
    result = str.replace(result, '3aceijknqry', '3')
    result = str.replace(result, '5aceijknqry', '5')
    result = str.replace(result, '2aceikn', '2')
    result = str.replace(result, '6aceikn', '6')
    result = str.replace(result, '1ce', '1')
    result = str.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:
Example #26
0
        f.close()


def matches(pat, x, y):
    for i in range(0, len(pat), 2):
        if g.getcell(pat[i] + x, pat[i + 1] + y) % 2 == 0:
            return 0


#   bkg = getbackground(pat)
#   for i in range(0, len(bkg), 2):
#      if g.getcell(bkg[i]+x, bkg[i+1]+y) % 2 == 1:
#         return 0
    return 1

if g.getrule() != "B3/S23":
    g.exit(
        "Please make sure the rule is set to standard B3/S23 Life before running this script."
    )

try:  # initialize the output script -- #TODO: ask for an output filename
    f = open(scriptFN, 'w')
    f.write("import golly as g\n")
    f.write("from glife import *\n")
    f.write("all = pattern()\n")
    f.close()
except:
    g.exit("Unable to initialize " + scriptFN)

nomatch = 1
namelist = []
Example #27
0
## This script takes a non-totalistic rule and return its on/off complement. e.g: B2ce3ai/S23 ->B0123478/S012345-ai6-ce78
## Written by Feng ([email protected]) Feb 2017.
import golly
import copy
alias=golly.getstring('NTCA alias',golly.getrule().split(':')[0]);
try:
	post=golly.getrule().split(':')[1];
except:
	post='';

ali=alias;

henseldict=['b0_','b1c','b1e','b2a','b2c','b3i','b2e','b3a','b2k','b3n','b3j','b4a','s0_','s1c','s1e','s2a','s2c','s3i','s2e','s3a','s2k','s3n','s3j','s4a','b2i','b3r','b3e','b4r','b4i','b5i','s2i','s3r','s3e','s4r','s4i','s5i','b2n','b3c','b3q','b4n','b4w','b5a','s2n','s3c','s3q','s4n','s4w','s5a','b3y','b3k','b4k','b4y','b4q','b5j','b4t','b4j','b5n','b4z','b5r','b5q','b6a','s3y','s3k','s4k','s4y','s4q','s5j','s4t','s4j','s5n','s4z','s5r','s5q','s6a','b4e','b5c','b5y','b6c','s4e','s5c','s5y','s6c','b5k','b6k','b6n','b7c','s5k','s6k','s6n','s7c','b4c','b5e','b6e','s4c','s5e','s6e','b6i','b7e','s6i','s7e','b8_','s8_',];
invhenseldict=['s8_','s7c','s7e','s6a','s6c','s5i','s6e','s5a','s6k','s5n','s5j','s4a','b8_','b7c','b7e','b6a','b6c','b5i','b6e','b5a','b6k','b5n','b5j','b4a','s6i','s5r','s5e','s4n','s4t', 's3i', 'b6i', 'b5r', 'b5e', 'b4n', 'b4t', 'b3i', 's6n', 's5c', 's5q', 's4r', 's4q', 's3a', 'b6n', 'b5c', 'b5q', 'b4r', 'b4q', 'b3a', 's5y', 's5k', 's4k', 's4j', 's4w', 's3j', 's4i', 's4y', 's3n', 's4z', 's3r', 's3q', 's2a', 'b5y', 'b5k', 'b4k', 'b4j', 'b4w', 'b3j', 'b4i', 'b4y', 'b3n', 'b4z', 'b3r', 'b3q', 'b2a', 's4c', 's3c', 's3y', 's2c', 'b4c', 'b3c', 'b3y', 'b2c', 's3k', 's2k', 's2n', 's1c', 'b3k', 'b2k', 'b2n', 'b1c', 's4e', 's3e', 's2e', 'b4e', 'b3e', 'b2e', 's2i', 's1e', 'b2i', 'b1e', 's0_', 'b0_']
henselproj=[101, 89, 99, 73, 81, 35, 95, 47, 87, 69, 66, 23, 100, 85, 97, 60, 77, 29, 92, 41, 83, 56, 53, 11, 98, 71, 94, 45, 67, 17, 96, 58, 91, 39, 54, 5, 88, 79, 72, 33, 65, 19, 84, 75, 59, 27, 52, 7, 80, 86, 63, 68, 46, 22, 34, 64, 21, 70, 31, 44, 15, 76, 82, 50, 55, 40, 10, 28, 51, 9, 57, 25, 38, 3, 93, 43, 61, 16, 90, 37, 48, 4, 62, 20, 42, 13, 49, 8, 36, 1, 78, 32, 18, 74, 26, 6, 30, 14, 24, 2, 12, 0]


# invhenseldict=[];
# inv={'b':'s','s':'b'};
# invsub={'c':'e','e':'c','k':'k','a':'a','i':'t','t':'i','n':'r','r':'n','y':'j','j':'y','q':'w','w':'q','z':'z'};
# for v in henseldict:
# 	if v[1]=='4':
# 		end=invsub[v[2]];
# 	else:
# 		end=v[2]
# 		pass
# 	k=inv[v[0]]+str(8-int(v[1]))+end;
# 	invhenseldict.append(k);


henselidx={k: v for v, k in enumerate(henseldict)};
Example #28
0
        clist = g.getcells(g.getselrect())
    return sum(clist[2::3].count(x) for x in live_cells)


dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]}

input = (g.getstring('How many steps?/similarity distance?', '2000/1'))
numsteps = int(input.split('/')[0])
dmax = int(input.split('/')[1])

poplist = []
hashlist = [int(g.hash(g.getrect()))]
popold = int(g.getpop())
dead = 0

if g.getrule().split(':')[0] in dict_lc:
    popfunc = lambda: popcount()

else:
    popfunc = lambda: g.getpop()

for i in range(numsteps):
    g.run(1)
    if g.empty():
        break
    poplist.append(int(popfunc()))
    h = int(g.hash(g.getrect()))
    if h in hashlist:
        break
    hashlist.append(h)
Example #29
0
## Written by Feng ([email protected]) March 2018.
import golly
import KBs

import random, re, os

# rulestr=golly.getstring('NTCA number',golly.getclipstr()).split('_')[-1];
kb = KBs.kb_2dntca()
# alias = golly.getrule()
prefix, curr, suffix = KBs.interpret(golly.getrule().split(':'))

rulestr = kb.alias2rulestr(curr)
bitstr = KBs.hex2bin(rulestr, 102)
# assert KBs.bin2hex(bitstr)==rulestr
bitlst = list(bitstr)

idx = random.randrange(102)
flip = {'0': '1', '1': '0'}
bitlst[idx] = flip[bitlst[idx]]
rulestr = KBs.bin2hex(''.join(bitlst))
alias = kb.rulestr2alias(rulestr)

if prefix:
    DIR = golly.getdir('rules')
    fname = os.path.join(DIR, prefix + alias + '.rule')
    with open(fname, 'w') as f:
        print >> f, kb.rulestr2table(rulestr, reverse=1)
newrule = '%s%s:%s' % (prefix, alias, suffix)
golly.note(newrule)
golly.setclipstr(newrule.split(':')[0])
Example #30
0
File: sss.py Project: apaap/sssss
def getRuleRangeElems(period, ruleRange='minmax'):
    if g.empty():
        return
    if period < 1:
        return

    rule = g.getrule().split(':')[0]

    if not (rule[0] == 'B' and '/S' in rule):
        g.exit('Please set Golly to an isotropic 2-state rule.')

    # Parse rule string to list of transitions for Birth and Survival
    oldrule = rule
    Bstr, Sstr = rule.split('/')
    Bstr = Bstr.lstrip('B')
    Sstr = Sstr.lstrip('S')
    b_need = parseTransitions(Bstr)
    b_OK = list(b_need)
    s_need = parseTransitions(Sstr)
    s_OK = list(s_need)

    patt = g.getcells(g.getrect())

    # Record behavior of pattern in current rule
    clist = []
    poplist = []
    for i in range(0, period):
        g.run(1)
        clist.append(g.getcells(g.getrect()))
        poplist.append(g.getpop())
    finalpop = g.getpop()

    if 'min' in ruleRange:
        # Test all rule transitions to determine if they are required
        for t in b_OK:
            b_need.remove(t)
            g.setrule('B' + ''.join(b_need) + '/S' + Sstr)
            r = g.getrect()
            if r:
                g.select(r)
                g.clear(0)
            g.putcells(patt)
            for j in range(0, period):
                g.run(1)
                try:
                    if not (clist[j] == g.getcells(g.getrect())):
                        b_need.append(t)
                        break
                except:
                    b_need.append(t)
                    break
        b_need.sort()

        for t in s_OK:
            s_need.remove(t)
            g.setrule('B' + Bstr + '/S' + ''.join(s_need))
            r = g.getrect()
            if r:
                g.select(r)
                g.clear(0)
            g.putcells(patt)
            for j in range(0, period):
                g.run(1)
                try:
                    if not (clist[j] == g.getcells(g.getrect())):
                        s_need.append(t)
                        break
                except:
                    s_need.append(t)
                    break
        s_need.sort()

    if 'max' in ruleRange:
        # Test unused rule transitions to determine if they are allowed
        allRuleElem = [t for l in Hensel for t in l]

        for t in allRuleElem:
            if t in b_OK:
                continue
            b_OK.append(t)
            g.setrule('B' + ''.join(b_OK) + '/S' + Sstr)
            r = g.getrect()
            if r:
                g.select(r)
                g.clear(0)
            g.putcells(patt)
            for j in range(0, period):
                g.run(1)
                try:
                    if not (clist[j] == g.getcells(g.getrect())):
                        b_OK.remove(t)
                        break
                except:
                    b_OK.remove(t)
                    break
        b_OK.sort()

        for t in allRuleElem:
            if t in s_OK:
                continue
            s_OK.append(t)
            g.setrule('B' + Bstr + '/S' + ''.join(s_OK))
            r = g.getrect()
            if r:
                g.select(r)
                g.clear(0)
            g.putcells(patt)
            for j in range(0, period):
                g.run(1)
                try:
                    if not (clist[j] == g.getcells(g.getrect())):
                        s_OK.remove(t)
                        break
                except:
                    s_OK.remove(t)
                    break
        s_OK.sort()

    r = g.getrect()
    if r:
        g.select(r)
        g.clear(0)
    g.putcells(patt)
    g.setrule(oldrule)

    return b_need, s_need, b_OK, s_OK
Example #31
0
## This script generate an ECA rule and emulate it on a torus of width 200.
## Written by Feng ([email protected]) Feb 2017.
import golly

ali = golly.getstring('TCA rulestring', golly.getrule().split(':')[0])


def alias2rnum(ali):
    rule = ['0'] * 18
    ali = ali.replace('/', '').lower().lstrip('b')
    (b, s) = ali.split('s')
    lst = list(str(int(i) + 9) for i in s)
    golly.note(str(lst))
    bs = list(b) + (lst)
    for i in bs:
        rule[int(i)] = '1'
    # golly.note(bs)
    # golly.note(''.join(rule[::-1]))
    rnum = int(''.join(rule[::-1]), 2)
    return (rnum)


# golly.setalgo("QuickLife")
# # golly.note(alias)
# golly.setrule(alias);
rnum = str(alias2rnum(ali))
golly.setclipstr(rnum)
golly.note(rnum)
Example #32
0
def oscillating():
   # return True if the pattern is empty, stable or oscillating
   
   # first get current pattern's bounding box
   prect = g.getrect()
   pbox = rect(prect)
   if pbox.empty:
      g.show("The pattern is empty.")
      return True
   
   # get current pattern and create hash of "normalized" version -- ie. shift
   # its top left corner to 0,0 -- so we can detect spaceships and knightships
   ## currpatt = pattern( g.getcells(prect) )
   ## h = hash( tuple( currpatt(-pbox.left, -pbox.top) ) )

   # use Golly's hash command (3 times faster than above code)
   h = g.hash(prect)

   # check if outer-totalistic rule has B0 but not S8
   rule = g.getrule().split(":")[0]
   hasB0notS8 = rule.startswith("B0") and (rule.find("/") > 1) and not rule.endswith("8")
   
   # determine where to insert h into hashlist
   pos = 0
   listlen = len(hashlist)
   while pos < listlen:
      if h > hashlist[pos]:
         pos += 1
      elif h < hashlist[pos]:
         # shorten lists and append info below
         del hashlist[pos : listlen]
         del genlist[pos : listlen]
         del poplist[pos : listlen]
         del boxlist[pos : listlen]
         break
      else:
         # h == hashlist[pos] so pattern is probably oscillating, but just in
         # case this is a hash collision we also compare pop count and box size
         if (int(g.getpop()) == poplist[pos]) and \
            (pbox.wd == boxlist[pos].wd) and \
            (pbox.ht == boxlist[pos].ht):
            period = int(g.getgen()) - genlist[pos]
            
            if hasB0notS8 and (period % 2 > 0) and (pbox == boxlist[pos]):
               # ignore this hash value because B0-and-not-S8 rules are
               # emulated by using different rules for odd and even gens,
               # so it's possible to have identical patterns at gen G and
               # gen G+p if p is odd
               return False
            
            if period == 1:
               if pbox == boxlist[pos]:
                  g.show("The pattern is stable.")
               else:
                  show_spaceship_speed(1, 0, 0)
            elif pbox == boxlist[pos]:
               g.show("Oscillator detected (period = " + str(period) + ")")
            else:
               deltax = abs(boxlist[pos].x - pbox.x)
               deltay = abs(boxlist[pos].y - pbox.y)
               show_spaceship_speed(period, deltax, deltay)
            return True
         else:
            # look at next matching hash value or insert if no more
            pos += 1
   
   # store hash/gen/pop/box info at same position in various lists
   hashlist.insert(pos, h)
   genlist.insert(pos, int(g.getgen()))
   poplist.insert(pos, int(g.getpop()))
   boxlist.insert(pos, pbox)

   return False
Example #33
0
import golly
import webbrowser

rule = golly.getrule().split(':')[0]
qrule = rule.replace('/', '').lower()

webbrowser.open('https://catagolue.appspot.com/census/{}/'.format(qrule))
Example #34
0
    p = int(item[1:6])
    perioddict[p] = item

    if item.find("_fixed") > -1:
        # have to re-open original LifeHistory pattern to get the right bounding box
        g.open(os.path.join(fixedfolder, item.replace("_fixed", "")))
        r = g.getrect()
        g.select(r)
        g.duplicate()
        g.setrule("LifeHistoryToLife")
        g.run(1)
        g.setrule("B3/S23")
        g.setgen("0")
        originalONcells = g.getcells(r)
        g.dellayer()
        if g.getrule() != "LifeHistory":
            g.exit("Uh-oh.")  # should already be for this layer
        # The above assumes that fixed guns' LifeHistory envelopes are correct.
        # TODO: check this?
        # going to assume no bounding-box-marker sparks in the fixed guns
        gunpat = str(g.getcells(r))
        cycles = 13  # we don't have any pseudoperiod guns with a factor more than 12, do we?
        while cycles > 0:
            g.show("LifeHistorifizing period " + str(p) + ", trial #" +
                   str(21 - cycles))
            cycles -= 1
            g.run(p)
            newgunpat = str(g.getcells(r))
            if gunpat == newgunpat:  # this checks LifeHistory cells also
                break
        g.clear(1)
Example #35
0
from glife import validint, inside
from string import lower
import golly as g
import math

rules = ("JvN29", "Nobili32", "Hutton32")

rule = g.getrule ()
if rule not in rules:
    g.exit ("Invalid rule: " + rule + " (must be " + rules + ")")

rect = g.getselrect ()
if len (rect) == 0:
    g.exit ("There is no selection.")

answer = g.getstring("Enter direction to rotate in\n" +
                     "(valid rotations are cw and ccw, default is cw):",
                     "cw",
                     "Rotate selection")

if answer != "cw" and answer != "ccw":
    g.exit ("Unknown direction: " + answer + " (must be cw/ccw)")

cells = g.getcells (rect)

jvn_rotate = (( 9, 12, 11, 10),
              (13, 16, 15, 14),
              (17, 20, 19, 18),
              (21, 24, 23, 22))

def rotated (rotations, direction, state):
Example #36
0
if metalayer < 0 and g.numlayers() == g.maxlayers():
    g.exit("You need to delete a layer.")

# rules and alive state for each Varlife state
varlife_rules = {
    0: [[], [], 0],
    1: [[], [], 1],
    2: [[1], [], 0],
    3: [[1], [], 1],
    4: [[2], [], 0],
    5: [[2], [], 1],
    6: [[1, 2], [1], 0],
    7: [[1, 2], [1], 1]
}
varlife = False
if g.getrule() == "Varlife":
    varlife = True
else:
    # note that getrule returns canonical rule string
    rulestr = g.getrule().split(":")[0]
    if (not rulestr.startswith("B")) or (rulestr.find("/S") == -1):
        g.exit("This script only works with B*/S* rules.")

# get the current selection
selx, sely, selwidth, selheight = selrect

if not varlife:
    # create a 2D list of 0s and 1s representing entire selection
    slist = g.getcells(selrect)
    livecell = [[0 for y in xrange(selheight)] for x in xrange(selwidth)]
    for i in xrange(0, len(slist), 2):
Example #37
0
    def Main(self):

        g.show("left click on a pattern to change, 'h' for help")
        gollyMode = False

        while True:

            event = g.getevent()

            if ("key" in event and "return" in event) or (gollyMode
                                                          and " a " in event):
                gollyMode = not gollyMode

                if gollyMode:
                    g.show("In golly mode")
                    g.update()

                else:
                    g.show("left click on a pattern, right click to finish")
                    g.setrule("B3/S23")
                    g.setalgo("HashLife")
                    g.reset()

                    g.update()

                continue

            if gollyMode:

                if " delete " in event:
                    g.clear(0)

                if "click" in event and "ctrl" in event and g.getxy() != "":

                    x, y = g.getxy().split()

                    cell = g.getcell(int(x), int(y))

                    if cell >= 0 and cell <= 1:
                        g.setcell(int(x), int(y), 1 - cell)

                    g.update()

                if " c " in event and "ctrl" in event and g.getselrect() != []:
                    g.copy()

                if " v " in event and "ctrl" in event and g.getxy() != "":

                    x, y = g.getxy().split()

                    g.paste(int(x), int(y), "or")

                if " space " in event:
                    if "ctrl" in event:
                        g.run(10)
                    else:
                        g.run(1)

                g.doevent(event)
                continue

            if "click" in event:

                if "left" in event:

                    if self.ExistinCircuitHandler() == None:
                        if self.SignalClickHandler(event) == None:
                            g.show("left click on a pattern, h for help")

            elif "key" in event:
                if " space " in event:
                    for i in xrange(0, 30):
                        g.run(60)
                        g.update()

                    g.reset()
                    g.update()

                if " a " in event:

                    if g.getrule() == "Perrier":
                        g.setrule("B3/S23")
                        g.setalgo("HashLife")
                        g.update()

                    else:
                        g.setrule("Perrier")

                        for key in self.smarCells:
                            x, y = key.split(":")
                            g.setcell(int(x), int(y), self.smarCells[key] + 2)

                        gollyMode = True
                        g.show("In golly mode")
                        g.update()

                if " s " in event:
                    fname = os.path.join(g.getdir("data"),
                                         "MetadataManager.json")
                    #self.Save(fname)

                if " h " in event:
                    noteMessage = "Viewing and Selecting\n\n"
                    noteMessage += "'left click' to chose gun or glider\n"
                    noteMessage += "'a' to see in colors, a to go back \n"
                    noteMessage += "'space' see ahead 1800 generations \n"
                    noteMessage += "'enter' gollyMode, stays in the script \n"

                    noteMessage += "\n Editing Gun \n\n"
                    noteMessage += "'left click' to place\n"
                    noteMessage += "'right click' to switch gun/orientation \n"
                    noteMessage += "'delete' to delete the gun \n"
                    noteMessage += "'left-right arrow' - one step adjustment\n"

                    noteMessage += "\n In Golly Mode \n\n"
                    noteMessage += "'delete' to clear selection\n"
                    noteMessage += "'ctrl' + 'click' to draw \n"
                    noteMessage += "'ctrl' + 'c' to copy selection \n"
                    noteMessage += "'ctrl' + 'v' to paste in mouse location \n"
                    noteMessage += "'space' + to run 1 generation \n"
                    noteMessage += "'ctrl' +'space' to run 10 generations \n"

                    g.note(noteMessage)
Example #38
0
selrect = g.getselrect()
if len(selrect) == 0: g.exit("There is no selection.")

# check that a layer is available for the metafied pattern;
# if metafied layer already exists then we'll use that
layername = "metafied"
metalayer = -1
for i in xrange(g.numlayers()):
   if g.getname(i) == layername:
      metalayer = i
      break
if metalayer < 0 and g.numlayers() == g.maxlayers():
   g.exit("You need to delete a layer.")

# note that getrule returns canonical rule string
rulestr = g.getrule().split(":")[0]
if (not rulestr.startswith("B")) or (rulestr.find("/S") == -1):
   g.exit("This script only works with B*/S* rules.")

# get the current selection
slist = g.getcells(selrect)
selwidth = selrect[2]
selheight = selrect[3]

# create a 2D list of 0s and 1s representing entire selection
livecell = [[0 for y in xrange(selheight)] for x in xrange(selwidth)]
for i in xrange(0, len(slist), 2):
   livecell[slist[i] - selrect[0]][slist[i+1] - selrect[1]] = 1

# build a patch pattern based on the current rule
#  that fixes the appropriate broken eaters in the rules table
Example #39
0
selrect = g.getselrect()
if len(selrect) == 0: g.exit("There is no selection.")

# check that a layer is available for the metafied pattern;
# if metafied layer already exists then we'll use that
layername = "metafied"
metalayer = -1
for i in xrange(g.numlayers()):
    if g.getname(i) == layername:
        metalayer = i
        break
if metalayer < 0 and g.numlayers() == g.maxlayers():
    g.exit("You need to delete a layer.")

# note that getrule returns canonical rule string
rulestr = g.getrule().split(":")[0]
if (not rulestr.startswith("B")) or (rulestr.find("/S") == -1):
    g.exit("This script only works with B*/S* rules.")

# get the current selection
slist = g.getcells(selrect)
selwidth = selrect[2]
selheight = selrect[3]

# create a 2D list of 0s and 1s representing entire selection
livecell = [[0 for y in xrange(selheight)] for x in xrange(selwidth)]
for i in xrange(0, len(slist), 2):
    livecell[slist[i] - selrect[0]][slist[i + 1] - selrect[1]] = 1

# build a patch pattern based on the current rule
#  that fixes the appropriate broken eaters in the rules table