def popcount(sel=0): dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]} rule = g.getrule().split(':')[0] try: live_cells = dict_lc[rule] except: live_cells = range(1, g.numstates()) if not sel: clist = g.getcells(g.getrect()) else: clist = g.getcells(g.getselrect()) return sum(clist[2::3].count(x) for x in live_cells)
def randfill_mash(rectcoords, amt, statemap): newstate = g.getoption("drawingstate") # g.note('%s'%statemap) for i in range(rectcoords[0], rectcoords[0] + rectcoords[2]): for j in range(rectcoords[1], rectcoords[1] + rectcoords[3]): if (100 * random.random() < amt): try: g.show('processing %i,%i' % (i, j)) g.setcell(i, j, statemap[g.getcell(i, j)]) except: dict_lc = [1] * g.numstates() dict_lc[0] = 0 dict_lc[1:3] = [2, 2] g.setcell(i, j, dict_lc[g.getcell(i, j)]) else: # g.setcell(i, j, 0) continue
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:
phase = -delay % 4 n = (delay + phase) // 4 for cells, dx, dy in obj_list: pat += g.transform(g.evolve(cells, phase), -n * dx, -n * dy) return pat def post_state(current_state, obj_list, delay): new_state = delay_construction(obj_list, delay) return g.evolve(current_state + new_state, delay + 256) if len(g.getrect()) == 0: if g.numstates() > 2: g.setrule("Life") # Script has been run starting from an empty universe. # Display a sample continuous synthesis starting from an incremental 46P4H1V0 synthesis. fill_void() g.select([]) if g.numstates() > 2: g.exit( "Please start this script with a two-state universe as the current layer." ) objs = [] add_it(objs, '3o$2bo$bo!', 1, -1) add_it(objs, '3o$o$bo!', -1, -1) add_it(objs, 'bo$2bo$3o!', 1, 1)
# 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 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)
if g.empty(): g.exit("There is no pattern.") prect = g.getrect() srect = g.getselrect() if len(srect) > 0: prect = srect # save selection rather than pattern x = prect[0] y = prect[1] wd = prect[2] ht = prect[3] # prevent Image.new allocating a huge amount of memory if wd * ht >= 100000000: g.exit("Image area is restricted to < 100 million cells.") # create RGB image filled initially with state 0 color multistate = g.numstates() > 2 colors = g.getcolors() # [0,r0,g0,b0, ... N,rN,gN,bN] g.show("Creating image...") im = Image.new("RGB", (wd, ht), (colors[1], colors[2], colors[3])) # get a row of cells at a time to minimize use of Python memory cellcount = 0 for row in xrange(ht): cells = g.getcells([x, y + row, wd, 1]) clen = len(cells) if clen > 0: inc = 2 if multistate: # cells is multi-state list (clen is odd) inc = 3 if clen % 3 > 0: clen -= 1 # ignore last 0
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 xrange(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)
# 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' inject_sheath = '701150116011' inject_trigger = '60117011701160116011' # (sometimes you don't need two blanks after each command but I haven't analysed this fully)
def popcount(): clist = g.getcells(g.getrect()) return sum(clist[2::3].count(x) for x in live_cells) vars = g.getstring( "yVar/yxVar, \n pop=population,\n gen=generation,\n boxy=width of bounding box,\n boxx=height of bounding box,\n density=population/area of bindingbox ,\n area=area of bounding box", "pop/gen") dict_lc = {'BDRainbow': [2, 4], 'BGRainbowR2': [2, 4]} try: live_cells = dict_lc[g.getrule().split(':')[0]] except: live_cells = range(1, g.numstates()) dict_f = {'popc':popcount,'pop': g.getpop, 'gen': g.getgen,'boxx':lambda:boxdm(2) ,'boxy': lambda: boxdm(3),'area':area,'density':density, \ 'logpop':lambda:float(math.log(float(g.getpop()))/math.log(2)),'popi':lambda:int(1000000000/float(g.getpop())), 'areai':lambda:int(1000000000/float(int(boxdm(2))*int(boxdm(3))))} dict_t={'popc':'Population','pop':'Population','gen':'Generation','boxx':'Box width','boxy':'Box height','area':'Box area','density':'Cell density (0.001)',\ 'logpop':'log(pop)','popi':'inverse of pop','areai':'inverse of area'} yfunc = dict_f[vars.split("/")[0]] xfunc = dict_f[vars.split("/")[1]] ytitle = dict_t[vars.split("/")[0]] xtitle = dict_t[vars.split("/")[1]] poplist = [int(yfunc())] genlist = [int(xfunc())] xlimlist = [int(g.getrect()[1])] oldsecs = time() for i in xrange(numsteps): g.step()
return stats1, stats2 # find an {outdir}-traveling glider equivalent to one with the statistics in statlist def findcanonical(statslist, outdir): dir, phase, x, y = statslist dphase, dx, dy = equivdict[dir] dphaseout, dxout, dyout = equivdict[outdir] # this is really all two-state arithmetic, so + vs. - below doesn't actually matter return [ outdir, (phase + dphase - dphaseout) % 4, x + dx - dxout, y + dy - dyout ] if g.numstates() != 2: g.exit( "Please convert to standard two-state Life before running this script." ) clist = g.getcells(g.getselrect()) if len(clist) != 20: g.exit("Please select a rectangle containing the two gliders to be synchronized, and nothing else." \ + "\nThere should be at least a four-cell gap between the gliders horizontally and vertically.") while 1: # iterate until we find NW0 stats1, stats2 = findgliders(clist) canonical1 = findcanonical(stats1, "NW") canonical2 = findcanonical(stats2, "SE") if canonical1[1] == 0: break clist = g.evolve(clist, 1) dir1, phase1, x1, y1 = canonical1 dir2, phase2, x2, y2 = canonical2
# check if prefix-shared.rule exists and ask user if they want to edit # the icons in that file sharedname = check_for_shared_rule(rulename) if len(sharedname) > 0: rulename = sharedname import_icons(rulename) iconnote = "" if len(iconcolors) == 0: iconnote = "There are currently no icons for this rule.\n\n" # check if icons are grayscale grayscale_icons = not multi_color_icons(iconcolors) g.new(layerprefix + rulename) livestates = g.numstates() - 1 deadcolor = g.getcolors(0) deadrgb = (deadcolor[1], deadcolor[2], deadcolor[3]) # switch to a Generations rule so we can have lots of colors g.setrule("//256") if grayscale_icons and deadrgb == (255,255,255): # if icons are grayscale and state 0 color was white then switch # to black background to avoid confusion (ie. we want black pixels # to be transparent) g.setcolors([0,0,0,0]) else: g.setcolors(deadcolor) graystate = init_colors() # if icons are grayscale then change deadrgb to black so that draw_icons
if g.empty(): g.exit("There is no pattern.") prect = g.getrect() srect = g.getselrect() if len(srect) > 0: prect = srect # save selection rather than pattern x = prect[0] y = prect[1] wd = prect[2] ht = prect[3] # prevent Image.new allocating a huge amount of memory if wd * ht >= 100000000: g.exit("Image area is restricted to < 100 million cells.") # create RGB image filled initially with state 0 color multistate = g.numstates() > 2 colors = g.getcolors() # [0,r0,g0,b0, ... N,rN,gN,bN] g.show("Creating image...") im = Image.new("RGB", (wd,ht), (colors[1],colors[2],colors[3])) # get a row of cells at a time to minimize use of Python memory cellcount = 0 for row in xrange(ht): cells = g.getcells( [ x, y + row, wd, 1 ] ) clen = len(cells) if clen > 0: inc = 2 if multistate: # cells is multi-state list (clen is odd) inc = 3 if clen % 3 > 0: clen -= 1 # ignore last 0
def testShip(rlepatt, rule, maxgen=2000): # Clear the layer and place the ship r = g.getrect() if rlepatt: patt = g.parse(rlepatt) # If rlepatt is in a multistate representation then patt will be # a multistate cell list. testShip() only works for ships in two # state rules, so convert to two state cell list. if (len(patt) % 2): # This assumes all cells have non-zero state - which is reasonable # for the results of g.parse() patt = [patt[i] for j, i in enumerate(patt[:-1]) if (j + 1) % 3] else: # Use the current pattern if not r: return (0, tuple()) patt = g.getcells(r) patt = g.transform(patt, -r[0], -r[1]) # g.note(str((rlepatt, rule))) if r: g.select(r) g.clear(0) g.putcells(patt) # g.note(str(len(patt)) + ", " + str(patt)) # rlepatt might be different to the rle representation determined by # giveRLE(), so ensure we have the correct representation testrle = giveRLE(patt) if rule: g.setrule(rule) speed = () startpop = int(g.getpop()) bbox = g.getrect() minpop = startpop minbboxarea = bbox[2] * bbox[3] mingen = 0 # Keep track of the total bbox maxx = bbox[2] maxy = bbox[3] maxpop = startpop # Ignore ship if rule is not a 2-state rule if not g.numstates() == 2: return (minpop, speed) for ii in xrange(maxgen): g.run(1) r = g.getrect() if not r: # Pattern has died out and is therefore not a ship mingen = 0 break pop = int(g.getpop()) bboxarea = r[2] * r[3] if pop < minpop: # Find phase with minimimum population minpop = pop minbboxarea = r[2] * r[3] mingen = ii + 1 elif pop == minpop: # Amongst phases with min pop, find one with minimum bbox area # bboxarea = r[2]*r[3] if bboxarea < minbboxarea: minbboxarea = bboxarea mingen = ii + 1 # Track the bounding box of the pattern's evolution maxx = max(maxx, r[2]) maxy = max(maxy, r[3]) maxpop = max(maxpop, pop) if (pop == startpop and r[2:4] == bbox[2:4]): if (giveRLE(g.getcells(r)) == testrle): # Starting ship has reappeared speed = (r[0] - bbox[0], r[1] - bbox[1], ii + 1 ) # displacement and period break # Check for rotated pattern elif (pop == startpop and r[2:4] == bbox[3:1:-1]): # For 2-cell oscillators this is sufficient if minpop == 2: speed = (0, 0, 2 * (ii + 1)) mingen = ii + 1 break g.run(mingen) # Evolve ship to generation with minimum population # return (minpop, speed) # return (minpop, speed, maxpop) return (minpop, speed, maxx * maxy)
# 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' inject_sheath = '701150116011' inject_trigger = '60117011701160116011' # (sometimes you don't need two blanks after each command but I haven't analysed this fully)
g.putcells(background) offset = max(background[1::2]) + 4 for glider, delta in gliderlist: clist, lane = glider g.putcells(clist, (lane + 1) // 2 + offset, offset) offset += delta g.setalgo("HashLife") glist = [ Glider("3o$o$bo!",0,0), Glider("bo$2o$obo!",1,-2), \ Glider("2o$obo$o!",2,-1), Glider("b2o$2o$2bo!",3,-1) ] gliderE, gliderO = g.transform(glist[0].clist, -glist[0].dx, 0), g.transform( glist[1].clist, -glist[1].dx, 0) # glist[0].clist, glist[1].clist if g.numstates() > 2: g.exit("Please use a two-state rule.") r = g.getrect() if len(r) == 0: g.exit("No pattern found.") nongliderpat, ngp3, recipelist, recipe, remainder, count = [], [], [], "", g.getcells( r), 0 all = remainder while len(remainder): matchflag = 0 for index in range(len(glist)): glider = glist[index] if g.getkey() == "q": g.exit() TLx, TLy = remainder[0], remainder[1] matchflag = matches(glider, TLx, TLy)
# Creates a histogram plot showing the frequencies of all cell states # in the current selection (if one exists) or the entire pattern. # Author: Andrew Trevorrow ([email protected]), September 2009. import golly as g import math from glife import getminbox, rect, rccw, pattern from glife.text import make_text from time import time # -------------------------------------------------------------------- barwd = 40 # width of each bar # length of axes xlen = g.numstates() * barwd ylen = 500 totalcells = 0 # -------------------------------------------------------------------- def draw_line(x1, y1, x2, y2, state=1): # draw a line of cells in given state from x1,y1 to x2,y2 # using Bresenham's algorithm g.setcell(x1, y1, state) if x1 == x2 and y1 == y2: return dx = x2 - x1 ax = abs(dx) * 2
# check if prefix-shared.rule exists and ask user if they want to edit # the icons in that file sharedname = check_for_shared_rule(rulename) if len(sharedname) > 0: rulename = sharedname import_icons(rulename) iconnote = "" if len(iconcolors) == 0: iconnote = "There are currently no icons for this rule.\n\n" # check if icons are grayscale grayscale_icons = not multi_color_icons(iconcolors) g.new(layerprefix + rulename) livestates = g.numstates() - 1 deadcolor = g.getcolors(0) deadrgb = (deadcolor[1], deadcolor[2], deadcolor[3]) # switch to a Generations rule so we can have lots of colors g.setrule("//256") if grayscale_icons and deadrgb == (255, 255, 255): # if icons are grayscale and state 0 color was white then switch # to black background to avoid confusion (ie. we want black pixels # to be transparent) g.setcolors([0, 0, 0, 0]) else: g.setcolors(deadcolor) graystate = init_colors() # if icons are grayscale then change deadrgb to black so that draw_icons