Example #1
0
def paste(g, fichier, x, y):
    g.addlayer()
    g.open(fichier)
    g.select([-1000, -1000, 2000, 2000])
    g.copy()
    g.dellayer()
    g.paste(x - 1000, y - 1000, 'or')
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
Example #3
0
def main():

    g.setstep(0)
    g.setalgo('QuickLife')

    velocity = g.getstring('Please specify velocity', '(2,1)c/6')
    a, b, p = parse_velocity(velocity)
    params = partial_derivatives(a, b, p)

    dvdx = params['dvdx']
    dudx = params['dudx']
    dvdy = params['dvdy']
    dudy = params['dudy']
    dvdt = params['dvdt']
    dudt = params['dudt']

    cells = []

    for t in xrange(p):

        things = g.getcells(g.getrect())
        things = zip(things[::2], things[1::2])
        cells += [(dudx * x + dudy * y + dudt * t,
                   dvdx * x + dvdy * y + dvdt * t) for (x, y) in things]
        g.step()

    g.setlayer(g.addlayer())
    g.putcells([x for y in cells for x in y])
Example #4
0
def golly_lhistory():

    ngens = int(g.getstring('How many generations to run the pattern?', '1'))

    d = threes_and_fours(0)

    g.setstep(0)
    for i in range(ngens):
        g.step()
        d.update(threes_and_fours(i + 1))

    exes = [k[0] for k in d]
    whys = [k[1] for k in d]
    zeds = [k[2] for k in d]

    minx = min(exes)
    maxx = max(exes)
    miny = min(whys)
    maxy = max(whys)

    width = (maxx - minx) + 10
    height = maxy - miny

    g.addlayer()
    g.setrule('Grills')

    for (k, v) in d.iteritems():

        x = (k[0] - minx) + (k[2] * width)
        y = k[1] - miny
        c = {3: LIVE_VARIABLE_STATE, 4: DEAD_VARIABLE_STATE}[v]
        g.setcell(x, y, c)

    for i in range(1, max(zeds) + 1):
        for j in range(height + 1):
            g.setcell(i * width - 5, j, VERTICAL_LINE_STATE)

    for i in range(max(zeds) + 1):
        g.setcell(i * width + 3, -3, ORIGIN_STATE)
        g.setcell(i * width + 3, -4, ZEROTH_GENERATION_STATE + i)
Example #5
0
def main():

    g.setstep(0)
    g.setalgo('QuickLife')

    velocity = g.getstring('Please specify velocity', '(2,1)c/6')
    a, b, p = parse_velocity(velocity)
    params = partial_derivatives(a, b, p)

    dvdy = params['dvdy']
    dudy = params['dudy']
    dvdt = params['dvdt']

    cells = g.getcells(g.getrect())
    cells = zip(cells[::2], cells[1::2])
    gcells = []

    for (u, v) in cells:
        for t in xrange(p):
            xp = dvdy * u - dudy * v - a * t
            yq = v - t * dvdt
            if (xp % p != 0):
                continue
            if (yq % dvdy != 0):
                continue
            x = xp // p
            y = yq // dvdy
            gcells.append((t, x, y))

    spacing = max([x for (_, x, _) in gcells]) - min([x for (_, x, _) in gcells])
    spacing += 10

    gcells = [(x + spacing * t, y) for (t, x, y) in gcells]

    g.setlayer(g.addlayer())
    g.putcells([x for y in gcells for x in y])
    g.fit()
Example #6
0
totalcells = sum(statecount)
if statecount[0] == counted: g.exit("Selection is empty.")

# save current layer's info before we switch layers
currname = g.getname()
currcursor = g.getcursor()
currcolors = g.getcolors()
currstates = g.numstates()
deads, deadr, deadg, deadb = g.getcolors(0)

# create histogram in separate layer
g.setoption("stacklayers", 0)
g.setoption("tilelayers", 0)
g.setoption("showlayerbar", 1)
if histlayer == -1:
    histlayer = g.addlayer()
else:
    g.setlayer(histlayer)

g.new(histname)
g.setcursor(currcursor)

# use a Generations rule so we can append extra state for drawing text & lines
g.setrule("//" + str(currstates + 1))
extrastate = currstates
currcolors.append(extrastate)
if (deadr + deadg + deadb) / 3 > 128:
    # use black if light background
    currcolors.append(0)
    currcolors.append(0)
    currcolors.append(0)
Example #7
0
# build a patch pattern based on the current rule
#  that fixes the appropriate broken eaters in the rules table
r1, r2 = rulestr.split("/")
if r1[:1] == "B":
    Bvalues, Svalues = r1.replace("B",""), r2.replace("S","")
elif r1[:1] == "S":
    Svalues, Bvalues = r1.replace("S",""), r2.replace("B","")
else:
    Svalues, Bvalues = r1, r2

# create metafied pattern in separate layer
if metalayer >= 0:
   g.setlayer(metalayer)         # switch to existing layer
else:
   metalayer = g.addlayer()      # create new layer

# set rule to Life
rule()

Brle = Srle = "b10$b10$b26$b10$b10$b26$b10$b10$b!"
for ch in Bvalues:
    ind = 32-int(ch)*4 # because B and S values are highest at the top!
    Brle = Brle[:ind] + "o" + Brle[ind+1:]
for ch in Svalues:
    ind = 32-int(ch)*4
    Srle = Srle[:ind] + "o" + Srle[ind+1:]
RuleBits = pattern(Brle, 148, 1404) + pattern(Srle, 162, 1406)

# load or generate the OFFcell tile:
OFFcellFileName = g.getdir("data") + "metapixel-OFF.rle"
    90,
    169,
    91,
    90,
    116,
    90,
    113,
    90
]  # 7move-29 -- widen the space between the two elbows
# The final number in each recipe below represents the amount of time that must elapse
#     before another recipe can be safely appended.
# To string recipes together, remove all leading "0"s except for the first, and
#     remove the final number from the last recipe to avoid a pi explosion at the end
#     (or append the elbowdestroy recipe to delete the elbow block completely).

g.addlayer()
g.setrule("LifeHistory")
g.putcells(g.transform(elbow, -5, -2))
g.setstep(4)
g.fit()
g.setmag(1)
makerecipe(recipe)
"""
# Sample recipes from slmake repository:  https://gitlab.com/apgoucher/slmake/blob/master/data/simeks/pp.txt

recipe = [0, 109, 90, 93, 91, 90, 90, 90, 90]    # elbowdestroy

# elbow duplicators
recipe = [0, 109, 91, 93, 91, 127, 91, 90, 145, 91, 90, 90, 146, 90, 91, 91, 92, 90]    # 7move9 7move-7
recipe = [0, 109, 90, 93, 91, 91, 90, 90, 100, 90, 90, 146, 96, 90, 90, 90, 92, 156, 144, 90]    # 7move19 0move-12
recipe = [0, 109, 91, 94, 91, 91, 128, 126, 90, 152, 91, 176, 125, 90, 90, 90, 91, 90, 90, 108, 90, 99, 90]    # 0move-4 0move-30
Example #9
0
    currindex += 1
    g.setlayer(currindex)
    startindex = currindex - 1
    envindex = currindex - 2

else:
    # start a new envelope using pattern in current layer
    if g.numlayers() + 1 > g.maxlayers():
        g.exit("You need to delete a couple of layers.")
    if g.numlayers() + 2 > g.maxlayers():
        g.exit("You need to delete a layer.")

    # get current layer's starting pattern
    startpatt = g.getcells(g.getrect())

    envindex = g.addlayer()       # create layer for remembering all live cells
    g.setcolors([-1,100,100,100]) # set all states to darkish gray
    g.putcells(startpatt)         # copy starting pattern into this layer

    startindex = g.addlayer()     # create layer for starting pattern
    g.setcolors([-1,0,255,0])     # set all states to green
    g.putcells(startpatt)         # copy starting pattern into this layer

    # move currindex to above the envelope and starting pattern
    g.movelayer(currindex, envindex)
    g.movelayer(envindex, startindex)
    currindex = startindex
    startindex = currindex - 1
    envindex = currindex - 2

    # name the starting and envelope layers so user can run script
Example #10
0
    return " " + get9char(minstr)


r = g.getselrect()
if r == []:
    g.exit("No selection.  Select something to find by fingerprint.")
g.fitsel()
r = g.getselrect()
if r == []:
    g.exit("No selection.  Select something to find by fingerprint.")

count = NUMLINES
outptrx, outptry, matches = 0, 0, 0
pat = g.getcells(r)

g.addlayer()  # do tests in a new layer, then put results there
hash = getoctohash(pat)
g.new("Output")
if pat != []:
    g.putcells(pat, -pat[0] - GRIDSIZE, -pat[1])

for i in range(10):
    s = "Scanning " + fingerprintfile + "_" + str(i) + ".txt"
    with open(fingerprintfile + "_" + str(i) + ".txt", "r") as f:
        for line in f:
            count -= 1
            if hash in line:
                matches += 1
                matchingpat = line[:line.index(" ")]
                g.putcells(g.parse(matchingpat), outptrx * GRIDSIZE,
                           outptry * GRIDSIZE)
Example #11
0
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:
        break
    hashlist.append(h)

layername = "recurrent plot"
poplayer = -1

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.")

if poplayer == -1:
    poplayer = g.addlayer()
else:
    g.setlayer(poplayer)
g.new(layername)

rp_plot(poplist)
Example #12
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)
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)
Example #14
0
# build a patch pattern based on the current rule
#  that fixes the appropriate broken eaters in the rules table
r1, r2 = rulestr.split("/")
if r1[:1] == "B":
    Bvalues, Svalues = r1.replace("B", ""), r2.replace("S", "")
elif r1[:1] == "S":
    Svalues, Bvalues = r1.replace("S", ""), r2.replace("B", "")
else:
    Svalues, Bvalues = r1, r2

# create metafied pattern in separate layer
if metalayer >= 0:
    g.setlayer(metalayer)  # switch to existing layer
else:
    metalayer = g.addlayer()  # create new layer

# set rule to Life
rule()

Brle = Srle = "b10$b10$b26$b10$b10$b26$b10$b10$b!"
for ch in Bvalues:
    ind = 32 - int(ch) * 4  # because B and S values are highest at the top!
    Brle = Brle[:ind] + "o" + Brle[ind + 1:]
for ch in Svalues:
    ind = 32 - int(ch) * 4
    Srle = Srle[:ind] + "o" + Srle[ind + 1:]
RuleBits = pattern(Brle, 148, 1404) + pattern(Srle, 162, 1406)

# load or generate the OFFcell tile:
OFFcellFileName = g.getdir("data") + "metapixel-OFF.rle"
Example #15
0
    else:
        clist = g.getcells(g.getselrect())
        sel = g.getselrect()
        for i in range(int(len(clist) / 3)):
            clist[3 * i] = clist[3 * i] - sel[0]
            clist[3 * i + 1] = clist[3 * i + 1] - sel[1]
        clist.insert(0, sel[2])
        clist.insert(1, sel[3])
        tile.append(clist)

        # tile.append(g.getcells(g.getselrect()))

if not tile == []:
    if int(g.getstring("make new layer?", "1")):
        try:
            newindex = g.addlayer()
            g.setlayer(newindex)
        except:
            g.show('too many layers')

    input = g.getstring('tilewidth', '100')
    wd = int(input)

    input = g.getstring('tile to take e.g.: 1,5,7,8,.....', 'all')
    poslist = input.split(',')
    if len(poslist) == 1:
        poslist = range(len(tile))
    else:
        for i in range(len(poslist)):
            poslist[i] = int(poslist[i])
Example #16
0
        if R != G or G != B: return True
    # grayscale
    return False

# --------------------------------------------------------------------

# check that a layer is available
if g.numlayers() == g.maxlayers():
    g.exit("You need to delete a layer.")

# WARNING: changing this prefix will require same change in icon-exporter.py
layerprefix = "imported icons for "
if g.getname().startswith(layerprefix):
    g.exit("You probably meant to run icon-exporter.py.")

g.addlayer()
rulename = g.getrule().split(":")[0]

# search for rulename.rule and import any icon data (also builds iconcolors)
import_icons(rulename)

if len(iconcolors) == 0 and ("-" in rulename) and not (rulename.endswith("-shared")):
    # rulename.rule has no icons and rulename contains a hyphen, so
    # 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 = ""
Example #17
0
def main ():
  g.update ()
  g.check (False)

  path = g.getstring ("Output directory:")
  files = glob.glob (os.path.join (path, "*.out"))

  mingls = g.getstring ("Min number of gliders at accept:")
  if mingls == "":
    mingl = 0
    minpop = 0
    maxpop = 1024
  else:
    mingl = int (mingls)
    minpops = g.getstring ("Min population except catalyzers:")
    if minpops == "":
      minpop = 0
      maxpop = 1024
    else:
      minpop = int (minpops)
      maxpop = int (g.getstring ("Max population except catalyzers:"))

  if g.getname () != "catbellman_temp":
    g.addlayer ()

  hashdir = {}
  catlist = []
  catix = 0

  g.new ("catbellman_temp")
  g.setrule ("LifeBellman")

  for fix, filename in enumerate (files):
    patt = g.getrect ()
    if patt != []:
      g.select (patt)
      g.clear (0)
  
    g.setgen ("0")
	
    with open(filename, 'r') as f:
      filetext = f.read ()
      if fix % 16 == 0:
        g.show ("Analysing " + str (fix) + "/" + str (len (files)))
		
      (gogen, glcnt) = convbellman (filetext, 0, 0)
      if gogen == -1:
	    gogen = 128
	  
      (use, hash) = analyse (gogen, glcnt, minpop, maxpop, mingl)

      if use:
        if not hash in hashdir:
          catlist.append ([])
          hashdir [hash] = catix
          catix += 1

        cat = hashdir [hash]
        catlist [cat].append (filetext)

  g.new ("catbellman_temp")
  g.setrule ("LifeBellman")

  fix = 0
  y = 0
  for cat in catlist:
    x = 96 * (len (cat) - 1)
    for filetext in cat:
      convbellman (filetext, x, y)
      x -= 96
      fix += 1
      if fix % 32 == 0:
        g.show ("Rendering " + str (fix) + "/" + str (len (files)))
        g.fit ()
        g.check (True)
        g.update ()
        g.check (False)

    y += 96

  g.show ("Done")
  g.fit ()
  g.setstep (-1)
  g.check (True)
Example #18
0
        fit_if_not_visible()
        g.update()
        g.show("Step %i of %i" % (i+1, numsteps))

fit_if_not_visible()

# save some info before we switch layers
stepsize = "%i^%i" % (g.getbase(), g.getstep())
pattname = g.getname()

# create population plot in separate layer
g.setoption("stacklayers", 0)
g.setoption("tilelayers", 0)
g.setoption("showlayerbar", 1)
if poplayer == -1:
    poplayer = g.addlayer()
else:
    g.setlayer(poplayer)
g.new(layername)

# use same rule but without any suffix (we don't want a bounded grid)
g.setrule(g.getrule().split(":")[0])

deadr, deadg, deadb = g.getcolor("deadcells")
if (deadr + deadg + deadb) / 3 > 128:
    # use black if light background
    g.setcolors([1,0,0,0])
else:
    # use white if dark background
    g.setcolors([1,255,255,255])
Example #19
0
    currindex += 1
    g.setlayer(currindex)
    startindex = currindex - 1
    envindex = currindex - 2

else:
    # start a new envelope using pattern in current layer
    if g.numlayers() + 1 > g.maxlayers():
        g.exit("You need to delete a couple of layers.")
    if g.numlayers() + 2 > g.maxlayers():
        g.exit("You need to delete a layer.")

    # get current layer's starting pattern
    startpatt = g.getcells(g.getrect())

    envindex = g.addlayer()  # create layer for remembering all live cells
    g.setcolors([-1, 100, 100, 100])  # set all states to darkish gray
    g.putcells(startpatt)  # copy starting pattern into this layer

    startindex = g.addlayer()  # create layer for starting pattern
    g.setcolors([-1, 0, 255, 0])  # set all states to green
    g.putcells(startpatt)  # copy starting pattern into this layer

    # move currindex to above the envelope and starting pattern
    g.movelayer(currindex, envindex)
    g.movelayer(envindex, startindex)
    currindex = startindex
    startindex = currindex - 1
    envindex = currindex - 2

    # name the starting and envelope layers so user can run script
Example #20
0
for x, y, z in cells:
    if x <= ox + offset // 2:
        if z == 3:
            example_cells.append(x - ox)
            example_cells.append(y - oy)
        elif z == 1:
            start_cells.append(x - ox)
            start_cells.append(y - oy)
    else:
        if z == 1:
            on_cells.append((x - ox - offset, y - oy))
        elif z == 2:
            off_cells.append((x - ox - offset, y - oy))

results_layer = g.addlayer()
g.setname("Results")
g.setrule("Life")
g.setalgo("QuickLife")
work_layer = g.addlayer()
g.setname("Work area")

g.putcells(start_cells)
g.putcells(example_cells)
g.run(delay)

if not all(g.getcell(x, y)
           for x, y in on_cells) or any(g.getcell(x, y) for x, y in off_cells):
    g.warn("Warning: the example pattern is not a solution")

results = 0