def bijoscar(maxsteps): initpop = int(g.getpop()) initrect = g.getrect() if (len(initrect) == 0): return 0 inithash = g.hash(initrect) for i in xrange(maxsteps): g.run(1) if (int(g.getpop()) == initpop): prect = g.getrect() phash = g.hash(prect) if (phash == inithash): period = i + 1 if (prect == initrect): return period else: return -period return -1
def bijoscar(maxsteps): initpop = int(g.getpop()) initrect = g.getrect() if (len(initrect) == 0): return 0, None inithash = g.hash(initrect) for i in range(maxsteps): g.run(1) if (int(g.getpop()) == initpop): prect = g.getrect() phash = g.hash(prect) if (phash == inithash): period = i + 1 if (prect == initrect): return period, (0, 0) else: dx = prect[0] - initrect[0] dy = prect[1] - initrect[1] return period, (dx, dy) return -1, None
def GunArea(cells, curGunPeriod): maxBox = [] minpop = -100000 for i in xrange(0, curGunPeriod, 4): g.new(str(i)) g.putcells(g.evolve(cells, i)) g.setbase(8) g.setstep(3) g.step() g.step() edgeGlider = EdgeGlider() while PerformDelete(edgeGlider, curGunPeriod): edgeGlider = DevolveGlider(edgeGlider, curGunPeriod) for j in xrange(0, 4): if g.getpop() > minpop: maxpop = g.getpop() maxpopgun = g.getcells(g.getrect()) maxBox = AppendBox(maxBox, g.getrect()) g.run(1) return [BoxValue(maxBox), maxpopgun, maxBox]
def testRule(rulestr): r = g.getrect() if r: g.select(r) g.clear(0) g.putcells(origPatt) g.setrule(rulestr) g.run(stabGen) if g.empty(): return () pop = int(g.getpop()) if (pop < minPop or pop > maxPop): return () r = g.getrect() testPatt = g.transform(g.getcells(r), -r[0], -r[1]) testPop = int(g.getpop()) testRect = g.getrect() stabPatt = list(testPatt) stabPop = testPop for ii in xrange(maxGen): g.run(1) pop = int(g.getpop()) if (pop < minPop or pop > maxPop): break if (pop == testPop): # Test for periodicity r = g.getrect() if testPatt == g.transform(g.getcells(r), -r[0], -r[1]): period = ii + 1 dy, dx = sss.minmaxofabs( (r[0] - testRect[0], r[1] - testRect[1])) if (dx == 0): # Oscillator (reject if low period or bOsc is False) if bOsc and period >= minOscP: return (0, 0, period) elif (period >= minShipP): # Spaceship return (dx, dy, period) elif ((dx + dy / 1.9) / (period * 1.0) > minSpeed and period >= fastShipP): # Fast spaceship return (dx, dy, period) break # Pattern is a low period oscillator or spaceship # Stability check if (ii % stabCheckP == 0): r = g.getrect() # First check for BBox expansion if maxDim > 0 and max(r[2:4]) > maxDim: # Pattern is expanding # XXX Attempt to separate components expanding in different directions break currPatt = g.transform(g.getcells(r), -r[0], -r[1]) if (pop == stabPop and currPatt == stabPatt): # Pattern has stabilised to low period oscillator / spaceship break stabPop = pop stabPatt = list(currPatt) return ()
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 shrink(): global d if g.empty(): return g.select(g.getrect()) d=int(10000*float(g.getpop())/(int(g.getselrect()[2])*int(g.getselrect()[3]))) while d<100: bbox=g.getselrect() bbox[0]=bbox[0]+1 bbox[1]=bbox[1]+1 bbox[2]=bbox[2]-2 bbox[3]=bbox[3]-2 g.select(bbox) g.shrink() d=int(10000*float(g.getpop())/(int(g.getselrect()[2])*int(g.getselrect()[3])))
def getwhp(): bbox = g.getrect() if len(bbox) == 0: return 0, 0, 0 return bbox[2], bbox[3], int(g.getpop())
def rule_boring(): explode = 0 die = 0 num_trial = 8 for i in range(num_trial): g.new("") g.select([0, 0, 32, 32]) g.randfill(50) g.run(16) if int(g.getpop()) == 0: die += 1 continue r = g.getrect() if r[2] > 60 and r[3] > 60: explode += 1 continue return -1 if explode == num_trial: return 0 if die == num_trial: return 1 return -1
def canonise(): p = bijoscar(4) 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) return "x"+prefix+"_"+representation
def calculate_density(): bbox = gl.rect(g.getrect()) if bbox.empty: d = 0 else: d = float(g.getpop()) / float(bbox.wd*bbox.ht) return d
def canonise(): p = bijoscar(MAXPERIOD) if p == -1: # In rules with photons the pattern may be periodic, but not in CGoL return "" 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 = "xq" + str(abs(p)) elif (p==1): prefix = "xs" + str(g.getpop()) else: prefix = "xp" + str(p) return prefix + "_" + representation
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 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)
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 analyse (gogen, glcnt, minpop, maxpop, mingl): if glcnt < mingl: return (False, 0) g.run (gogen) inrect = g.getrect () clean (inrect) endpop = int (g.getpop ()) if endpop < minpop or endpop > maxpop: return (False, 0) rect = g.getrect () if rect == []: return (True, 0) else: addmarkers (inrect) return (True, g.hash (inrect))
def find_all_glider_idx(mask): idxs = extract_indexes(mask) idxs.sort(key=lambda idx: (1.01 * gliders_in[idx][0] + gliders_in[idx][1])) copy_idxs = idxs[:] for edge_i in enum_shooters(mask): reaction_cells = shoot_defs[edge_i][4] stable_cells = shoot_defs[edge_i][5] for g_i in list(copy_idxs): g.new("") for g_j in idxs: x, y, idx = gliders_in[g_j] if g_j == g_i: g.putcells(g.evolve(reaction_cells, idx), x, y) else: g.putcells(g.evolve(gld, idx), x - 128, y + 128) g.setbase(8) g.setstep(3) g.step() x, y, _ = gliders_in[g_i] # test if the pattern consists of the stable cells plus the # necessary gliders and nothing else g.putcells(stable_cells, x, y, 1, 0, 0, 1, "xor") if int(g.getpop()) != 5 * len(idxs): continue for g_j in idxs: x, y, idx = gliders_in[g_j] g.putcells(g.evolve(gld, idx), x, y, 1, 0, 0, 1, "xor") if g.empty(): copy_idxs.remove(g_i) yield g_i,edge_i
def CountSL(): result = [] while int(g.getpop()) > 0: xy = [FindActive()] while True: newXY = FindConnected(xy) #g.getstring(str(xy) + " : " + str(newXY) ) if len(newXY) == len(xy): break xy = newXY result.append(xy) RemoveList(xy) return result
def PlaySound(): # the next (non-empty) generation has just been created # so get the current population and update minpop and maxpop global minpop, maxpop, prevsound, samecount currpop = int(g.getpop()) if currpop < minpop: minpop = currpop if currpop > maxpop: maxpop = currpop poprange = maxpop - minpop if poprange == 0: g.sound("play", sounds[numsounds // 2], volume) else: p = (currpop - minpop) / poprange # p is from 0.0 to 1.0 i = int(p * (numsounds - 1)) g.sound("play", sounds[i], volume) # occasionally play a chord if random() < 0.1: # two notes up will be a major or minor third # since only white notes are used j = i + 2 if j >= numsounds: j = 0 g.sound("play", sounds[j], volume) # note that we can end up repeating the same sound # (eg. if the initial pattern is a dense Life soup), # so if that happens we reset minpop and maxpop if i == prevsound: samecount = samecount + 1 if samecount == numsounds: minpop = currpop maxpop = currpop prevsound, samecount = 0, 0 else: prevsound = i samecount = 0
status = "" g.new("") g.reset() g.putcells(test_list,0,0,1,0,0,1,"xor") g.show("Checking for oscillation... (hit escape to abort)") oldsecs = time() # -------------------------------------------------------------------- bbox = rect( g.getrect() ) if bbox.empty: initial_d = 0 else: initial_d = float( g.getpop() ) / ( float(bbox.wd) * float(bbox.ht) ) initial_pop = g.getpop() # -------------------------------------------------------------------- while not oscillating() and iterations < max_iter: g.run(1) iterations += 1 newsecs = time() if newsecs - oldsecs >= 1.0: # show pattern every second oldsecs = newsecs fit_if_not_visible() g.update() if iterations >= max_iter:
if not os.path.isfile("colseqs.txt"): g.show("Decompressing colseqs.txt.bz2...") temp = bz2.BZ2File('colseqs.txt.bz2', 'rb') data = temp.read().decode() with open("colseqs.txt", "w") as f: f.write(data) patts = open("rles.txt", "r", newline="\r\n") cols = open("colseqs.txt", "r", newline="\r\n") sols = 0 count = 0 popseq = "" for i in range(0, GEN_CHECK): popseq += str(chr(33 + (int(g.getpop()) % 64))) g.run(1) g.new("Solutions") curr_patt = patts.readline() while curr_patt != "": curr_col = cols.readline() g.show( str(sols) + " solutions found, " + str(count) + " collisions tried. Press <x> to copy current results to clipboard. Press <esc> to quit." ) if popseq in curr_col: g.putcells(g.parse(curr_patt), offset, 0) offset += 75 sols += 1 event = g.getevent() if event.startswith("key x"):
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") if g.getrule() != "LifeHistory": g.exit("Uh-oh 2.") # should already be for this layer g.setrule("LifeHistoryToLife") g.run(1) g.setrule("B3/S23") g.putcells(originalONcells, 0, 0, 1, 0, 0, 1, "xor") if cycles == 0 or g.getpop() != "0": mismatchreport += "Fixed-gun LifeHistory mismatch found at period " + str( p) + "-- Cycles: " + str( cycles) + ", pop = " + g.getpop() + "\n" # if cycles==0 and g.getpop()=="0": # # This is most often due to a single missing state-2 cell just in front of the output glider # # TODO: catch this case and dispose of it without unnecessary warning messages # g.setclipstr(str([gunpat, newgunpat])) # g.exit() #################################3 else: # not a fixed gun, therefore a gun built from a template g.open(os.path.join(outfolder, item)) r = g.getrect() g.select(r) g.run(p) # get rid of bounding-box marker sparks first g.setrule("LifeHistory") # there are no pseudo-period template guns, so one cycle should be enough
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
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) 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:
def sof_canonise(duration, dxdy): sof = '' moving = 's' # Stationary # For spaceships the pattern needs to be oriented in the standard direction # N, NW, or in between. if not dxdy == (0, 0): dx, dy = dxdy if abs(dx) > abs(dy): a, b, c, d = 0, -sign(dy), -sign(dx), 0 else: a, b, c, d = -sign(dx), 0, 0, -sign(dy) rect = g.getrect() ship = g.getcells(rect) g.select(rect) g.clear(0) g.putcells(ship, 0, 0, a, b, c, d) dx, dy = (dx * a + dy * b, dx * c + dy * d) if dx == 0: moving = 'o' # Orthogonal elif dx == -dy: moving = 'd' # Diagonal else: moving = 'k' # Oblique # We need to compare each phase to find the one used to determine the # pattern's standard form. The standard form is selected from a phase # with the minimum population minpop = int(g.getpop()) if (duration > 1): for t in range(duration): minpop = min(minpop, int(g.getpop())) g.run(1) if minpop == 0: return '0' for t in range(duration): if int(g.getpop()) == minpop: rect = g.getrect() ox = rect[0] oy = rect[1] x_length = rect[2] y_breadth = rect[3] # Choose the orientation which comes first according to sof comparison rules: sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox, oy, 1, 0, 0, 1)) # Identity if moving in ('s', 'o'): sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox + x_length - 1, oy, -1, 0, 0, 1)) # flip_x if moving in ('s', 'd'): sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox + x_length - 1, oy + y_breadth - 1, 0, -1, -1, 0)) # swap_xy_flip if moving == 's': sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox, oy + y_breadth - 1, 1, 0, 0, -1)) # flip_y sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox + x_length - 1, oy + y_breadth - 1, -1, 0, 0, -1)) # 180 sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy, 0, 1, 1, 0)) # swap_xy sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox + x_length - 1, oy, 0, -1, 1, 0)) # cw 90 sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy + y_breadth - 1, 0, 1, -1, 0)) # ccw 90 if (duration > 1): g.run(1) return sof
def chunks(l,w): for i in xrange(0, len(l), 2): yield l[i]+(w*l[i+1]) if g.empty(): g.exit("The pattern is empty.") s = g.getstring("Enter the period:","", "Heat calculator") if not validint(s): g.exit('Bad number: %s' % s) numsteps = int(s) if numsteps < 2: g.exit('Period must be at least 2.') g.show('Processing...') heat = 0; maxheat = 0; minheat = 9*g.getpop(); for i in range(0, numsteps): bb = g.getrect() clist = list(chunks(g.getcells(bb), bb[2]+2)) g.run(1) dlist = list(chunks(g.getcells(g.getrect()), bb[2]+2)) theat = (len(clist)+len(dlist)-2*len([x for x in set(clist).intersection( set(dlist) )])) heat += theat maxheat = max(theat, maxheat) minheat = min(theat, minheat) g.show('Heat: %.4f, Max change: %d, Min change: %d' % ((float(heat)/numsteps), maxheat, minheat))
status = "" g.new("") g.reset() g.putcells(test_list, 0, 0, 1, 0, 0, 1, "xor") g.show("Checking for oscillation... (hit escape to abort)") oldsecs = time() # -------------------------------------------------------------------- bbox = rect(g.getrect()) if bbox.empty: initial_d = 0 else: initial_d = float(g.getpop()) / (float(bbox.wd) * float(bbox.ht)) initial_pop = g.getpop() # -------------------------------------------------------------------- while not oscillating() and iterations < max_iter: g.run(1) iterations += 1 newsecs = time() if newsecs - oldsecs >= 1.0: # show pattern every second oldsecs = newsecs fit_if_not_visible() g.update() if iterations >= max_iter:
for i in xrange(g.numlayers()): if g.getname(i) == layername: poplayer = i break if poplayer == -1 and g.numlayers() == g.maxlayers(): g.exit("You need to delete a layer.") # prompt user for number of steps numsteps = xlen s = g.getstring("Enter the number of steps:", str(numsteps), "Population plotter") if len(s) > 0: numsteps = int(s) if numsteps <= 0: g.exit() # generate pattern for given number of steps poplist = [ int(g.getpop()) ] genlist = [ int(g.getgen()) ] oldsecs = time() for i in xrange(numsteps): g.step() poplist.append( int(g.getpop()) ) genlist.append( int(g.getgen()) ) newsecs = time() if newsecs - oldsecs >= 1.0: # show pattern every second oldsecs = newsecs fit_if_not_visible() g.update() g.show("Step %i of %i" % (i+1, numsteps)) fit_if_not_visible()
# extract-single-channel-recipe.py # glider stream should be pointed northwest. First glider should be in 3o$o$bo! phase, point at (0,0). # no selection needed -- script works on entire pattern in current universe # # For very large single-channel streams, a variant of recognizer.py would be enormously more efficient import golly as g count = 0 recipe = [] while int(g.getpop())>0: if g.getcell(0,0)==1 and g.getcell(1,0)==1 and g.getcell(2,0)==1 and g.getcell(0,1)==1 and g.getcell(1,2)==1: g.setcell(0,0,0) g.setcell(1,0,0) g.setcell(2,0,0) g.setcell(0,1,0) g.setcell(1,2,0) recipe+=[count] count=0 if len(recipe)%10 == 0: g.show(str(len(recipe))) g.fit() g.update() else: count+=1 g.run(1) g.note("Done. Click OK to copy results to clipboard.") g.setclipstr(str(recipe)) g.show(str(len(recipe)))
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): g.step() if g.empty(): break pop=int(popfunc())
def FindAllHs(cells): g.new("") g.putcells(cells) rect = g.getrect() min = 10000 max = -10000 for i in xrange(1, len(cells), 2): cx = cells[i - 1] cy = cells[i] dx = 40 - cx cy += dx if cy < min: min = cy if cy > max: max = cy answer = [[],[]] if (min - 9) % 2 != 0: min += 1 for i in xrange(min - 9 - 40, max + 6 - 40, 2): g.new("") g.putcells(cells) g.putcells(gld, 40, 40 + i) g.setstep(3) g.step() g.step() if int(g.getpop()) > 80 or int(g.getpop()) == 0: continue if g.getrect()[0] < -120: continue rect = g.getrect() if rect[2] > 25 or rect[3] > 25: continue s = str(g.getcells(g.getrect())) g.run(1) if s == str(g.getcells(g.getrect())): key = str(rect) + ":" + str(g.getpop()) SLs = [] if rect[2] < 8 and rect[3] < 8: SLs = CountSL() if len(SLs) == 1: SLs[0].sort(key=lambda r: 100000 * r[1] + r[0]) x1 = SLs[0][0][0] y1 = SLs[0][0][1] for o in xrange(0, len(SLs[0])): SLs[0][o][0] -= x1 SLs[0][o][1] -= y1 answer[0].append([i, x1, y1, SLs[0]]) if not (key in existingKeys): existingDic[key] = [] existingKeys.append(key) if s in existingDic[key]: continue else: existingDic[key].append(s) answer[1].append(i) return answer
soupnum = int(input.split('/')[1]) soupwd = int(input.split('/')[2]) density = int(input.split('/')[3]) gen_thres = int(input.split('/')[4]) if g.getrule().split(':')[0] in dict_lc: yfunc = 'popc' else: yfunc = 'pop' 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", "%s/gen" % yfunc) dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]} live_cells = dict_lc[g.getrule().split(':')[0]] dict_f = {'popc':popcount,'pop': g.getpop, 'gen': g.getgen,'boxx':lambda:boxdm(2) ,'boxy': lambda: boxdm(3),'area':area,'density':density, \ 'logpop':lambda:int(int(g.getpop())*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]] htlist = [] plotlist = [] tile = loadtopo(maxnum, step) # g.note(str(tile[0])) if not tile == []: # add a layer layername = "Topology_Search"
g.autoupdate(False) f = open(out_filename, 'w') f.write("id,number_of_iterations,initial_pop,final_pop,initial_density,final_density,end_status,elapsed_time\n") #f2 = open(patterns_filename, 'w') #f2.write("id, initial_cell_list\n") trial_number = 1 for test_list in create_cell_list(grid_size): iterations = 0 status = '' o.clear() g.new(name) g.reset() g.putcells(test_list) initial_pop = g.getpop() initial_d = calculate_density() start_time = time() while not o.oscillating() and iterations<max_iter: g.step() iterations += 1 end_time = time() status = o.status if iterations >= max_iter: status = "timeout" #f2.write("%d, %s\n" % (trial_number, str(test_list))) #g.store(test_list, rlepatterns_filename%(trial_number))
g.setmag(screen_mag) # screen magnification g.setrule(rule) # set the rule that Golly will use offset = int(initial_size / 2) # this centers the matrix in the display # # write initial matrix into the Golly universe # 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 #
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: soupfile.write("\n".join(soups)) g.show("Soups successfully saved in {}.".format(soupfilepath))
# getminpopandminbb.py import golly as g maxticks = g.getstring ("Enter maximum number of ticks to search: ", "1024") r = g.getrect() count, minT, minpop, minbbx, minbby, minbbt = 0, 0, int(g.getpop()), r[2], r[3], 0 newpop = minpop while count<int(maxticks): if count%100==0: g.show("T: " + str(count) + " Current pop: "+str(newpop)+" Current minimum pop: " + str(minpop) + " at T = " + str(minT) + ". Min box = "+str([minbbx, minbby]) + " at T = " + str(minbbt) + ". 'q' to quit.") g.update() cancel=0 for i in range(100): # clear buffer if, e.g., mouse events have been piling up evt = g.getevent() if evt == "key q none": cancel = 1 if cancel==1: break g.run(1) count+=1 newpop = int(g.getpop()) if newpop<minpop: minpop = newpop minT = count r = g.getrect() if r[2]*r[3]<minbbx*minbby: minbbx, minbby, minbbt = r[2], r[3], count g.note("Finished scan of " + str(count) + " ticks. Minimum population: " +str(minpop) + " at T = " + str(minT) + ". Min box = "+str([minbbx, minbby]) + " at T = " + str(minbbt))
def FindAllHs(cells, minx): g.new("") g.putcells(cells) rect = g.getrect() min = 10000 max = -10000 for i in xrange(1, len(cells), 2): cx = cells[i - 1] cy = cells[i] dx = 40 - cx cy += dx if cy < min: min = cy if cy > max: max = cy answer = [[],[]] if (min - 9) % 2 != 0: min += 1 for i in xrange(min - 9 - 40, max + 6 - 40, 2): g.new("") g.putcells(cells) g.putcells(gld, 40, 40 + i) g.setstep(3) g.step() g.step() if int(g.getpop()) > 60: continue if int(g.getpop()) == 0: continue if g.getrect()[0] < -120: continue edgeType = HasEdgeShooter(minx) if edgeType != False: answer[0].append([i, 0, 0, [edgeType]]) rect = g.getrect() if rect[2] > 12 or rect[3] > 12: continue s = str(g.getcells(g.getrect())) g.run(2) if s == str(g.getcells(g.getrect())): key = str(rect) + ":" + str(g.getpop()) if not (key in existingKeys): existingDic[key] = [] existingKeys.append(key) if s in existingDic[key]: continue else: existingDic[key].append(s) answer[1].append(i) return answer
# Calculates the density of live cells in the current pattern. # Author: Andrew Trevorrow ([email protected]), March 2006. # Updated to use exit command, Nov 2006. from glife import rect import golly as g bbox = rect( g.getrect() ) if bbox.empty: g.exit("The pattern is empty.") d = float( g.getpop() ) / ( float(bbox.wd) * float(bbox.ht) ) if d < 0.000001: g.show("Density = %.1e" % d) else: g.show("Density = %.6f" % d)
periodlist = map(int, rawentry1.split(',')) maxgens = int(rawentry2) soups = int(rawentry3) totalperiod = 1 for period in periodlist: totalperiod = lcm(period, totalperiod) longest = [], 0 for soupnum in range(soups): g.new('') g.select([0, 0, 5, 5]) g.randfill(50) currsoup = g.getcells([0, 0, 5, 5]) currpop = g.getpop() sameaslast = 0 totalgens = 0 success = False while totalgens < maxgens: g.run(totalperiod) totalgens += totalperiod if g.getpop() == currpop: sameaslast += 1 else: sameaslast == 0 currpop = g.getpop() if sameaslast == 5: # We assume it's stabilized success = True totalgens -= totalperiod * 5
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") if g.getrule()!="LifeHistory": g.exit("Uh-oh 2.") # should already be for this layer g.setrule("LifeHistoryToLife") g.run(1) g.setrule("B3/S23") g.putcells(originalONcells, 0, 0, 1, 0, 0, 1, "xor") if cycles==0 or g.getpop()!="0": mismatchreport+="Fixed-gun LifeHistory mismatch found at period " + str(p) + "-- Cycles: "+str(cycles)+", pop = "+g.getpop()+"\n" # if cycles==0 and g.getpop()=="0": # # This is most often due to a single missing state-2 cell just in front of the output glider # # TODO: catch this case and dispose of it without unnecessary warning messages # g.setclipstr(str([gunpat, newgunpat])) # g.exit() #################################3 else: # not a fixed gun, therefore a gun built from a template g.open(os.path.join(outfolder,item)) r = g.getrect() g.select(r) g.run(p) # get rid of bounding-box marker sparks first g.setrule("LifeHistory") # there are no pseudo-period template guns, so one cycle should be enough g.run(p) originalONcells = g.getcells(r)
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
#!/usr/bin/env python2.6 # Q: http://www.hacker.org/challenge/chal.php?id=117 # A: http://www.hacker.org/challenge/chal.php?answer=821%2C319&id=117&go=Submit # Use Golly, a Game of Life simulator. It can be shown that after 1500 generations, the populations are always 116. So only need to search the first 1500 generations to find the max population. import golly as g GENERATION_NUM = 1500 max_population = -1 best_generation = -1 for generation in range(GENERATION_NUM): population = int(g.getpop()) if population > max_population: max_population = population best_generation = generation g.step() g.note('%d,%d' % (best_generation, max_population))