Script request thread

For scripts to aid with computation or simulation in cellular automata.
atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » July 23rd, 2022, 3:00 am

Apgcode-to-rle that works on multistate apgcodes.

carsoncheng
Posts: 471
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng » July 23rd, 2022, 3:13 am

atavoidirc wrote:
July 23rd, 2022, 3:00 am
Apgcode-to-rle that works on multistate apgcodes.
Here is an example script using lifelib:

Code: Select all

import lifelib
sess = lifelib.load_rules('g3b2s')
lt = sess.lifetree()
apgcode = "xq4_3482h8a_03482lx8"
pat = lt.pattern(apgcode)
rle = pat.rle_string()
print(rle)
Note that in a lifetree, a pattern can be formed from an apgcode as well, other than an RLE. Modify the rule and the apgcode according to your own needs.

A solution for Golly is actually at the very beginning of this thread. However, it should be modified as the Golly script mentioned copies the RLE onto the clipboard, whereas you probably want it stored in a variable.

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » July 23rd, 2022, 3:40 am

carsoncheng wrote:
July 23rd, 2022, 3:13 am
atavoidirc wrote:
July 23rd, 2022, 3:00 am
Apgcode-to-rle that works on multistate apgcodes.
Here is an example script using lifelib:

Code: Select all

import lifelib
sess = lifelib.load_rules('g3b2s')
lt = sess.lifetree()
apgcode = "xq4_3482h8a_03482lx8"
pat = lt.pattern(apgcode)
rle = pat.rle_string()
print(rle)
Note that in a lifetree, a pattern can be formed from an apgcode as well, other than an RLE. Modify the rule and the apgcode according to your own needs.

A solution for Golly is actually at the very beginning of this thread. However, it should be modified as the Golly script mentioned copies the RLE onto the clipboard, whereas you probably want it stored in a variable.
1. Is the script a golly script?
2.The apgcode-to-rle fails if there's more than 2 states.

carsoncheng
Posts: 471
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng » July 23rd, 2022, 4:36 am

atavoidirc wrote:
July 23rd, 2022, 3:40 am
carsoncheng wrote:
July 23rd, 2022, 3:13 am
atavoidirc wrote:
July 23rd, 2022, 3:00 am
Apgcode-to-rle that works on multistate apgcodes.
Here is an example script using lifelib:

Code: Select all

import lifelib
sess = lifelib.load_rules('g3b2s')
lt = sess.lifetree()
apgcode = "xq4_3482h8a_03482lx8"
pat = lt.pattern(apgcode)
rle = pat.rle_string()
print(rle)
Note that in a lifetree, a pattern can be formed from an apgcode as well, other than an RLE. Modify the rule and the apgcode according to your own needs.

A solution for Golly is actually at the very beginning of this thread. However, it should be modified as the Golly script mentioned copies the RLE onto the clipboard, whereas you probably want it stored in a variable.
1. Is the script a golly script?
2.The apgcode-to-rle fails if there's more than 2 states.
I don't know of any Golly scripts that can convert an apgcode in such rules to an RLE. I am posting the lifelib solution because I thought you might be writing a lifelib script. However, the lifelib script above works for all rules, as far as I know. Therefore, I suggest rewriting your script with lifelib if you would like to.

User avatar
confocaloid
Posts: 2729
Joined: February 8th, 2022, 3:15 pm

Re: Script request thread

Post by confocaloid » July 29th, 2022, 5:03 am

toroidalet wrote:
January 19th, 2021, 6:00 pm
Here's a useful script for this sort of thing. You give it a pattern and it will find all rules where it behaves exactly like the original rule for a given number of generations (this version doesn't use minus signs).
Here is a modified script from here that should hopefully work with Python 3.

Code: Select all

# Rule computation script for use with Golly.
# Author: Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
# Updated by: Peter, NASZVADI (), June 2017.

# Gives the maximal family of rules that a still life, oscillator, or spaceship
# works under. Must be called while the rule is set of one such family
# For example, to find out what rules a glider works in, first set the rule
# to Life or HighLife, not Seeds.
# Handles nontotalistic rules, too, so it needs Golly 2.8 or newer.

import golly as g
from glife import validint
# from string import replace

def replace(s, old, new, count = None):
   if count is None:
      return s.replace(old, new)
   return s.replace(old, new, count)

Hensel = [
    ['0'],
    ['1c', '1e'],
    ['2a', '2c', '2e', '2i', '2k', '2n'],
    ['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
    ['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
    ['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
    ['6a', '6c', '6e', '6i', '6k', '6n'],
    ['7c', '7e'],
    ['8']
]

# Python versions < 2.4 don't have "sorted" built-in
try:
    sorted
except NameError:
    def sorted(inlist):
        outlist = list(inlist)
        outlist.sort()
        return outlist

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

def chunks(l, n):
    for i in range(0, len(l), n):
        yield l[i:i+n]

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

def rulestringopt(a):
    result = ''
    context = ''
    lastnum = ''
    lastcontext = ''
    for i in a:
        if i in 'BS':
            context = i
            result += i
        elif i in '012345678':
            if (i == lastnum) and (lastcontext == context):
                pass
            else:
                lastcontext = context
                lastnum = i
                result += i
        else:
            result += i
    result = replace(result, '4aceijknqrtwyz', '4')
    result = replace(result, '3aceijknqry', '3')
    result = replace(result, '5aceijknqry', '5')
    result = replace(result, '2aceikn', '2')
    result = replace(result, '6aceikn', '6')
    result = replace(result, '1ce', '1')
    result = replace(result, '7ce', '7')
    return result

clist = []
rule = g.getrule().split(':')[0]

fuzzer = rule + '9'
oldrule = rule
rule = ''
context = ''
deletefrom = []
for i in fuzzer:
    if i == '-':
        deletefrom = [x[1] for x in Hensel[int(context)]]
    elif i in '0123456789/S':
        if deletefrom:
            rule += ''.join(deletefrom)
            deletefrom = []
        context = i
    if len(deletefrom) == 0:
        rule += i
    elif i in deletefrom:
        deletefrom.remove(i)
rule = rule.strip('9')

if not (rule[0] == 'B' and '/S' in rule):
    g.exit('Please set Golly to a two-state isotropic rule.')

if g.empty():
    g.exit('The pattern is empty.')

s = g.getstring('Enter the period:', '', 'Rules calculator')
if not validint(s):
    g.exit('Bad number: %s' % s)

numsteps = int(s)
if numsteps < 1:
    g.exit('Period must be at least 1.')

g.select(g.getrect())
g.copy()
s = int(s)

for i in range(0,s):
    g.run(1)
    clist.append(list(chunks(g.getcells(g.getrect()), 2)))
    mcc = min(clist[i])
    clist[i] = [[x[0] - mcc[0], x[1] - mcc[1]] for x in clist[i]]

g.show('Processing...')

ruleArr = rule.split('/')
ruleArr[0] = ruleArr[0].lstrip('B')
ruleArr[1] = ruleArr[1].lstrip('S')

b_need = []
b_OK = []
s_need = []
s_OK = []

context = ''
fuzzed = ruleArr[0] + '9'
for i in fuzzed:
    if i in '0123456789':
        if len(context) == 1:
            b_need += Hensel[int(context)]
            b_OK += Hensel[int(context)]
        context = i
    elif context != '':
        b_need.append(context[0] + i)
        b_OK.append(context[0] + i)
        context += context[0]
context = ''
fuzzed = ruleArr[1] + '9'
for i in fuzzed:
    if i in '0123456789':
        if len(context) == 1:
            s_need += Hensel[int(context)]
            s_OK += Hensel[int(context)]
        context = i
    elif context != '':
        s_need.append(context[0] + i)
        s_OK.append(context[0] + i)
        context += context[0]

for i in [iter2 for iter1 in Hensel for iter2 in iter1]:
    if not i in b_OK:
        b_OK.append(i)
        execfor = 1
        # B0 and nontotalistic rulestrings are mutually exclusive
        try:
            g.setrule(rulestringopt('B' + ''.join(b_OK) + '/S' + ruleArr[1]))
        except:
            b_OK.remove(i)
            execfor = 0
        for j in range(0, s * execfor):
            g.run(1)
            try:
                dlist = list(chunks(g.getcells(g.getrect()), 2))
                mcc = min(dlist)
                dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                if not(clist[j] == dlist):
                    b_OK.remove(i)
                    break
            except:
                b_OK.remove(i)
                break
        g.new('')
        g.paste(0, 0, 'or')
        g.select(g.getrect())
        b_OK.sort()

    if not i in s_OK:
        s_OK.append(i)
        execfor = 1
        # B0 and nontotalistic rulestrings are mutually exclusive
        try:
            g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_OK)))
        except:
            s_OK.remove(i)
            execfor = 0
        for j in range(0, s * execfor):
            g.run(1)
            try:
                dlist = list(chunks(g.getcells(g.getrect()), 2))
                mcc = min(dlist)
                dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                if not(clist[j] == dlist):
                    s_OK.remove(i)
                    break
            except:
                s_OK.remove(i)
                break
        g.new('')
        g.paste(0, 0, 'or')
        g.select(g.getrect())
        s_OK.sort()

    if i in b_need:
        b_need.remove(i)
        g.setrule(rulestringopt('B' + ''.join(b_need) + '/S' + ruleArr[1]))
        for j in range(0, s):
            g.run(1)
            try:
                dlist = list(chunks(g.getcells(g.getrect()), 2))
                mcc = min(dlist)
                dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                if not(clist[j] == dlist):
                    b_need.append(i)
                    break
            except:
                b_need.append(i)
                break
        g.new('')
        g.paste(0, 0, 'or')
        g.select(g.getrect())
        b_need.sort()

    if i in s_need:
        s_need.remove(i)
        g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_need)))
        for j in range(0, s):
            g.run(1)
            try:
                dlist = list(chunks(g.getcells(g.getrect()), 2))
                mcc = min(dlist)
                dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                if not(clist[j] == dlist):
                    s_need.append(i)
                    break
            except:
                s_need.append(i)
                break
        g.new('')
        g.paste(0, 0, 'or')
        g.select(g.getrect())
        s_need.sort()

g.setrule(oldrule)
ruleres = 'B' + ''.join(sorted(b_need)) + '/S' + ''.join(sorted(s_need)) + \
    ' - B' + ''.join(sorted(b_OK)) + '/S' + ''.join(sorted(s_OK))
ruleres = rulestringopt(ruleres)
g.show(ruleres)
Last edited by confocaloid on March 25th, 2024, 3:28 pm, edited 1 time in total.
127:1 B3/S234c User:Confocal/R (isotropic rules, incomplete)
Unlikely events happen.
My silence does not imply agreement, nor indifference. If I disagreed with something in the past, then please do not construe my silence as something that could change that.

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » July 31st, 2022, 8:13 pm

carsoncheng wrote:
July 23rd, 2022, 4:36 am

I don't know of any Golly scripts that can convert an apgcode in such rules to an RLE. I am posting the lifelib solution because I thought you might be writing a lifelib script. However, the lifelib script above works for all rules, as far as I know. Therefore, I suggest rewriting your script with lifelib if you would like to.
how do you use lifelib scripts?

carsoncheng
Posts: 471
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng » August 1st, 2022, 7:45 am

If you want to set up lifelib, run:

Code: Select all

pip install python-lifelib
After that, you can import the module and run the setup script in your lifelib program:

Code: Select all

import lifelib
sess = lifelib.load_rules('b3s23')
lt = sess.lifetree()
If you still have trouble setting up lifelib, please visit this documentation page on the lifelib repository:
https://gitlab.com/apgoucher/lifelib/blob/master/doc/quickstart.md

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » August 2nd, 2022, 7:35 pm

an inflator script, one that applies inflation to a pattern.

User avatar
Ian07
Moderator
Posts: 891
Joined: September 22nd, 2018, 8:48 am
Location: New Jersey, US

Re: Script request thread

Post by Ian07 » August 2nd, 2022, 8:16 pm

atavoidirc wrote:
August 2nd, 2022, 7:35 pm
an inflator script, one that applies inflation to a pattern.
EDIT: Removing my original script since it was vastly inferior in terms of speed, and replacing with a modified version of LaundryPizza03's script. Still has separate scale factors for x and y.

Code: Select all

import golly as g
from glife import *

# inflate.py
# Automatically inflates the current pattern
# LaundryPizza03, 2020
# Added separate factors for x and y (and set default options to 2)
# Ian07, 2022

try:
    scale_x = g.getstring("Scale factor (x)", "2")
    scale_x = int(scale_x)
except:
    g.exit("Bad integer value: {0}".format(scale_x))

try:
    scale_y = g.getstring("Scale factor (y)", "2")
    scale_y = int(scale_y)
except:
    g.exit("Bad integer value: {0}".format(scale_y))

P0 = g.getcells(g.getrect())
g.new('')
for x in range(scale_x):
    for y in range(scale_y):
        g.putcells(P0,x,y,scale_x,0,0,scale_y)
Last edited by Ian07 on August 2nd, 2022, 9:44 pm, edited 1 time in total.

User avatar
confocaloid
Posts: 2729
Joined: February 8th, 2022, 3:15 pm

Re: Script request thread

Post by confocaloid » August 2nd, 2022, 8:28 pm

There is also this script for inflating.
127:1 B3/S234c User:Confocal/R (isotropic rules, incomplete)
Unlikely events happen.
My silence does not imply agreement, nor indifference. If I disagreed with something in the past, then please do not construe my silence as something that could change that.

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » August 3rd, 2022, 4:33 pm

Multistate version of the Apgcode-to-clipboard-RLE golly script.

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » August 7th, 2022, 4:08 am

A script based on text.py that pulls up a dialogue box where you input text as well as select a font, than the rle gets pasted to clipboard.

Cyclotrons
Posts: 129
Joined: January 26th, 2021, 12:19 am

Re: Script request thread

Post by Cyclotrons » October 1st, 2022, 9:43 pm

I want a script that creates a .rule file of a rule with StateInvestigator-like states for any given INT rule.
I wrote a stdin script that generates random soups of a provided number of a given spaceship. It works for all (non-B0) spaceships in the INT rulespace!
A Multistate INT notation + script.

User avatar
rattlesnake
Posts: 146
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake » October 6th, 2022, 9:22 pm

I want a script that converts a .mc file to a .rle file.
I have discovered SKOP for 115, 188, 492 and gun_ and guntrue_ for 200, 226, 339, 752, 1944, 6624.

carsoncheng
Posts: 471
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng » October 7th, 2022, 11:24 am

rattlesnake wrote:
October 6th, 2022, 9:22 pm
I want a script that converts a .mc file to a .rle file.
Here it is:

Code: Select all

mc = '''Macrocell file here'''
import lifelib
sess = lifelib.load_rules('b3s23')
lt = sess.lifetree(n_layers=1)
print(lt.pattern(mc).rle_string())
You need to modify the mc variable to read a file to see the pattern in the macrocell format. You also need to install lifelib for the script to run.

But most of the time mc files are used when the patterns grow really colossal (like the caterpillar or the waterbear, which are engineered spaceships). For example, the caterpillar mc file used as the input to the script is 6.7 megabytes, which is already huge, and if you write the RLE to a file, you will have a 30-megabyte file. So most of the time dealing with such enormous patterns actually doesn't require the RLE format. The macrocell format is enough for it to be reconstructed using Golly or lifelib.

User avatar
rattlesnake
Posts: 146
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake » October 10th, 2022, 1:41 am

carsoncheng wrote:
October 7th, 2022, 11:24 am
rattlesnake wrote:
October 6th, 2022, 9:22 pm
I want a script that converts a .mc file to a .rle file.
Here it is:

Code: Select all

...
You need to modify the mc variable to read a file to see the pattern in the macrocell format. You also need to install lifelib for the script to run.

But most of the time mc files are used when the patterns grow really colossal (like the caterpillar or the waterbear, which are engineered spaceships). For example, the caterpillar mc file used as the input to the script is 6.7 megabytes, which is already huge, and if you write the RLE to a file, you will have a 30-megabyte file. So most of the time dealing with such enormous patterns actually doesn't require the RLE format. The macrocell format is enough for it to be reconstructed using Golly or lifelib.
When I run this script, I get this error:

Code: Select all

Traceback (most recent call last):
  File "D:/Python/waterbear.py", line 4, in <module>
    lt = sess.lifetree(n_layers=1)
  File "D:\Python\lib\site-packages\lifelib\pythlib\session.py", line 239, in lifetree
    return Lifetree(self, *args, **kwargs)
  File "D:\Python\lib\site-packages\lifelib\pythlib\session.py", line 25, in __init__
    self.ptr = lifelib('CreateLifetree', memory, n_layers)
  File "D:\Python\lib\site-packages\lifelib\pythlib\lowlevel.py", line 206, in __call__
    retval = pickle.load(self.the_library.stdout)
_pickle.UnpicklingError: invalid load key, '/'.
I have discovered SKOP for 115, 188, 492 and gun_ and guntrue_ for 200, 226, 339, 752, 1944, 6624.

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

Re: Script request thread

Post by dvgrn » October 10th, 2022, 10:06 am

rattlesnake wrote:
October 10th, 2022, 1:41 am
carsoncheng wrote:
October 7th, 2022, 11:24 am
You also need to install lifelib for the script to run.
When I run this script, I get this error:

Code: Select all

{lifelib-related error}
Did you install lifelib? If so, did you run into any problems that might be useful to report?

It's always a good idea to mention your operating system and Golly version when reporting an error.

That said, invoking lifelib for a problem like this does seem like it's dragging in a huge unnecessary dependency. Golly has Lua embedded in it, such that there's no need to install anything else at all. If you open the .mc file in Golly as a starting point, then you can run this to get an RLE file:

Code: Select all

local g = golly()

currentname = g.getname()

if not string.find(currentname, "%.mc") then
  g.note("Current pattern is not named like a macrocell file. Saving an RLE anyway...")
  trialfname = "pattern.rle"
else
  trialfname = string.gsub(currentname,"%.mc",".rle")
end

local fname = g.savedialog("Save RLE file", "RLE files (*.rle)|*.rle", "", trialfname)
if #fname > 0 then
  g.save(fname,"rle")
  g.show("File saved as "..fname..".")
end
If you want it with no manual intervention in Golly, then the following would be generally equivalent to carsoncheng's script, where you'd have to edit the input filename manually:

Code: Select all

local g = golly()

-- edit the following two lines to add valid paths, to get a working sample
inputfname = "your/path/to/Golly/Patterns/HashLife/Eventful/jagged.mc"
outputfname = "your/path/to/where/you/want/jagged.rle"

g.addlayer()
g.open(inputfname)
g.save(outputfname,"rle")
g.dellayer()
g.show("File saved as "..outputfname..".")
-- Of course, if you take one step in the opposite direction, you don't need a script at all -- just open the file in Golly and save it in RLE format.

EDIT by Andrew: fixed some problems in the above scripts.

User avatar
rattlesnake
Posts: 146
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake » October 10th, 2022, 6:24 pm

Thanks.
I have discovered SKOP for 115, 188, 492 and gun_ and guntrue_ for 200, 226, 339, 752, 1944, 6624.

Book
Posts: 385
Joined: August 28th, 2021, 2:38 pm
Location: California
Contact:

Re: Script request thread

Post by Book » November 18th, 2022, 4:11 pm

Is there a script to determine an oscillator's kinetic symmetry?
Phil Bookman

IlTifoneHaiyan
Posts: 6
Joined: October 6th, 2022, 10:19 am
Location: Sharm el-Shrek

Re: Script request thread

Post by IlTifoneHaiyan » November 23rd, 2022, 11:14 am

Is there a script to generalize LifeOnTheEdge rule?
Thank you.

User avatar
pipsqueek
Posts: 265
Joined: September 10th, 2022, 4:42 pm

Re: Script request thread

Post by pipsqueek » December 13th, 2022, 9:17 pm

is there a script that can find the smallest phase of an oscillator? (in population)

Code: Select all

x=17,y=16,rule=B3/S23
3bo3bobo2bob2o$bobo4bo4b4o$bobo5bobo2b3o$b2obob2o3b2o$3o4b2ob2o2b2o$4b
o4bo$4b2obobob2ob3o$3ob3o2b2o$b3o2bobobo5bo$o3b2o3bobo2b2o$4bo3bob2o3b
o$2obo2bobobo2b2o$3b3o5bo2b2o$2obo4bo2bob2o$o3bob2obo3b2o$2bo8bobobo![[ STOP 3 GPS 4 ]]

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

Re: Script request thread

Post by dvgrn » December 13th, 2022, 9:59 pm

pipsqueek wrote:
December 13th, 2022, 9:17 pm
is there a script that can find the smallest phase of an oscillator? (in population)
There's this code that I used to get minimum population and bounding box for some of the big self-constructing spaceships. Some patience is required for huge patterns, but otherwise it should work fine.

AlbertArmStain
Posts: 1233
Joined: January 28th, 2022, 7:18 pm
Location: Planet Z

Re: Script request thread

Post by AlbertArmStain » December 19th, 2022, 5:26 pm

I want a script that converts each step of a catalogue synthesis into a 1G seed composed of spartan splitters, OTTs, etc.

It can also be paired with slmake for multiple purposes.

HartmutHolzwart
Posts: 840
Joined: June 27th, 2009, 10:58 am
Location: Germany

Re: Script request thread

Post by HartmutHolzwart » February 6th, 2023, 2:28 pm

I'd like to have a script that classifies teh evolution of random patterns similar to agpsearch, only on small witdh tubes. I'm only interested in moving patterns, so we'd have spaceships, waves and super strings. And puffer forms thereof.

I would be completely OK with a local python or lua version. This might be too much special interest for catagolue.

atavoidirc
Posts: 49
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc » April 15th, 2023, 8:36 pm

a script that provides a census of a single pattern

Post Reply