def LoadMoveTable(self, path, report): ins = open(path, "r" ) array = [] bestdxrecipe = [] bestdx = 1 idx = 0 for line in ins: vals = line.split(":") vals[0] = vals[0].replace("m", "") vals[0] = vals[0].split(",") x = int(vals[0][0]) y = int(vals[0][1]) vals[1] = vals[1].replace("E", "").replace("\n", "").replace(" ", "") vals[1] = vals[1].split(",") for i in xrange(0, len(vals[1])): vals[1][i] = int(vals[1][i]) if x < 0 and -x * len(bestdxrecipe) > -bestdx * len(vals[1]): bestdxrecipe = vals[1] bestdx = x idx = len(array) array.append([x, y, vals[1]]) if report: g.show(str(bestdxrecipe) + ":" + str(idx)) g.setclipstr(str(bestdxrecipe)) ins.close() return array
def GetObjectByClick(event): x = int(event.split()[1]) y = int(event.split()[2]) found = False for i in [0, -1, 1, -2, 2]: for j in [0, -1, 1]: if found: break o = IsObjectExists(objectArray, x + i, y + j) if o != None: g.show("found!") for k in xrange(0, len(o[0]), 2): dx = o[0][k] dy = o[0][k + 1] g.setcell(x + i + dx, y + j + dy, 0) found = True g.update() if found: return o else : return None
def randtopo(num, low, high): # global hashlist,topolist, arealist hashlist = [] topolist = [] arealist = [] i = 0 while i < num: g.show('searching topo %i of %i ' % (i, num)) size = random.choice(range(low, high + 1)) area = size * size sel = [size, size, size, size] g.new('') randfill(sel, (1 + random.randrange(area)) * int(100 / area), mixpercent) if g.empty(): continue h = g.hash(g.getrect()) if h in hashlist: continue else: hashlist.append(h) pbox = g.getrect() actarea = pbox[2] * pbox[3] clist = g.getcells(g.getrect()) g.store(clist, workingdir + 'topo_area%i_hash%i' % (actarea, h)) clist.insert(0, pbox[2]) #prepare for tiling clist.insert(1, pbox[3]) topolist.append(clist) arealist.append(actarea) i = i + 1 continue return [topolist, hashlist, arealist]
def show_message(g, log_handle, message): """ A function for writing a message to both the Golly window and the log file. """ log_handle.write(message) g.show(message)
def envelope(): # draw stacked layers using same location and scale g.setoption("stacklayers", 1) g.show("Hit escape key to stop script...") while True: g.run(1) if g.empty(): g.show("Pattern died out.") break # copy current pattern to envelope layer; # we temporarily disable event checking so thumb scrolling # and other mouse events won't cause confusing changes currpatt = g.getcells(g.getrect()) g.check(0) g.setlayer(envindex) g.putcells(currpatt) g.setlayer(currindex) g.check(1) step = 1 exp = g.getstep() if exp > 0: step = g.getbase()**exp if int(g.getgen()) % step == 0: # display all 3 layers (envelope, start, current) g.update()
def EvolveRecipes(recipes): newrecipes = [] cnt = 0 for recipe in recipes: cnt += 1 if cnt % 100 == 0: g.show(str(cnt) + "/" + str(len(recipes))) minx = EvolveRecipe(recipe) cells = g.getcells(g.getrect()) answer = FindAllHs(cells, minx) for h in answer[0]: i = h[0] x1 = h[1] y1 = h[2] xySL = h[3] res = copy(recipe) res.append(i) result.append([res, x1, y1, xySL]) for h in answer[1]: res = copy(recipe) res.append(h) newrecipes.append(res) return newrecipes
def Place(path): cats = FillCategories(path) keysL = sorted(cats.keys(), key=lambda x: cats[x].results[0][0]) g.show("Found {0} Categories".format(len(keysL))) dx, dy = 0, 0 for c in keysL: results = cats[c].results AddText(str(len(results)), dx - 30, dy + 10) for i in xrange(0, len(results)): fname = os.path.splitext(os.path.basename(results[i][0]))[0] fname = fname.replace("result", "").lstrip("0").replace("-4", "") mdx, mdy = putcells(results[i][0], (dx, dy)) AddText(fname, dx + int(mdx / 2), dy - 10) dx += mdx + 60 dy += 60 + mdy dx = 0 AddText(path, 0, -100)
def envelope (): # draw stacked layers using same location and scale g.setoption("stacklayers", 1) g.show("Hit escape key to stop script...") while True: g.run(1) if g.empty(): g.show("Pattern died out.") break # copy current pattern to envelope layer; # we temporarily disable event checking so thumb scrolling # and other mouse events won't cause confusing changes currpatt = g.getcells(g.getrect()) g.check(0) g.setlayer(envindex) g.putcells(currpatt) g.setlayer(currindex) g.check(1) step = 1 exp = g.getstep() if exp > 0: step = g.getbase()**exp if int(g.getgen()) % step == 0: # display all 3 layers (envelope, start, current) g.update()
def setupLog(logName='noName.txt'): logDir = user_log_dir('LifeGenes','7yl4r-ware') try: makedirs(logDir) except OSError: pass # probably the dir already exists... logPath = join(logDir,logName) logging.basicConfig(filename=logPath,\ level=logging.DEBUG,\ format='%(asctime)s %(levelname)s:%(message)s',\ filemode='w') # # assume that you want your logs in LifeGenes source which is in your home directory # # (this works best on my linux machine) # home = expanduser("~") # logDir = home+'/LifeGenes/__logs' # try: # mkdir(logDir) # except OSError: # pass # probably the dir already exists... # # logPath = logDir+'/'+logName # print str(logging.getLogger()) # logging.basicConfig(filename=logPath,\ # level=logging.DEBUG,\ # format='%(asctime)s %(levelname)s:%(message)s',\ # filemode='w') try: import golly as g g.show('created .log at '+str(logPath)) except ImportError: print 'created .log at '+str(logPath)
def draw(self, addstr = ""): xy = [] xz = [] yz = [] proj = [] for (k, v) in self.cur_state.items(): x, y, z = k xy.append(x) xy.append(y) xz.append(x + 128) xz.append(z) yz.append(y) yz.append(z + 128) proj.append(x + y + z + 128) proj.append(- x + y + z + 128) if len(g.getrect()) > 0: g.select(g.getrect()) g.clear(0) g.select([]) g.putcells(xy) g.putcells(xz) g.putcells(yz) g.putcells(proj) g.setpos("64", "64") g.setmag(1) g.show("Size: {0}, (w, d, h): {1}".format(self.get_pop(), str(self.get_wdh())) + addstr) g.update()
def CreateWssMovementData(recipes, dir): result = [] g.show(str(len(recipes.WssCreator))) for i in xrange(0, len(recipes.WssCreator)): recipes.Reset() recipes.Goto(-23, 1) recipes.AddWss(i) PlaceReadingHeads(recipes.recipe) goto(150000) g.fit() g.update() x, y, res = FindWssByDirection(True, distForward)[0] x += 23 y += -21 y = y % distForward result.append((x, y, res)) pickle.dump( result, open( path.join(dir, str(step) + "_" + str(period) + "_ForwardWssBase.pkl"), "wb")) g.note(str(result))
def FillCategories(path): files = glob.glob(os.path.join(path, "*.out")) g.show("Loading {0} files, please wait...".format(str(len(files)))) cats = {} idx = 0 for f in files: lines = subprocess.Popen([os.path.join(os.path.dirname(os.path.realpath('__file__')), "bellman.exe"), "-c", f], stdout=subprocess.PIPE, shell=True).communicate()[0] lines = lines.split("\n") d = {} for l in lines: idx = l.find(":") if idx > 0: key = l[:idx].strip() val = l[idx+1:].strip() if d.has_key(key): prev = d[key] + "\n" else: prev = "" d[key] = prev + val category = d["hash"] if not cats.has_key(category): cats[category] = Category(category) cats[category].results.append((f, d["log"])) return cats
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 CreateWssMovementData(recipes, dir): result = [] g.show(str(len(recipes.WssCreator))) for i in xrange(0, len(recipes.WssCreator)): recipes.Reset() recipes.Goto(-23, 1) recipes.AddWss(i) PlaceReadingHeads(recipes.recipe) goto(150000) g.fit() g.update() x, y, res = FindWssByDirection(True, distForward)[0] x += 23 y += -21 y = y % distForward result.append((x, y, res)) pickle.dump(result, open(path.join(dir, str(step) + "_" + str(period) + "_ForwardWssBase.pkl"), "wb")) g.note(str(result))
def gofast(newgen, delay): ''' Fast goto ''' #Save current settings oldbase = g.getbase() # oldhash = g.setoption("hashing", True) g.show('gofast running, hit escape to abort') oldsecs = time() #Advance by binary powers, to maximize advantage of hashing g.setbase(2) for i, b in enumerate(intbits(newgen)): if b: g.setstep(i) g.step() g.dokey(g.getkey()) newsecs = time() if newsecs - oldsecs >= delay: # do an update every sec oldsecs = newsecs g.update() if g.empty(): break g.show('') #Restore settings # g.setoption("hashing", oldhash) g.setbase(oldbase)
def LoadMoveTable(self, path, report): ins = open(path, "r" ) array = [] bestdxrecipe = [] for line in ins: vals = line.split(":") vals[0] = vals[0].replace("m", "") vals[0] = vals[0].split(",") x = int(vals[0][0]) y = int(vals[0][1]) vals[1] = vals[1].replace("E", "").replace("\n", "") vals[1] = vals[1].split(",") for i in xrange(0, len(vals[1])): vals[1][i] = int(vals[1][i]) if x - y == -1 and len(bestdxrecipe) == 0: bestdxrecipe = vals[1] array.append([x, y, vals[1]]) if report: g.show(str(bestdxrecipe)) g.setclipstr(str(bestdxrecipe)) ins.close() return array
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 a_star_search(): gen = 0 start = 2 ** len(gliders_in) - 1 frontier = [(popcount(start), gen, start)] cost = { start : 0 } prev = { start : None } while frontier: current = heapq.heappop(frontier)[2] g.show("Gliders remaining %d. Current cost %d. Minimum possible cost %d" % (popcount(current), cost[current], popcount(current) + cost[current])) if current == 0: break for g_i, edge_i in find_all_glider_idx(current): new_cost = cost[current] + shoot_defs[edge_i][0] new_mask = current ^ (2 ** g_i) if new_mask not in cost or new_cost < cost[new_mask]: cost[new_mask] = new_cost priority = new_cost + popcount(new_mask) gen -= 1 heapq.heappush(frontier, (priority, gen, new_mask)) prev[new_mask] = g_i, edge_i if shoot_defs[edge_i][0] == 1: break return prev
def lookforkeys(event, deltax, deltay): global oldcells, selrect, selpatt # look for keys used to flip/rotate selection if event == "key x none" or event == "key y none": # flip floating selection left-right or top-bottom if len(oldcells) > 0: g.clear(0) g.putcells(selpatt, deltax, deltay) if " x " in event: g.flip(0) else: g.flip(1) selpatt = g.transform(g.getcells(selrect), -deltax, -deltay) if len(oldcells) > 0: g.clear(0) g.putcells(oldcells) g.putcells(selpatt, deltax, deltay) g.update() return if event == "key > none" or event == "key < none": # rotate floating selection clockwise or anticlockwise; # because we use g.rotate below we have to use the exact same # calculation (see Selection::Rotate in wxselect.cpp) for rotrect: midx = selrect[0] + int((selrect[2]-1)//2) midy = selrect[1] + int((selrect[3]-1)//2) newleft = midx + selrect[1] - midy newtop = midy + selrect[0] - midx rotrect = [ newleft, newtop, selrect[3], selrect[2] ] if not rectingrid(rotrect): g.show("Rotation is not allowed if selection would be outside grid.") return g.clear(0) if len(oldcells) > 0: g.putcells(oldcells) oldcells = g.join(oldcells, g.getcells(rotrect)) g.clear(0) g.select(rotrect) g.clear(0) g.select(selrect) g.putcells(selpatt, deltax, deltay) if " > " in event: g.rotate(0) else: g.rotate(1) selrect = g.getselrect() selpatt = g.transform(g.getcells(selrect), -deltax, -deltay) if len(oldcells) > 0: g.clear(0) g.putcells(oldcells) g.putcells(selpatt, deltax, deltay) g.update() return if event == "key h none": # best not to show Help window while dragging selection! return g.doevent(event)
def submitEntry(self): # save the cell name = self.entry.get() g.show('saving ' + name + ' to ' + CELL_COLLECTION_DIR) self.pallate.saveCell(self.cell,name) self.frame.quit() # close dialog g.show('DNA sample saved to collection')
def to_golly_rule(self): ''' Writes the rule file directly into rule directory. ''' from golly import getdir, show with open(getdir('rules') + self.n + '.rule', 'w') as f: f.write(str(self)) show("Saved rule to " + getdir('rules') + self.n + '.rule') return self
def makerecipe(recipe): g.putcells(gliderlist[0]) totaltime = 0 for i in recipe[1:]: totaltime += i g.putcells( g.transform(gliderlist[totaltime % 4], totaltime / 4, totaltime / 4)) g.show(str(totaltime))
def add_data(PATTERN_FN): g.select([-2753, 891, 1092, 1397]) g.clear(0) g.select([]) input_str = open(PATTERN_FN, "r").read() firstbreak = input_str.find("\n") if firstbreak == -1: g.show("Error, no newlines found, invalid format") g.exit() info_line = input_str[0:firstbreak] input_str = input_str[firstbreak:] #x = 1581, y = 1396, rule = Varlife dataptrn = re.compile( br'x = (?P<xval>[0-9]{1,4}), y = (?P<yval>[0-9]{1,4}), rule = .*') match = dataptrn.match(info_line) xval = 0 yval = 0 if (match): xval = int(match.group("xval"), 10) yval = int(match.group("yval"), 10) else: g.show("ERROR invalid format {}".format(info_line)) g.exit() ipat = pattern(input_str) minbox = getminbox(ipat) if max(xval, minbox.x) > 1200: g.show("ERROR inserted cell area too wide, max width is 1090") g.exit() if max(yval, minbox.y) > 1397: g.show("ERROR inserted cell area too tall, max height is 1397") g.exit() startx = -1661 - xval starty = 891 #blankptrn.put(startx, starty) g.show( "width={}, height={} startx={}, starty={}, xval={}, yval={}, bytes={}". format(minbox.wd, minbox.height, startx, starty, xval, yval, len(input_str))) ipat.put(startx, starty) g.save("/tmp/output.mc", "rle", False) return "Pattern load data: width={}, height={} startx={}, starty={}, xval={}, yval={}, bytes={}".format( minbox.wd, minbox.height, startx, starty, xval, yval, len(input_str))
def to_golly_rule(self): ''' Writes the rule file directly into rule directory. ''' from golly import getdir, show with open(getdir('rules')+self.n+'.rule','w') as f: f.write(str(self)) show("Saved rule to "+getdir('rules')+self.n+'.rule') return self
def lookforkeys(event): global oldcells, object # look for keys used to flip/rotate object if event == "key x none" or event == "key y none": # flip floating object left-right or top-bottom g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) obox = getminbox(object) if event == "key x none": # translate object so that bounding box doesn't change xshift = 2 * (obox.left + int(obox.wd//2)) if obox.wd % 2 == 0: xshift -= 1 object = g.transform(object, xshift, 0, -1, 0, 0, 1) else: # translate object so that bounding box doesn't change yshift = 2 * (obox.top + int(obox.ht//2)) if obox.ht % 2 == 0: yshift -= 1 object = g.transform(object, 0, yshift, 1, 0, 0, -1) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key > none" or event == "key < none": # rotate floating object clockwise or anticlockwise # about the center of the object's bounding box obox = getminbox(object) midx = obox.left + int(obox.wd//2) midy = obox.top + int(obox.ht//2) newleft = midx + obox.top - midy newtop = midy + obox.left - midx rotrect = [ newleft, newtop, obox.ht, obox.wd ] if not rectingrid(rotrect): g.show("Rotation is not allowed if object would be outside grid.") return g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) if event == "key > none": # rotate clockwise object = g.transform(object, 0, 0, 0, -1, 1, 0) else: # rotate anticlockwise object = g.transform(object, 0, 0, 0, 1, -1, 0) # shift rotated object to same position as rotrect obox = getminbox(object) object = g.transform(object, newleft - obox.left, newtop - obox.top) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key h none": # best not to show Help window while dragging object! return g.doevent(event)
def main(): apgcode = canonise() if not apgcode: g.warn( 'Failed to detect periodic behaviour after {} generations.'.format( MAXPERIOD)) # 2G collisions if apgcode in twoGcols: cols = twoGcols[apgcode] else: cols = [] # 3G and 4G collisions for cFile in compFiles: with open(cFile) as cF: found_code = False for l in cF: line = l.strip() if not found_code: if line == apgcode: found_code = True continue elif '>' in line: in_code, gstr, _ = line.split(">") if in_code: g.warn( 'Non-empty starting target in glider collision - Not implemented' ) else: cols.append(gstr) else: break Ncols = len(cols) if Ncols: try: cols = [reconstruct(col) for col in cols] except Exception: g.note(str(cols)) g.new("solutions") g.show("{} collisions found".format(Ncols)) g.setname(apgcode) if Ncols <= 20: N = 5 else: N = math.ceil(math.sqrt(Ncols)) + 1 offset = 100 for i, col in enumerate(cols): g.putcells(col, int((i % N) * offset), int((i // N) * offset)) g.fit() else: g.note( "No glider collisions found for constellation {}. Better luck next time" .format(apgcode))
def PlaceRecipe(self, x = 0, y = 0, makenew = True): if makenew: g.new("Results") g.show(str(self.recipeIdxList)) g.setclipstr(str(self.recipeIdxList)) g.putcells(blck, x, y) i = 0 for r in self.recipe: g.putcells(gld, x + 80 + i * 128, y + 80 + i * 128 + r) i += 1
def replace_sel(IN, ): od = IN.split('/') od = [int(x) for x in od] sel = (g.getselrect() != []) if g.empty(): g.show('universe is empty') else: if sel: replace(g.getselrect(), od) else: replace(g.getrect(), od)
def ClearCellDictionary(self, curdict, obejctIdx): before = len(curdict) removeList = [key for key in curdict if curdict[key] == obejctIdx] for key in removeList: x, y = key.split(":") g.setcell(int(x), int(y), 0) del curdict[key] after = len(curdict) g.show("size change: " + str(before) + "," + str(after) + "," + str(obejctIdx))
def goto(newgen): currgen = int(g.getgen()) if newgen < currgen: # try to go back to starting gen (not necessarily 0) and # then forwards to newgen; note that reset() also restores # algorithm and/or rule, so too bad if user changed those # after the starting info was saved; # first save current location and scale midx, midy = g.getpos() mag = g.getmag() g.reset() # restore location and scale g.setpos(midx, midy) g.setmag(mag) # current gen might be > 0 if user loaded a pattern file # that set the gen count currgen = int(g.getgen()) if newgen < currgen: g.error("Can't go back any further; pattern was saved " + "at generation " + str(currgen) + ".") return if newgen == currgen: return oldsecs = time() # before stepping we advance by 1 generation, for two reasons: # 1. if we're at the starting gen then the *current* step size # will be saved (and restored upon Reset/Undo) rather than a # possibly very large step size # 2. it increases the chances the user will see updates and so # get some idea of how long the script will take to finish # (otherwise if the base is 10 and a gen like 1,000,000,000 # is given then only a single step() of 10^9 would be done) g.run(1) currgen += 1 # use fast stepping (thanks to PM 2Ring) oldstep = g.getstep() for i, d in enumerate(intbase(newgen - currgen, g.getbase())): if d > 0: g.setstep(i) for j in xrange(d): if g.empty(): g.show("Pattern is empty.") return g.step() newsecs = time() if newsecs - oldsecs >= 1.0: # do an update every sec oldsecs = newsecs g.update() g.setstep(oldstep)
def getstring(prompt): # prompt user and return entered string cursor1 = "_" cursor2 = "" golly.show(prompt + " " + cursor1) inp = "" oldsecs = time.time() while True: newsecs = time.time() if newsecs - oldsecs >= 0.5: # blink cursor each sec oldsecs = newsecs cursor1, cursor2 = cursor2, cursor1 golly.show(prompt + " " + inp + cursor1) time.sleep(0.05) # avoid hogging cpu ch = golly.getkey() if len(ch) > 0: if ch == chr(13): # return golly.show("") return inp if ch == chr(8): # backspace inp = inp[:-1] ch = "" elif ch < ' ': ch = "" # ignore tab, arrow keys, etc inp += ch golly.show(prompt + " " + inp + cursor1)
def recur(self,at): if at == 0: return self.transFunc(self.params) n = str(at) for i in xrange(self.numStates): # report progress if at == self.numParams: golly.show('Generating rule tree: '+str(int(100*i/self.numStates))+'%...') # allow golly to update if at == self.numParams-1: golly.update() self.params[self.numParams-at] = i n += " " + str(self.recur(at-1)) return self.getNode(n)
def writeRuleTree(self,name): # create a .tree file in user's rules directory f=open(golly.getdir("rules")+name+".tree", 'w') f.write("# Automatically generated by make-ruletree.py.\n") f.write("num_states=" + str(self.numStates)+"\n") f.write("num_neighbors=" + str(self.numNeighbors)+"\n") f.write("num_nodes=" + str(len(self.r))+"\n") for rule in self.r: f.write(rule+"\n") f.flush() # ensure file is complete (only on Windows?) f.close() golly.setalgo("RuleTree") # in case name.table exists golly.setrule(name) golly.show("Created "+name+".tree in "+golly.getdir("rules"))
def show_spaceship_speed(period, deltax, deltay): # we found a moving oscillator if (deltax == deltay) or (deltax == 0) or (deltay == 0): speed = "" if (deltax == 0) or (deltay == 0): # orthogonal spaceship if (deltax > 1) or (deltay > 1): speed += str(deltax + deltay) else: # diagonal spaceship (deltax == deltay) if deltax > 1: speed += str(deltax) if period == 1: g.show("Spaceship detected (speed = " + speed + "c)") else: g.show("Spaceship detected (speed = " + speed + "c/" + str(period) + ")") else: # deltax != deltay and both > 0 speed = str(deltay) + "," + str(deltax) if period == 1: g.show("Knightship detected (speed = " + speed + "c)") else: g.show("Knightship detected (speed = " + speed + "c/" + str(period) + ")")
def ConvertRuleTableTransitionsToRuleTree(neighborhood,n_states,transitions,input_filename): '''Convert a set of vonNeumann or Moore transitions directly to a rule tree.''' rule_name = os.path.splitext(os.path.split(input_filename)[1])[0] remap = { "vonNeumann":[0,3,2,4,1], # CNESW->CSEWN "Moore":[0,5,3,7,1,4,6,2,8] # C,N,NE,E,SE,S,SW,W,NW -> C,S,E,W,N,SE,SW,NE,NW } numNeighbors = len(remap[neighborhood])-1 tree = RuleTree(n_states,numNeighbors) for i,t in enumerate(transitions): golly.show("Building rule tree... ("+str(100*i/len(transitions))+"%)") tree.add_rule([ t[j] for j in remap[neighborhood] ],t[-1][0]) tree.write(golly.getdir('rules')+rule_name+".tree" ) return rule_name
def find_best_selection(): r = g.getrect() all = g.getcells(r) sep = 1 # - run the pattern for 4096 ticks, get the new settled pattern # - try XORing new pattern with original pattern for every possible offset up to 512 # - one of the offsets should give the lowest total population # (will probably decrease the population instead of increasing it, # unless what is being built is a prolific puffer or gun or some such) bestscore, bestsep = len(all), -1 # = population * 2 allplus4096 = g.evolve(all, 4096) g.addlayer() while sep <= 512: g.show("Finding stage spacing -- testing " + str(sep)) g.new("sep=" + str(sep)) g.putcells(all) g.putcells(allplus4096, sep, 0, 1, 0, 0, 1, "xor") score = int(g.getpop()) if bestscore > score: bestscore, bestsep = score, sep sep += 1 g.dellayer() sep = bestsep g.show("found separation: " + str(sep)) bestblockscore, bestoffset = -999999, -1 for offset in range(sep): g.select([r[0] - offset, r[1], sep, r[3]]) g.update() blockscore = 0 for blockx in range(r[0] - offset, r[0] + r[2], sep): g.select([blockx, r[1], sep, r[3]]) blockrect = g.getselrect() block = g.getcells(blockrect) if len( block ) == 0: # ran into empty block, this must not be the right separation g.exit("Invalid pattern format found at separation = " + str(sep) + ": selected block is empty.") g.shrink(1) shrunkblockrect = g.getselrect() leftdiff = shrunkblockrect[0] - blockrect[0] rightdiff = (blockrect[0] + blockrect[2]) - (shrunkblockrect[0] + shrunkblockrect[2]) blockscore += leftdiff + rightdiff if leftdiff < 10: blockscore -= (10 - leftdiff)**2 if rightdiff < 10: blockscore -= (10 - rightdiff)**2 if blockscore > bestblockscore: bestblockscore, bestoffset = blockscore, offset g.select([r[0] - bestoffset, r[1], r[2] + offset, r[3]]) return sep
def TriangularTransitionsToRuleTree_CheckerboardMethod(neighborhood, n_states, transitions, rule_name): # Background state 0 has no checkerboard, we infer it from its neighboring cells. def encode_lower(s): return s def encode_upper(s): ### AKT: this code causes syntax error in Python 2.3: ### return [0 if se==0 else n_states+se-1 for se in s] temp = [] for se in s: if se == 0: temp.append(0) else: temp.append(n_states + se - 1) return temp total_states = n_states * 2 - 1 if total_states > 256: golly.warn("Number of states exceeds Golly's limit of 256!") golly.exit() tree = RuleTree(total_states, 4) for t in transitions: # as lower tree.add_rule( [ encode_lower(t[0]), # C encode_upper(t[2]), # S encode_upper(t[1]), # E encode_upper(t[3]), # W range(total_states) ], # N encode_lower(t[4])[0]) # C' # as upper tree.add_rule( [ encode_upper(t[0]), # C range(total_states), # S encode_lower(t[3]), # E encode_lower(t[1]), # W encode_lower(t[2]) ], # N encode_upper(t[4])[0]) # C' # output the rule tree golly.show("Compressing rule tree and saving to file...") tree.write(golly.getdir('rules') + rule_name + '.tree')
def AdaptiveGoto(hwssRecipe, enablePrinting=True): #g.setrule("LifeHistory") fense50 = g.parse( "F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F!" ) helixD = CalcHelix(hwssRecipe) curgen = -helixD * 2 curgen += 2 * distForward goto(curgen) g.setbase(8) g.setstep(3) delta = 10 lastmaxi = delta idx = 0 for i in hwssRecipe: if enablePrinting and (100 * (idx + 1)) / len(hwssRecipe) != ( 100 * idx) / len(hwssRecipe): percent = (100 * (idx + 1)) / len(hwssRecipe) g.update() g.show("Iterating forward progress " + str(percent) + "%") curgen += 2 * distForward idx += 1 while int(g.getgen()) < curgen: g.step() if i == 'SKIP': continue if i > lastmaxi: g.select([fenseX, helixD + fenseY + lastmaxi - delta, 1, delta]) g.clear(0) lastmaxi += delta #g.update() if i < lastmaxi - delta: g.putcells(fense50, fenseX, helixD + fenseY + lastmaxi - 2 * delta) lastmaxi -= delta
def __init__(self): logging.info('script started') lg_envmt = lifegenes_environment() lg_envmt.drawColor() logging.info('setup complete; beginning evolution cycles') try: while(True): #until stopped by golly g.step() #g.update() lg_envmt.update() lg_envmt.drawColor() g.update() finally: logging.info('cycling halted from external source (probably golly)') g.show('closing gracefully, hold on just a sec...') lg_envmt.teardown()
def getinp(s): ########################### temp = g.getcell(x, y) g.setcell(x, y, 5) g.show(s + "Ptr:" + str(ptr) + " x:" + str(x) + " y:" + str(y)) g.fit() g.update() g.setcell(x, y, temp) # return k = g.getevent() count = 0 while k == "": sleep(.01) k = g.getevent() count += 1 if k == "key q none": g.exit() return
def FindBestDx(recipes): bestX = -1 bestY = -1 bestRation = -10000 for x in xrange(-24, -4): for y in xrange(-50, 51): val = recipes.BlockMoveTableEven[(-23, x, y)] if val[0] == 'X' or val[0] == '': continue if -x / len(val) > bestRation: bestRation = -x / len(val) bestX = x bestY = y g.show(str((bestX, bestY)))
def getallorientations(name, clist, maxticks, matchtype=0): names = [] uniques = [] xforms = [] uhashes = [] orients = [] dticks = [] ticks = 0 rangemax = (8 if matchtype == 0 else matchtype ) # 1 (no rot/ref) or 4 (rotation only) are reasonable nomatch = 1 while nomatch: # check next generation until a repeat occurs in orientation 1 for i in range( rangemax ): # TODO: invent a structure to avoid having to use indexes like this pat, xform = getorientation(clist, i) h = gethash(pat) if uhashes.count(h) == 0: names.append(name) uniques.append(pat) uhashes.append(h) xforms.append(xform) orients.append(i) dticks.append(ticks) else: if i == 0: nomatch = 0 # if we've already seen the first phase, we've seen them all from here on out. break # (for other phases the duplication might be due to symmetry, so we try them all) if nomatch == 0: break # TODO: this is silly -- find a better structural way to do this ticks += 1 if maxticks <= 0: if ticks >= 8: g.show("No periodicity found within 8 ticks -- ending search.") nomatch = 0 break else: # g.note(str(ticks) + " :: " + str(maxticks) + " :: " + str(ticks>=1)) ##################### if ticks >= maxticks: nomatch = 0 break # stop collecting patterns silently if a maximum has been specified clist = g.evolve(clist, 1) x, y = findTLsorted(clist) return [names, uniques, xforms, orients, dticks]
def AdaptiveGoto(hwssRecipe, enablePrinting = True): #g.setrule("LifeHistory") fense50 = g.parse("F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F$F!") helixD = CalcHelix(hwssRecipe) curgen = -helixD * 2 curgen += 2 * distForward goto(curgen) g.setbase(8) g.setstep(3) delta = 10 lastmaxi = delta idx = 0 for i in hwssRecipe: if enablePrinting and (100 * (idx + 1)) / len(hwssRecipe) != (100 * idx) / len(hwssRecipe): percent = (100 * (idx + 1)) / len(hwssRecipe) g.update() g.show("Iterating forward progress " + str(percent) + "%") curgen += 2 * distForward idx += 1 while int(g.getgen()) < curgen: g.step() if i == 'SKIP': continue if i > lastmaxi: g.select([fenseX, helixD + fenseY + lastmaxi - delta, 1, delta]) g.clear(0) lastmaxi += delta #g.update() if i < lastmaxi - delta: g.putcells(fense50, fenseX, helixD + fenseY + lastmaxi - 2 * delta) lastmaxi -= delta
def drawlines(): global oldline, firstcell started = False oldmouse = "" while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left altctrlshift" evt, x, y, butt, mods = event.split() oldmouse = x + ' ' + y if started: # draw permanent line from start pos to end pos endx = int(x) endy = int(y) drawline(startx, starty, endx, endy) # this is also the start of another line startx = endx starty = endy oldline = [] firstcell = [] else: # start first line startx = int(x) starty = int(y) firstcell = [ startx, starty, g.getcell(startx, starty) ] g.setcell(startx, starty, drawstate) g.update() started = True g.show("Click where to end this line (and start another line)...") else: # event might be "" or "key m none" if len(event) > 0: g.doevent(event) mousepos = g.getxy() if started and len(mousepos) == 0: # erase old line if mouse is not over grid if len(oldline) > 0: eraseline(oldline) oldline = [] g.update() elif started and len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so erase old line (if any) and draw new line if len(oldline) > 0: eraseline(oldline) x, y = mousepos.split() oldline = drawline(startx, starty, int(x), int(y)) oldmouse = mousepos
def TestRecipe(recipe, recipes): recipes.Goto(-23, 1) for i in xrange(0, len(recipe)): recipes.recipe.append(recipe[i] + recipes.blockY - recipes.blockX) PlaceReadingHeads(recipes.recipe) goto(150000) g.fit() g.update() x, y, res = FindWssByDirection(True, distForward)[0] x += 23 y += -21 y = y % distForward g.show(str((x, y, res)))
def TriangularTransitionsToRuleTree_CheckerboardMethod(neighborhood,n_states,transitions,rule_name): # Background state 0 has no checkerboard, we infer it from its neighboring cells. def encode_lower(s): return s def encode_upper(s): ### AKT: this code causes syntax error in Python 2.3: ### return [0 if se==0 else n_states+se-1 for se in s] temp = [] for se in s: if se==0: temp.append(0) else: temp.append(n_states+se-1) return temp total_states = n_states*2 - 1 if total_states>256: golly.warn("Number of states exceeds Golly's limit of 256!") golly.exit() tree = RuleTree(total_states,4) for t in transitions: # as lower tree.add_rule([encode_lower(t[0]), # C encode_upper(t[2]), # S encode_upper(t[1]), # E encode_upper(t[3]), # W range(total_states)], # N encode_lower(t[4])[0]) # C' # as upper tree.add_rule([encode_upper(t[0]), # C range(total_states), # S encode_lower(t[3]), # E encode_lower(t[1]), # W encode_lower(t[2])], # N encode_upper(t[4])[0]) # C' # output the rule tree golly.show("Compressing rule tree and saving to file...") tree.write(golly.getdir('rules') + rule_name + '.tree')
def goto(newgen, delay): g.show("goto running, hit escape to abort...") oldsecs = time() # before stepping we advance by 1 generation, for two reasons: # 1. if we're at the starting gen then the *current* step size # will be saved (and restored upon Reset/Undo) rather than a # possibly very large step size # 2. it increases the chances the user will see updates and so # get some idea of how long the script will take to finish # (otherwise if the base is 10 and a gen like 1,000,000,000 # is given then only a single step() of 10^9 would be done) if delay <= 1.0: g.run(1) newgen -= 1 # use fast stepping (thanks to PM 2Ring) for i, d in enumerate(intbase(newgen, g.getbase())): if d > 0: g.setstep(i) for j in xrange(d): if g.empty(): g.show("Pattern is empty.") return g.step() newsecs = time() if newsecs - oldsecs >= delay: # time to do an update? oldsecs = newsecs g.update() g.show("")
def __init__(self): logging.info('script started') lg_envmt = lifegenes_environment() lg_envmt.drawColor() logging.info('setup complete; beginning evolution cycles') try: while(True): #until stopped by golly g.show('cells moving') for i in range(5): # rounds of cell movement #logging.debug('movement round '+str(i)) lg_envmt.cellMotions() #logging.debug('cells moved') lg_envmt.drawColor() #logging.debug('cells recolored') g.update() #logging.debug('golly updated') #time.sleep(1) g.show('cells evolving') # one round of evolution: #logging.debug('evolution round started') g.step() #g.update() #logging.debug('golly evolution complete') lg_envmt.update() #logging.debug('cellList updated') lg_envmt.drawColor() #logging.debug('cells recolored') g.update() #logging.debug('golly updated') #time.sleep(1) finally: logging.info('cycling halted from external source (probably golly)') g.show('closing gracefully, hold on just a sec...') lg_envmt.teardown()
def FinadOptimalRecipe(slv, idx): moveTable = slv.SLsMoveTable[idx] bests = [-1, -1] slCount = [1000, 1000] g.setrule("B3/S23") g.setalgo("HashLife") for i in xrange(0, len(moveTable)): g.new("") slv.ApplyRecipeSmart(i, idx) slv.PlaceRecipe() g.setstep(5) g.step() numSL = len(CountSL()) laneID = (moveTable[i][1] + 10000) % 2 if slCount[laneID] > numSL: slCount[laneID] = numSL bests[laneID] = i slv.Reset() g.setrule("LifeHistory") for i in xrange(0, len(bests)): slv.ApplyRecipeSmart(bests[i], idx) slv.PlaceRecipe(i * 100, 0, i == 0) slv.Reset() g.show(str(bests)) #11 - [32, 249] #12 - [138, 123] #13 - [29, 27] #14 - [89, 15] return bests
def show_status_text(s, d, t): if d==-1: if t==1: g.show(s + "Speed is " + str(t) + " tick per step.") else: g.show(s + "Speed is " + str(t) + " ticks per step.") else: g.show(s + "Delay between ticks is " + str(d) + " seconds.")
def CreateWssMovementData(recipes, dir, isUp = True): result = [] for i in xrange(0, len(recipes.WssCreator)): g.show(str(i)) recipes.Reset() if isUp: recipes.Goto(-23, 1) recipes.AddWss(i) PlaceReadingHeads(recipes.recipe) goto(150000) g.fit() g.update() if isUp: x, y, res = FindWssByDirection(isUp, distForward)[0] x += 23 y += -21 y = y % distForward else: x, y, res = FindWssByDirection(isUp, distBack)[0] y = y % distBack result.append((x, y, res)) if isUp: pickle.dump(result, open(path.join(dir, str(step) + "_" + str(period) + "_ForwardWssBase.pkl"), "wb")) else: pickle.dump(result, open(path.join(dir, str(step) + "_" + str(period) + "_BackwardWssBase.pkl"), "wb")) g.note(str(result))
def main( step = 1, start = 0 ): # set dir name from current date d = datetime.datetime.today() dirName = "shiki_%02d-%02d-%02d-%02d" % (d.day, d.hour, d.minute, d.second) # create directory exportDir = "%s/%s" % (dstDir, dirName) if not os.path.exists( exportDir ): os.makedirs( exportDir ) # get bound size = getImageSize( srcPath ) bound = [ -expand, -expand, size[0] + expand * 2, size[1] + expand * 2 ] # loop for f in xrange( repeat ): g.show( "Processing... %d / %d" % (f+1, repeat) ) loadImage( srcPath ) g.run( 1 ) g.update() for i in xrange( interval ): g.run( 1 ) g.update() frame = f * interval + i saveImage( bound, "%s/%s/%s_%06d.png" % (dstDir, dirName, dirName, frame) )