def ReplaceTreeSection(rulepath, newtree): # replace @TREE section in existing .rule file with new tree data try: rulefile = open(rulepath,'r') except: golly.exit('Failed to open existing .rule file: '+rulepath) # create a temporary file for writing new rule info temphdl, temppath = mkstemp() tempfile = open(temppath,'w') skiplines = False for line in rulefile: if line.startswith('@TREE'): tempfile.write('@TREE\n\n') tempfile.write(newtree) skiplines = True elif skiplines and line.startswith('@'): tempfile.write('\n') skiplines = False if not skiplines: tempfile.write(line) # 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)
def draw_icons(iconinfo, transparent): global colorstate if len(iconinfo) == 0: return width = iconinfo[0] height = iconinfo[1] num_colors = iconinfo[2] chars_per_pixel = iconinfo[3] colordict = iconinfo[4] pos = 5 numicons = height // width for i in range(numicons): x = i * 32 y = 0 if width == 15: y = 32 if width == 7: y = 48 for row in range(width): pxls = iconinfo[pos] pos += 1 for col in range(width): offset = col * chars_per_pixel key = pxls[offset:offset + chars_per_pixel] if not key in colordict: g.exit("Unexpected key in icon data: " + key) rgb = colordict[key] if rgb != transparent: g.setcell(x + col, y + row, colorstate[rgb])
def ReplaceTreeSection(rulepath, newtree): # replace @TREE section in existing .rule file with new tree data try: rulefile = open(rulepath, 'r') except: golly.exit('Failed to open existing .rule file: ' + rulepath) # create a temporary file for writing new rule info temphdl, temppath = mkstemp() tempfile = open(temppath, 'w') skiplines = False for line in rulefile: if line.startswith('@TREE'): tempfile.write('@TREE\n\n') tempfile.write(newtree) skiplines = True elif skiplines and line.startswith('@'): tempfile.write('\n') skiplines = False if not skiplines: tempfile.write(line) # 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)
def draw_icons(iconinfo, transparent): global colorstate if len(iconinfo) == 0: return width = iconinfo[0] height = iconinfo[1] num_colors = iconinfo[2] chars_per_pixel = iconinfo[3] colordict = iconinfo[4] pos = 5 numicons = height/width for i in xrange(numicons): x = i*32 y = 0 if width == 15: y = 32 if width == 7: y = 48 for row in xrange(width): pxls = iconinfo[pos] pos += 1 for col in xrange(width): offset = col*chars_per_pixel key = pxls[offset : offset + chars_per_pixel] if not key in colordict: g.exit("Unexpected key in icon data: " + key) rgb = colordict[key] if rgb != transparent: g.setcell(x+col, y+row, colorstate[rgb])
def retrieveparam(article, param, s): if s.find(param) < 0: g.note("Setting clipboard to current html -- can't find '" + param + "'.") g.setclipstr(s) g.exit() regexstr = param + r'\s*=\s*(.*)$' ####################### match = re.search(regexstr, s, re.MULTILINE) if match: # pval = match.group(1) # if pval[-1:]=="\n": pval = pval[:-1] # # handle the case where newlines are not added before each pipe character # pval += "|" # g.note(pval + " :: " + pval[:pval.index("|")]) # return pval[:pval.index("|")] # try to fix problem with multiple EmbedViewers on one line and pname as last parameter, as in Density article grp = match.group(1) if grp.find("}") > -1: pval = grp[:grp.find("}")] + "|" else: pval = grp + "|" return pval[:pval.index("|")].strip() else: g.note("Could not find definition of parameter '" + param + "' in article '" + article + "'.") g.setclipstr(s) g.exit()
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 firstdiffs(values): if len(values) < 1: g.warn("No polynomial entered, apparently.") g.exit() return # Just for good measure. if len(values) == 1: return [values[0]] if len(values) > 1: diffs = [] for n in xrange(len(values) - 1): diffs.append(values[n + 1] - values[n]) return firstdiffs(diffs) + [values[0]]
def firstvalues(terms): vals = [] for x in xrange(len(terms)): sum = 0 for exp, coef in enumerate(terms): sum += coef * x**exp if sum != int(sum): g.warn( "Polynomial must produce integer values when x is an integer.") g.exit() return vals.append(int(sum)) return vals
def retrieveparam(article, param, s): if s.find(param)<0: g.note("Setting clipboard to current html -- can't find '"+param+"'.") g.setclipstr(s) g.exit() regexstr = param+r'\s*=\s*(.*)$' ####################### match = re.search(regexstr, s, re.MULTILINE) if match: pval = match.group(1)+"|" return pval[:pval.index("|")] # handle the case where newlines are not added before each pipe character else: g.note("Could not find definition of parameter '"+param+"' in article '"+article+"'.") g.setclipstr(s) g.exit()
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 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 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 init_colors(): global iconcolors, colorstate if len(iconcolors) > 240: g.exit("The imported icons use too many colors!") # start with gradient from white to black (this makes it easier to # copy grayscale icons from one rule to another rule) s = 1 g.setcolors([s, 255, 255, 255]) colorstate[(255, 255, 255)] = s s += 1 graylevel = 256 while graylevel > 0: graylevel -= 32 g.setcolors([s, graylevel, graylevel, graylevel]) colorstate[(graylevel, graylevel, graylevel)] = s s += 1 # now add all the colors used in the imported icons (unless added above) for rgb in iconcolors: if not rgb in colorstate: R, G, B = rgb g.setcolors([s, R, G, B]) colorstate[rgb] = s s += 1 # finally add rainbow colors in various shades (bright, pale, dark) for hue in range(12): if s > 255: break R, G, B = hsv_to_rgb(hue / 12.0, 1.0, 1.0) g.setcolors([s, int(255 * R), int(255 * G), int(255 * B)]) s += 1 for hue in range(12): if s > 255: break R, G, B = hsv_to_rgb(hue / 12.0, 0.5, 1.0) g.setcolors([s, int(255 * R), int(255 * G), int(255 * B)]) s += 1 for hue in range(12): if s > 255: break R, G, B = hsv_to_rgb(hue / 12.0, 1.0, 0.5) g.setcolors([s, int(255 * R), int(255 * G), int(255 * B)]) s += 1 # return the 50% gray state (used for drawing boxes and text) return colorstate[(128, 128, 128)]
def init_colors(): global iconcolors, colorstate if len(iconcolors) > 240: g.exit("The imported icons use too many colors!") # start with gradient from white to black (this makes it easier to # copy grayscale icons from one rule to another rule) s = 1 g.setcolors([s,255,255,255]) colorstate[(255,255,255)] = s s += 1 graylevel = 256 while graylevel > 0: graylevel -= 32 g.setcolors([s, graylevel, graylevel, graylevel]) colorstate[(graylevel, graylevel, graylevel)] = s s += 1 # now add all the colors used in the imported icons (unless added above) for rgb in iconcolors: if not rgb in colorstate: R,G,B = rgb g.setcolors([s,R,G,B]) colorstate[rgb] = s s += 1 # finally add rainbow colors in various shades (bright, pale, dark) for hue in xrange(12): if s > 255: break R,G,B = hsv_to_rgb(hue/12.0, 1.0, 1.0) g.setcolors([s, int(255*R), int(255*G), int(255*B)]) s += 1 for hue in xrange(12): if s > 255: break R,G,B = hsv_to_rgb(hue/12.0, 0.5, 1.0) g.setcolors([s, int(255*R), int(255*G), int(255*B)]) s += 1 for hue in xrange(12): if s > 255: break R,G,B = hsv_to_rgb(hue/12.0, 1.0, 0.5) g.setcolors([s, int(255*R), int(255*G), int(255*B)]) s += 1 # return the 50% gray state (used for drawing boxes and text) return colorstate[(128,128,128)]
def getenvelope(pat): env = [] if len(pat) % 2: g.exit("Must be a 2-state list.") for i in range(0, len(pat) - 1, 2): for x in range(-1, 2): for y in range(-1, 2): if abs(x) != 0 or abs( y ) != 0: # add eight neighbors of each ON cell to the mask if [pat[i] + x, pat[i + 1] + y] not in env: env.append([pat[i] + x, pat[i + 1] + y]) for i in range(0, len(pat), 2): if [pat[i], pat[i + 1]] in env: env.remove([pat[i], pat[i + 1]]) # take original pattern back out of mask # else: # with the reduced envelope, this will now happen, e.g. with *WSS singleton sparks # g.note("Technical error: " + str([pat[i],pat[i+1]])+ " not in envelope:" + str(env) + " \n\n" + str(pat)) return list(itertools.chain.from_iterable(env))
def main(): # get selection and set to boundary bound = g.getselrect() if len( bound ) == 0: g.note( "No selection." ) g.exit() # get current Golly states left = bound[ 0 ] top = bound[ 1 ] width = bound[ 2 ] height = bound[ 3 ] for y in xrange( 0, height ): for x in xrange( 0, width ): state = g.getcell( left + x, top + y ) g.setcell( height - y - 600, x - 600, state )
def check_keyboard(): global runflag while 1: evt = g.getevent() if evt != "": g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers) + " -- 'r' to toggle run mode, any key to step") if evt == "key q none": g.setclipstr(s) g.exit() if evt == "key r none": runflag = 1 - runflag elif evt == "key g none": break else: g.doevent(evt) if runflag == 1: break
def golly_main(): bounding_box = g.getrect() g.show('Installing rule file...') src_rule = os.path.join(scriptdir, 'grills-examples', 'Grills.rule') dst_rule = os.path.join(g.getdir('rules'), 'Grills.rule') shutil.copyfile(src_rule, dst_rule) g.show('...installed.') if (len(bounding_box) == 0): g.setrule("Grills") g.exit("Please draw or load an input pattern.") elif (g.getrule() == "Grills"): golly_grills() elif (g.getrule() == "LifeHistory"): golly_lhistory() else: g.exit("Pattern has the incorrect rule: '%s' != '%s'" % (g.getrule(), 'Grills'))
def 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 calc_p_boring(p_rule): boring_explode = 0 boring_die = 0 for i in range(1000): g.show(str(i)) rand_rule(p_rule) bor = rule_boring() if bor == 0: boring_explode += 1 if bor == 1: boring_die += 1 if bor == -1: g.exit() return (boring_explode, boring_die)
def open_file2(file): if not os.path.exists(file): oldfile = file file = g.opendialog("Please locate " + file + ":", "Text files (*.txt)|*.txt", "", file) if not os.path.exists(file): g.exit("Could not find '" + oldfile + "' or '" + file + "'.") f = open(file, 'r') f1 = f.read() f1 = f1.replace('b3/s23', 'B3/S23') while '\n\n\n' in f1: f1 = f1.replace('\n\n\n', '\n\n') f1 = f1.split('\n\n') #f1 = f1[:-2] #last two are larger than column width and will cause infinite loop for i in f1: #try: # i = i[i.index('x ='):] #except ValueError: # print('No "x =": ' + i) patterns.append(i) show_message("Pass 1 of 3: processing pattern #" + str(len(patterns)),0.001) show_message('Total number of patterns: %s' % len(patterns),0.5)
def setrule(self, rulestring): # neighbours_flat = [n for x in neighbours for n in x] b = {} s = {} sep = '' birth = '' survive = '' rulestring = rulestring.lower() if '/' in rulestring: sep = '/' elif '_' in rulestring: sep = '_' elif (rulestring[0] == 'b'): sep = 's' else: sep = 'b' survive, birth = rulestring.split(sep) if (survive[0] == 'b'): survive, birth = birth, survive survive = survive.replace('s', '') birth = birth.replace('b', '') b = self.ruleparts(birth) s = self.ruleparts(survive) if b and s: self.alphanumeric = 'B' + birth + 'S' + survive self.rulename = 'B' + birth + '_S' + survive + "History" self.bee = b self.ess = s else: # Error g.note("Unable to process rule definition.\n" + "b = " + str(b) + "\ns = " + str(s)) g.exit()
def get_bitmap(): ''' Get current selection & turn it into a bitmap. ''' selrect = golly.getselrect() if len(selrect) == 0: golly.exit("There is no selection, aborting.") #Get bitmap size w, h = selrect[2:] #Adjust width, so it's in the form of 4m, m>1 w = (w + 3) // 4 * 4 w = max(8, w) #Initialize empty bitmap row = w * [0] bm = [row[:] for i in xrange(h)] #Populate bitmap with cell data u, v = selrect[:2] cells = golly.getcells(selrect) cellsxy = [(cells[i] - u, cells[i + 1] - v) for i in xrange(0, len(cells), 2)] for x, y in cellsxy: bm[y][x] = 1 return bm
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 get_bitmap(): selrect = golly.getselrect() if len(selrect) == 0: golly.exit("There is no selection, aborting.") #Get bitmap size w, h = selrect[2:] #Adjust width, so it's in the form of 4m, m>1 w = (w + 3) // 4 * 4 w = max(8, w) #Initialize empty bitmap row = w * ['0'] bm = [row[:] for i in xrange(h)] #Populate bitmap with cell data u, v = selrect[:2] cells = golly.getcells(selrect) cellsxy = [(cells[i] - u, cells[i+1] - v) for i in xrange(0, len(cells), 2)] for x, y in cellsxy: bm[y][x] = '1' #Convert to CSV string return ','.join([''.join(row) for row in bm])
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 encode_row(row): result = '' # find te rightmost 1 bit in this row far_right = x + width - 1 while g.getcell(far_right, row) == 0: far_right -= 1 if far_right < x: g.exit('Empty rows forbidden: ' + str(row)) col = x while col <= far_right: cell_value = g.getcell(col, row) num_consecutive = count_bits(row, col, cell_value) if cell_value == 1: # next cell 1? col += num_consecutive result += encode_consecutive_ones(num_consecutive) else: col += num_consecutive + 1 result += encode_consecutive_zeros(num_consecutive) result += '0' * (chunk_size // 2 + 3) # end of row return result
from glife import validint, inside from string import lower import golly as g import math rules = ("JvN29", "Nobili32", "Hutton32") rule = g.getrule () if rule not in rules: g.exit ("Invalid rule: " + rule + " (must be " + rules + ")") rect = g.getselrect () if len (rect) == 0: g.exit ("There is no selection.") answer = g.getstring("Enter axis to mirror on\n" + "(valid axes are x and y, default is y):", "y", "Mirror selection") if answer != "x" and answer != "y": g.exit ("Unknown mode: " + answer + " (must be x/y)") cells = g.getcells (rect) jvn_flip_x = ((10, 12), (14, 16), (18, 20), (22, 24)) jvn_flip_y = ((9, 11), (13, 15), (17, 19), (21, 23)) if answer == "x": flips = jvn_flip_x else:
# this script allows for testing of lifegenes functionality from the python command line rather than the golly environment. Currently this is accomplished by using a mock-golly module called folly (short for fake-golly). The folly module does not actually perform all functions as golly would, it just looks like it for testing. try: # print a nice message if someone tries to open this script from w/in golly import golly as g g.exit('this script is for dev test only and cannot be run from within golly, check out the scripts in the "LifeGenes" folder instead') except: from LifeGenes.lifegenes_core.tests.folly import folly as g from LifeGenes.lifegenes_core.setupLog import setupLog from LifeGenes.lifegenes_core.tests.optimization_tools import timedRuns from os import system import logging setupLog('__test_LifeGenes.log') def wait(): try: system('pause') #windows, doesn't require enter except: system('read -p "Press any key to continue"') #linux # MAIN logging.info('script started') nruns = 10 print 'testing environment...' from LifeGenes.lifegenes_core.environment import environment as lifegenes_environment lg_envmt = lifegenes_environment() testNames = list() testTimes = list()
(Larger values of N can take a long time.) """, "N3", "Enter specification:", ) # work out what the string meant nhood = "" nhoods = {"N": "vonNeumann", "TM": "triangularMoore", "M": "Moore", "T": "triangularVonNeumann", "H": "hexagonal"} for nh in nhoods.keys(): if nh in spec: nhood = nhoods[nh] n = int(spec.replace(nh, "")) break if nhood == "": golly.exit("Unsupported string: " + spec) if n < 2 or n > 255: golly.exit("Value of N must lie between 2 and 255.") # assemble the transitions nbors = {"vonNeumann": 4, "Moore": 8, "hexagonal": 6, "triangularVonNeumann": 3, "triangularMoore": 12} transitions = [] for sl in product(range(n), repeat=nbors[nhood]): transitions += [[range(n)] + [[s] for s in sl] + [[sum(sl) % n]]] rule_name = "Fredkin_mod" + str(n) + "_" + nhood Converters = { "vonNeumann": ConvertRuleTableTransitionsToRuleTree, "Moore": ConvertRuleTableTransitionsToRuleTree, "triangularVonNeumann": EmulateTriangular, "triangularMoore": EmulateTriangular,
# Use multiple layers to create a history of the current pattern. # The "envelope" layer remembers all live cells. # Author: Andrew Trevorrow ([email protected]), December 2006. # Updated for better compatibility with envelope.pl, June 2007. # Updated to use new setcolors command, September 2008. import golly as g if g.empty(): g.exit("There is no pattern.") currindex = g.getlayer() startindex = 0 envindex = 0 startname = "starting pattern" envname = "envelope" if currindex > 1 and g.getname(currindex - 1) == startname \ and g.getname(currindex - 2) == envname : # continue from where we left off startindex = currindex - 1 envindex = currindex - 2 elif currindex + 2 < g.numlayers() \ and g.getname(currindex + 1) == startname \ and g.getname(currindex) == envname : # switch from envelope layer to current layer and continue currindex += 2 g.setlayer(currindex) startindex = currindex - 1 envindex = currindex - 2
import golly as g import quiescentauton as q soupfilepath = "/home/scorbie/Apps/ptbtest/random" nsoups = int(g.getstring("How many soups?", "1000")) soupsize = 10 # int(g.getstring('Soup size?', '10')) if g.getrule() == "LifeHistory": g.setrule("B3/S23") if g.numstates() > 2: g.exit("This script only works with two-state rules.") soups = [] x, y, w, h = r = [0, 0, soupsize, soupsize] cellchar = [".", "a"] while len(soups) < nsoups: g.new("Generating Soups") g.select(r) g.randfill(40) g.run(250) # To avoid 'Empty Pattern!' messages in status bar. if int(g.getpop()) == 0: continue if not q.testquiescence(60): g.reset() soupstr = "!".join( "".join(cellchar[g.getcell(i, j)] for j in xrange(0, soupsize + 1)) for i in xrange(0, soupsize + 1) ) soups.append(soupstr) g.show("Soup {}/{}".format(len(soups), nsoups)) with open(soupfilepath, "w") as soupfile:
H = hexagonal, TM = triangular Moore) and the value of N (2-255). e.g. H2, N7 (Larger values of N can take a long time.) ''', 'N3', 'Enter specification:') # work out what the string meant nhood = '' nhoods = {'N':'vonNeumann','TM':'triangularMoore','M':'Moore', 'T':'triangularVonNeumann','H':'hexagonal'} for nh in nhoods.keys(): if nh in spec: nhood = nhoods[nh] n = int(spec.replace(nh,'')) break if nhood=='': golly.exit('Unsupported string: '+spec) if n<2 or n>255: golly.exit('Value of N must lie between 2 and 255.') # assemble the transitions nbors = {'vonNeumann':4,'Moore':8,'hexagonal':6,'triangularVonNeumann':3, 'triangularMoore':12} transitions = [] for sl in product(range(n),repeat=nbors[nhood]): transitions += [ [range(n)] + [[s] for s in sl] + [[sum(sl)%n]] ] rule_name = 'Fredkin_mod'+str(n)+'_'+nhood Converters = { "vonNeumann":ConvertRuleTableTransitionsToRuleTree, "Moore":ConvertRuleTableTransitionsToRuleTree, "triangularVonNeumann":EmulateTriangular,
# Make a pattern from states 1 and 0, select it and then # run this script to make a Codd CA pattern that will then # construct the pattern. The constructor will then attempt # to inject sheathing and triggering signals to a point one # up from the pattern's bottom-left corner. # # See example: Patterns/Codd/golly-constructor.rle # # Tim Hutton <*****@*****.**> from glife import rect from time import time import golly as g r = rect( g.getselrect() ) if r.empty: g.exit("There is no selection.") oldsecs = time() maxstate = g.numstates() - 1 # these are the commands: extend = '70116011' extend_left = '4011401150116011' extend_right = '5011501140116011' retract = '4011501160116011' retract_left = '5011601160116011' retract_right = '4011601160116011' mark = '701160114011501170116011' erase = '601170114011501160116011' sense = '70117011' cap = '40116011'
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() # ------------------------------------------------------------------------------ selrect = g.getselrect() if len(selrect) == 0: g.exit("There is no selection.") selpatt = g.getcells(selrect) # remember initial selection in case user aborts script firstrect = g.getselrect() firstpatt = g.getcells(selrect) g.show("Click anywhere in selection, move mouse and click again..." + helpmsg) oldcursor = g.getcursor() g.setcursor("Move") oldcells = [] try: aborted = True moveselection() aborted = False
def iscomment(line): return line.strip() == "" or line.lstrip().startswith("#") g.setrule("LifeHistory") try: currcats = [] with open(catfilename) as catfile: for line in catfile: if iscomment(line): # Organize all the previous cats. if currcats: currcat = reduce(operator.add, (cat.translate(0, idx * size) for idx, cat in enumerate(currcats))) cats.append(currcat) # Prepare new cat container currcats = [] else: currcats.append(glife.pattern(line)) currcat = reduce(operator.add, (cat.translate(0, idx * size) for idx, cat in enumerate(currcats))) cats.append(currcat) except: if catfilename == "": g.exit() else: raise totalpat = reduce(operator.add, (currcat.translate(idx * size, 0) for idx, currcat in enumerate(cats))) totalpat.put()
# (program length is mostly unrelated to machine size, so it all works) write_program(program) # write the data tape data_tape = '' rect = g.getrect() # copy everything within the bounding rectangle width = rect[2] height = rect[3] x = rect[0] y = rect[1] for row in inclusive_range(y+height-1,y): far_right = x+width-1 while g.getcell(far_right,row)==0: far_right -= 1 if far_right<x: g.exit('Empty rows forbidden: '+str(row)) col = x while col <= far_right: if g.getcell(col,row)==1: data_tape+='11' # write 1 col += 1 else: if not g.getcells([col,row,n,1]): # next N cells zero? data_tape+='01' col += n else: data_tape+='10' # write 0 col += 1 data_tape+='001' # end of row #data_tape+='000' # end of construction (actually we skip this command) write_data_string(data_tape[::-1])
# Shift current selection by given x y amounts using optional mode. # Author: Andrew Trevorrow ([email protected]), June 2006. # Updated to use exit command, Nov 2006. # Updated to check for bounded grid, Oct 2010. from glife import validint, inside from string import lower import golly as g selrect = g.getselrect() if len(selrect) == 0: g.exit("There is no selection.") answer = g.getstring("Enter x y shift amounts and an optional mode\n" + "(valid modes are copy/or/xor, default is or):", "0 0 or", "Shift selection") xym = answer.split() # extract x and y amounts if len(xym) == 0: g.exit() if len(xym) == 1: g.exit("Supply x and y amounts separated by a space.") if not validint(xym[0]): g.exit("Bad x value: " + xym[0]) if not validint(xym[1]): g.exit("Bad y value: " + xym[1]) x = int(xym[0]) y = int(xym[1]) # extract optional mode if len(xym) > 2: mode = lower(xym[2]) if mode=="c": mode="copy" if mode=="o": mode="or"
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() # ------------------------------------------------------------------------------ if len(g.getrect()) == 0: g.exit("There are no objects.") g.show("Click on or near live cell in object, move mouse and click again..." + helpmsg) oldcursor = g.getcursor() g.setcursor("Move") oldcells = [] # cells under moved object object = [] # cells in moving object object1 = [] # cells in initial object try: aborted = True moveobject() aborted = False finally: g.setcursor(oldcursor) if aborted:
edgeGlider = EdgeGlider() while PerformDelete(edgeGlider, curGunPeriod): edgeGlider = DevolveGlider(edgeGlider, curGunPeriod) for j in xrange(0, 4): maxBox = AppendBox(maxBox, g.getrect()) g.run(1) if i == 0: somegun = g.getcells(g.getrect()) return [BoxValue(maxBox), somegun, maxBox] cells = g.getcells(g.getrect()) curGunPeriod = PeriodCalculator() if curGunPeriod == -1: note("Failed to find gun period") g.exit("No gun found") edgeGlider = EdgeGlider() if edgeGlider == -1: g.note("Please orient the gun properly") g.exit("No glider found in bottom right corner") valueGun = GunArea(cells, curGunPeriod) g.show("The value = " + str(valueGun[0]) + ", The box = " + str(valueGun[2]) )
# use same file name as in goto.lua GotoINIFileName = g.getdir("data") + "goto.ini" previousgen = "" try: f = open(GotoINIFileName, 'r') previousgen = f.readline() f.close() if not validint(previousgen): previousgen = "" except: # should only happen 1st time (GotoINIFileName doesn't exist) pass gen = g.getstring("Enter the desired generation number,\n" + "or -n/+n to go back/forwards by n:", previousgen, "Go to generation") if len(gen) == 0: g.exit() elif gen == "+" or gen == "-": # clear the default savegen(GotoINIFileName, "") elif not validint(gen): g.exit('Sorry, but "' + gen + '" is not a valid integer.') else: # best to save given gen now in case user aborts script savegen(GotoINIFileName, gen) oldstep = g.getstep() goto(gen.replace(",","")) g.setstep(oldstep)
def ConvertTreeToRule(rule_name, total_states, icon_pixels): ''' Convert rule_name.tree to rule_name.rule and delete the .tree file. If rule_name.colors exists then use it to create an @COLORS section and delete the .colors file. If icon_pixels is supplied then add an @ICONS section. Format of icon_pixels (in this example there are 4 icons at each size): --------------------------------------------------------- | | | | | | | | | | | 31x31 | 31x31 | 31x31 | 31x31 | | | | | | | | | | | --------------------------------------------------------- | |.....| |.....| |.....| |.....| | 15x15 |.....| 15x15 |.....| 15x15 |.....| 15x15 |.....| | |.....| |.....| |.....| |.....| --------------------------------------------------------- |7x7|.........|7x7|.........|7x7|.........|7x7|.........| --------------------------------------------------------- The top layer of 31x31 icons is optional -- if not supplied (ie. the height is 22) then there are no gaps between the 15x15 icons. ''' rulepath = golly.getdir('rules')+rule_name+'.rule' treepath = golly.getdir('rules')+rule_name+'.tree' colorspath = golly.getdir('rules')+rule_name+'.colors' # get contents of .tree file try: treefile = open(treepath,'r') treedata = treefile.read() treefile.close() except: golly.exit('Failed to open .tree file: '+treepath) # if the .rule file already exists then only replace the @TREE section # so we don't clobber any other info added by the user if os.path.isfile(rulepath): ReplaceTreeSection(rulepath, treedata) os.remove(treepath) if os.path.isfile(colorspath): os.remove(colorspath) return # create a new .rule file rulefile = open(rulepath,'w') rulefile.write('@RULE '+rule_name+'\n\n') rulefile.write('@TREE\n\n') # append contents of .tree file, then delete that file rulefile.write(treedata) os.remove(treepath) # if .colors file exists then append @COLORS section and delete file if os.path.isfile(colorspath): colorsfile = open(colorspath,'r') rulefile.write('\n@COLORS\n\n') for line in colorsfile: if line.startswith('color') or line.startswith('gradient'): # strip off everything before 1st digit line = line.lstrip('colorgadient= \t') rulefile.write(line) colorsfile.close() os.remove(colorspath) # if icon pixels are supplied then append @ICONS section if len(icon_pixels) > 0: wd = len(icon_pixels[0]) ht = len(icon_pixels) iconsize = 15 # size of icons in top row if ht > 22: iconsize = 31 # 31x31 icons are present numicons = wd / iconsize # get colors used in all icons (we assume each icon size uses the same set of colors) colors, multi_colored = GetColors(icon_pixels, wd, ht) if len(colors) > 256: golly.warn('Icons use more than 256 colors!') rulefile.flush() rulefile.close() return if multi_colored: # create @COLORS section using color info in icon_pixels (not grayscale) rulefile.write('\n@COLORS\n\n') if numicons >= total_states: # extra icon is present so use top right pixel to set the color of state 0 R,G,B = icon_pixels[0][wd-1] rulefile.write('0 ' + str(R) + ' ' + str(G) + ' ' + str(B) + '\n') numicons -= 1 # set colors for each live state to the average of the non-black pixels # in each icon on top row (note we've skipped the extra icon detected above) for i in xrange(numicons): nbcount = 0 totalR = 0 totalG = 0 totalB = 0 for row in xrange(iconsize): for col in xrange(iconsize): R,G,B = icon_pixels[row][col + i*iconsize] if R > 0 or G > 0 or B > 0: nbcount += 1 totalR += R totalG += G totalB += B if nbcount > 0: rulefile.write(str(i+1) + ' ' + str(totalR / nbcount) + ' ' \ + str(totalG / nbcount) + ' ' \ + str(totalB / nbcount) + '\n') else: # avoid div by zero rulefile.write(str(i+1) + ' 0 0 0\n') # create @ICONS section using (r,g,b) triples in icon_pixels[row][col] rulefile.write('\n@ICONS\n') if ht > 22: # top row of icons is 31x31 CreateXPMIcons(colors, icon_pixels, 31, 0, 31, numicons, rulefile) CreateXPMIcons(colors, icon_pixels, 15, 31, 31, numicons, rulefile) CreateXPMIcons(colors, icon_pixels, 7, 46, 31, numicons, rulefile) else: # top row of icons is 15x15 CreateXPMIcons(colors, icon_pixels, 15, 0, 15, numicons, rulefile) CreateXPMIcons(colors, icon_pixels, 7, 15, 15, numicons, rulefile) rulefile.flush() rulefile.close()
# Change the entire pattern from emulated-Margolus states to N-state: from glife import rect import golly as g r = rect( g.getrect() ) if r.empty: g.exit("There is no pattern.") for row in xrange(r.top, r.top + r.height): for col in xrange(r.left, r.left + r.width): s = g.getcell(col,row) g.setcell(col, row, (s+s%2)/2-1)
# # 3 July 2007: added code to avoid errors in rules like Seeds, # where the Golly canonical form of the rule doesn't include a '/' # # Modified by Andrew Trevorrow, 20 July 2006 (faster, simpler and # doesn't change the current clipboard). # # Modified by Andrew Trevorrow, 5 October 2007 (metafied pattern is # created in a separate layer so we don't clobber the selection). import os import golly as g from glife import * selrect = g.getselrect() if len(selrect) == 0: g.exit("There is no selection.") # check that a layer is available for the metafied pattern; # if metafied layer already exists then we'll use that layername = "metafied" metalayer = -1 for i in xrange(g.numlayers()): if g.getname(i) == layername: metalayer = i break if metalayer < 0 and g.numlayers() == g.maxlayers(): g.exit("You need to delete a layer.") # note that getrule returns canonical rule string rulestr = g.getrule().split(":")[0] if (not rulestr.startswith("B")) or (rulestr.find("/S") == -1):
import golly import os from glife.ReadRuleTable import * from glife.RuleTree import * from glife.EmulateTriangular import * from glife.EmulateMargolus import * from glife.EmulateOneDimensional import * from glife.EmulateHexagonal import * # ask user to select .table file filename = golly.opendialog('Open a rule table to convert:', 'Rule tables (*.table)|*.table', golly.getdir('rules')) if len(filename) == 0: golly.exit() # user hit Cancel # add new converters here as they become available: Converters = { "vonNeumann":ConvertRuleTableTransitionsToRuleTree, "Moore":ConvertRuleTableTransitionsToRuleTree, "triangularVonNeumann":EmulateTriangular, "triangularMoore":EmulateTriangular, "Margolus":EmulateMargolus, "square4_figure8v":EmulateMargolus, "square4_figure8h":EmulateMargolus, "square4_cyclic":EmulateMargolus, "oneDimensional":EmulateOneDimensional, "hexagonal":EmulateHexagonal, } golly.show("Reading from rule table file...")
important[3], important[4])) pointer = [0, 0] instruction_pointer = "start" while True: command = commands[[i[0] for i in commands].index(instruction_pointer)] pointer = [pointer[0] + command[1], pointer[1] + command[2]] x = pointer[0] y = pointer[1] print(command, pointer) if golly.getcell(x, y): golly.fit() golly.exit() else: golly.setcell(x, y, 1) neighbours = [ golly.getcell(x - 1, y), golly.getcell(x + 1, y), golly.getcell(x, y - 1), golly.getcell(x, y + 1), ] if any(neighbours): instruction_pointer = command[3] else:
) != 0: # add eight neighbors of each ON cell to the mask if [pat[i] + x, pat[i + 1] + y] not in env: env.append([pat[i] + x, pat[i + 1] + y]) for i in range(0, len(pat), 2): if [pat[i], pat[i + 1]] in env: env.remove([pat[i], pat[i + 1]]) # take original pattern back out of mask # else: # with the reduced envelope, this will now happen, e.g. with *WSS singleton sparks # g.note("Technical error: " + str([pat[i],pat[i+1]])+ " not in envelope:" + str(env) + " \n\n" + str(pat)) return list(itertools.chain.from_iterable(env)) r = g.getselrect() if len(r) == 0: r = g.getrect() if len(r) == 0: g.exit("No pattern, nothing to do.") sel = g.getcells(r) if len(sel) == 0: g.exit("Nothing in selection.") if len(sel) % 2: g.exit("Can't do the rewinding trick on multistate rules.") all = g.getcells(g.getrect()) allcoords = [] for i in range(0, len(all), 2): allcoords.append([all[i], all[i + 1]]) # g.show("Processing object library...") odict = dict() for i in range(len(lib)): # g.show("Processing object " + lib[i][0]) # run and normalize each library object until a duplicate of the original pattern appears # The number of ticks to duplication, and the offset, give all the information needed to rewind... obj = g.parse(lib[i][1])
# Fill clicked region with current drawing state. # Author: Andrew Trevorrow ([email protected]), Jan 2011. import golly as g from time import time # avoid an unbounded fill if g.empty(): if g.getwidth() == 0 or g.getheight() == 0: g.exit("You cannot fill an empty universe that is unbounded!") else: # set fill limits to the pattern's bounding box # (these will be extended below if the grid is bounded) r = g.getrect() minx = r[0] miny = r[1] maxx = minx + r[2] - 1 maxy = miny + r[3] - 1 # allow filling to extend to the edges of bounded grid if g.getwidth() > 0: minx = -int(g.getwidth()/2) maxx = minx + g.getwidth() - 1 if g.getheight() > 0: miny = -int(g.getheight()/2) maxy = miny + g.getheight() - 1 # ------------------------------------------------------------------------------ def checkneighbor(x, y, oldstate): # first check if x,y is outside fill limits
import golly as g from bitstring import BitArray try: from PIL import Image from PIL import ImageSequence except: g.exit("You need to install PIL (Python Imaging Library).") fname = g.opendialog("Open File", "*.gif", "", "") if not len(fname): g.exit("") outfile = g.savedialog("Save RAW Data File", "*.*", "", "ROM.dat") if not len(outfile): g.exit("") image = Image.open(fname) buff = BitArray() for frame in ImageSequence.Iterator(image): frame = list(frame.convert("1").getdata()) for i in range(len(frame)): buff.append('0b0' if frame[i] & 0x1 else '0b1') # normalize to 256k if buff.length < 1 << 18: for i in range ((1 << 18 - 3) - (buff.length >> 3)): buff.append('0x00') elif buff.length > 1 << 18: del buff[(1 << 18) + 1 : buff.length]
return result userSpeed = g.getstring("Please enter step/period", "1/8") if userSpeed.split("/")[0] == 'c': userSpeed = userSpeed.replace("c", "1") else: userSpeed = userSpeed.replace("c", "") iniStep = int(userSpeed.split("/")[0]) iniPeriod = int(userSpeed.split("/")[1]) speed = float(iniStep) / iniPeriod if speed >= 0.25: g.exit("This speed should be strictly less than c/4") if (iniPeriod + 2 * iniStep) % 8 == 0: g.exit("This period and step are not supported: period + 2 * step, should not be 0 mod 8") if (iniPeriod - 2 * iniStep) % 8 == 0: g.exit("This period and step are not supported: period - 2 * step, should not be 0 mod 8") fenseY = 220 fenseX = 0 for k in xrange(1, 1000000): step = iniStep * k period = iniPeriod * k distBack = period / 2 + step
# so to get .cells file for new articles, first .rle files are created # and (manually) uploaded, then those same .rle files are downloaded again # the next time the script is run, and are used to make .cells files) import golly as g import urllib.request import re import os samplepath = g.getstring("Enter path to generate .rle and .cells files", "C:/users/{username}/Desktop/LW/") if samplepath == "C:/users/{username}/Desktop/LW/": g.note("Please run this script again and change the sample path to something that works on your system.\n\n" \ + "If the path you supply does not point to folders that you have permission to write to, " \ + "or if synthfile is not present, the data collection process will eventually fail with an error.") g.exit() outfolder = samplepath + "rle/" cellsfolder = samplepath + "cells/" rlefolder = samplepath + "rledata/" synthfolder = samplepath + "synthesis-costs/" synthfile = synthfolder + "synthesis-costs.txt" if not os.path.exists(samplepath): resp = g.getstring( "No folder exists at '" + samplepath + "'. Create it and subfolders?", "Yes") if resp.lower()[:1] == "y": os.makedirs( outfolder ) # this has no effect if folder(s) already present and/or contain files
# Invert all cell states in the current selection. # Author: Andrew Trevorrow ([email protected]), Jun 2006. # Updated to use exit command, Nov 2006. # Updated to use numstates command, Jun 2008. from glife import rect from time import time import golly as g r = rect( g.getselrect() ) if r.empty: g.exit("There is no selection.") oldsecs = time() maxstate = g.numstates() - 1 for row in xrange(r.top, r.top + r.height): # if large selection then give some indication of progress newsecs = time() if newsecs - oldsecs >= 1.0: oldsecs = newsecs g.update() # also allow keyboard interaction g.dokey( g.getkey() ) for col in xrange(r.left, r.left + r.width): g.setcell(col, row, maxstate - g.getcell(col, row)) if not r.visible(): g.fitsel()
# use name.tree to create name.rule (with no icons); # note that if name.rule already exists then we only replace the info in # the @TREE section to avoid clobbering any other info added by the user ConvertTreeToRule(name, n_states, []) golly.setalgo("RuleLoader") golly.setrule(name) golly.show("Created "+golly.getdir("rules")+name+".rule and switched to that rule.") except: import sys import traceback exception, msg, tb = sys.exc_info() golly.warn(\ '''To use this script, copy a Python format rule definition into the clipboard, e.g.: name = "ParityNWE" n_states = 5 n_neighbors = 4 # order for 4 neighbors is N, W, E, S, C def transition_function ( s ) : return ( s[0] + s[1] + s[2] ) % 5 For more examples, see the script file (right-click on it). ____________________________________________________ A problem was encountered with the supplied rule: '''+ '\n'.join(traceback.format_exception(exception, msg, tb))) golly.exit()
# Randomly fill cells in the current selection. # Author: Andrew Trevorrow ([email protected]), March 2011. import golly as g from glife import rect, validint from time import time from random import randint r = rect(g.getselrect()) if r.empty: g.exit("There is no selection.") maxlive = g.numstates() - 1 # use previous values if they exist inifilename = g.getdir("data") + "random-fill.ini" previousvals = "50 1 " + str(maxlive) try: f = open(inifilename, "r") previousvals = f.readline() f.close() except: # should only happen 1st time (inifilename doesn't exist) pass result = g.getstring( "Enter percentage minstate maxstate values\n" + "where the percentage is an integer from 0 to 100\n" + "and the state values are integers from 1 to " + str(maxlive) + "\n"
def ReadRuleTable(filename): ''' Return n_states, neighborhood, transitions e.g. 2, "vonNeumann", [[0],[0,1],[0],[0],[1],[1]] Transitions are expanded for symmetries and bound variables. ''' f = open(filename, 'r') vars = {} symmetry_string = '' symmetry = [] n_states = 0 neighborhood = '' transitions = [] numParams = 0 for line in f: if line[0] == '#' or line.strip() == '': pass elif line[0:9] == 'n_states:': n_states = int(line[9:]) if n_states < 0 or n_states > 256: golly.warn('n_states out of range: ' + n_states) golly.exit() elif line[0:13] == 'neighborhood:': neighborhood = line[13:].strip() if not neighborhood in SupportedSymmetries: golly.warn('Unknown neighborhood: ' + neighborhood) golly.exit() numParams = len(SupportedSymmetries[neighborhood].items()[0][1][0]) elif line[0:11] == 'symmetries:': symmetry_string = line[11:].strip() if not symmetry_string in SupportedSymmetries[neighborhood]: golly.warn('Unknown symmetry: ' + symmetry_string) golly.exit() symmetry = SupportedSymmetries[neighborhood][symmetry_string] elif line[0:4] == 'var ': line = line[4:] # strip var keyword if '#' in line: line = line[:line.find('#')] # strip any trailing comment # read each variable into a dictionary mapping string to list of ints entries = line.replace('=',' ').replace('{',' ').replace(',',' ').\ replace(':',' ').replace('}',' ').replace('\n','').split() vars[entries[0]] = [] for e in entries[1:]: if e in vars: vars[entries[0]] += vars[e] # vars allowed in later vars else: vars[entries[0]].append(int(e)) else: # assume line is a transition if '#' in line: line = line[:line.find('#')] # strip any trailing comment if ',' in line: entries = line.replace('\n', '').replace(',', ' ').replace(':', ' ').split() else: entries = list(line.strip()) # special no-comma format if not len(entries) == numParams: golly.warn('Wrong number of entries on line: ' + line + ' (expected ' + str(numParams) + ')') golly.exit() # retrieve the variables that repeat within the transition, these are 'bound' bound_vars = [ e for e in set(entries) if entries.count(e) > 1 and e in vars ] # iterate through all the possible values of each bound variable var_val_indices = dict(zip(bound_vars, [0] * len(bound_vars))) while True: ### AKT: this code causes syntax error in Python 2.3: ### transition = [ [vars[e][var_val_indices[e]]] if e in bound_vars \ ### else vars[e] if e in vars \ ### else [int(e)] \ ### for e in entries ] transition = [] for e in entries: if e in bound_vars: transition.append([vars[e][var_val_indices[e]]]) elif e in vars: transition.append(vars[e]) else: transition.append([int(e)]) if symmetry_string == 'permute' and neighborhood in PermuteLater: # permute all but C,C' (first and last entries) for permuted_section in permu2(transition[1:-1]): permuted_transition = [ transition[0] ] + permuted_section + [transition[-1]] if not permuted_transition in transitions: transitions.append(permuted_transition) else: # expand for symmetry using the explicit list for s in symmetry: tran = [transition[i] for i in s] if not tran in transitions: transitions.append(tran) # increment the variable values (or break out if done) var_val_to_change = 0 while var_val_to_change < len(bound_vars): var_label = bound_vars[var_val_to_change] if var_val_indices[var_label] < len(vars[var_label]) - 1: var_val_indices[var_label] += 1 break else: var_val_indices[var_label] = 0 var_val_to_change += 1 if var_val_to_change >= len(bound_vars): break f.close() return n_states, neighborhood, transitions
from glife import validint, inside from string import lower import golly as g import math rules = ("JvN29", "Nobili32", "Hutton32") rule = g.getrule () if rule not in rules: g.exit ("Invalid rule: " + rule + " (must be " + rules + ")") rect = g.getselrect () if len (rect) == 0: g.exit ("There is no selection.") answer = g.getstring("Enter direction to rotate in\n" + "(valid rotations are cw and ccw, default is cw):", "cw", "Rotate selection") if answer != "cw" and answer != "ccw": g.exit ("Unknown direction: " + answer + " (must be cw/ccw)") cells = g.getcells (rect) jvn_rotate = (( 9, 12, 11, 10), (13, 16, 15, 14), (17, 20, 19, 18), (21, 24, 23, 22)) def rotated (rotations, direction, state):
draw_line(x + barwd, 0, x + barwd, -barht, extrastate) if barht > 1: # fill bar with corresponding color x1 = x + 1 x2 = x + barwd - 1 for y in xrange(barht - 1): draw_line(x1, -(y + 1), x2, -(y + 1), state) if statecount[state] > 0: # show count on top of bar t, twd, tht = color_text(str(statecount[state]), extrastate) t.put(barwd * (state + 1) - barwd / 2 - twd / 2, -barht - tht - 3) # -------------------------------------------------------------------- if g.empty(): g.exit("There is no pattern.") if g.numstates() == 256: g.exit("No room for extra state.") # check that a layer is available for the histogram histname = "histogram" histlayer = -1 for i in xrange(g.numlayers()): if g.getname(i) == histname: histlayer = i break if histlayer == -1 and g.numlayers() == g.maxlayers(): g.exit("You need to delete a layer.") # use selection rect if it exists, otherwise use pattern bounds label = "Selection" r = rect(g.getselrect())
# 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)