Pipe into apgsearch running some stdin symmetry.
Script request thread
Re: Script request thread
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
Re: Script request thread
On my list of things to do is a rewrite/replacement of my partition and census functions, if I can find the time. The methods I wrote date back to the last century and could use an update. I'd like to look at how apgsearch (or lifelib) does this and look for ideas to steal. Pointers to the relevant files and functions would be appreciated. Or broad descriptions of what it is doing.
Re: Script request thread
The bulk of code responsible for separating patterns into objects belongs to https://gitlab.com/apgoucher/lifelib/-/ ... assifier.h . It uses a disjoint-set-union data structure.hkoenig wrote: ↑April 19th, 2023, 9:12 pmOn my list of things to do is a rewrite/replacement of my partition and census functions, if I can find the time. The methods I wrote date back to the last century and could use an update. I'd like to look at how apgsearch (or lifelib) does this and look for ideas to steal. Pointers to the relevant files and functions would be appreciated. Or broad descriptions of what it is doing.
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
-
- Posts: 45
- Joined: April 14th, 2022, 3:09 pm
Re: Script request thread
A script that takes a glider synthesis and convert it to Quadlife by coloring the gliders according to direction.
Re: Script request thread
That's an easy hack from glider-rewinder.py:atavoidirc wrote: ↑June 29th, 2023, 2:02 pmA script that takes a glider synthesis and convert it to Quadlife by coloring the gliders according to direction.
Code: Select all
# glider-colorizer-by-direction-QuadLife.py
# https://conwaylife.com/w/index.php?title=Rule:QuadLife&action=raw
#
# If you have a selection, then only the gliders inside the selection will get updated.
# The others will stay in state 1, which is supposed to be the color for NW-traveling gliders
import golly as g
import os
import itertools
from glife import *
lib=[["NW","bo$2o$obo!"],["NE","2o$b2o$o!"],["SE","obo$b2o$bo!"],["SW","2bo$2o$b2o!"]]
def getenvelope(pat):
env=[]
if len(pat)%2:
g.exit("Must be a 2-state list.")
for i in range(0,len(pat)-1,2):
for x in range(-1,2):
for y in range(-1,2):
if abs(x)!=0 or abs(y)!=0: # add eight neighbors of each ON cell to the mask
if [pat[i]+x,pat[i+1]+y] not in env:
env.append([pat[i]+x,pat[i+1]+y])
for i in range(0,len(pat),2):
if [pat[i],pat[i+1]] in env:
env.remove([pat[i],pat[i+1]]) # take original pattern back out of mask
# else: # with the reduced envelope, this will now happen, e.g. with *WSS singleton sparks
# g.note("Technical error: " + str([pat[i],pat[i+1]])+ " not in envelope:" + str(env) + " \n\n" + str(pat))
return list(itertools.chain.from_iterable(env))
r=g.getselrect()
if len(r)==0:
r=g.getrect()
if len(r)==0: g.exit("No pattern, nothing to do.")
sel = g.getcells(r)
if len(sel)==0: g.exit("Nothing in selection.")
if len(sel)%2: g.exit("Can't do colorization starting with a multistate rule. Try Alt+J / Option+J first.")
all = g.getcells(g.getrect())
allcoords=[]
for i in range(0,len(all),2):
allcoords.append([all[i],all[i+1]])
# g.show("Processing object library...")
odict=dict()
for i in range(len(lib)):
# g.show("Processing object " + lib[i][0])
# run and normalize each library object until a duplicate of the original pattern appears
# The number of ticks to duplication, and the offset, give all the information needed to rewind...
obj = g.parse(lib[i][1])
basex, basey,ticks,newobj=obj[0],obj[1],0,[]
baseobj = g.transform(obj,-basex,-basey)
basepat = pattern(baseobj) # use glife to avoid having to add a layer in Golly
# TODO: figure out the actual right way to compare in Python 3.x... baseobj>newobj or baseobj<newobj, maybe?
while str(baseobj) != str(newobj):
ticks+=1
newpat=basepat[ticks]
newlist = list(newpat)
newobj=g.transform(newpat,-newlist[0],-newlist[1])
if ticks>999:
g.exit(obj[0] + " in library has no reasonable repeat time.")
stridex,stridey=newlist[0],newlist[1]
# odict key is name+phase, and there's an entry for each phase of each object
# Contains list of repeat, stridex, stridey, dx, dy, clist, envclist.
# By convention, the first ON cell in phase 0 is at (0,0) and dx and dy are also 0,0.
# The first ON cell in other phases is also 0,0 but dx and dy will be altered appropriately.
odict[lib[i][0]+"_0"]=[ticks, stridex, stridey, 0, 0, baseobj, getenvelope(baseobj)]
for t in range(1,ticks):
newlist=list(basepat[t])
normalized=g.transform(newlist,-newlist[0],-newlist[1])
odict[lib[i][0]+"_"+str(t)]=[ticks,stridex,stridey,newlist[0],newlist[1],normalized,getenvelope(normalized)]
g.show("")
# make a list of coordinate pairs that might be Objects of Interest (gliders or LWSSes)
coords=[]
for i in range(0,len(sel),2):
coords.append([sel[i],sel[i+1]])
rewindable=[]
# now go through the selection and find all the recognizable patterns
i=0
while i<len(coords):
x0,y0=coords[i][0], coords[i][1]
for k, v in list(odict.items()):
clist = v[5] # object cell list
match=1
for j in range(0,len(clist),2):
if [x0+clist[j],y0+clist[j+1]] not in coords:
match=0
break # a cell in this object is not in the selected pattern
if match:
envclist=v[6] # object envelope cell list
for j in range(0,len(envclist),2):
if [x0+envclist[j],y0+envclist[j+1]] in allcoords: # could use coords instead, but selection should be increased 2 cells all around
match=0
break # a cell in the surrounding must-be-OFF area is ON
if match:
# remove all recognized cells from coords
for j in range(0,len(clist),2):
crd=[x0+clist[j],y0+clist[j+1]]
if crd in coords:
coords.remove(crd)
else:
g.exit("A coordinate that should have been there wasn't: " + str(crd) + "\n\n" + str(coords))
rewindable.append([k,x0-v[3],y0-v[4]])
break # no need to go through rest of items in dictionary
if not match:
i+=1 # only increment index if current coord has not been removed due to a match
g.setrule("QuadLife")
# color all gliders
for item in rewindable:
lookup=odict[item[0]]
# odict[name+phase]=[ticks, stridex, stridey, dx, dy, clist, getenvelope(clist)]
clist = lookup[5]
# lookup[1] and lookup[2] will contain each glider's x and y offsets every four ticks --
# convert those numbers into a value from 1 to 4
color = (lookup[1]*4+lookup[2]*2 + 10) // 4
for i in range(0,len(clist),2):
g.setcell(clist[i]+item[1]+lookup[3],clist[i+1]+item[2]+lookup[4],color)
-
- Posts: 164
- Joined: January 9th, 2019, 2:44 am
Re: Script request thread
A script to determine critical mass of a rule. Something along the lines of:
Code: Select all
Set n to some preset number (16?)
While necessary {
Repeat 1000 times {
Run a random n*n soup
Check if it stabilises
}
If a majority of soups do not stabilise {
Choose larger n
} Else {
Choose smaller n
}
}
Return smallest n such that a majority of n*n soups do not stabilise
Re: Script request thread
(moved from script-related questions because this is a better thread for this)
Would someone like to provide a stdin script for apgsearch that provides multistate random soups?
Would someone like to provide a stdin script for apgsearch that provides multistate random soups?
Support Conway's Story Mode!
- confocaloid
- Posts: 1169
- Joined: February 8th, 2022, 3:15 pm
Re: Script request thread
Barring bugs, this Python 3 script should print a given number of multistate soups. Change the constants at the beginning as needed. No express or implied warranty.
Code: Select all
import random
################################################################################
# The number of cellstates:
N_STATES = 16
# The rulestring to be used:
RULESTRING = "QuadB3S23"
# The number of columns:
RLE_WIDTH = 16
# The number of rows:
RLE_HEIGHT = 16
# The number of RLEs to generate (set to 0 to run 'forever'; set to 10 to generate 10 RLEs, etc.)
N_RLES = 0
################################################################################
def random_cellstate():
return random.randrange(0, N_STATES)
S1 = ["", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"]
S2 = "ABCDEFGHIJKLMNOPQRSTUVWX"
def cellstate_to_rle(c):
if c == 0:
return "."
return S1[(c - 1) // 24] + S2[(c - 1) % 24]
def random_rle():
rle = ""
for y in range(RLE_HEIGHT):
rle = rle + "".join(cellstate_to_rle(random_cellstate()) for x in range(RLE_WIDTH))
rle = rle + "{}\n".format("$" if y < RLE_HEIGHT - 1 else "!")
return "x = {}, y = {}, rule = {}\n{}".format(RLE_WIDTH, RLE_HEIGHT, RULESTRING, rle)
def main():
print(random_rle())
i = 1
while i != N_RLES:
print(random_rle())
i += 1
main()
127:1 B3/S234c User:Confocal/R (incomplete table of INT rules)
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.
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.