Golly scripts
Re: Golly scripts
Is there any way to get Golly to write text (not RLE or pattern file) to a .txt file?
I've managed to modify the census script in this thread so it repeatedly generates and census-es loads of random soups, keeping a running total of each object it finds. So far I've managed to get it to output the cumulative results to the clipboard after each game, just by using things out of the scripting help file that came with Golly. But it'd be easier (and free up the clipboard while the script is running) if I could get it to export the results to a file every so often.
I can't help but feel that there's a really obvious way to do this that I'm missing...
I've managed to modify the census script in this thread so it repeatedly generates and census-es loads of random soups, keeping a running total of each object it finds. So far I've managed to get it to output the cumulative results to the clipboard after each game, just by using things out of the scripting help file that came with Golly. But it'd be easier (and free up the clipboard while the script is running) if I could get it to export the results to a file every so often.
I can't help but feel that there's a really obvious way to do this that I'm missing...
Re: Golly scripts
Have a look at savegen() in goto.py -- it has everything you need to write a line of text to a text file.Lewis wrote:Is there any way to get Golly to write text (not RLE or pattern file) to a .txt file?
Other parts of that script show how to read a single line back again.
Writing multiple lines takes a little more getting used to. Python's read() and readlines() functions do pretty much what you expect, but write() and writelines() tend to write everything into a single line of text -- you have to add "\n" characters to your text whenever you want to start a new line.
Let me know if you can't get something working.
Re: Golly scripts
Another quick question: is there any way to get a script to generate random soups with eight-way symmetry (ie. reflective symmetry in the horizontal, vertical and both diagonal axes) without using the copy/paste function (This is for the same census script as before).
So far I'm just using this kind of long winded method, which is just automating the way I'd do it by hand:
But this sometimes brings up "Could not copy text to clipboard" errors and things. I had a look at the 'Quadsymm' here which seemed to do a similar job, but I can't figure out how it does what it does, so I can't just modify it.
So far I'm just using this kind of long winded method, which is just automating the way I'd do it by hand:
Code: Select all
g.new("")
g.select([0,0,24,24])
g.randfill(5)
g.copy()
g.flip(0)
g.paste(0,0, "or")
g.copy()
g.flip(1)
g.paste(0,0, "or")
g.copy()
g.rotate(0)
g.paste(0,0, "or")
The savegen() function seems to be working fine, luckily Nathaniel's census script stores the object counts as one long line.dvgrn wrote:Let me know if you can't get something working.
Re: Golly scripts
The quick answer is "yes" -- use the optional transform coordinates on golly.putcells(), or just use golly.transform().Lewis wrote:Another quick question: is there any way to get a script to generate random soups with eight-way symmetry (ie. reflective symmetry in the horizontal, vertical and both diagonal axes) without using the copy/paste function...?
If you find you need sample code, I can write something up. The easy way might be to draw a triangle of cells starting at (0,0), and then put it into a variable:
pat=golly.getcells(golly.getrect())
Then
golly.putcells(pat,0,0,a,b,c,d)
for seven different a, b, c, d combinations corresponding to all the standard rotations and reflections.
Re: Golly scripts
Here is a prototype slow salvo search script in 22da. It produces a set of collisions between a glider and an oscillator the user selects.
Feel free to post comments and results in the thread for 22da.
Code: Select all
# Creates a set of collisions between a glider and another object,
# selected by the user.
import golly as g
from glife.base import *
rule("22da")
glider = pattern("o2$2bo$2o$2o2bo!")
oscillator = pattern(g.getcells(g.getselrect()))
def collision (i, j):
return glider + oscillator[i + 9] (-10 + j, 30)
all = pattern ()
for i in xrange (-7, 7):
for j in xrange (-9, 10):
all += collision (i, j) (100 * i, 100 * j)
all.display("synthesis")
Re: Golly scripts
Here is the new slow salvo synthesis search script, edited to find more syntheses.
Code: Select all
# Creates a set of collisions between a glider and another object,
# selected by the user.
import golly as g
from glife.base import *
rule("22da")
glider = pattern("o2$2bo$2o$2o2bo!")
osc = pattern(g.getcells(g.getselrect()))
def collision (i, j):
return glider + osc[i + 9] (-25 + j, 30)
all = pattern ()
for i in xrange (-9, 10):
for j in xrange (-9, 10):
all += collision (i, j) (100 * i, 100 * j)
all.display("synthesis")
Re: Golly scripts
Here is Python code to test whether the current pattern is "quiescent": that is,
consists solely of still lifes, oscillators, gliders and *WSSs, with
the gliders and *WSSs being so placed that they will never interact
with each other, or with any of the still lifes or oscillators.
To use the code, write a simple script such as:
consists solely of still lifes, oscillators, gliders and *WSSs, with
the gliders and *WSSs being so placed that they will never interact
with each other, or with any of the still lifes or oscillators.
Code: Select all
# Code to test whether the current pattern is "quiescent": that is,
# consists solely of still lifes, oscillators, gliders and *WSSs, with
# the gliders and *WSSs being so placed that they will never interact
# with each other, or with any of the still lifes or oscillators. The
# "period" argument to testquiescence determines the periods of
# oscillators that the function will recognise as oscillators: all
# periods that are divisors of the given period. So if period is 60,
# oscillators of periods 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 and 60 will
# be recognised as such. If there is an oscillator of period 7 or 8,
# for example, it will not be recognised and testquiescence will
# return <false>.
import golly as g
from glife import *
def testquiescence (period):
boundrect = g.getrect ()
clist, el, em, eh, sl, sm, sh, wl, wm ,wh, nl, nm, nh, se, sw, nw, ne = diviup (boundrect)
return quiescent (boundrect, period, clist, el, em, eh, sl, sm, sh, wl, wm ,wh, nl, nm, nh, se, sw, nw, ne)
def quiescent (boundrect, period, clist, el, em, eh, sl, sm, sh, wl, wm ,wh, nl, nm, nh, se, sw, nw, ne):
if boundrect == []:
boundrect = g.getrect ()
if boundrect != []:
boundrect[0] = boundrect [0] - 1
boundrect[1] = boundrect [1] - 1
boundrect[2] = boundrect [2] + 2
boundrect[3] = boundrect [3] + 2
eastcells = allcells (el + em + eh)
clist = clistdiff (clist, eastcells)
if clist == []:
return (True)
if (eastcells != []) and (max (clist[::2]) + (2 * (period + 1)) > min (eastcells[::2])):
return (False)
southcells = allcells (sl + sm + sh)
clist = clistdiff (clist, southcells)
if clist == []:
return (True)
if (southcells != []) and (max (clist[1::2]) + (2 * (period + 1)) > min (southcells[1::2])):
return (False)
westcells = allcells (wl + wm + wh)
clist = clistdiff (clist, westcells)
if clist == []:
return (True)
if (westcells != []) and (min (clist[::2]) - (2 * (period + 1)) < max (westcells[::2])):
return (False)
northcells = allcells (nl + nm + nh)
clist = clistdiff (clist, northcells)
if clist == []:
return (True)
if (northcells != []) and (min (clist[1::2]) - (2 * (period + 1)) < max (northcells[1::2])):
return (False)
secells = allcells (se)
clist = clistdiff (clist, secells)
if clist == []:
return (True)
if (secells != []) and \
(max ([clist [n] + clist [n+1] for n in range (0, len (clist) - 1, 2)]) + (2 * (period + 1)) > \
min ([secells [n] + secells [n+1] for n in range (0, len (secells) - 1, 2)])):
return (False)
swcells = allcells (sw)
clist = clistdiff (clist, swcells)
if clist == []:
return (True)
if (swcells != []) and \
(max ([clist [n+1] - clist [n] for n in range (0, len (clist) - 1, 2)]) + (2 * (period + 1)) > \
min ([swcells [n+1] - swcells [n] for n in range (0, len (swcells) - 1, 2)])):
return (False)
nwcells = allcells (nw)
clist = clistdiff (clist, nwcells)
if clist == []:
return (True)
if (nwcells != []) and \
(min ([clist [n] + clist [n+1] for n in range (0, len (clist) - 1, 2)]) - (2 * (period + 1)) < \
max ([nwcells [n] + nwcells [n+1] for n in range (0, len (nwcells) - 1, 2)])):
return (False)
necells = allcells (ne)
clist = clistdiff (clist, necells)
if clist == []:
return (True)
if (necells != []) and \
(max ([clist [n] - clist [n+1] for n in range (0, len (clist) - 1, 2)]) + (2 * (period + 1)) > \
min ([necells [n] - necells [n+1] for n in range (0, len (necells) - 1, 2)])):
return (False)
wssmove = period/2
if eastcells != []:
for n in range (0, len(eastcells) - 1, 2):
eastcells[n] += wssmove
if southcells != []:
for n in range (1, len(southcells), 2):
southcells[n] += wssmove
if westcells != []:
for n in range (0, len(westcells) - 1, 2):
westcells[n] -= wssmove
if northcells != []:
for n in range (1, len(northcells), 2):
northcells[n] -= wssmove
glimove = period/4
if secells != []:
for n in range (0, len (secells) - 1, 2):
secells[n] += glimove
secells[n+1] += glimove
if swcells != []:
for n in range (0, len (swcells) - 1, 2):
swcells[n] -= glimove
swcells[n+1] += glimove
if nwcells != []:
for n in range (0, len (nwcells) - 1, 2):
nwcells[n] -= glimove
nwcells[n+1] -= glimove
if necells != []:
for n in range (0, len (necells) - 1, 2):
necells[n] += glimove
necells[n+1] -= glimove
g.run (period)
boundrect[0] = boundrect [0] - period/2
boundrect[1] = boundrect [1] - period/2
boundrect[2] = boundrect [2] + period
boundrect[3] = boundrect [3] + period
newclist = g.getcells (boundrect)
checkclist = northcells + nwcells + necells + westcells + clist + eastcells + swcells + secells + southcells
return (clistssame (newclist, checkclist))
def allcells (listofrects):
clist = []
for rect in listofrects:
clist = clist + g.getcells (rect)
return (clist)
def clistdiff (clist1, clist2):
while clist2 != []:
for n in range (0, len (clist1) - 1, 2):
if clist2[0] == clist1[n] and clist2[1] == clist1[n+1]:
del clist1 [n:n+2]
break
clist2 = clist2 [2:]
return (clist1)
def clistssame (clist1, clist2):
if len (clist1) != len (clist2):
return (False)
while clist2 != []:
unmatched = True
for n in range (0, len (clist1) - 1, 2):
if clist2[0] == clist1[n] and clist2[1] == clist1[n+1]:
del clist1 [n:n+2]
unmatched = False
break
if unmatched:
return (False)
clist2 = clist2 [2:]
return (clist2 == [])
# Not currently in use.
def containingrect (listofrects):
if listofrects == []:
contrect = []
else:
firstrect = listofrects[0]
left = firstrect[0]
top = firstrect[1]
rightplus1 = firstrect[0] + firstrect[2]
bottomplus1 = firstrect[1] + firstrect[3]
for rect in listofrects[1:]:
left = min ([rect[0], left])
top = min ([rect[1], top])
rightplus1 = max ([rect[0] + rect[2], rightplus1])
bottomplus1 = max ([rect[1] + rect[3], bottomplus1])
#g.show (str ([left, top, rightplus1, bottomplus1]))
#ch = chr (8)
#while ch != chr (9):
# ch = g.getkey ()
contrect = [left, top, rightplus1 - left, bottomplus1 - top]
return (contrect)
# Note that when used on listofrects derived from diviup, this will
# return a rectangle with one empty layer of cells on the outside.
def diviup (boundrect):
clist = g.getcells (boundrect)
if clist == []:
g.show ("Empty pattern!")
el = list ()
em = list ()
eh = list ()
sl = list ()
sm = list ()
sh = list ()
wl = list ()
wm = list ()
wh = list ()
nl = list ()
nm = list ()
nh = list ()
se = list ()
sw = list ()
nw = list ()
ne = list ()
else:
boundrect[0] = boundrect [0] - 1
boundrect[1] = boundrect [1] - 1
boundrect[2] = boundrect [2] + 2
boundrect[3] = boundrect [3] + 2
el = matchpattern (lwsse0wrapped, 2, 1, 7, 6, boundrect) + \
matchpattern (lwsse1wrapped, 2, 1, 7, 6, boundrect) + \
matchpattern (lwsse2wrapped, 1, 1, 7, 6, boundrect) + \
matchpattern (lwsse3wrapped, 3, 1, 7, 6, boundrect)
em = matchpattern (mwsse0wrapped, 2, 1, 8, 7, boundrect) + \
matchpattern (mwsse1wrapped, 2, 1, 8, 6, boundrect) + \
matchpattern (mwsse2wrapped, 3, 1, 8, 7, boundrect) + \
matchpattern (mwsse3wrapped, 4, 1, 8, 6, boundrect)
eh = matchpattern (hwsse0wrapped, 2, 1, 9, 7, boundrect) + \
matchpattern (hwsse1wrapped, 2, 1, 9, 6, boundrect) + \
matchpattern (hwsse2wrapped, 3, 1, 9, 7, boundrect) + \
matchpattern (hwsse3wrapped, 5, 1, 9, 6, boundrect)
sl = matchpattern (lwsss0wrapped, 1, 1, 6, 7, boundrect) + \
matchpattern (lwsss1wrapped, 2, 1, 6, 7, boundrect) + \
matchpattern (lwsss2wrapped, 2, 1, 6, 7, boundrect) + \
matchpattern (lwsss3wrapped, 2, 1, 6, 7, boundrect)
sm = matchpattern (mwsss0wrapped, 2, 1, 7, 8, boundrect) + \
matchpattern (mwsss1wrapped, 2, 1, 6, 8, boundrect) + \
matchpattern (mwsss2wrapped, 2, 1, 7, 8, boundrect) + \
matchpattern (mwsss3wrapped, 2, 1, 6, 8, boundrect)
sh = matchpattern (hwsss0wrapped, 2, 1, 7, 9, boundrect) + \
matchpattern (hwsss1wrapped, 2, 1, 6, 9, boundrect) + \
matchpattern (hwsss2wrapped, 2, 1, 7, 9, boundrect) + \
matchpattern (hwsss3wrapped, 2, 1, 6, 9, boundrect)
wl = matchpattern (lwssw0wrapped, 1, 1, 7, 6, boundrect) + \
matchpattern (lwssw1wrapped, 3, 1, 7, 6, boundrect) + \
matchpattern (lwssw2wrapped, 2, 1, 7, 6, boundrect) + \
matchpattern (lwssw3wrapped, 2, 1, 7, 6, boundrect)
wm = matchpattern (mwssw0wrapped, 1, 1, 8, 7, boundrect) + \
matchpattern (mwssw1wrapped, 3, 1, 8, 6, boundrect) + \
matchpattern (mwssw2wrapped, 4, 1, 8, 7, boundrect) + \
matchpattern (mwssw3wrapped, 2, 1, 8, 6, boundrect)
wh = matchpattern (hwssw0wrapped, 1, 1, 9, 7, boundrect) + \
matchpattern (hwssw1wrapped, 3, 1, 9, 6, boundrect) + \
matchpattern (hwssw2wrapped, 4, 1, 9, 7, boundrect) + \
matchpattern (hwssw3wrapped, 2, 1, 9, 6, boundrect)
nl = matchpattern (lwssn0wrapped, 2, 1, 6, 7, boundrect) + \
matchpattern (lwssn1wrapped, 2, 1, 6, 7, boundrect) + \
matchpattern (lwssn2wrapped, 1, 1, 6, 7, boundrect) + \
matchpattern (lwssn3wrapped, 3, 1, 6, 7, boundrect)
nm = matchpattern (mwssn0wrapped, 3, 1, 7, 8, boundrect) + \
matchpattern (mwssn1wrapped, 2, 1, 6, 8, boundrect) + \
matchpattern (mwssn2wrapped, 1, 1, 7, 8, boundrect) + \
matchpattern (mwssn3wrapped, 3, 1, 6, 8, boundrect)
nh = matchpattern (hwssn0wrapped, 3, 1, 7, 9, boundrect) + \
matchpattern (hwssn1wrapped, 2, 1, 6, 9, boundrect) + \
matchpattern (hwssn2wrapped, 1, 1, 7, 9, boundrect) + \
matchpattern (hwssn3wrapped, 3, 1, 6, 9, boundrect)
se = matchpattern (gliderse0wrapped, 2, 1, 5, 5, boundrect) + \
matchpattern (gliderse1wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (gliderse2wrapped, 3, 1, 5, 5, boundrect) + \
matchpattern (gliderse3wrapped, 1, 1, 5, 5, boundrect)
sw = matchpattern (glidersw0wrapped, 2, 1, 5, 5, boundrect) + \
matchpattern (glidersw1wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (glidersw2wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (glidersw3wrapped, 3, 1, 5, 5, boundrect)
nw = matchpattern (glidernw0wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (glidernw1wrapped, 2, 1, 5, 5, boundrect) + \
matchpattern (glidernw2wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (glidernw3wrapped, 2, 1, 5, 5, boundrect)
ne = matchpattern (gliderne0wrapped, 1, 1, 5, 5, boundrect) + \
matchpattern (gliderne1wrapped, 2, 1, 5, 5, boundrect) + \
matchpattern (gliderne2wrapped, 2, 1, 5, 5, boundrect) + \
matchpattern (gliderne3wrapped, 1, 1, 5, 5, boundrect)
return (clist, el, em, eh, sl, sm, sh, wl, wm ,wh, nl, nm, nh, se, sw, nw, ne)
def matchpattern (patt, xsub, ysub, txsize, tysize, rectlist):
clist = g.getcells (rectlist)
lmr = []
while len (clist) > 0:
testrect = [clist[0] - xsub, clist[1] - ysub, txsize, tysize]
testpatt = g.getcells (testrect)
if len (patt) == len (testpatt):
z = 0
while z < len (testpatt):
testpatt [z] = testpatt [z] - testrect [0]
testpatt [z+1] = testpatt [z+1] - testrect [1]
z = z + 2
if patt == testpatt:
lmr = lmr + [testrect]
clist = clist [2:]
return (lmr)
block = pattern ("""
**
**
""")
hblinker = pattern ("""
***
""")
vblinker = pattern ("""
*
*
*
""")
gliderse0wrapped = pattern ("""
.....
..*..
...*.
.***.
.....
""")
gliderse1wrapped = pattern ("""
.....
.*.*.
..**.
..*..
.....
""")
gliderse2wrapped = pattern ("""
.....
...*.
.*.*.
..**.
.....
""")
gliderse3wrapped = pattern ("""
.....
.*...
..**.
.**..
.....
""")
glidersw0wrapped = pattern ("""
.....
..*..
.*...
.***.
.....
""")
glidersw1wrapped = pattern ("""
.....
.*.*.
.**..
..*..
.....
""")
glidersw2wrapped = pattern ("""
.....
.*...
.*.*.
.**..
.....
""")
glidersw3wrapped = pattern ("""
.....
...*.
.**..
..**.
.....
""")
glidernw0wrapped = pattern ("""
.....
.***.
.*...
..*..
.....
""")
glidernw1wrapped = pattern ("""
.....
..*..
.**..
.*.*.
.....
""")
glidernw2wrapped = pattern ("""
.....
.**..
.*.*.
.*...
.....
""")
glidernw3wrapped = pattern ("""
.....
..**.
.**..
...*.
.....
""")
gliderne0wrapped = pattern ("""
.....
.***.
...*.
..*..
.....
""")
gliderne1wrapped = pattern ("""
.....
..*..
..**.
.*.*.
.....
""")
gliderne2wrapped = pattern ("""
.....
..**.
.*.*.
...*.
.....
""")
gliderne3wrapped = pattern ("""
.....
.**..
..**.
.*...
.....
""")
lwsse0wrapped = pattern ("""
.......
..****.
.*...*.
.....*.
.*..*..
.......
""")
lwsse1wrapped = pattern ("""
.......
..**...
.****..
.**.**.
...**..
.......
""")
lwsse2wrapped = pattern ("""
.......
.*..*..
.....*.
.*...*.
..****.
.......
""")
lwsse3wrapped = pattern ("""
.......
...**..
.**.**.
.****..
..**...
.......
""")
lwsss0wrapped = pattern ("""
......
.*.*..
....*.
....*.
.*..*.
..***.
......
""")
lwsss1wrapped = pattern ("""
......
..**..
..***.
.*.**.
.***..
..*...
......
""")
lwsss2wrapped = pattern ("""
......
..*.*.
.*....
.*....
.*..*.
.***..
......
""")
lwsss3wrapped = pattern ("""
......
..**..
.***..
.**.*.
..***.
...*..
......
""")
lwssw0wrapped = pattern ("""
.......
.****..
.*...*.
.*.....
..*..*.
.......
""")
lwssw1wrapped = pattern ("""
.......
...**..
..****.
.**.**.
..**...
.......
""")
lwssw2wrapped = pattern ("""
.......
..*..*.
.*.....
.*...*.
.****..
.......
""")
lwssw3wrapped = pattern ("""
.......
..**...
.**.**.
..****.
...**..
.......
""")
lwssn0wrapped = pattern ("""
......
..***.
.*..*.
....*.
....*.
.*.*..
......
""")
lwssn1wrapped = pattern ("""
......
..*...
.***..
.*.**.
..***.
..**..
......
""")
lwssn2wrapped = pattern ("""
......
.***..
.*..*.
.*....
.*....
..*.*.
......
""")
lwssn3wrapped = pattern ("""
......
...*..
..***.
.**.*.
.***..
..**..
......
""")
mwsse0wrapped = pattern ("""
........
..*****.
.*....*.
......*.
.*...*..
...*....
........
""")
mwsse1wrapped = pattern ("""
........
..***...
.*****..
.***.**.
....**..
........
""")
mwsse2wrapped = pattern ("""
........
...*....
.*...*..
......*.
.*....*.
..*****.
........
""")
mwsse3wrapped = pattern ("""
........
....**..
.***.**.
.*****..
..***...
........
""")
mwsss0wrapped = pattern ("""
.......
..*.*..
.....*.
.*...*.
.....*.
..*..*.
...***.
.......
""")
mwsss1wrapped = pattern ("""
......
..**..
..***.
..***.
.*.**.
.***..
..*...
......
""")
mwsss2wrapped = pattern ("""
.......
..*.*..
.*.....
.*...*.
.*.....
.*..*..
.***...
.......
""")
mwsss3wrapped = pattern ("""
......
..**..
.***..
.***..
.**.*.
..***.
...*..
......
""")
mwssw0wrapped = pattern ("""
........
.*****..
.*....*.
.*......
..*...*.
....*...
........
""")
mwssw1wrapped = pattern ("""
........
...***..
..*****.
.**.***.
..**....
........
""")
mwssw2wrapped = pattern ("""
........
....*...
..*...*.
.*......
.*....*.
.*****..
........
""")
mwssw3wrapped = pattern ("""
........
..**....
.**.***.
..*****.
...***..
........
""")
mwssn0wrapped = pattern ("""
.......
...***.
..*..*.
.....*.
.*...*.
.....*.
..*.*..
.......
""")
mwssn1wrapped = pattern ("""
......
..*...
.***..
.*.**.
..***.
..***.
..**..
......
""")
mwssn2wrapped = pattern ("""
.......
.***...
.*..*..
.*.....
.*...*.
.*.....
..*.*..
.......
""")
mwssn3wrapped = pattern ("""
......
...*..
..***.
.**.*.
.***..
.***..
..**..
......
""")
hwsse0wrapped = pattern ("""
.........
..******.
.*.....*.
.......*.
.*....*..
...**....
.........
""")
hwsse1wrapped = pattern ("""
.........
..****...
.******..
.****.**.
.....**..
.........
""")
hwsse2wrapped = pattern ("""
.........
...**....
.*....*..
.......*.
.*.....*.
..******.
.........
""")
hwsse3wrapped = pattern ("""
.........
.....**..
.****.**.
.******..
..****...
.........
""")
hwsss0wrapped = pattern ("""
.......
..*.*..
.....*.
.*...*.
.*...*.
.....*.
..*..*.
...***.
.......
""")
hwsss1wrapped = pattern ("""
......
..**..
..***.
..***.
..***.
.*.**.
.***..
..*...
......
""")
hwsss2wrapped = pattern ("""
.......
..*.*..
.*.....
.*...*.
.*...*.
.*.....
.*..*..
.***...
.......
""")
hwsss3wrapped = pattern ("""
......
..**..
.***..
.***..
.***..
.**.*.
..***.
...*..
......
""")
hwssw0wrapped = pattern ("""
.........
.******..
.*.....*.
.*.......
..*....*.
....**...
.........
""")
hwssw1wrapped = pattern ("""
.........
...****..
..******.
.**.****.
..**.....
.........
""")
hwssw2wrapped = pattern ("""
.........
....**...
..*....*.
.*.......
.*.....*.
.******..
.........
""")
hwssw3wrapped = pattern ("""
.........
..**.....
.**.****.
..******.
...****..
.........
""")
hwssn0wrapped = pattern ("""
.......
...***.
..*..*.
.....*.
.*...*.
.*...*.
.....*.
..*.*..
.......
""")
hwssn1wrapped = pattern ("""
......
..*...
.***..
.*.**.
..***.
..***.
..***.
..**..
......
""")
hwssn2wrapped = pattern ("""
.......
.***...
.*..*..
.*.....
.*...*.
.*...*.
.*.....
..*.*..
.......
""")
hwssn3wrapped = pattern ("""
......
...*..
..***.
.**.*.
.***..
.***..
.***..
..**..
......
""")
Code: Select all
import sys
import golly as g
from glife import *
import quiescentauton as q
if q.testquiescence (60):
g.show ("quiescent")
else:
g.show ("active")
Re: Golly scripts
This script demonstrates usage of matrices to rotate patterns as cell lists in hexagonal rules. It takes the selection and pastes copies of it rotated by multiples of 60deg, as well as rotation followed by a flip. Because the rotation is around the origin the selection is translated to the origin, transformed and then translated back when pasted into the layer. The matrices could readily be used with glife but I haven't done so here.dvgrn wrote:In a regular square neighborhood rule, not hexagonal?codeholic wrote:Is there an easy way to rotate clockwise/counterclockwise a cell array?
putcells(), transform(), and parse() all have optional transform parameters. Sample usage -- draw something in a new universe between (0,0) and (99,99) before you run it:
But maybe golly.transform() is a better answer, if you want to put a cell array in and get a cell array out. (?)Code: Select all
import golly as g all=g.getcells(g.getrect()) g.putcells(all,100,0,0,-1,1,0) # clockwise turn g.putcells(all,0,100,0,1,-1,0) # counterclockwise g.putcells(all,100,100,-1,0,0,-1) # 180 degrees g.fit()
The essence of the trick is that in Golly's hexagonal neighbourhood - which is embedded within the Moore neighbourhood - rotation by 60 deg corresponds to a 90deg rotation and then a shear.
Code: Select all
# Hexagonal transformations
import golly as g
if g.empty(): g.exit("There is no pattern.")
rect = g.getselrect()
if len(rect) == 0: g.exit("There is no selection.")
x = rect[0] + rect[2]//2
y = rect[1] + rect[3]//2
clist = g.getcells(rect)
if (len(clist) % 2 == 0):
cellints = 2
else:
cellints = 3
pop = len(clist) // cellints
# Translate centre to origin
for ii in xrange(0, cellints*pop, cellints):
clist[ii] -= x
clist[ii+1] -= y
# Identity - I
g.putcells(clist, x, y, 1, 0, 0, 1)
# 60 cw - 90 cw then shear x
g.putcells(clist, x+30, y, 1, -1, 1, 0)
# 120 cw - 90 cw then shear y
g.putcells(clist, x+60, y, 0, -1, 1, -1)
# 180 - 180
g.putcells(clist, x+90, y, -1, 0, 0, -1)
# 120 ccw - 90 ccw then shear x
g.putcells(clist, x+120, y, -1, 1, -1, 0)
# 60 ccw - 90 ccw then shear y
g.putcells(clist, x+150, y, 0, 1, -1, 1)
# Swap xy - swap xy
g.putcells(clist, x, y+30, 0, 1, 1, 0)
# 60 ccw flip - flip x then shear x
g.putcells(clist, x+30, y+30, -1, 1, 0, 1)
# 120 ccw flip - flip x then shear y
g.putcells(clist, x+60, y+30, -1, 0, -1, 1)
# Swap xy flip - swap xy flip
g.putcells(clist, x+90, y+30, 0, -1, -1, 0)
# 120 cw flip - flip y then shear x
g.putcells(clist, x+120, y+30, 1, -1, 0, -1)
# 60 cw flip - flip y then shear y
g.putcells(clist, x+150, y+30, 1, 0, 1, -1)
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.
Semi-active here - recovering from a severe case of LWTDS.
Semi-active here - recovering from a severe case of LWTDS.
Re: Golly scripts
Blazingly fast LifeHistory2Life script:
And a script to add text in LifeHistory (state 4):
Those scripts are result of this discussion with dvgrn.
Code: Select all
#Blazingly fast LifeHistory to Life converter
#Creates special rule and run it for one generation then switch to Life
#Replace 2k + 1-> 1 and 2k -> 0
#Preserves step
import golly as g
import os
if not(g.getrule()[:11]=="LifeHistory" or g.getrule()=="HistoricalLife" or g.getrule()=="CBRLife"):
g.exit()
def CreateRule():
fname = os.path.join(g.getdir("rules"), "LifeHistory2Life.rule")
with open(fname, 'wb') as f:
f.write('@RULE LifeHistory2Life\n')
f.write('\n')
f.write('@TABLE\n')
f.write('n_states:7\n')
f.write('neighborhood:vonNeumann\n')
f.write('symmetries:none\n')
f.write('\n')
f.write('var a={0,1,2,3,4,5,6}\n')
f.write('var b={a}\n')
f.write('var c={a}\n')
f.write('var d={a}\n')
f.write('var f={a}\n')
f.write('\n')
f.write('1,a,b,c,d,1\n')
f.write('2,a,b,c,d,0\n')
f.write('3,a,b,c,d,1\n')
f.write('4,a,b,c,d,0\n')
f.write('5,a,b,c,d,1\n')
f.write('6,a,b,c,d,0\n')
CreateRule()
g.setrule("LifeHistory2Life")
g.run(1)
step = g.getstep()
g.setrule("B3/S23")
g.setalgo("HashLife")
g.setstep(step)
g.setgen("-1")
Code: Select all
import golly as g
from glife.text import make_text
if g.numstates() - 1 < 4:
g.exit("Please select LifeHistory rule")
val = g.getstring("Enter string to place in golly", "Write here", "String Selection")
t = make_text(val, "mono")
newt = []
cnt = 0
for i in t:
cnt += 1
newt.append(i)
if cnt % 2 == 0:
newt.append(4)
if len(newt) % 2 == 0:
newt.append(0)
if g.getselrect() == []:
g.putcells(newt)
else:
rect = g.getselrect()
g.putcells(newt, rect[0], rect[1])
Last edited by simsim314 on December 5th, 2014, 10:28 am, edited 1 time in total.
Re: Golly scripts
You can take care of the generation change very easily withsimsim314 wrote:Blazingly fast LifeHistory2Life script:
...
Those scripts are result of this discussion with dvgrn.
EDIT [from other thread] Notice this script is raising the generation by one. It's also sometimes for some reason shows the pattern in LifeHistory2Life rule instead of the original LifeHistory. I didn't manage to reproduce this bug, but it's sometimes happens.
g.setgen("-1")
Haven't seen the other problem yet. The code seems straightforward enough, so I'm not sure why the script would get interrupted there in the last few lines.
Re: Golly scripts
Change done to the script posted here. Thx.dvgrn wrote:g.setgen("-1")
It's not exactly interrupted. What happens is the script looks OK, but when you chose "reset" or "undo" option, sometimes it brings you back to the LifeHistory2Life state instead to LifeHistory. This is golly bug, that happens from time to time, sometimes the undo works fine and the reset fails and sometimes the opposite, but usually it works fine - so I couldn't find steps to reproduce the issue. Anyway using it for a while now, and in general it doesn't cause any issues.dvgrn wrote:Haven't seen the other problem yet. The code seems straightforward enough, so I'm not sure why the script would get interrupted there in the last few lines.
Re: Golly scripts
Ah, that problem. I've been trying to find steps to reproduce what I think is a related bug for years now. It happens rarely and apparently randomly, and usually you don't lose work -- there's generally some way to combine Reset, Undo and Redo to get back to where you were, more or less.simsim314 wrote:It's not exactly interrupted. What happens is the script looks OK, but when you chose "reset" or "undo" option, sometimes it brings you back to the LifeHistory2Life state instead to LifeHistory. This is golly bug, that happens from time to time, sometimes the undo works fine and the reset fails and sometimes the opposite, but usually it works fine - so I couldn't find steps to reproduce the issue. Anyway using it for a while now, and in general it doesn't cause any issues.dvgrn wrote:Haven't seen the other problem yet. The code seems straightforward enough, so I'm not sure why the script would get interrupted there in the last few lines.
But if you're doing a lot of editing combined with script-running, you can get into situations where as you step through Undo or Redo, changes to the universe are placed in the wrong locations relative to other features -- very strange. I suspect that this is somehow related to the incorrect-rule bug; at least, they both involve some kind of confusion in the Undo buffer.
Re: Golly scripts
Here is another script for glider roll-back in the spirit of last days ideas. It uses two rules, one converts gliders in 16 possible phases and orientations into a single state (and back), and then uses another rule to roll-back the "gliders" any amount of iterations, then the script switch it back to gliders and usual Life rule.
NOTE The script assumes gliders only. If you have something else, it will probably be deleted.
Code: Select all
import golly as g
import os
def CreateRules():
fname = os.path.join(g.getdir("rules"), "GliderDetection.rule")
with open(fname, 'wb') as f:
f.write('@RULE GliderDetection\n')
f.write('\n')
f.write('@TABLE\n')
f.write('n_states:18\n')
f.write('neighborhood:Moore\n')
f.write('symmetries:none\n')
f.write('\n')
f.write('var a = {0, 1}\n')
f.write('var b = {a}\n')
f.write('var c = {a}\n')
f.write('var d = {a}\n')
f.write('var e = {a}\n')
f.write('var f = {a}\n')
f.write('var g = {a}\n')
f.write('var h = {a}\n')
f.write('\n')
f.write('0,1,1,0,0,1,0,1,1,2\n')
f.write('1,1,0,0,1,0,1,1,0,3\n')
f.write('0,1,0,1,0,0,1,1,1,4\n')
f.write('1,1,1,0,1,0,0,1,0,5\n')
f.write('\n')
f.write('0,1,1,1,0,1,0,0,1,6\n')
f.write('1,1,0,1,1,0,1,0,0,7\n')
f.write('0,1,1,1,1,0,0,1,0,8\n')
f.write('1,1,0,1,0,0,1,0,1,9\n')
f.write('\n')
f.write('0,1,0,1,1,1,1,0,0,10\n')
f.write('1,0,1,1,0,1,0,0,1,11\n')
f.write('0,0,1,1,1,1,0,1,0,12\n')
f.write('1,0,0,1,0,1,1,0,1,13\n')
f.write('\n')
f.write('0,1,0,0,1,1,1,1,0,14\n')
f.write('1,0,1,0,0,1,0,1,1,15\n')
f.write('0,0,0,1,0,1,1,1,1,16\n')
f.write('1,0,1,0,1,1,0,1,0,17\n')
f.write('\n')
f.write('1,a,b,c,d,e,f,g,h,0\n')
f.write('\n')
f.write('\n')
f.write('0,0,0,0,13,0,0,0,0,1\n')
f.write('13,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,13,0,1\n')
f.write('0,0,13,0,0,0,0,0,0,1\n')
f.write('0,13,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,9,0,0,0,0,1\n')
f.write('0,0,0,0,0,9,0,0,0,1\n')
f.write('9,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,9,0,1\n')
f.write('0,0,9,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,0,0,12,0,0,1\n')
f.write('0,0,0,12,0,0,0,0,0,1\n')
f.write('12,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,12,0,1\n')
f.write('0,12,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,12,1\n')
f.write('\n')
f.write('0,0,0,0,0,8,0,0,0,1\n')
f.write('0,0,0,0,0,0,8,0,0,1\n')
f.write('0,0,0,8,0,0,0,0,0,1\n')
f.write('8,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,8,0,1\n')
f.write('0,0,0,0,0,0,0,0,8,1\n')
f.write('\n')
f.write('0,0,0,0,0,0,5,0,0,1\n')
f.write('0,0,0,0,0,5,0,0,0,1\n')
f.write('0,0,0,5,0,0,0,0,0,1\n')
f.write('5,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,5,1\n')
f.write('\n')
f.write('0,0,0,0,0,0,17,0,0,1\n')
f.write('0,0,0,17,0,0,0,0,0,1\n')
f.write('17,0,0,0,0,0,0,0,0,1\n')
f.write('0,17,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,17,1\n')
f.write('\n')
f.write('0,0,0,0,4,0,0,0,0,1\n')
f.write('0,0,0,0,0,4,0,0,0,1\n')
f.write('0,0,0,4,0,0,0,0,0,1\n')
f.write('4,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,4,0,1\n')
f.write('0,0,4,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,16,0,0,0,0,1\n')
f.write('0,0,0,16,0,0,0,0,0,1\n')
f.write('16,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,16,0,1\n')
f.write('0,0,16,0,0,0,0,0,0,1\n')
f.write('0,16,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,11,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,11,0,0,1\n')
f.write('11,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,11,0,1\n')
f.write('0,11,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,0,7,0,0,0,1\n')
f.write('7,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,7,0,1\n')
f.write('0,0,7,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,7,1\n')
f.write('\n')
f.write('0,0,0,0,0,10,0,0,0,1\n')
f.write('10,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,10,0,1\n')
f.write('0,0,10,0,0,0,0,0,0,1\n')
f.write('0,10,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,10,1\n')
f.write('\n')
f.write('0,0,0,0,6,0,0,0,0,1\n')
f.write('0,0,0,0,0,6,0,0,0,1\n')
f.write('0,0,0,0,0,0,6,0,0,1\n')
f.write('6,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,6,0,1\n')
f.write('0,6,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,0,3,0,0,0,1\n')
f.write('0,0,0,3,0,0,0,0,0,1\n')
f.write('3,0,0,0,0,0,0,0,0,1\n')
f.write('0,0,3,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,3,1\n')
f.write('\n')
f.write('0,0,0,0,15,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,15,0,0,1\n')
f.write('0,0,0,15,0,0,0,0,0,1\n')
f.write('15,0,0,0,0,0,0,0,0,1\n')
f.write('0,15,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,2,0,0,0,0,1\n')
f.write('0,0,0,0,0,2,0,0,0,1\n')
f.write('0,0,0,0,0,0,2,0,0,1\n')
f.write('0,0,0,2,0,0,0,0,0,1\n')
f.write('2,0,0,0,0,0,0,0,0,0\n')
f.write('0,2,0,0,0,0,0,0,0,1\n')
f.write('\n')
f.write('0,0,0,0,0,14,0,0,0,1\n')
f.write('0,0,0,14,0,0,0,0,0,1\n')
f.write('14,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,14,0,0,0,0,0,0,1\n')
f.write('0,14,0,0,0,0,0,0,0,1\n')
f.write('0,0,0,0,0,0,0,0,14,1\n')
fname = os.path.join(g.getdir("rules"), "GliderRunBack.rule")
with open(fname, 'wb') as f:
f.write('@RULE GliderRunBack\n')
f.write('\n')
f.write('@TABLE\n')
f.write('n_states:18\n')
f.write('neighborhood:Moore\n')
f.write('symmetries:none\n')
f.write('\n')
f.write('var a = {0, 1}\n')
f.write('var b = {a}\n')
f.write('var c = {a}\n')
f.write('var d = {a}\n')
f.write('var e = {a}\n')
f.write('var f = {a}\n')
f.write('var g = {a}\n')
f.write('var h = {a}\n')
f.write('\n')
f.write('2,0,0,0,0,0,0,0,0,5\n')
f.write('\n')
f.write('5,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,5,0,4\n')
f.write('\n')
f.write('4,0,0,0,0,0,0,0,0,3\n')
f.write('\n')
f.write('3,0,0,0,0,0,0,0,0,0\n')
f.write('0,3,0,0,0,0,0,0,0,2\n')
f.write('\n')
f.write('\n')
f.write('7,0,0,0,0,0,0,0,0,0\n')
f.write('0,7,0,0,0,0,0,0,0,6\n')
f.write('\n')
f.write('6,0,0,0,0,0,0,0,0,9\n')
f.write('\n')
f.write('9,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,9,0,0,0,0,0,8\n')
f.write('\n')
f.write('8,0,0,0,0,0,0,0,0,7\n')
f.write('\n')
f.write('\n')
f.write('11,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,11,0,0,0,10\n')
f.write('\n')
f.write('12,0,0,0,0,0,0,0,0,11\n')
f.write('\n')
f.write('13,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,13,0,0,0,0,0,12\n')
f.write('\n')
f.write('10,0,0,0,0,0,0,0,0,13\n')
f.write('\n')
f.write('\n')
f.write('14,0,0,0,0,0,0,0,0,17\n')
f.write('\n')
f.write('17,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,0,0,17,0,16\n')
f.write('\n')
f.write('16,0,0,0,0,0,0,0,0,15\n')
f.write('\n')
f.write('15,0,0,0,0,0,0,0,0,0\n')
f.write('0,0,0,0,0,15,0,0,0,14\n')
def GliderBack(num):
g.setrule("GliderDetection")
g.run(1)
g.setrule("GliderRunBack")
g.run(num)
g.setrule("GliderDetection")
g.run(1)
CreateRules()
s = g.getstring("How many generation run back?", "1", "Iteration Chooser")
try:
GliderBack(int(s))
g.setrule("B3/S23")
g.setalgo("HashLife")
except:
g.show("Failed to run back" + s + "generations")
Re: Golly scripts
That's basically the unique major bug in Golly -- does it still exist? I haven't noticed it recently, but then again I haven't done much manual pattern editing recently.But if you're doing a lot of editing combined with script-running, you can get into situations where as you step through Undo or Redo, changes to the universe are placed in the wrong locations relative to other features -- very strange. I suspect that this is somehow related to the incorrect-rule bug; at least, they both involve some kind of confusion in the Undo buffer.
What do you do with ill crystallographers? Take them to the mono-clinic!
Re: Golly scripts
I only see it when I'm a dozen edits deep in a really complicated construction -- and then it's always hopeless to reproduce the steps that led to the bug, because I can't reconstruct more than three or four steps back, and even those aren't exact.calcyman wrote:That's basically the unique major bug in Golly -- does it still exist? I haven't noticed it recently, but then again I haven't done much manual pattern editing recently.But if you're doing a lot of editing combined with script-running, you can get into situations where as you step through Undo or Redo, changes to the universe are placed in the wrong locations relative to other features -- very strange. I suspect that this is somehow related to the incorrect-rule bug; at least, they both involve some kind of confusion in the Undo buffer.
I believe I've seen it even in the latest beta that I'm running, which is a 2.7b2 that Andrew set up for me to try to catch another bug that I used to see all the time, having to do with menu and toolbars suddenly going transparent, and then getting fixed as soon as some window besides Golly gets and loses the focus. I don't think that bug's fixed either, but like you I haven't had time to build anything big and interesting recently.*
@simsim314: are you running Golly 2.6, or an earlier version? If it's 2.6, then at least the Undo bug related to scripts-doing-rule-changes has been seen in a recent build.
* The Demonoid spaceship is waiting in the wings, but it may have to wait for a while -- until after the new year at the very least.
Re: Golly scripts
Yep...dvgrn wrote:@simsim314: are you running Golly 2.6
--
If we talking about major golly bugs - so the most annoying bug is when I paste something into golly and it crushes, sometimes losing work. Maybe auto-save and crush recovery option would be nice addition. I couldn't manage to reproduce this bug, but it happens from time to time.
Re: Golly scripts
Simple glider pertrubation script:
Also here is glider gun scripts and p14-1000 updated collection in single rle:
Code: Select all
import golly as g
gld = g.parse("3o$o$bo!", -1, -1)
def Iterate(x, y, w, h, gld, pat, pw, ph, dx, dy):
d = ph * 3
for i in xrange(0, w):
for j in xrange(0, h):
for k in xrange(0, 4):
g.putcells(pat, -pw, 0 + d)
g.putcells(g.evolve(gld, k), -pw + x + i, y + j + d)
d += ph * 3
def ClearRect(x, y, w, h):
for i in xrange(0, w):
for j in xrange(0, h):
g.setcell(x + i, y + j, 0)
selRect = g.getselrect()
if selRect != []:
patW = selRect[2]
patH = selRect[3]
pat = g.getcells(selRect)
patDx = selRect[0]
patDy = selRect[1] + 4 * patH
else:
g.exit("Please select a pattern")
moving = True
selecting = False
val = g.getxy()
x = "a"
y = "a"
g.show("left click to place, right click to rotate")
g.update()
while True:
event = g.getevent()
if "click" in event:
if "left" in event:
if moving:
g.show("select area to petrub the glider")
moving = False
selecting = True
g.update()
elif "right" in event and moving:
ClearRect(x - 1, y - 1, 3, 3)
gld = g.transform(gld,0,0, 0, -1, 1, 0)
ClearRect(x - 1, y - 1, 3, 3)
g.putcells(gld, x, y)
elif "right" in event and selecting and g.getselrect() != []:
selrect = g.getselrect()
Iterate(selrect[0], selrect[1], selrect[2], selrect[3], gld, pat, patW, patH, patDx, patDy)
g.exit()
elif event == "" and moving and not selecting:
if g.getxy() != "":
val = g.getxy()
if x != "a":
ClearRect(x - 1, y - 1, 3, 3)
g.putcells(under)
if val == "":
continue
x = int(val.split()[0])
y = int(val.split()[1])
under = g.getcells([x - 1, y - 1, 3, 3])
g.putcells(gld, x, y)
g.update()
if selecting:
g.doevent(event)
if g.getselrect() != []:
g.show("Select perturbation area. Right mouse click to generate")
g.update()
Last edited by simsim314 on December 17th, 2014, 7:40 pm, edited 2 times in total.
Re: Golly scripts
Golly script that allows smart move of reflectors in golly (will iterate reflector back, allow move diagonally only in the correct orientation, of reflector's input):
Try it on this sample:
Code: Select all
#This script recognize set of reflectors, and allows only according movement, while iterating it.
#Written by Michael Simkin 2014
import golly as g
import copy
data = []
data.append(["2o5b2o$2o5bo$5bobo$5b2o$b2o$bobo$2bo2$5b3o$5b3o$5b3o$8b3o$8b3o$8b3o!", "P8 Reflector"])
data.append(["22b2o$22bo$11b2o7bobo$11bobo6b2o$6b2o4b3o$5bo2bo4b3o$7bo4b3o$3bo7bobo$2bob2o5b2o$2bo$b2o!", "P30 Reflector"])
data.append(["13bo$11b3o$10bo$10b2o3$18b2ob2o$19bob2o$19bo$11b2o4b3o$11b2o3bo3b2o$16b4o2bo$2b2o15bob2o$bobo12b3o2bo$bo13bo5bo$2o14b5o$18bo!", "Snark1"])
data.append(["13bo$11b3o$10bo$10b2o3$18b2o$19bo$19bob2o$11b2o4b3o2bo$11b2o3bo3b2o$16b4o$2b2o15bo$bobo12b3o$bo13bo$2o14b5o$20bo$18bo$18b2o!", "Snark2"])
def FindPeriod(obj):
evolved = g.evolve(obj, 1)
for i in xrange(1, 1000):
if str(evolved) == str(obj):
return i
evolved = g.evolve(evolved, 1)
return -1
def GetSize(obj):
maxX = -1
maxY = -1
minX = 1000
minY = 1000
for i in xrange(0, len(obj), 2):
if obj[i] > maxX:
maxX = obj[i]
if obj[i + 1] > maxY:
maxY = obj[i + 1]
if obj[i] < minX:
minX = obj[i]
if obj[i + 1] < minY:
minY = obj[i + 1]
return (maxX - minX, maxY - minY)
def GetTransList():
transList = []
for i in xrange(-1, 2, 2):
for j in xrange(-1, 2, 2):
transList.append((i, 0, 0, j))
transList.append((0, i, j, 0))
return transList
def GetObjectClickArray(obj, objName, t, period):
result = []
for i in xrange(0, len(obj), 2):
x = obj[i]
y = obj[i + 1]
l = copy.copy(obj)
for j in xrange(0, len(obj), 2):
l[j] -= x
l[j + 1] -= y
result.append([l, objName, t, period])
return result
def GetObjectArray(iniobj):
result = []
transList = GetTransList()
period = FindPeriod(iniobj[0])
for i in xrange(0, period):
obj = g.evolve(iniobj[0], i)
for t in transList:
dxx, dxy, dyx, dyy = t
curobj = g.transform(obj, 0, 0, dxx, dxy, dyx, dyy)
result.extend(GetObjectClickArray(curobj, iniobj[1], t, period))
return result
def IsObjectExists(objectArray, x, y):
for obj, objName, t, p in objectArray:
found = True
for i in xrange(0, len(obj), 2):
dx = obj[i]
dy = obj[i + 1]
if g.getcell(x + dx, y + dy) == 0:
found = False
break
if found:
return [obj, objName, x, y, t, p]
return None
def GetObjectByClick(event):
x = int(event.split()[1])
y = int(event.split()[2])
found = False
for i in [0, -1, 1, -2, 2]:
for j in [0, -1, 1]:
if found:
break
o = IsObjectExists(objectArray, x + i, y + j)
if o != None:
g.show("found!")
for k in xrange(0, len(o[0]), 2):
dx = o[0][k]
dy = o[0][k + 1]
g.setcell(x + i + dx, y + j + dy, 0)
found = True
g.update()
if found:
return o
else :
return None
def ClearRect(x, y, w, h):
for i in xrange(0, w):
for j in xrange(0, h):
g.setcell(x + i, y + j, 0)
def GetDirection(t):
dxx, dxy, dyx, dyy = t
if dxy == 0:
return dxx * dyy
else:
return dxy * dyx
def GetEvolveDirection(t):
dxx, dxy, dyx, dyy = t
if dxy == 0:
return -dxx
else:
return -dxy
def UpdateMove(d, w, h, x0, y0, p, t):
under = d[0]
obj = d[1]
x = d[2]
y = d[3]
if under != -1:
ClearRect(x - w, y - h, 2 * w + 1, 2 * h + 1)
g.putcells(under)
val = g.getxy()
if val == "":
return
x1 = int(val.split()[0])
y1 = y0 + GetDirection(t) * (x1 - x0)
d[0] = g.getcells([x1 - w, y1 - h, 2 * w + 1, 2 * h + 1])
#ClearRect(x1 - w, y1 - h, 2 * w + 1, 2 * h + 1)
g.putcells(g.evolve(obj, p + GetEvolveDirection(t) * ((4 * (x1 - x0)) % p)), x1, y1)
g.update()
d[2] = x1
d[3] = y1
def InitUpdateMove(obj, x, y):
return [-1, obj, x, y]
objectArray = []
for d in data:
objectArray.extend(GetObjectArray([g.parse(d[0]), d[1]]))
moving = False
g.show("Select known object with left click, exit with right click")
handling = False
while True:
event = g.getevent()
if handling:
continue
handling = True
if "click" in event:
if "right" in event:
g.show("finish smart movement")
g.exit()
if not moving:
found = GetObjectByClick(event)
if found != None:
p = found[5]
t = found[4]
curMove = InitUpdateMove(found[0], found[2], found[3])
g.show("Found: " + str(found[1]) + ", click left to place and continue, right to place and exit")
w, h = GetSize(found[0])
moving = True
else:
if "left" in event:
moving = False
g.show("Object moved, select known object with left click, exit with right click")
g.update()
if moving and event == "":
UpdateMove(curMove, w, h, found[2], found[3], p, t)
handling = False
Code: Select all
x = 298, y = 155, rule = B3/S23
234b2o3b2o$234b2o2bob3o$238bo4bo$234b4ob2o2bo$234bo2bobobob2o$237bobob
obo$238b2obobo$242bo2$228b2o$229bo7b2o$229bobo5b2o$230b2o7$240b2o$240b
o$241b3o$243bo15$214b2o$213bobo$215bo34$296bo$3o292bo$3o292b3o$3o10bo$
3b3o5b3o$3b3o4bo$3b3o4b2o264bo$276b3o$8bo270bo$7bobo268b2o$8b2o2b2o
136bobo$12b2o136b2o$151bo118b2o$270bo$267b2obo$267bo2b3o4b2o$268b2o3bo
3b2o$270b4o$270bo15b2o$271b3o12bobo$274bo13bo$269b5o14b2o$269bo$271bo$
270b2o11$116bo$116b3o$119bo$118b2o7$120b3o$119bo3bo$118bo5bo$118b2obob
2o6$123b2o$123bo$124b3o$126bo22$75b2o$74b2o$76bo!
Last edited by simsim314 on December 16th, 2014, 8:26 pm, edited 1 time in total.
Re: Golly scripts
Nice! This isn't quite out of beta yet -- e.g., the bounding box of the reflector will overwrite nearby objects, and sometimes a reflector is removed and not replaced anywhere (no doubt there's a reason for that, but I haven't figured out how I'm clicking wrong.) But it's a very nice start on the problem, anyway.simsim314 wrote:Golly script that allows smart move of reflectors in golly (will iterate reflector back, allow move diagonally only in the correct orientation, of reflector's input):...
If you're up for a little more of a challenge, a really nice improvement would be the ability to shift-click two or more reflectors and move them diagonally as a group, adjusting the phasing as before. Sample pattern for selecting one, two, three, or four reflectors:
Code: Select all
x = 106, y = 76, rule = B3/S23
29bobo$29b2o$30bo10$57bo$57b2o$56b2obo$55bo2b3o$45bo8bobobo$45b3o5bobo
bo$48bo2b3o2bo$47b2o3bob2o$o52b2o$3o47bo3bo$3bo45bobo$2b2o41b2o2b2o$
45b2o6$2b2o3b2o$5bo$2bo5bo$3b2ob2o$4bobo$5bo$5bo3$7b2o$7bo$8b3o$10bo$
46b2o$46bo$39bo4bobo$38bobo3b2o$38b2obo$38b2ob2o$38b2obo$27b2o9bobo$
26bobo10bo$26bo$25b2o4$96bo$94b3o$93bo$93b2o3$101b2o$102bo$102bob2o$
94b2o4b3o2bo$94b2o3bo3b2o$99b4o$85b2o15bo$84bobo12b3o$84bo13bo$83b2o
14b5o$103bo$101bo$101b2o!
Re: Golly scripts
Managed to reproduce few issues:
A: If you select the eater of this one, it leaves debris.
B: Double click and the pattern will disappear.
--
Anyway fixed the move issue (was dumb bug in the first place - I just over controlled the visualization):
EDIT Will gladly make Shift + click if you tell me how do I know whether shift is down or not?
EDIT2 I think it's not hard to lookup in the output diagonal in search for recognizable components. for starters it can just find the first living cell on the diagonal (with some width), if the living cell belong to recognizable component, will add it as well to movement object list.
EDIT3 Moved to other thread.
A: If you select the eater of this one, it leaves debris.
Code: Select all
x = 31, y = 20, rule = B3/S23
5$27b2o$27bo$19bo5bobo$18b4o3b2o$17b2obobo$16b3obo2bo$17b2obobo$8b2o8b
4o$7bobo9bo$7bo$6b2o!
--
Anyway fixed the move issue (was dumb bug in the first place - I just over controlled the visualization):
Code: Select all
#This script recognize set of reflectors, and allows only according movement, while iterating it.
#Written by Michael Simkin 2014
import golly as g
import copy
data = []
data.append(["2o5b2o$2o5bo$5bobo$5b2o$b2o$bobo$2bo2$5b3o$5b3o$5b3o$8b3o$8b3o$8b3o!", "P8 Reflector"])
data.append(["22b2o$22bo$11b2o7bobo$11bobo6b2o$6b2o4b3o$5bo2bo4b3o$7bo4b3o$3bo7bobo$2bob2o5b2o$2bo$b2o!", "P30 Reflector"])
data.append(["13bo$11b3o$10bo$10b2o3$18b2ob2o$19bob2o$19bo$11b2o4b3o$11b2o3bo3b2o$16b4o2bo$2b2o15bob2o$bobo12b3o2bo$bo13bo5bo$2o14b5o$18bo!", "Snark1"])
data.append(["13bo$11b3o$10bo$10b2o3$18b2o$19bo$19bob2o$11b2o4b3o2bo$11b2o3bo3b2o$16b4o$2b2o15bo$bobo12b3o$bo13bo$2o14b5o$20bo$18bo$18b2o!", "Snark2"])
def FindPeriod(obj):
evolved = g.evolve(obj, 1)
for i in xrange(1, 1000):
if str(evolved) == str(obj):
return i
evolved = g.evolve(evolved, 1)
return -1
def GetSize(obj):
maxX = -1
maxY = -1
minX = 1000
minY = 1000
for i in xrange(0, len(obj), 2):
if obj[i] > maxX:
maxX = obj[i]
if obj[i + 1] > maxY:
maxY = obj[i + 1]
if obj[i] < minX:
minX = obj[i]
if obj[i + 1] < minY:
minY = obj[i + 1]
return (maxX - minX, maxY - minY)
def GetTransList():
transList = []
for i in xrange(-1, 2, 2):
for j in xrange(-1, 2, 2):
transList.append((i, 0, 0, j))
transList.append((0, i, j, 0))
return transList
def GetObjectClickArray(obj, objName, t, period):
result = []
for i in xrange(0, len(obj), 2):
x = obj[i]
y = obj[i + 1]
l = copy.copy(obj)
for j in xrange(0, len(obj), 2):
l[j] -= x
l[j + 1] -= y
result.append([l, objName, t, period])
return result
def GetObjectArray(iniobj):
result = []
transList = GetTransList()
period = FindPeriod(iniobj[0])
for i in xrange(0, period):
obj = g.evolve(iniobj[0], i)
for t in transList:
dxx, dxy, dyx, dyy = t
curobj = g.transform(obj, 0, 0, dxx, dxy, dyx, dyy)
result.extend(GetObjectClickArray(curobj, iniobj[1], t, period))
return result
def IsObjectExists(objectArray, x, y):
for obj, objName, t, p in objectArray:
found = True
for i in xrange(0, len(obj), 2):
dx = obj[i]
dy = obj[i + 1]
if g.getcell(x + dx, y + dy) == 0:
found = False
break
if found:
return [obj, objName, x, y, t, p]
return None
def GetObjectByClick(event):
x = int(event.split()[1])
y = int(event.split()[2])
found = False
for i in [0, -1, 1, -2, 2]:
for j in [0, -1, 1]:
if found:
break
o = IsObjectExists(objectArray, x + i, y + j)
if o != None:
g.show("found!")
for k in xrange(0, len(o[0]), 2):
dx = o[0][k]
dy = o[0][k + 1]
g.setcell(x + i + dx, y + j + dy, 0)
found = True
g.update()
if found:
return o
else :
return None
def ClearRect(x, y, w, h):
for i in xrange(0, w):
for j in xrange(0, h):
g.setcell(x + i, y + j, 0)
def GetDirection(t):
dxx, dxy, dyx, dyy = t
if dxy == 0:
return dxx * dyy
else:
return dxy * dyx
def GetEvolveDirection(t):
dxx, dxy, dyx, dyy = t
if dxy == 0:
return -dxx
else:
return -dxy
def UpdateMove(d, w, h, x0, y0, p, t):
under = d[0]
obj = d[1]
x = d[2]
y = d[3]
if under != -1:
ClearRect(x - w, y - h, 2 * w + 1, 2 * h + 1)
g.putcells(under)
val = g.getxy()
if val == "":
return
x1 = int(val.split()[0])
y1 = y0 + GetDirection(t) * (x1 - x0)
d[0] = g.getcells([x1 - w, y1 - h, 2 * w + 1, 2 * h + 1])
#ClearRect(x1 - w, y1 - h, 2 * w + 1, 2 * h + 1)
g.putcells(g.evolve(obj, p + GetEvolveDirection(t) * ((4 * (x1 - x0)) % p)), x1, y1)
g.update()
d[2] = x1
d[3] = y1
def InitUpdateMove(obj, x, y):
return [-1, obj, x, y]
objectArray = []
for d in data:
objectArray.extend(GetObjectArray([g.parse(d[0]), d[1]]))
moving = False
g.show("Select known object with left click, exit with right click")
handling = False
while True:
event = g.getevent()
if handling:
continue
handling = True
if "click" in event:
if "right" in event:
g.show("finish smart movement")
g.exit()
if not moving:
found = GetObjectByClick(event)
if found != None:
p = found[5]
t = found[4]
curMove = InitUpdateMove(found[0], found[2], found[3])
g.show("Found: " + str(found[1]) + ", click left to place and continue, right to place and exit")
w, h = GetSize(found[0])
moving = True
else:
if "left" in event:
moving = False
g.show("Object moved, select known object with left click, exit with right click")
g.update()
if moving and event == "":
UpdateMove(curMove, w, h, found[2], found[3], p, t)
handling = False
EDIT2 I think it's not hard to lookup in the output diagonal in search for recognizable components. for starters it can just find the first living cell on the diagonal (with some width), if the living cell belong to recognizable component, will add it as well to movement object list.
EDIT3 Moved to other thread.
- Gustavo6046
- Posts: 647
- Joined: December 7th, 2013, 6:26 pm
- Location: Brazil.
Re: Golly scripts
Sorry but how do I get pyton dll? It says it didn't found Python library!
*yawn* What a nothing-to-do day! Let's be the only person in the world to do CGOL during boring times.
- Gustavo6046
- Posts: 647
- Joined: December 7th, 2013, 6:26 pm
- Location: Brazil.
Re: Golly scripts
Oh, thanks! But it says the site is down.
*yawn* What a nothing-to-do day! Let's be the only person in the world to do CGOL during boring times.
Re: Golly scripts
Keep trying, and maybe look around the Web for alternatives -- that link works fine on my machine.Gustavo6046 wrote:Oh, thanks! But it says the site is down.
You'll want the Python 2.7.x download, by the way, not the Python 3.x.