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)
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)
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)
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)
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'))
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)
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
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)
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")
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
# 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)
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:
# 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;
# 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()
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)
# 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()
# 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()
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
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:
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]
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 = []
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:
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 = []
## 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)};
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)
## 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])
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
## 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)
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
import golly import webbrowser rule = golly.getrule().split(':')[0] qrule = rule.replace('/', '').lower() webbrowser.open('https://catagolue.appspot.com/census/{}/'.format(qrule))
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)
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):
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):
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
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