Script request thread

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

Re: Script request thread

Post by atavoidirc »

Apgcode-to-rle that works on multistate apgcodes.
carsoncheng
Posts: 509
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng »

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: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

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: 509
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng »

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: 6697
Joined: February 8th, 2022, 3:15 pm
Location: learn to protect yourself against stray gliders and sparks and self-destruct mechanisms

Re: Script request thread

Post by confocaloid »

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 CA, 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: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

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: 509
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng »

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: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

an inflator script, one that applies inflation to a pattern.
User avatar
Ian07
Moderator
Posts: 899
Joined: September 22nd, 2018, 8:48 am
Location: Pennsylvania, US

Re: Script request thread

Post by Ian07 »

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.
Wiki: http://www.conwaylife.com/wiki/User:Ian07
Discord: lan07 (yes, that's a lowercase L)

xs24_69bobjob96
User avatar
confocaloid
Posts: 6697
Joined: February 8th, 2022, 3:15 pm
Location: learn to protect yourself against stray gliders and sparks and self-destruct mechanisms

Re: Script request thread

Post by confocaloid »

There is also this script for inflating.
127:1 B3/S234c User:Confocal/R (isotropic CA, 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: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

Multistate version of the Apgcode-to-clipboard-RLE golly script.
atavoidirc
Posts: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

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: 132
Joined: January 26th, 2021, 12:19 am

Re: Script request thread

Post by Cyclotrons »

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: 167
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake »

I want a script that converts a .mc file to a .rle file.
I have discovered SKOP for 105, 115, 188, 476, 492 and gun_ and guntrue_ for 226, 339, 752.
carsoncheng
Posts: 509
Joined: June 11th, 2022, 11:24 pm

Re: Script request thread

Post by carsoncheng »

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: 167
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake »

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 105, 115, 188, 476, 492 and gun_ and guntrue_ for 226, 339, 752.
User avatar
dvgrn
Moderator
Posts: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn »

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: 167
Joined: May 28th, 2022, 10:10 pm
Location: Following a 37P4H1V0

Re: Script request thread

Post by rattlesnake »

Thanks.
I have discovered SKOP for 105, 115, 188, 476, 492 and gun_ and guntrue_ for 226, 339, 752.
Book
Posts: 385
Joined: August 28th, 2021, 2:38 pm
Location: California
Contact:

Re: Script request thread

Post by Book »

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 »

Is there a script to generalize LifeOnTheEdge rule?
Thank you.
User avatar
pipsqueek
Posts: 304
Joined: September 10th, 2022, 4:42 pm
Location: Abstract mathematical space

Re: Script request thread

Post by pipsqueek »

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: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn »

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.
User avatar
Anivec
Posts: 1983
Joined: January 28th, 2022, 7:18 pm
Location: In 4.3 miles, take a right onto Exit 54

Re: Script request thread

Post by Anivec »

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: 939
Joined: June 27th, 2009, 10:58 am
Location: Germany

Re: Script request thread

Post by HartmutHolzwart »

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: 50
Joined: April 14th, 2022, 3:09 pm

Re: Script request thread

Post by atavoidirc »

a script that provides a census of a single pattern
Post Reply