Re: Script request thread
Posted: 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)
1. Is the script a golly script?carsoncheng wrote: July 23rd, 2022, 3:13 amHere is an example script using lifelib: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.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)
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.
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.atavoidirc wrote: July 23rd, 2022, 3:40 am1. Is the script a golly script?carsoncheng wrote: July 23rd, 2022, 3:13 amHere is an example script using lifelib: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.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)
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.
2.The apgcode-to-rle fails if there's more than 2 states.
Here is a modified script from here that should hopefully work with Python 3.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).
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)
how do you use lifelib scripts?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.
Code: Select all
pip install python-lifelibCode: Select all
import lifelib
sess = lifelib.load_rules('b3s23')
lt = sess.lifetree()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.atavoidirc wrote: August 2nd, 2022, 7:35 pm an inflator script, one that applies inflation to a pattern.
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)
Here it is:rattlesnake wrote: October 6th, 2022, 9:22 pm I want a script that converts a .mc file to a .rle file.
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())
When I run this script, I get this error:carsoncheng wrote: October 7th, 2022, 11:24 amHere it is:rattlesnake wrote: October 6th, 2022, 9:22 pm I want a script that converts a .mc file to a .rle file.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.Code: Select all
...
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.
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, '/'.Did you install lifelib? If so, did you run into any problems that might be useful to report?rattlesnake wrote: October 10th, 2022, 1:41 amWhen I run this script, I get this error:carsoncheng wrote: October 7th, 2022, 11:24 am You also need to install lifelib for the script to run.Code: Select all
{lifelib-related error}
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
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..".")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.pipsqueek wrote: December 13th, 2022, 9:17 pm is there a script that can find the smallest phase of an oscillator? (in population)