Script request thread

For scripts to aid with computation or simulation in cellular automata.
Post Reply
User avatar
muzik
Posts: 5647
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Post by muzik » August 31st, 2017, 11:30 am

I've been trying to make the phaselister script, but, being the idiot that I am, I'm getting stuck on step 1. I get an input box with stuff already in it just fine, but when i submit the information I get errors. Tried making it display the inputted variables on the top information bar thing in golly, which leads off into this error right here:

Code: Select all

Traceback (most recent call last):
File "<string>", line 1, in <module>
File
"C:\Users\.\Documents\CA\apps\sim\golly-3.0b3-win-64bit\golly-3.0b...\phaselister.py",
line 32, in <module>
g.show(x + y)
TypeError: must be string, not int
So either I'm lazy, not seeing something laughably obvious, or the script is trying to call another script and is getting invalid answers from it.

Here's the script so far, in case it is a fault with it directly:

Code: Select all

from glife import validint, inside
from string import lower
import golly as g

selrect = g.getselrect()
if len(selrect) == 0: g.exit("Error: Nothing seems to be selected")

# use same file name as in shift.lua
INIFileName = g.getdir("data") + "shift.ini"
oldparams = "10 10 and"
try:
    f = open(INIFileName, 'r')
    oldparams = f.readline()
    f.close()
except:
    # should only happen 1st time (INIFileName doesn't exist)
    pass

answer = g.getstring("enter rectangle dimensions\n" +
                     "(valid modes are h, default is or):",
                     oldparams, "Shift selection")
xym = answer.split()

# extract x and y amounts
if len(xym) == 0: g.exit()
if len(xym) == 1: g.exit("Supply x and y amounts separated by a space.")
if not validint(xym[0]): g.exit("Bad x value: " + xym[0])
if not validint(xym[1]): g.exit("Bad y value: " + xym[1])
x = int(xym[0])
y = int(xym[1])
gens = xym[2]
g.show(x + y)

User avatar
dvgrn
Moderator
Posts: 10669
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » August 31st, 2017, 11:46 am

muzik wrote:I've been trying to make the phaselister script, but, being the idiot that I am, I'm getting stuck on step 1. I get an input box with stuff already in it just fine, but when i submit the information I get errors. Tried making it display the inputted variables on the top information bar thing in golly, which leads off into this error right here:

Code: Select all

Traceback (most recent call last):
File "<string>", line 1, in <module>
File
"C:\Users\.\Documents\CA\apps\sim\golly-3.0b3-win-64bit\golly-3.0b...\phaselister.py",
line 32, in <module>
g.show(x + y)
TypeError: must be string, not int
No need to beat yourself up for getting errors -- that happens to everybody.

Also, Python often gives annoyingly irrelevant errors, in cases where the problem is really something like a missing parenthesis on the previous line... so watch out for that as you go forward. In this case Python really is trying hard to explain the actual problem to you, involving g.show(x + y).

g.show needs a string input, but you've put in a number. Whenever this kind of thing comes up, use str() to convert to a string: g.show(str(x + y))... or in this case, g.show("x="+str(x)+", y="+str(y)), or slightly less awkward might be g.show(str([x, y]) .

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Script request thread

Post by Saka » September 16th, 2017, 1:17 am

Can someone strip down the nt rule generator script to generate the transitions only? I'm absolutely horrible at classes.

User avatar
muzik
Posts: 5647
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Post by muzik » October 11th, 2017, 5:40 pm

How about something like hexgrid.lua, but for simulating triangular rules?

User avatar
muzik
Posts: 5647
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Post by muzik » October 22nd, 2017, 9:06 pm

Here's an idea I've had for a while: a script that takes a specified high-period oscillator and meshes together multiple copies of it, printing out any resultant guns, breeders, and new resultant oscillator periods that pop up.

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Script request thread

Post by drc » October 24th, 2017, 10:27 pm

Can someone modify nbsearch1 to make a separate layer and save all the unique results there?

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Script request thread

Post by wildmyron » October 30th, 2017, 6:21 am

drc wrote:Can someone modify nbsearch1 to make a separate layer and save all the unique results there?
This does the first part of what you want and also runs a lot faster by virtue of not calling g.new() for every pattern tested. There's still some further optimisation that could be done and there's no duplicate checking on the results, but I'll leave that for now. (Have a look at my scripts in the rulesrc thread for inspiration on that front). You could also very easily adapt this to check for spaceships at the same time as searching for oscillators if you so desired.

Code: Select all

import golly as g
import math

rule=g.getstring("Rule:","B3/S23")
algo=g.getstring("Algorithm:","QuickLife")

max_period=20
result_spacing=50

exclude_periods=[1]
if rule=="GlideLife":
    exclude_periods=[1,2,4]
if rule=="olife":
    exclude_periods=[1,2,3,4,5,12,10,35,6]
if rule=="B3/S23":
    exclude_periods=[1,2,3,15,8,5,4,6,30]
if rule=="tlife":
    exclude_periods=[1,2,5,4,3,6,8,33,12]
if rule=="salad":
    exclude_periods=[1,2,4,5,3,10,29,6,7]
if rule=="B2i3-r4cS23":
    exclude_periods=[1,2,5,8,16,10,14,13,3,4]
if rule=="B2inkce_S12":
    exclude_periods=[1,6,4,3,2,14,5,10,12]
if rule=="B2inkce3_S1":
    exclude_periods=[1,8,4,6]
if rule=="B3678/S235678":
    exclude_periods=[1,2,3,4,5,6,14,12,8,10,17,24,7,34,9,15,11]
if rule=="B013578/S02":
    exclude_periods=[1,2,3,4,5,6,7,8,9,10,11,12,15,16,20,21,22,23,24,29,30,32,33,34,47,48]
if rule=="MoveIt":
    exclude_periods=[1,2,24,8,12,4,3,16,48,6,32,5,14,11,10]
if rule=="B34tw5y_S23":
    exclude_periods=[1,2,4,7,3,10]
if rule=="B35678/S357":
    exclude_periods=[1,2,6,3,4,8,5,35,14,12,13]
if rule=="B2-aS12":
    exclude_periods=[1,3,4,6,26,14,2,12,7,5,10,42,19,11,16,28,9,78,24,8]
if rule=="B1e4ay5ai6i7eS0123eijr4atwri5ayn6cai7":
    exclude_periods=[1]
if rule=="B2in3S2-in37":
    exclude_periods=[1,2,5,3,4,8,10,6,12]
if rule=="B2in3S02-in3-n":
    exclude_periods=[1,4,2,8,7,6,5,10,3,9,16,12]
if rule=="B37/S2-i34q":
    exclude_periods=[1,2,5,4,3]
if rule=="B3/S235e":
    exclude_periods=[1,2,5,3,15,8]
if rule=="PuffLife":
    exclude_periods=[1,4,2,3,6,8]
if rule=="B3-k/S2-i3-k4cen":
    exclude_periods=[1,2,5,4,3]
if rule=="B34ek5ak/S2-c34iz5y":
    exclude_periods=[1,2,4,6]
if rule=="b2ce3aiys12aei3r":
    exclude_periods=[1,2,6,8,4,14,10]
if rule=="B3-cnry4-acery5i/S23-a4-jknqr5y8":
    exclude_periods=[1,2,4]
if rule=="B3/S23-a4eiktz":
    exclude_periods=[1,2,4,5,3,6,9,7]
if rule=="B34e5e/S2-in3-y5jk":
    exclude_periods=[1,2,4,13,3,10,6]
if rule=="B2e3-r5i8/S23-a4kz7c":
    exclude_periods=[1,2,7,4,9,14,5,6,3]


def osc_test():
    if g.empty():
        return [False]
    g.setstep(0)
    cells=g.getcells(g.getrect())
    hash=g.hash(g.getrect())
    for i in range(1,max_period):
        g.step()
        if g.empty():
            return [False]
        if g.hash(g.getrect())==hash:
            if g.getcells(g.getrect())==cells:
                if i not in exclude_periods:
                    return [True,i]
                else:
                    return [False]
    return [False]


def put_symm(cell_list,x0=0,y0=0,axx=1,axy=0,ayx=0,ayy=1,mode="or"):
    
    g.putcells(cell_list,x0,y0,axx,axy,ayx,ayy,mode)
    if symm=="C2_1" or symm=="C4_1" or symm=="D4_+1" or symm=="D8_1" or symm=="D4_x1":
        g.putcells(cell_list,-x0,-y0,-axx,-axy,-ayx,-ayy,mode)
    
    if symm=="C4_1" or symm=="D8_1":
        g.putcells(cell_list,y0,-x0,ayx,ayy,-axx,-axy,mode)
        g.putcells(cell_list,-y0,x0,-ayx,-ayy,axx,axy,mode)
    
    if symm=="C2_2" or symm=="D4_+2":
        g.putcells(cell_list,-x0-1,-y0,-axx,-axy,-ayx,-ayy,mode)
    
    if symm=="C2_4" or symm=="C4_4" or symm=="D4_+4" or symm=="D8_4" or symm=="D4_x4":
        g.putcells(cell_list,-x0-1,-y0-1,-axx,-axy,-ayx,-ayy,mode)
    
    if symm=="D2_+1" or symm=="D8_1" or symm=="D4_+1":
        g.putcells(cell_list,-x0,y0,-axx,-axy,ayx,ayy,mode)
    
    if symm=="D4_+1" or symm=="D8_1" or symm=="D4_+2":
        g.putcells(cell_list,x0,-y0,axx,axy,-ayx,-ayy,mode)
    
    if symm=="D2_+2" or symm=="D4_+2" or symm=="D4_+4" or symm=="D8_4":
        g.putcells(cell_list,-x0-1,y0,-axx,-axy,ayx,ayy,mode)
    
    if symm=="D4_+4" or symm=="D8_4":
        g.putcells(cell_list,x0,-y0-1,axx,axy,-ayx,-ayy,mode)
    
    if symm=="C4_4" or symm=="D8_4":
        g.putcells(cell_list,y0,-x0-1,ayx,ayy,-axx,-axy,mode)
        g.putcells(cell_list,-y0-1,x0,-ayx,-ayy,axx,axy,mode)
    
    if symm=="D8_4":
        g.putcells(cell_list,-y0-1,-x0-1,-ayx,-ayy,-axx,-axy,mode)
    
    if symm=="D2_x" or symm=="D8_1" or symm=="D8_4" or symm=="D4_x1" or symm=="D4_x4":
        g.putcells(cell_list,y0,x0,ayx,ayy,axx,axy,mode)
    
    if symm=="D4_x1" or symm=="D8_1":
        g.putcells(cell_list,-y0,-x0,-ayx,-ayy,-axx,-axy,mode)
    
    if symm=="D4_x4" or symm=="D8_4":
        g.putcells(cell_list,-y0-1,-x0-1,-ayx,-ayy,-axx,-axy,mode)
    
x=int(g.getstring("Size:","4"))

start=int(g.getstring("Start:"))

def next(max_x):
    w=0
    h=0
    
    while g.getcell(w,h)==1:
        g.setcell(w,h,0)
        w+=1
        if w==max_x:
            w=0
            h+=1
            if h==max_x:
                return True
    g.setcell(w,h,1)
    return False

def clear_layer():
    r = g.getrect()
    if r:
        g.select(r)
        g.clear(0)
    return

def main():
    g.new("BrutOsc")
    global symm
    
    count=start
    if start>2**(x**2):
        g.show("Start > "+str(2**(x**2)))
        return False
    for i in range(start):
        next(x)
    cell_list=g.getcells([0,0,x,x])
    
    g.setrule(rule)
    g.setalgo(algo)
    
    test_layer=g.getlayer()
    if g.numlayers()<g.maxlayers():
        results_layer=g.addlayer()
        g.setname('OscResults')
        g.setlayer(test_layer)
    else:
        resultslayer=-1
    results=0
    
    while True:
        for i in range(16):
            clear_layer()
            g.setbase(2)
            g.setstep(6)
            
            symm=["C1", "C2_1", "C2_2", "C2_4", "D2_x", "D2_+1", "D2_+2", "C4_1", "C4_4", "D4_x1", "D4_x4", "D4_+1", "D4_+2", "D4_+4", "D8_1", "D8_4"][i]
            put_symm(cell_list)
            
            g.step()
            
            v=osc_test()
            if v[0]:
                g.show(str(count)+"*16,   Period "+str(v[1]))
                osc = g.getcells(g.getrect())
                results+=1
                if results_layer>=0:
                    g.setlayer(results_layer)
                    g.putcells(osc, result_spacing*results, 0)
                    g.setname('OscResults (%d)' % results)
                    g.fit()
                    g.update()
                    g.setlayer(test_layer)
                else:
                    return True
        
        count+=1
        
        if count>2**(x**2):
            if results==0:
                g.setlayer(results_layer)
                g.dellayer()
                g.setlayer(test_layer)
            else:
                g.setlayer(results_layer)
            g.show("%d*16 patterns tested, %d solutions found." %(2**(x**2), results))
            return False
        
        if count%100==0:
            g.show("%d*16 patterns tested, %d solutions found so far." %(count, results))
            g.new("")
        else:
            clear_layer()
            
        g.putcells(cell_list)
        next(x)
        
        cell_list=g.getcells([0,0,x,x])

main()
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.

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Script request thread

Post by Saka » October 30th, 2017, 6:27 am

That one "direct cycle oscar" thing (I think it's called bijoscar?) but for linear growths? Please?

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Script request thread

Post by wildmyron » October 30th, 2017, 11:32 pm

Saka wrote:That one "direct cycle oscar" thing (I think it's called bijoscar?) but for linear growths? Please?
This already exists in the form of linearlyse() from the Python version of apgsearch.
Is there anything preventing you from using linearlyse() to do what you want?
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.

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Script request thread

Post by Saka » October 31st, 2017, 3:40 am

wildmyron wrote: This already exists in the form of linearlyse() from the Python version of apgsearch.
Is there anything preventing you from using linearlyse() to do what you want?
Ooh nice I didn't see that even I scrolled past it like 5 times.

dani
Posts: 1222
Joined: October 27th, 2017, 3:43 pm

Re: Script request thread

Post by dani » October 31st, 2017, 3:17 pm

wildmyron wrote:This does the first part of what you want and also runs a lot faster by virtue of not calling g.new() for every pattern tested.
Nice! I find this looks great with 'Tile Layers' on, as it makes a great side-by-side view of the search and its results.
Having a nbsearch2 version of this would be great, but I won't hassle you.

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Script request thread

Post by wildmyron » November 8th, 2017, 6:04 am

danny wrote:
wildmyron wrote:This does the first part of what you want and also runs a lot faster by virtue of not calling g.new() for every pattern tested.
Nice! I find this looks great with 'Tile Layers' on, as it makes a great side-by-side view of the search and its results.
Having a nbsearch2 version of this would be great, but I won't hassle you.
I was going to suggest that you give modifying nbsearch2 a go yourself - it's definitely worthwhile having enough of an understanding of programming languages to make small changes like this one. But I couldn't resist.

Code: Select all

import golly as g
import math
import random
from timeit import default_timer as timer

rule=g.getstring("Rule:","B3/S23")
algo=g.getstring("Algorithm:","QuickLife")
s=g.getstring("Symmetry","All")

symm=0
if s!="All":
    symm=s

#symm can be either C1, C2_1, C2_2, C2_4, D2_x, D2_+1, D2_+2, C4_1, C4_4, D4_x1, D4_x4, D4_+1, D4_+2, D4_+4, D8_1, D8_4, All, Rot

max_period=300
result_spacing=100
stab_step=7

exclude_periods=[1]
if rule=="GlideLife":
    exclude_periods=[1,2,4,6,12,16]
if rule=="olife":
    exclude_periods=[1,2,3,4,5,6,9,10,12,15,18,20,26,30,35]
if rule=="B3/S23":
    exclude_periods=[1,2,3,6,8,4,5,10,15,30,14]
if rule in ["tlife","B3/S2-i34q"]:
    exclude_periods=[1,2,4,5,160]
if rule=="salad":
    exclude_periods=[1,2,4]
if rule=="B2inkce_S12":
    exclude_periods=[1,2,4]
if rule=="B3678/S235678":
    exclude_periods=[1,2,3,4,6,12,8]
if rule=="MoveIt":
    exclude_periods=[1,2,3,4,6,8,12,16,24,32,48]
if rule=="B35678/S357":
    exclude_periods=[1,2,6,4,3,8,12,35,5,14,24,13,10,15]
if rule=="B2-aS12":
    exclude_periods=[1,14,6,3,2,4,7,26,42,9,28,12,78,16,48,236,24,84,182,13,156,5,130,21,10,208,234,15,11,70,8,19]
if rule=="B2i35r_S023-a4i":
    exclude_periods=[1,2,4]
if rule=="B2in3S02-in3-n":
    exclude_periods=[1,4,5,8,7,6,20,12,28,2,9,16,36,10,42,72,14,56,3,40,63,30,140,45,35]
if rule=="B37/S2-i34q":
    exclude_periods=[1,2,5,4,3,20]
if rule=="B3/S235e":
    exclude_periods=[1,2,15,3,5,10,8,30,4,6,14,40]
if rule=="randomnn":
    exclude_periods=[20,4,14,7,28,140,84]
if rule=="Rotator":
    exclude_periods=[12,40,120,4,60,10,20,24,8]
if rule=="B2ein3/S13":
    exclude_periods=[1,2,4,6,5,10]
if rule=="PuffLife":
    exclude_periods=[1,2,4,8,3,6,16,12]
if rule=="B3-k/S2-i3-k4cen":
    exclude_periods=[1,2,5,4,3]
if rule=="B34ek5ak/S2-c34iz5y":
    exclude_periods=[1,2,4,6]
if rule=="B35/S2":
    exclude_periods=[2,4,1,3]
if rule=="B3568/S256":
    exclude_periods=[1,2,3,4,6,12,5,10,15,20,14,42]
if rule=="B356/S234i":
    exclude_periods=[1,2,4,6,12]
if rule=="b2ce3aiys12aei3r":
    exclude_periods=[1,2,4,6,7,8,10,12,14,15,24,26,28,29,30,58,42,62,94,126,138,170,186,202,234,266]
if rule=="B3-cnry4-acery5i/S23-a4-jknqr5y8":
    exclude_periods=[1,2,36,92,4,28,12,18,8]
if rule=="B3/S23-a4eiktz":
    exclude_periods=[1,2,4,5,10,78,7,14,9,36,3,6]
if rule=="B34e5e/S2-in3-y5jk":
    exclude_periods=[1,2,4,10,13,26,6,3]
if rule=="B2e3-r5i8/S23-a4kz7c":
    exclude_periods=[1,2,7,14,4]
if rule=="B3/S23-e4k":
    exclude_periods=[1,2,4,5,6,10,98,294,14,22,12]
if rule=="B34aq5c/S135":
    exclude_periods=[1,2,4,3,6,13,26,8,12,52,39]
if rule=="B2-a3/S1c23-ainr4cekn":
    exclude_periods=[1,2,4,12,31,6,62,8,5,10,124,28,20]
if rule=="B2-a3-in/S23":
    exclude_periods=[1,2,6,4,44,12,3,16,9,18,132,5,8,36,220,20,30,22,60]
if rule=="B2-a3-in/S235c":
    exclude_periods=[1,2,4,3,6,44,12,10,20,132,16,60,5,58,8]

def osc_test():
    if g.empty():
        return False
    testcells=g.getcells(g.getrect())
    testpop=g.getpop() # String representation
    testhash=g.hash(g.getrect())
    for i in range(1,max_period):
        g.run(1)
        if g.empty():
            return False
        if g.getpop()==testpop and g.hash(g.getrect())==testhash:
            if g.getcells(g.getrect())==testcells:
                if i not in exclude_periods:
                    return True
                else:
                    return False
    return False


def put_symm(cell_list,x0=0,y0=0,axx=1,axy=0,ayx=0,ayy=1,mode="or"):
    global symm
   
    if s=="All":
        symm=["C1", "C2_1", "C2_2", "C2_4", "D2_x", "D2_+1", "D2_+2", "C4_1", "C4_4", "D4_x1", "D4_x4", "D4_+1", "D4_+2", "D4_+4", "D8_1", "D8_4"][random.randrange(16)]

    if s=="Rot":
        symm=["C1", "C2_1", "C2_2", "C2_4", "C4_1", "C4_4"][random.randrange(6)]
   
    # g.putcells(cell_list,x0,y0,axx,axy,ayx,ayy,mode)
    if symm=="C2_1" or symm=="C4_1" or symm=="D4_+1" or symm=="D8_1" or symm=="D4_x1":
        g.putcells(cell_list,-x0,-y0,-axx,-axy,-ayx,-ayy,mode)
   
    if symm=="C4_1" or symm=="D8_1":
        g.putcells(cell_list,y0,-x0,ayx,ayy,-axx,-axy,mode)
        g.putcells(cell_list,-y0,x0,-ayx,-ayy,axx,axy,mode)
   
    if symm=="C2_2" or symm=="D4_+2":
        g.putcells(cell_list,-x0-1,-y0,-axx,-axy,-ayx,-ayy,mode)
   
    if symm=="C2_4" or symm=="C4_4" or symm=="D4_+4" or symm=="D8_4" or symm=="D4_x4":
        g.putcells(cell_list,-x0-1,-y0-1,-axx,-axy,-ayx,-ayy,mode)
   
    if symm=="D2_+1" or symm=="D8_1" or symm=="D4_+1":
        g.putcells(cell_list,-x0,y0,-axx,-axy,ayx,ayy,mode)
   
    if symm=="D4_+1" or symm=="D8_1" or symm=="D4_+2":
        g.putcells(cell_list,x0,-y0,axx,axy,-ayx,-ayy,mode)
   
    if symm=="D2_+2" or symm=="D4_+2" or symm=="D4_+4" or symm=="D8_4":
        g.putcells(cell_list,-x0-1,y0,-axx,-axy,ayx,ayy,mode)
   
    if symm=="D4_+4" or symm=="D8_4":
        g.putcells(cell_list,x0,-y0-1,axx,axy,-ayx,-ayy,mode)
   
    if symm=="C4_4" or symm=="D8_4":
        g.putcells(cell_list,y0,-x0-1,ayx,ayy,-axx,-axy,mode)
        g.putcells(cell_list,-y0-1,x0,-ayx,-ayy,axx,axy,mode)
   
    if symm=="D8_4":
        g.putcells(cell_list,-y0-1,-x0-1,-ayx,-ayy,-axx,-axy,mode)
   
    if symm=="D2_x" or symm=="D8_1" or symm=="D8_4" or symm=="D4_x1" or symm=="D4_x4":
        g.putcells(cell_list,y0,x0,ayx,ayy,axx,axy,mode)
   
    if symm=="D4_x1" or symm=="D8_1":
        g.putcells(cell_list,-y0,-x0,-ayx,-ayy,-axx,-axy,mode)
   
    if symm=="D4_x4" or symm=="D8_4":
        g.putcells(cell_list,-y0-1,-x0-1,-ayx,-ayy,-axx,-axy,mode)

def clear_layer():
    r = g.getrect()
    if r:
        g.select(r)
        g.clear(0)
    return

x=10
main_fill=50

def main():
    g.new("RandOsc")
    g.setrule(rule)
    g.setalgo(algo)
    g.setbase(2)
    
    test_layer=g.getlayer()
    if g.numlayers()<g.maxlayers():
        results_layer=g.addlayer()
        g.setname('OscResults')
        g.setlayer(test_layer)
    else:
        resultslayer=-1
    results=0
   
    count=0
    prevcount=0
    t_start=timer()
    t_prev=t_start
    while True:
        clear_layer()
       
        g.select([0,0,x,x])
        g.randfill(main_fill)
        cell_list=g.getcells([0,0,x,x])
        # g.clear(0)
        put_symm(cell_list)
       
        g.setstep(stab_step)
        g.step()
       
        if osc_test():
            osc = g.getcells(g.getrect())
            results+=1
            if results_layer>=0:
                g.setlayer(results_layer)
                g.putcells(osc, result_spacing*results, 0)
                g.setname('OscResults (%d)' % results)
                g.fit()
                g.update()
                g.setlayer(test_layer)
            else:
                return True
       
        count+=1
        if count%1000==0:
            t_end=timer()
            g.show("%d results found after %d soups tested (%d/sec current, %d/sec overall)" % (results, count, (count-prevcount)/(t_end-t_prev), (count)/(t_end-t_start)))
            g.select([])
            g.update()
            g.new("")
            g.setbase(2)
            t_prev=t_end
            prevcount=count

main()
I also couldn't resist making a few performance improvements. You should see about a six-fold performance improvement for CGoL. I haven't performance tested the script with any other rules though, but I expect that they'll be similar. I also modified the base step and the excluded periods list for tlife. I haven't added any duplicate checking to this script, so it will output results similarly to nbsearch1. Abort the script with 'Esc' to view the results.
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.

User avatar
gameoflifemaniac
Posts: 1242
Joined: January 22nd, 2017, 11:17 am
Location: There too

Re: Script request thread

Post by gameoflifemaniac » December 1st, 2017, 11:26 am

This script:

Code: Select all

local g = golly()
g.reset()
g.randfill(50)
g.flip(0)
g.putcells(g.getselrect(), 8, 0, 0, 0, 0, 0, "or")
g.run(10000)
g.setmag(1)
was supposed to run symmetric soups, but it isn't working as I wanted to. Can someone help me?
I was so socially awkward in the past and it will haunt me for the rest of my life.

Code: Select all

b4o25bo$o29bo$b3o3b3o2bob2o2bob2o2bo3bobo$4bobo3bob2o2bob2o2bobo3bobo$
4bobo3bobo5bo5bo3bobo$o3bobo3bobo5bo6b4o$b3o3b3o2bo5bo9bobo$24b4o!

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Script request thread

Post by wildmyron » December 1st, 2017, 11:48 am

gameoflifemaniac wrote:This script:

Code: Select all

local g = golly()
g.reset()
g.randfill(50)
g.flip(0)
g.putcells(g.getselrect(), 8, 0, 0, 0, 0, 0, "or")
g.run(10000)
g.setmag(1)
was supposed to run symmetric soups, but it isn't working as I wanted to. Can someone help me?
There are three problems:
* g.getselrect() gives you a rect list, not a cell list. You want g.getcells(g.getselrect())
* If you flip the selection, then copy the current selection and paste it - you will have two copies of the same pattern, neither of them flipped.
* What does the magic number 8 refer to? It doesn't relate to the current selection, whatever that is. Better to make the selection in the script so you control everything, or determine where to paste based on the current selection, not hardcoded.
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.

User avatar
dvgrn
Moderator
Posts: 10669
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » December 1st, 2017, 12:05 pm

gameoflifemaniac wrote:This script...was supposed to run symmetric soups, but it isn't working as I wanted to. Can someone help me?
One problem is your "8,0,0,0,0,0" affine transformation -- too many zeroes. Also there's an implicit assumption that the selection is always in the same place. And also I misquoted some code in my last post -- said listofcells = g.getselrect() when I should have said listofcells = g.getcells(g.getselrect()).

If the selection really is in a standard location every time -- upper left-hand corner always at (0,0), let's say -- then you could get away with something like

Code: Select all

local g = golly()
g.randfill(50)
g.putcells(g.getcells(g.getselrect()), 0, 0, -1, 0, 0, 1, "or")
g.run(10000)
g.setmag(1)
Or

g.putcells(g.getcells(g.getselrect()), -1, 0, -1, 0, 0, 1, "or")

if you want even symmetry instead of odd symmetry.

Otherwise, as wildmyron says, you're better off doing something like a g.select(0,0,x,y), to avoid having to do slightly more complicated math to figure out what the correct affine transformation is for that particular selection. And probably a g.new() before that, so you're sure there isn't any leftover non-symmetric junk in the universe.

-------------------------------

Those six affine transformation values are very simple math, but not so easy to explain in words. From Golly help:
transform(cell_array, x0, y0, axx=1, axy=0, ayx=0, ayy=1)
Apply an affine transformation to the given cell array and return the resulting cell array. For each x,y cell in the input array the corresponding xn,yn cell in the output array is calculated as xn = x0 + x*axx + y*axy, yn = y0 + x*ayx + y*ayy.
Short summary: the first two numbers are (delta x, delta y). The default (identity) transformation would be (1, 0, 0, 1) for the other four parameters, which means:

To get the new X value, multiply the old X value by 1 and add the old Y value multiplied by 0.
To get the new Y value, multiply the old X value by 0 and add the old Y value multiplied by 1.

So if you're saying "don't move or rotate or reflect anything", that's "0, 0, 1, 0, 0, 1" -- not all zeroes.

If you experiment with affine transformations enough, they'll start to make a whole lot of sense -- and they tie in with sines and cosines and IFS fractals and all kinds of other fun stuff. So taking the time to develop a low-level understanding of them would definitely not be a wasted investment.

User avatar
gameoflifemaniac
Posts: 1242
Joined: January 22nd, 2017, 11:17 am
Location: There too

Re: Script request thread

Post by gameoflifemaniac » December 3rd, 2017, 8:51 am

I wanted to do a script that returns all the digits representing all transitions in a rule in the status bar or anywhere else.
I don't know how to do this. At least I tried:

Code: Select all

local g = golly()
local gp = require "gplus"
g.new("Rule string")
g.show(g.getrule())
g.setcursor("Draw")
Something like this was in the universal megafier script, but don't fully understand how this works.
I was so socially awkward in the past and it will haunt me for the rest of my life.

Code: Select all

b4o25bo$o29bo$b3o3b3o2bob2o2bob2o2bo3bobo$4bobo3bob2o2bob2o2bobo3bobo$
4bobo3bobo5bo5bo3bobo$o3bobo3bobo5bo6b4o$b3o3b3o2bo5bo9bobo$24b4o!

User avatar
dvgrn
Moderator
Posts: 10669
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » December 3rd, 2017, 10:32 am

gameoflifemaniac wrote:I wanted to do a script that returns all the digits representing all transitions in a rule in the status bar or anywhere else.
...
Something like this was in the universal megafier script, but don't fully understand how this works.
Specifics, please. I'm guessing you want 512 binary digits, representing transitions for all possible Moore neighborhoods. But that's too much information to fit in the status bar. Maybe you want a similar report just for Life-like rules, or just for isotropic rules?

The universal megafier script collects the 512 bits of information described above, so if that's what you're looking for it should be possible to re-use the same code. That function works by drawing all possible neighborhoods for both possible center-cell states, running the whole test pattern for one tick, and seeing what happens.

Unfortunately this doesn't work correctly in cases where Golly is doing its anti-strobe simulation trick for rules with B0. It has been on my to-do list to fix that, but it's going to be slightly annoying so I've been avoiding it. One way would be to redraw all the neighborhoods at T=1, run for another tick, and collect 512 more bits of information. If the two sets of 512 bits are different, then compare them to deduce the actual rule that Golly is simulating.

I shouldn't say "slightly annoying" -- I should say "a nice challenge that I'll leave as an exercise for the reader."

User avatar
muzik
Posts: 5647
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Post by muzik » December 15th, 2017, 3:48 pm

I've had an idea for a (probably super inefficient) soup-searching script for a while now: how about it runs through all possible fillings of a nxn square using a binary counter and counting the bottom right corner as the last digit?

Oh, and it would probably upload results to catagolue while it's at it as well.

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Script request thread

Post by Apple Bottom » December 15th, 2017, 4:12 pm

muzik wrote:I've had an idea for a (probably super inefficient) soup-searching script for a while now: how about it runs through all possible fillings of a nxn square using a binary counter and counting the bottom right corner as the last digit?

Oh, and it would probably upload results to catagolue while it's at it as well.
This would be doable for small n anyway. (I'll leave it up to you to determine the number of equivalent soups of size n by n though.)

The script already exists, too; it's called apgsearch. All you really need to do is modify hashsoup() and tweak the main loop's logic a bit.
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

User avatar
dvgrn
Moderator
Posts: 10669
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » December 15th, 2017, 4:36 pm

Apple Bottom wrote:The script already exists, too; it's called apgsearch. All you really need to do is modify hashsoup() and tweak the main loop's logic a bit.
Even that modification has already been done.

AforAmpere
Posts: 1334
Joined: July 1st, 2016, 3:58 pm

Re: Script request thread

Post by AforAmpere » December 20th, 2017, 5:34 pm

This is a complicated one, but is it possible to modify qfind, gfind or zfind into searching knightships, with speeds of (3,2)c/10 for example? Knight2 and knightt kind of do, but they don't work for higher periods. On another note, where can I find WLS? I can't seem to find the link I had seen before.
I manage the 5S project, which collects all known spaceship speeds in Isotropic Non-totalistic rules. I also wrote EPE, a tool for searching in the INT rulespace.

Things to work on:
- Find (7,1)c/8 and 9c/10 ships in non-B0 INT.
- EPE improvements.

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Script request thread

Post by Apple Bottom » December 21st, 2017, 4:42 am

AforAmpere wrote:On another note, where can I find WLS? I can't seem to find the link I had seen before.
It's on the wiki!
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

AforAmpere
Posts: 1334
Joined: July 1st, 2016, 3:58 pm

Re: Script request thread

Post by AforAmpere » December 27th, 2017, 4:07 pm

I know I keep requesting things but, can this glider script from David Eppstein be modified to work on non-totalistic rules? I am not very good with c scripts, so I am not sure exactly how I could modify it. I will use this for adding in NT ships to a downloadable file, so known ships can be searched.
I manage the 5S project, which collects all known spaceship speeds in Isotropic Non-totalistic rules. I also wrote EPE, a tool for searching in the INT rulespace.

Things to work on:
- Find (7,1)c/8 and 9c/10 ships in non-B0 INT.
- EPE improvements.

User avatar
Macbi
Posts: 903
Joined: March 29th, 2009, 4:58 am

Re: Script request thread

Post by Macbi » December 28th, 2017, 4:08 am

Does anyone have some python code for parsing rulestrings? Ideally I'd like it to at least work for anything that Golly or apgsearch accepts. Doesn't really matter what form the output takes since that will be easy enough to change.
Last edited by Macbi on January 23rd, 2018, 9:37 am, edited 1 time in total.

User avatar
calcyman
Moderator
Posts: 2936
Joined: June 1st, 2009, 4:32 pm

Re: Script request thread

Post by calcyman » December 28th, 2017, 9:41 am

Macbi wrote:Does anyone have some pyhton code for parsing rulestrings? Ideally I'd like it to at least work for anything that Golly or apgsearch accepts. Doesn't really matter what form the output takes since that will be easy enough to change.
The rule-parsing code in apgluxe is entirely written in Python. Look at def main in the following file:

https://gitlab.com/apgoucher/lifelib/bl ... ule2asm.py

For non-totalistic isotropic rules, it delegates to ntcanon.py. The relevant initial segment of the script is:

Code: Select all

#!/usr/bin/python

from sys import argv

rulestring = argv[1]
isotrans = {}
centre = 0

for c in rulestring.lower().replace('v', 'r'):
    if c in '012345678':
        lastloc = int(c)
        isotrans[(centre, lastloc)] = "+";
    elif (c == 'b'):
        centre = 0
    elif (c == 's'):
        centre = 1
    elif (c == '/'):
        centre = 1 - centre
    elif c in 'ceaiknjqrytwz-':
        isotrans[(centre, lastloc)] += c

lord = "";
lord += "_ceaccaieaeaknja_ceaccaieaeaknjaekejanaairerririekejanaairerriri";
lord += "ccknncqnaijaqnwaccknncqnaijaqnwakykkqyqjrtjnzrqakykkqyqjrtjnzrqa";
lord += "ekirkyrtejerkkjnekirkyrtejerkkjnekejjkrnejecjyccekejjkrnejecjycc";
lord += "anriqyzraariqjqaanriqyzraariqjqajkjywkqkrnccqkncjkjywkqkrnccqknc";
lord += "cnkqccnnkqkqyykjcnkqccnnkqkqyykjaqjwinaarzjqtrnaaqjwinaarzjqtrna";
lord += "ccyyccyennkjyekeccyyccyennkjyekenykknejeirykrikenykknejeirykrike";
lord += "aqrznyirjwjqkkykaqrznyirjwjqkkykaqrqajiarqcnnkccaqrqajiarqcnnkcc";
lord += "intrneriaanajekeintrneriaanajekeajnkaeaeiaccaec_ajnkaeaeiaccaec_";
popcounts = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]
lord2 = []

for i in xrange(512):

    centre = (i >> 4) & 1
    ncount = popcounts[i & 15] + popcounts[i >> 5]
    if (centre, ncount) in isotrans:
        fragment = isotrans[(centre, ncount)]
        if (len(fragment) == 1):
            lord2.append(1)
        else:
            l = 1 if (fragment[1] == '-') else 0
            for c in fragment:
                if (c == lord[i]):
                    l = 1 - l
            lord2.append(l)
    else:
        lord2.append(0)

rule_letters = {}
rule_letters[1] = "ce" ;
rule_letters[2] = "ceaikn" ;
rule_letters[3] = "ceaiknjqry" ;
rule_letters[4] = "ceaiknjqrytwz" ;
rule_letters[5] = "ceaiknjqry" ;
rule_letters[6] = "ceaikn" ;
rule_letters[7] = "ce" ;

canonicals = [['' for i in xrange(9)] for j in xrange(2)]
canstring = ''

for i in xrange(512):
    centre = (i >> 4) & 1
    ncount = popcounts[i & 15] + popcounts[i >> 5]
    if (lord2[i] == 1):
        canonicals[centre][ncount] += lord[i]

for (centre, z) in enumerate('bs'):
    canstring += z
    for ncount in xrange(9):
        goodies = set(canonicals[centre][ncount])
        if (len(goodies) == 0):
            continue
        canstring += str(ncount)
        if ncount not in rule_letters:
            continue
        a = ''.join(sorted([c for c in rule_letters[ncount] if c in goodies]))
        b = '-' + (''.join(sorted([c for c in rule_letters[ncount] if c not in goodies])))
        if (len(b) == 1):
            continue
        elif (len(b) < len(a)):
            canstring += b
        else:
            canstring += a

if (rulestring != canstring):
    print('\033[31;1mError:\033[0m %s is a non-canonical version of %s' % (rulestring, canstring))
    print('Please re-run the code with the canonical rulestring:')
    print('./recompile.sh --rule \033[36;1m%s\033[0m' % canstring)
    exit(1)

print lord2
It produces a 512-bit list of binary digits (lord2), indexed by a 9-bit integer whose bits correspond to the neighbourhood read in lexicographical order. It accepts outer-totalistic and non-totalistic isotropic rules in basically any format (such as Golly's B3/S23, Life32's 23/3, and apgsearch's b3s23).

EDIT: Technically you only need the top half of the code snippet I posted, because the second half converts lord2 back into a canonical rulestring to see whether it matches the original rulestring.
What do you do with ill crystallographers? Take them to the mono-clinic!

Post Reply