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 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 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.warn("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() if selrect != rotrect: g.warn("Bug: selrect != rotrect") 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": showhelp2() return g.doevent(event)
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.warn("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": showhelp2() return g.doevent(event)
def trygliders(ginfo): gdistance = ginfo / 4 phase = ginfo % 4 bstatus = boxstatus pstatus = popstatus for num in xrange(8): tlist = form(celllist, num) rect = boxform(fullrect, num) g.new('') g.putcells(tlist) gx = rect[0] - 3 - gdistance gy = rect[1] - 3 - gdistance for w in xrange(rect[2] + 5): g.new('') g.putcells(tlist) g.putcells(glider[phase], gx + w, gy) g.fit() g.update() for gen in xrange(1000): g.run(1) if int(g.getpop()) <= 2: g.new('') g.show("Found clean glider destruction.") status = 0, num, phase, [gx + w, gy] putcells_and_fit(result(celllist, status)) g.exit() box = g.getrect()[2:] # Checking the bounding box size and population against the current lowest found. if reduce(mul, box) < reduce(mul, bstatus[0]): bstatus = (box, num, phase, [gx + w, gy]) pop = int(g.getpop()) if pop < pstatus[0]: pstatus = (pop, num, phase, [gx + w, gy]) # Show results if the user presses certain keys event = g.getevent() if event.startswith("key x"): g.new('') put_result_pair(celllist, bstatus, pstatus) g.select(g.getrect()) g.copy() g.select([]) g.note( "Minimum bounding box and population collisions copied to clipboard." ) if event.startswith("key q"): g.new('') g.show("Search stopped.") put_result_pair(celllist, bstatus, pstatus) g.fit() g.exit() g.show( "Searching for a 1-glider destruction... press <x> to copy minimum bounding box and population results to clipboard; press <q> to quit. Stats: minimum bounding box %dx%d, minimum population %d" % (bstatus[0][0], bstatus[0][1], pstatus[0])) return bstatus, pstatus
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 FinishMove(d, w, h, x0, y0, p, t): under = d[0] obj = d[1] x = d[2] y = d[3] if under != -1: g.putcells(under) g.putcells(g.evolve(obj, p + GetEvolveDirection(t) * ((4 * (x - x0)) % p)), x, y) g.update()
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 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 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 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
def UpdateState(self, newPat, dx, dy): self.under = [] self.curPat = newPat self.dx = dx self.dy = dy for i in xrange(0, len(self.curPat), 2): if g.getcell(self.curPat[i] + self.dx, self.curPat[i + 1] + self.dy) == 1: self.under.append(self.curPat[i] + self.dx) self.under.append(self.curPat[i + 1] + self.dy) g.setcell(self.curPat[i] + self.dx, self.curPat[i + 1] + self.dy, 1) g.update()
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 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 drawline(x1, y1, x2, y2): # draw a line of cells from x1,y1 to x2,y2 using Bresenham's algorithm; # we also return the old cells in the line so we can erase line later oldcells = [] # note that x1,y1 has already been drawn # oldcells.append( (x1, y1, g.getcell(x1, y1)) ) # g.setcell(x1, y1, drawstate) if x1 == x2 and y1 == y2: g.update() return oldcells dx = x2 - x1 ax = abs(dx) * 2 sx = 1 if dx < 0: sx = -1 dy = y2 - y1 ay = abs(dy) * 2 sy = 1 if dy < 0: sy = -1 if ax > ay: d = ay - (ax / 2) while x1 != x2: oldcells.append( (x1, y1, g.getcell(x1, y1)) ) g.setcell(x1, y1, drawstate) if d >= 0: y1 += sy d -= ax x1 += sx d += ay else: d = ax - (ay / 2) while y1 != y2: oldcells.append( (x1, y1, g.getcell(x1, y1)) ) g.setcell(x1, y1, drawstate) if d >= 0: x1 += sx d -= ay y1 += sy d += ax oldcells.append( (x2, y2, g.getcell(x2, y2)) ) g.setcell(x2, y2, drawstate) g.update() return oldcells
def run_patt(known_cells): global patt_count, meth_count g.new("PlutoniumSearch") g.reset() g.update() patt_count += 1 #patt = g.parse(known_cells + "!") patt = g.parse(known_cells[1:] + "!") #g.note(known_cells[1:] + "!") g.putcells(patt) g.update() hashlist = {} for gene in range(999): if g.empty(): break if g.hash(g.getrect()) in hashlist: p = int(g.getgen()) - hashlist[g.hash(g.getrect())] if not p in boring_periods: g.reset() g.save("p" + str(p) + "_" + str(cnt[p]) + ".rle", "rle") cnt[p] += 1 break else: hashlist[g.hash(g.getrect())] = int(g.getgen()) g.run(1) """ except: # Pattern dies if int(g.getgen()) > min_lifespan: meth_count += 1 newlifespan = int(g.getgen()) g.new("Saving methuselah") g.putcells(patt) try: g.save("diehard-" + str(newlifespan) + ".rle", "rle") except: pass g.update() #max_final_pop = newpop break""" #g.warn(str(hashlist)) g.show(str(patt_count) + "/" + str(2**(bx * by)))
def add_shooter(cost, inserter_cells, left_g, right_g=[], flip=True): global shoot_defs g.new('') g.putcells(inserter_cells) g.putcells(left_g) g.putcells(right_g) g.run(2048) reaction_cells = g.getcells([-150,-150,300,300]) g.run(512) if not all(g.getcell(x, y) for x, y in gld_pairs): g.fit() g.update() assert(False) stable_cells = set(zip(reaction_cells[::2], reaction_cells[1::2])) for _ in range(4): g.run(1) for i in range(0, len(reaction_cells), 2): tup = reaction_cells[i], reaction_cells[i+1] if tup in stable_cells and not g.getcell(*tup): stable_cells.remove(tup) stable_cells2 = [] for x, y in stable_cells: stable_cells2.append(x) stable_cells2.append(y) stable_cells = stable_cells2 tup = (cost, inserter_cells, left_g, right_g, reaction_cells, stable_cells) shoot_defs.append(tup) if flip: shoot_defs.append((cost, f(inserter_cells), f(right_g), f(left_g), f(reaction_cells), f(stable_cells)))
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) )
def EventLoop(): global volume, genspersec nextgen = 0.0 running = True while True: space = False event = g.getevent() if len(event) == 0: sleep(0.005) # don't hog CPU if idle elif event == "key space none": running = False space = True nextgen = 0 elif event == "key return none": running = not running elif event == "key h none": ShowHelp() elif event == "key up none": volume = min(1.0, volume + 0.1) ShowInfo() elif event == "key down none": volume = max(0.0, volume - 0.1) ShowInfo() elif event == "key = none" or event == "key + none": genspersec = min(30, genspersec + 1) ShowInfo() elif event == "key - none": genspersec = max(1, genspersec - 1) ShowInfo() else: g.doevent(event) # might be a keyboard shortcut if (running or space) and time() >= nextgen: g.run(1) if g.empty(): g.exit("The pattern died.") PlaySound() g.update() if not space: nextgen = time() + 1.0 / genspersec
def Placement(self, movementData, idx, attachedPatList, snip): while True: event = g.getevent() if event == "": self.ManageMove(attachedPatList[idx], movementData) elif "click" in event: if "right" in event: movementData.RevertState() idx = (idx + 1) % len(attachedPatList) movementData = self.GetMovementData(attachedPatList, idx) self.ManageMove(attachedPatList[idx], movementData) elif "left" in event: if snip == None: snip = PlacementSnippet(attachedPatList, idx, movementData) self.snippets.append(snip) else: snip.Update(attachedPatList, idx, movementData) movementData.UpdateCellDictionary(self.smarCells, snip.id) return elif "key" in event: if "space" in event: for i in xrange(0, 30): g.run(60) g.update() g.reset() g.update() elif "right" in event: movementData.delta += 1 elif "left" in event: movementData.delta -= 1 elif "delete" in event: movementData.RevertState() g.update() return
def export_icons(iconsection, rulename): global multi_color_icons if multi_color_icons: # prepend a new @COLORS section with the average colors in each icon iconsection = create_average_colors(iconsection) + iconsection # replace any illegal filename chars with underscores filename = rulename.replace("/", "_").replace("\\", "_") # we will only create/update a .rule file in the user's rules folder # (ie. we don't modify the supplied Rules folder) rulepath = g.getdir("rules") + filename + ".rule" fileexists = os.path.isfile(rulepath) if fileexists: # .rule file already exists so replace or add @ICONS section rulefile = open(rulepath, "rU") # create a temporary file for writing new rule info temphdl, temppath = mkstemp() tempfile = open(temppath, "w") wroteicons = False skiplines = False for line in rulefile: if line.startswith("@ICONS"): # replace the existing @ICONS section tempfile.write(iconsection) wroteicons = True skiplines = True elif line.startswith("@COLORS") and multi_color_icons: # skip the existing @COLORS section # (iconsection contains a new @COLORS section) skiplines = True elif skiplines and line.startswith("@"): if wroteicons: tempfile.write("\n") skiplines = False if not skiplines: tempfile.write(line) if not wroteicons: # .rule file had no @ICONS section tempfile.write("\n") tempfile.write(iconsection) # close files rulefile.close() tempfile.flush() tempfile.close() os.close(temphdl) # remove original .rule file and rename temporary file os.remove(rulepath) move(temppath, rulepath) else: # .rule file doesn't exist so create it rulefile = open(rulepath, "w") rulefile.write("@RULE " + filename + "\n\n") if not multi_color_icons: # grayscale icons, so check if Rules/filename.rule exists # and if so copy any existing @COLORS section suppliedrule = g.getdir("app") + "Rules/" + filename + ".rule" if os.path.isfile(suppliedrule): colordata = get_color_section(suppliedrule) if len(colordata) > 0: rulefile.write(colordata) rulefile.write(iconsection) rulefile.flush() rulefile.close() # create another layer for displaying the new icons if g.numlayers() < g.maxlayers(): g.addlayer() g.new("icon test") g.setrule(rulename) for i in range(g.numstates() - 1): g.setcell(i, 0, i + 1) g.fit() g.setoption("showicons", True) g.update() if fileexists: g.note("Updated the icon data in " + rulepath) else: g.note("Created " + rulepath)
def floodfill(): newstate = g.getoption("drawingstate") oldstate = newstate # wait for user to click a cell g.show("Click the region you wish to fill... (hit escape to abort)") while oldstate == newstate: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() x = int(xstr) y = int(ystr) if x < minx or x > maxx or y < miny or y > maxy: # click is outside pattern's bounding box in unbounded universe g.warn("Click within the pattern's bounding box\n" + "otherwise the fill will be unbounded.") else: # note that user might have changed drawing state newstate = g.getoption("drawingstate") oldstate = g.getcell(x, y) if oldstate == newstate: g.warn("The clicked cell must have a different state\n" + "to the current drawing state.") else: g.doevent(event) # tell Golly to handle all further keyboard/mouse events g.getevent(False) # do flood fill starting with clicked cell g.show("Filling clicked region... (hit escape to stop)") clist = [(x, y)] g.setcell(x, y, newstate) oldsecs = time() while len(clist) > 0: # remove cell from start of clist x, y = clist.pop(0) newsecs = time() if newsecs - oldsecs >= 0.5: # show changed pattern every half second oldsecs = newsecs g.update() # check if any orthogonal neighboring cells are in oldstate if checkneighbor(x, y - 1, oldstate): g.setcell(x, y - 1, newstate) clist.append((x, y - 1)) if checkneighbor(x, y + 1, oldstate): g.setcell(x, y + 1, newstate) clist.append((x, y + 1)) if checkneighbor(x + 1, y, oldstate): g.setcell(x + 1, y, newstate) clist.append((x + 1, y)) if checkneighbor(x - 1, y, oldstate): g.setcell(x - 1, y, newstate) clist.append((x - 1, y)) # diagonal neighbors are more complicated because we don't # want to cross a diagonal line of live cells if checkneighbor(x + 1, y + 1, oldstate) and (g.getcell( x, y + 1) == 0 or g.getcell(x + 1, y) == 0): g.setcell(x + 1, y + 1, newstate) clist.append((x + 1, y + 1)) if checkneighbor(x + 1, y - 1, oldstate) and (g.getcell( x, y - 1) == 0 or g.getcell(x + 1, y) == 0): g.setcell(x + 1, y - 1, newstate) clist.append((x + 1, y - 1)) if checkneighbor(x - 1, y + 1, oldstate) and (g.getcell( x, y + 1) == 0 or g.getcell(x - 1, y) == 0): g.setcell(x - 1, y + 1, newstate) clist.append((x - 1, y + 1)) if checkneighbor(x - 1, y - 1, oldstate) and (g.getcell( x, y - 1) == 0 or g.getcell(x - 1, y) == 0): g.setcell(x - 1, y - 1, newstate) clist.append((x - 1, y - 1))
def score_pair(g, seed1, seed2, width_factor, height_factor, \ time_factor, num_trials): """ Put seed1 and seed2 into the Immigration Game g and see which one wins and which one loses. Note that this function does not update the histories of the seeds. """ # # Make copies of the original two seeds, so that the following # manipulations do not change the originals. # s1 = copy.deepcopy(seed1) s2 = copy.deepcopy(seed2) # # Initialize scores # score1 = 0.0 score2 = 0.0 # # Run several trials with different rotations and locations. # for trial in range(num_trials): # # Randomly rotate and flip s1 and s2 # s1 = s1.random_rotate() s2 = s2.random_rotate() # # Switch cells in the second seed (s2) from state 1 (red) to state 2 (blue) # s2.red2blue() # # Rule file is "Immigration.rule" # Set toroidal universe of height yspan and width xspan # Base the s1ze of the universe on the s1zes of the seeds # # g = the Golly universe # [g_width, g_height, g_time] = dimensions(s1, s2, \ width_factor, height_factor, time_factor) # # set algorithm -- "HashLife" or "QuickLife" # g.setalgo("QuickLife") # use "HashLife" or "QuickLife" g.autoupdate(False) # do not update the view unless requested g.new("Immigration") # initialize cells to state 0 g.setrule("Immigration:T" + str(g_width) + "," + str(g_height)) # make a toroid # # Find the min and max of the Golly toroid coordinates # [g_xmin, g_xmax, g_ymin, g_ymax] = get_minmax(g) # # Set magnification for Golly viewer # g.setmag(set_mag(g)) # # Randomly place seed s1 somewhere in the left s1de of the toroid # s1.insert(g, g_xmin, -1, g_ymin, g_ymax) # # Randomly place seed s2 somewhere in the right s1de of the toroid # s2.insert(g, +1, g_xmax, g_ymin, g_ymax) # # Run for a fixed number of generations. # Base the number of generations on the sizes of the seeds. # Note that these are generations ins1de one Game of Life, not # generations in an evolutionary sense. Generations in the # Game of Life correspond to growth and decay of a phenotype, # whereas generations in evolution correspond to the reproduction # of a genotype. # g.run(g_time) # run the Game of Life for g_time time steps g.update() # need to update Golly to get counts # # Count the populations of the two colours. State 1 = red = seed1. # State 2 = blue = seed2. # [count1, count2] = count_pops(g) # if (count1 > count2): score1 = score1 + 1.0 elif (count2 > count1): score2 = score2 + 1.0 else: score1 = score1 + 0.5 score2 = score2 + 0.5 # # # Normalize the scores # score1 = score1 / num_trials score2 = score2 / num_trials # return [score1, score2]
def moveselection(): global oldcells, selrect, selpatt # wait for 1st click in selection while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() x = int(xstr) y = int(ystr) if cellinrect(x, y, selrect): oldmouse = xstr + ' ' + ystr firstx = x firsty = y xoffset = firstx - selrect[0] yoffset = firsty - selrect[1] if mods == "alt": # don't delete pattern in selection oldcells = g.getcells(selrect) break elif event == "key h none": showhelp1() else: g.doevent(event) # wait for 2nd click while moving selection g.show("Move mouse and click again..." + helpmsg) gotclick = False while not gotclick: event = g.getevent() if event.startswith("click"): evt, x, y, butt, mods = event.split() mousepos = x+' '+y gotclick = True else: if len(event) > 0: lookforkeys(event, x - firstx, y - firsty) # update xoffset,yoffset in case selection was rotated xoffset = x - selrect[0] yoffset = y - selrect[1] mousepos = g.getxy() if len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so move selection rect and pattern g.clear(0) if len(oldcells) > 0: g.putcells(oldcells) xstr, ystr = mousepos.split() x = int(xstr) y = int(ystr) selrect[0] = x - xoffset selrect[1] = y - yoffset if g.getwidth() > 0: # ensure selrect doesn't move beyond left/right edge of grid if selrect[0] < gridl: selrect[0] = gridl x = selrect[0] + xoffset elif selrect[0] + selrect[2] - 1 > gridr: selrect[0] = gridr + 1 - selrect[2] x = selrect[0] + xoffset if g.getheight() > 0: # ensure selrect doesn't move beyond top/bottom edge of grid if selrect[1] < gridt: selrect[1] = gridt y = selrect[1] + yoffset elif selrect[1] + selrect[3] - 1 > gridb: selrect[1] = gridb + 1 - selrect[3] y = selrect[1] + yoffset g.select(selrect) oldcells = g.getcells(selrect) g.putcells(selpatt, x - firstx, y - firsty) oldmouse = mousepos g.update()
def GotoAdvanced(self, x, y, tableIdx, targetL = -1): if self.GotoSmart(x, y, tableIdx): self.recipeIdxList.append("MOVE") self.recipeIdxList.append(self.lastGotoIdx) self.recipeIdxList.append(tableIdx) return True xtemp0 = self.block0[0] ytemp0 = self.block0[1] tempRecipe0 = copy.copy(self.recipe) besti = -1 bestL = 10000000 lastx = -1 lasty = -1 worked = [] for i in xrange(0, len(self.moveTable )): x1 = self.moveTable[i][0] y1 = self.moveTable[i][1] if (str(x1) + "," + str(y1)) in worked: continue g.show(str(x) + "," + str(y) + "," + str(i) + "/" + str( len(self.moveTable )) + " BESTi = {0}, BESTL {1}".format(besti, bestL)) g.update() self.block0[0] = xtemp0 self.block0[1] = ytemp0 self.recipe = copy.copy(tempRecipe0) if self.CanApplyRecipe(self.moveTable[i][2], g.transform(blck, x1, y1)): worked.append(str(x1) + "," + str(y1)) self.AppendRecipe(self.moveTable[i][2]) self.block0[0] += x1 self.block0[1] += y1 recipeLength = bestL - len(self.recipe) if self.GotoSmartConstrained(x, y, tableIdx, recipeLength): if bestL > len(self.recipe) and targetL == -1: bestL = len(self.recipe) besti = i if len(self.recipe) == targetL: bestL = len(self.recipe) besti = i break self.block0[0] = xtemp0 self.block0[1] = ytemp0 self.recipe = tempRecipe0 if besti == -1: return False else: self.AppendRecipe(self.moveTable[besti][2]) x1 = self.moveTable[besti][0] y1 = self.moveTable[besti][1] self.block0[0] += x1 self.block0[1] += y1 self.recipeIdxList.append("MOVE") self.recipeIdxList.append(besti) self.recipeIdxList.append(-1) self.GotoSmart(x, y, tableIdx) self.recipeIdxList.append("MOVE") self.recipeIdxList.append(self.lastGotoIdx) self.recipeIdxList.append(tableIdx) return True
def CreateWssMovementData(recipes, dir, isUp=True): result = [] for i in xrange(0, len(recipes.WssCreator)): recipes.Reset() if isUp: recipes.Goto(-23, 1) recipes.AddWss(i) PlaceReadingHeads(recipes.recipe) if isUp: gen = period * (len(recipes.recipe) + 10) while gen % (2 * distForward) != 0: gen += 1 goto(gen) g.fit() g.update() rect = g.getrect() g.select([rect[0], -6 * distBack, rect[2], 7 * distBack]) g.clear(1) x, y, res = FindWssByDirection(isUp, distForward)[0] x += 23 y += -21 y = y % distForward else: gen = period * (len(recipes.recipe) + 10) while gen % (2 * distBack) != 0: gen += 1 goto(gen) g.fit() g.update() rect = g.getrect() helixy = CalcHelix(recipes.recipe) g.select([rect[0], helixy - distBack, rect[2], 7 * distBack]) g.clear(1) 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) + "_ForwardWssBaseAuto.pkl"), "wb")) else: pickle.dump( result, open( path.join( dir, str(step) + "_" + str(period) + "_BackwardWssBaseAuto.pkl"), "wb")) recipes.Reset()
rule_name = mparam.rule_name [g_width, g_height, g_time] = mfunc.dimensions(s1, s2, \ width_factor, height_factor, time_factor) g.setalgo("QuickLife") # use the QuickLife algorithm g.new(rule_name) # initialize cells to state 0 g.setrule(rule_name + ":T" + str(g_width) + "," + str(g_height)) # make a toroid [g_xmin, g_xmax, g_ymin, g_ymax] = mfunc.get_minmax(g) # find range of coordinates s1.insert(g, g_xmin, -1, g_ymin, g_ymax) # insert the first seed into Golly s2.insert(g, +1, g_xmax, g_ymin, g_ymax) # insert the second seed into Golly g.setmag(mfunc.set_mag(g)) # set magnification # g.update() # show the intial state # g.note("These are the intial seeds.\n" + \ "Red is on the left and blue is on the right.\n" + \ "The file names are in the header of the main window.\n" + \ "Drag this note to a new location if it is blocking your view.\n\n" + \ "Red seed directory: " + head1 + "\n" + \ "Red seed file: " + tail1 + "\n" + \ "Red seed size: {} x {}\n".format(seed1.xspan, seed1.yspan) + \ "Red seed density: {:.4f} ({} ones)\n\n".format(seed1.density(), \ seed1.count_ones()) + \ "Blue seed directory: " + head2 + "\n" + \ "Blue seed file: " + tail2 + "\n" + \ "Blue seed size: {} x {}\n".format(seed2.xspan, seed2.yspan) + \ "Blue seed density: {:.4f} ({} ones)\n\n".format(seed2.density(), \ seed2.count_ones()) + \
def score_pair(g, seed1, seed2, width_factor, height_factor, \ time_factor, num_trials): """ Put seed1 and seed2 into the Immigration Game g and see which one wins and which one loses. Note that this function does not update the histories of the seeds. For updating histories, use update_history(). """ # # Make copies of the original two seeds, so that the following # manipulations do not change the originals. # s1 = copy.deepcopy(seed1) s2 = copy.deepcopy(seed2) # # Check the number of living cells in the seeds. If the number # is zero, it is probably a mistake. The number is initially # set to zero and it should be updated when the seed is filled # with living cells. We could use s1.count_ones() here, but # we're trying to be efficient by counting only once and # storing the count. # assert s1.num_living > 0 assert s2.num_living > 0 # # Initialize scores # score1 = 0.0 score2 = 0.0 # # Run several trials with different rotations and locations. # for trial in range(num_trials): # # Randomly rotate and flip s1 and s2 # s1 = s1.random_rotate() s2 = s2.random_rotate() # # Switch cells in the second seed (s2) from state 1 (red) to state 2 (blue) # s2.red2blue() # # Rule file # rule_name = "Immigration" # # Set toroidal universe of height yspan and width xspan # Base the s1ze of the universe on the s1zes of the seeds # # g = the Golly universe # [g_width, g_height, g_time] = dimensions(s1, s2, \ width_factor, height_factor, time_factor) # # set algorithm -- "HashLife" or "QuickLife" # g.setalgo("QuickLife") # use "HashLife" or "QuickLife" g.autoupdate(False) # do not update the view unless requested g.new(rule_name) # initialize cells to state 0 g.setrule(rule_name + ":T" + str(g_width) + "," + str(g_height)) # make a toroid # # Find the min and max of the Golly toroid coordinates # [g_xmin, g_xmax, g_ymin, g_ymax] = get_minmax(g) # # Set magnification for Golly viewer # g.setmag(set_mag(g)) # # Randomly place seed s1 somewhere in the left s1de of the toroid # s1.insert(g, g_xmin, -1, g_ymin, g_ymax) # # Randomly place seed s2 somewhere in the right s1de of the toroid # s2.insert(g, +1, g_xmax, g_ymin, g_ymax) # # Run for a fixed number of generations. # Base the number of generations on the sizes of the seeds. # Note that these are generations ins1de one Game of Life, not # generations in an evolutionary sense. Generations in the # Game of Life correspond to growth and decay of a phenotype, # whereas generations in evolution correspond to the reproduction # of a genotype. # g.run(g_time) # run the Game of Life for g_time time steps g.update() # need to update Golly to get counts # # Count the populations of the two colours. State 1 = red = seed1. # State 2 = blue = seed2. # [count1, count2] = count_pops(g) # # We need to make an adjustment to these counts. We don't want to # use the total count of living cells; instead we want to use # the increase in the number of living cells over the course of # the contest between the two organisms. The idea here is that # we want to reward seeds according to their growth during the # contest, not according to their initial states. This should # avoid an evolutionary bias towards larger seeds simply due # to size rather than due to functional properties. It should # also encourage efficient use of living cells, as opposed to # simply ignoring useless living cells. # # s1.num_living = initial number of living cells in s1 # s2.num_living = initial number of living cells in s2 # if (s1.num_living < count1): count1 = count1 - s1.num_living else: count1 = 0 # if (s2.num_living < count2): count2 = count2 - s2.num_living else: count2 = 0 # # Now we are ready to determine the winner. # if (count1 > count2): score1 = score1 + 1.0 elif (count2 > count1): score2 = score2 + 1.0 else: score1 = score1 + 0.5 score2 = score2 + 0.5 # # # Normalize the scores # score1 = score1 / num_trials score2 = score2 / num_trials # return [score1, score2]
def moveobject(): global oldcells, object, object1 # wait for click in or near a live cell while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() result = findlivecell(int(xstr), int(ystr)) if len(result) > 0: prevx = int(xstr) prevy = int(ystr) oldmouse = xstr + ' ' + ystr g.show("Extracting object...") x, y = result object = getobject(x, y) object1 = list(object) # save in case user aborts script if mods == "alt": # don't delete object oldcells = list(object) break else: g.warn("Click on or near a live cell belonging to the desired object.") elif event == "key h none": showhelp() else: g.doevent(event) # wait for mouse-up while moving object g.show("Move mouse and release button...") mousedown = True while mousedown: event = g.getevent() if event.startswith("mup"): mousedown = False elif len(event) > 0: lookforkeys(event) mousepos = g.getxy() if len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so move object g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) xstr, ystr = mousepos.split() x = int(xstr) y = int(ystr) if g.getwidth() > 0: # ensure object doesn't move beyond left/right edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.left < gridl: x += gridl - obox.left elif obox.right > gridr: x -= obox.right - gridr if g.getheight() > 0: # ensure object doesn't move beyond top/bottom edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.top < gridt: y += gridt - obox.top elif obox.bottom > gridb: y -= obox.bottom - gridb object = g.transform(object, x - prevx, y - prevy) oldcells = underneath(object) g.putcells(object) prevx = x prevy = y oldmouse = mousepos g.update()
add_it(objs, 'bobo$o$o$o2bo$3o!', 0, 2) add_it(objs, 'o2bo$4bo$o3bo$b4o!', 2, 0) add_it(objs, 'bo2bo$o$o3bo$4o!', -2, 0) site_step = 0 rect = g.getselrect() if not rect: site_step = find_best_selection() rect = g.getselrect() if not rect: g.exit( "No selection. Could not locate a valid separation and offset automatically." ) g.fitsel() g.update() if site_step == 0: site_step = int(g.getstring("Enter step between construction sites")) delay2 = int( g.getstring( "Enter delay for 2nd construction (only relevant for spaceships)", "0")) offset = 100 paranoidcheck = int( g.getstring( "Enter number of ticks to check below binary search result (min=1)", "100")) if paranoidcheck < 1: g.exit(
attempt_id = os.getenv("GOLLY_ATTEMPT_ID") if attempt_id is None and os.getenv("LIFEBOX_DEBUG") is not None: attempt_id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff" BASE_RESULTS_PATH = os.path.join(os.sep, "tmp", attempt_id) if not os.path.exists(BASE_RESULTS_PATH): os.makedirs(BASE_RESULTS_PATH) RESULTS_FN = os.path.join(BASE_RESULTS_PATH, "results.log") open(RESULTS_FN,"a").write("Opening up MC file..\n") g.open("adventure_lifebooox.mc") g.setrule('Varlife') g.show("Starting....") g.update() g.setstep(6) start_time = time.time() open(RESULTS_FN,"a").write("BOOTING..\n") PATTERN_FN = os.path.join(BASE_RESULTS_PATH, "pattern.dat") results = add_data(PATTERN_FN) open(RESULTS_FN,"a").write(results + "\n") boot_completed = False for x in range(0, 40): g.run(1000000)
density = rand.uniform(density_range[0], density_range[1]) for x in range(initial_size): for y in range(initial_size): if (rand.uniform(0, 1) <= density): g.setcell(x - offset, y - offset, 1) # set cell to 1 # # initial population count # initial_pop_count = float(g.getpop()) initial_bounding_box = g.getrect() initial_area = float(initial_size * initial_size) # # run Golly for num_steps # g.run(num_steps) g.update() # update the Golly display # # final population count # final_pop_count = float(g.getpop()) final_bounding_box = g.getrect() # # final area # if (len(final_bounding_box) == 0): final_area = 0.0 else: [x, y, width, height] = final_bounding_box final_area = float(width * height) # # update probability of area increase