The issue appears to be the presence of the string "sleep(#)" within the script's source, where # is replaced with a number like 123 or 0.4. Attempting to post or preview with that in the body causes a 403.hotdogPi wrote: September 3rd, 2026, 3:33 pm Hopefully this won't 403, because for some inexplicable reason, trying to post this unzipped gives me a 403 error on both the forum and the wiki.
Golly scripts
- rabbit
- Posts: 250
- Joined: March 4th, 2024, 6:00 am
- Location: Stuck inside a magician's hat. it hurts so bad
Re: Golly scripts
That's the bunny.
Check out my OCA exploration script, crule.lua!
Check out my OCA exploration script, crule.lua!
- NNlk05
- Posts: 806
- Joined: January 14th, 2026, 8:42 pm
- Location: Exploring in the Jungle of the INT Rulespace
- Contact:
Re: Golly scripts
Can comfirmrabbit wrote: September 3rd, 2026, 3:54 pm The issue appears to be the presence of the string "sleep(#)" within the script's source, where # is replaced with a number like 123 or 0.4. Attempting to post or preview with that in the body causes a 403.
Feci quod potui, faciant meliora potentes.
https://nnlk05.github.io
=3
The world is my country, science my religion.
Code: Select all
x = 10, y = 3, rule = B34twz/S23
b2o4b2o$obo4bobo$2bo4bo!
[[ AUTOSTART AUTOHIDEGUI TRACK 0 -47/270 ZOOM 4 GPS 45 STEP 3 THEME BOOK ]]
=3
The world is my country, science my religion.
Re: Golly scripts
There were four instances, but they were all commented out anyway, so here is the code.
Code: Select all
import golly as g
import time
'''Initializing'''
g.select([0,0,1,1])
#g.autoupdate(1)
g.new("example")
sparker = g.parse('''
14b3o$14bobo$6b2o6b3o$5bobo6b3o$2o3bo8b3o$2o3bobo6b3o$6b2o6bobo$14b3o
5$10bo$9bobo$10b2o!
''')
g.putcells(sparker, 0, 0)
sparker_pop = int(g.getpop())
sparker_box = g.getrect()
g.new("example")
type_ = 'r'
if type_ == 'hf':
target_pattern = g.parse('2b3o$bo3bo$o5bo$o5bo$o5bo$bo3bo$2b3o!')
elif type_ == 'tl':
target_pattern = g.parse('2bo$bobo$o3bo$bobo$2bo!')
elif type_ == 'pi':
target_pattern = g.parse('b3o$o3bo$2ob2o!')
elif type_ == 'r':
target_pattern = g.parse('2bo$2ob2o$o2bo$b2o!')
elif type_ == 'c':
target_pattern = g.parse('b3o$bobo$o2bo$2o!')
rotation = 2
g.putcells(target_pattern, 0, 0)
for i in range(rotation):
g.select(g.getrect())
g.rotate(1)
if i == 3:
g.flip(0)
target_pop = int(g.getpop())
target_box = g.getrect()
if type_ == 'pi' and rotation == 0:
target_box[3] += 1
hash1 = g.hash(target_box)
g.select(target_box)
g.flip(0)
g.flip(1) #180 degree rotation
target_pattern = g.getcells(target_box)
period = 45
g.new("example")
g.putcells(sparker, 0, 0)
minpop = int(g.getpop())
initial_box = g.getrect()
stator_cells = set(zip(g.getcells(g.getrect())[::2],g.getcells(g.getrect())[1::2]))
for i in range(period):
g.run(1)
minpop = min(minpop, int(g.getpop()))
for j in (0,1):
initial_box[j] = min(initial_box[j],g.getrect()[j])
for j in (2,3):
initial_box[j] = max(initial_box[j],g.getrect()[j])
stator_cells = set.intersection(stator_cells,set(zip(g.getcells(g.getrect())[::2],g.getcells(g.getrect())[1::2])))
g.show(str(len(stator_cells)))
#g.update()
#time.REDACTED(0.1)
width = g.getrect()[2]
height = g.getrect()[3]
#single_cell = g.parse('o!')
start_x, end_x, start_y, end_y = -15, 20, -9, 0
for y in range(start_y, end_y+1):
for x in range(start_x, end_x+1):
#if y == -18 and x < 4:
# continue
recent_pops = list(range(100,109)) #9 same population in a row: end
recent_min_x = list(range(100,108)) #checking for escaping gliders
current_gen = None
g.new("example")
'''Putting patterns in place'''
g.putcells(sparker, 0, 0)
#g.putcells(target_pattern, x, y)
g.run(0)
if g.empty():
continue
found = []
for generation in range(period):
g.new("example")
g.putcells(sparker, 0, 0)
g.run(generation)
sparker_pop = int(g.getpop())
g.putcells(target_pattern, x, y)
if int(g.getpop()) != sparker_pop + target_pop:
continue
original = g.getcells(g.getrect())
hash_list = []
broken = False
if generation == 0:
g.show('%s, %s' % (x, y))
g.update()
for generation1 in range(200):
if broken:
break
g.run(1)
if generation1 % 15 == 0 and not g.getcell(14,0): #temporary
break
if generation1 % 12 == 0 or generation1 % period == 0: # checks for same pattern
hash_list.append(g.hash(g.getrect()))
if hash_list[-1] in hash_list[:-1]:
break
max_x = None
if max_x is None:
top_rect = g.getrect()
else:
g.select([-50,-50,50+max_x,100]) # maximum x to check
g.shrink()
top_rect = g.getselrect()
g.select(top_rect)
# g.update()
# time.REDACTED(.1)
top_rect[1] = top_rect[1]
top_rect[3] = target_box[3]
g.select(top_rect)
#g.update()
#time.REDACTED(.1)
g.shrink()
top_rect = g.getselrect()
top_rect[1] = top_rect[1]
top_rect[2] = target_box[2]
top_rect[3] = target_box[3]
#g.update()
#time.REDACTED(0.2)
for cell in stator_cells:
if not g.getcell(cell[0],cell[1]):
broken = True
break
'''if generation1 % period == 1 or g.hash(top_rect) == hash1:
temp = g.getcells(g.getrect())
g.select(sparker_box)
g.clear(1)
#g.warn('%s, %s, %s, %s' % (generation, generation1, int(g.getpop()), sparker_pop))
#g.update()
if generation1 % period == 1 and int(g.getpop()) < sparker_pop:
break
if int(g.getpop()) < minpop:
g.warn('%s, %s' % (int(g.getpop()), minpop))
g.new("example")
g.putcells(temp, 0, 0)'''
if g.hash(top_rect) == hash1:
total_gens = generation+generation1
#if total_gens < 3:
# continue
if len(g.getcells(sparker_box))//2 < minpop: #sparker region has missing cells
#g.warn(str([len(g.getcells(sparker_box)) // 2, minpop]))
continue
if int(g.getpop()) < minpop + target_pop: #total has too few cells
continue
if generation1 in (10,13) and type_ == 'tl': #common 11 and 14 pushes for traffic lights
continue
if generation1 == 77 and type_ == 'hf': # common 78 push for honey farms
continue
if generation1 in (10,61) and type_ == 'lom': # common 11 and 62 pushes for lumps of muck
continue
if generation1 == 25 and type_ == 'r' and rotation == 0: # p52 shuttle (26-tick push)
continue
if generation1 == 41 and type_ == 'r' and rotation == 1: # p84 shuttle (42-tick push)
continue
if generation1 == 122 and type_ == 'c' and rotation == 4: # p246 shuttle (123-tick push)
continue
if generation1 == 87 and type_ == 'pi' and rotation == 1: # p246 shuttle (123-tick push)
continue
if generation+generation1 in found:
continue
#if int(g.getpop()) == 178:
# continue
#if min(recent_pops1[-min(10,total_gens):]) == max(recent_pops1[-min(10,total_gens):]):
# continue
#g.putcells(current_gen_a, 100, 0)
#g.new("example")
g.putcells(original, -100, 0)
#g.getcells(g.getrect())
g.update()
g.warn('Found: %s, %s, %s' % (y, x, generation1+1))
#generation_snapshots = [''] * 200
found.append(generation+generation1)
break
User:HotdogPi/My discoveries
Periods discovered:
All evens ≤128 except 52,58,78,82,92,94,98,104,118,122
5-15,㉕-㉛,㉟㊺,51,63,65,73,75
1㊳㊵㊹㊼㊽,54,56,72,74,80,90,92
217,240,300,486,576
Guns: 20,21,32,54,55,57,114,117,124,126
SKOPs: 32,74,76,102,196
Periods discovered:
All evens ≤128 except 52,58,78,82,92,94,98,104,118,122
5-15,㉕-㉛,㉟㊺,51,63,65,73,75
1㊳㊵㊹㊼㊽,54,56,72,74,80,90,92
217,240,300,486,576
Guns: 20,21,32,54,55,57,114,117,124,126
SKOPs: 32,74,76,102,196
- TheWayOfTheCon
- Posts: 417
- Joined: March 28th, 2025, 11:40 pm
- Location: Always moving, always traveling through time
Re: Golly scripts
Branching off of this, I present (if we're all fine with the nomenclature) nbsearch2b.May13 wrote: August 26th, 2022, 2:06 am From B34q/S23-k thread:
I found it using modified version of nbsearch2.
My modification (I call it nbsearch2a) does not affect performance, but makes searching easier and supports bounded grids:Code: Select all
I only added a few things to this version, though, those being
- An option to dump the results pattern in a file, making long-term searches more viable
- Gutter symmetries, specifically for D2_+1, D4_+1 along one axis, D4_+1 along both axes, D4_+2, and D8_1. You can also just type "Gut" to search all of them
- A bit more user-friendliness
Code: Select all
import golly as g
import math
import random
from timeit import default_timer as timer
from glife.text import make_text
from glife import getminbox, rect
autoRAB=True #automatically detect rule, algorithm and border
group_by_period=True
auto_exclude=50 #maximal number of oscillators of specific period (if group_by_period)
show_periods=True #print list of periods (if group_by_period)
auto_stop=True #stop if no more oscillators can be added (if group_by_period)
max_period=100 #the highest oscillator period to detect in the search
result_spacing=150
stab_step=8 #how many generations to simulate a soup before detecting periodicity (2^stab_step)
x=10 #size of the soup (actually larger in most symmetries besides C1 )
main_fill=50 #density of the soup
count_update=1000 #how frequently the soup count will be updated
file_dump=False #creates rle files containing the results
if autoRAB:
rule=g.getrule()
algo=g.getalgo()
if ":" in rule:
rule,bound=rule.split(":")
bound=":"+bound
else: bound=""
else:
rule=g.getstring("Rule:","B3/S23")
algo=g.getstring("Algorithm:","QuickLife")
bound=g.getstring("Bound:","T32,32")
if not (bound=="" or bound.startswith(":")): bound=":"+bound
s=g.getstring("Symmetry","All")
g.note("You can further specify your search by looking through the .py file and changing the parameters near the top.", False)
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, D2_+1 gutter, D4_+1 gutter, D4_+1 two gutter, D8_+1 gutter, Gut
max_period+=1
oc=[0]*max_period
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]
exclude_periods=[]
def all_periods(q):
if not show_periods: return ""
gmin = gmax = 0
text = "["
for i in q+[0]:
if i==0: text += str(gmin) + ("-"+str(gmax)+"]" if gmax>gmin else "]")
elif gmin==0: gmin = gmax = i
elif i-gmax==1: gmax = i
else:
text += str(gmin) + ("-"+str(gmax)+"," if gmax>gmin else ",")
gmin = gmax = i
return text
def osc_test():
global exclude_periods
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:
if auto_exclude==1: exclude_periods+=[i]
return i
return 0
return 0
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)]
if s=="Gut":
symm=["D2_+1 gutter", "D4_+1 gutter", "D4_+1 two gutter", "D4_+2 gutter", "D8_+1 gutter"][random.randrange(5)]
# 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)
if symm=="D2_+1 gutter" or symm=="D4_+1 gutter" or symm=="D4_+1 two gutter" or symm=="D4_+2 gutter":
g.putcells(cell_list,x0,-y0-2,axx,axy,-ayx,-ayy,mode)
if symm=="D4_+1 gutter":
g.putcells(cell_list,x0,-y0,-axx,-axy,ayx,ayy,mode)
g.putcells(cell_list,-x0,-y0-2,-axx,-axy,ayx,-ayy,mode)
if symm=="D4_+1 two gutter":
g.putcells(cell_list,x0-2,-y0,-axx,-axy,ayx,ayy,mode)
g.putcells(cell_list,-x0-2,-y0-2,-axx,-axy,ayx,-ayy,mode)
if symm=="D4_+2 gutter":
g.putcells(cell_list,x0-1,-y0,-axx,-axy,ayx,ayy,mode)
g.putcells(cell_list,-x0-1,-y0-2,-axx,-axy,ayx,-ayy,mode)
if symm=="D8_1 gutter":
g.putcells(cell_list,-x0-2,-y0-2,-axx,-axy,-ayx,-ayy,mode)
g.putcells(cell_list,x0,y0-2,axx,axy,-ayx,-ayy,mode)
g.putcells(cell_list,x0-2,y0,-axx,-axy,ayx,ayy,mode)
def clear_layer():
r = g.getrect()
if r:
g.select(r)
g.clear(0)
return
def main():
global oc
g.new("RandOsc")
g.setrule(rule+bound)
g.setalgo(algo)
g.setbase(2)
test_layer=g.getlayer()
if g.numlayers()<g.maxlayers():
results_layer=g.addlayer()
g.setname('OscResults')
g.setrule(rule)
for i in range(max_period-1):
t = make_text(str(i+1), "mono")
t.put((i+1)*result_spacing,0)
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()
test=osc_test()
if test>0:
osc = g.getcells(g.getrect())
if group_by_period:
if oc[test]==0: results+=1
if oc[test]<auto_exclude:
if results_layer>-1:
oc[test]+=1
g.setlayer(results_layer)
g.putcells(osc, result_spacing*test, result_spacing*oc[test])
g.setname('OscResults (%d)' % results)
if file_dump:
g.save('OscResults (%d).rle' % results, 'rle')
g.fit()
g.update()
g.setlayer(test_layer)
g.setname('RandOsc (%d)' % results)
else:
return True
else:
results+=1
if results_layer>-1:
g.setlayer(results_layer)
g.putcells(osc, result_spacing*results, 0)
g.setname('OscResults (%d)' % results)
g.fit()
g.update()
g.setlayer(test_layer)
g.setname('RandOsc (%d)' % results)
else:
return True
count+=1
if count%count_update==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))+" "+all_periods([i for i in range(max_period) if oc[i]>0]))
g.select([])
g.update()
g.new("")
g.setbase(2)
t_prev=t_end
prevcount=count
if auto_stop and auto_exclude>0:
if sum(oc)==(max_period-1-len([i for i in exclude_periods if i<max_period]))*auto_exclude: break
main()If I feel like improving this version more, here's what to expect:
- Period verify to filter out non interacting LCMs
- A few more weird symmetries
- Optimizations if I can find them
I could've chose a better username, but oh well.
I think I've learned the ropes of cellular automata. My current interest is range-two LTLs.
I think I've learned the ropes of cellular automata. My current interest is range-two LTLs.
- qqd
- Posts: 637
- Joined: September 10th, 2022, 4:24 pm
- Location: In a superposition of multiple different locations.
Re: Golly scripts
Here's a script that generates and displays devote parents of the barge family (which means there are infinitely many still lives with devote parents and all barges are "faithful"):Rudyj wrote: September 20th, 2026, 2:16 pm Greetings everyone!
I would like to invite the community to join a fun challenge that I call searching for "Devote Parents" (Щирі Батьки by ukrainian).
For a given pattern P1, a Devote Parent is a strict phoenix configuration P0 (where no live cell survives to the next generation, i.e., every cell dies by underpopulation or overcrowding) that gives birth to pattern P1 in exactly one generation, while none of the parent's cells survive into P1.
...
Code: Select all
local g = golly()
g.new("Devote Parents for Barges")
local function makeDevoteParentForLine(lengthOfLine)
-- For the sake of demonstration it will be quicker to write for generating an RLE than to write for generating a cell array directly
local length = lengthOfLine + 2 -- We need this length for most of the generation
local RLE = ""
for i = 2, length do
local rowStart = (i % 3 == 0) and "2o" or "2b"
RLE = RLE..rowStart..i.."o$"
end
if length % 3 == 0 then
RLE = RLE.."2b"..length.."o$"
elseif length % 3 == 1 then
RLE = RLE.."3b"..(length - 1).."o$"
else
RLE = RLE.."2o"..length.."o$"
end
local lastRows = string.rep("b", (length - 1) % 3)..string.rep("bob", (length - 1) // 3 + 1)
RLE = RLE..lastRows.."$"
if length % 3 == 1 then lastRows = lastRows:gsub("o", "b", 1) end
RLE = RLE..lastRows.."!"
return g.parse(RLE)
end
local function makeDevoteParentForBarge(lengthOfBarge)
local dpLine1 = makeDevoteParentForLine(lengthOfBarge)
local dpLine2 = g.transform(dpLine1, lengthOfBarge + 8, lengthOfBarge - 2, -1, 0, 0, -1)
return g.join(dpLine1, dpLine2)
end
local k = 2
while true do
g.select{-2, -2, 1, 1}
g.clear(1) -- Doing this so that you can zoom in and out without resetting the zoom (which would occur using g.new)
g.select{}
g.putcells(makeDevoteParentForBarge(k))
g.update()
g["sleep"](500) -- Currently using g . sleep directly in a post causes a 403 forbidden error (It appears the security system has been updated)
g.run(1)
g.update()
g["sleep"](500)
k = k + 1
end
Currently writing a utility in Lua that may be helpful for faster manual pattern manipulation.
- qqd
- Posts: 637
- Joined: September 10th, 2022, 4:24 pm
- Location: In a superposition of multiple different locations.
Re: Golly scripts
(Apologies for double posting, but this is an unrelated script.)
There is a script called create-custom-ltl.lua in Golly that allows you to create a custom Larger than Life neighborhood. However, no such Lua script exists for weighted neighborhoods, so here is one for that as well:
There is a script called create-custom-ltl.lua in Golly that allows you to create a custom Larger than Life neighborhood. However, no such Lua script exists for weighted neighborhoods, so here is one for that as well:
Code: Select all
-- create-weighted-ltl.lua
-- A script that creates a weighted Larger than Life rule using the current selection
-- By qqd (conwaylife.com forum user) based on Chris Rowett's create-custom-ltl script located in Scripts > Lua in Golly
-- Instructions:
--[[
1. Run this script WITHOUT making a selection first so that the layer colors will be set in a way that
corresponds to the weights each cell state has (this step can be omitted but that is not recommended)
2. Draw your weighted Larger than Life neighborhood, ensuring it fits in a square with odd dimensions
For all states their corresponding weights are:
0, 1, ... 127, -127, ... -1 for states from 0 to 255 for the -127 to 127 range
0, 1, ... 7, -7 ,... -1 for states from 0 to 15 for to -7 to 7 range
0 is black, positive weights range in a dark blue-reddish purple-brown-yellow gradient,
and negative weights range in a maroon-bluish purple-blue-cyan gradient
Darker the color, lesser the magnitude of the weight
3. Select your desired neighborhood, ensuring that the selection is square with odd dimensions from 3 to 99
4. Run this script again to convert your selection to a weighted Larger than Life neighborhood
--]]
local g = golly()
local selrect = g.getselrect()
local minlen = 3
local maxlen = 99
if selrect[1] then -- Selection exists
if selrect[3] ~= selrect[4] then
g.exit("Selection must be square")
elseif selrect[3] & 1 == 0 then
g.exit("Square selection must have odd dimensions")
elseif selrect[3] < minlen or selrect[3] > maxlen then
g.exit("Square selection must have dimensions from "..minlen.." to "..maxlen)
end
local width = selrect[3]
local maxweight = (g.numstates() > 15) and 127 or 7
local array = g.getcells(selrect)
local weightmap = {}
for i = 1, width*width do
weightmap[i] = (maxweight == 127) and "00" or "0"
end
local arraylen = #array
if arraylen & 1 == 1 then
for i = 1, arraylen - 3, 3 do
local x, y, state = array[i], array[i+1], array[i+2]
local weight = (state + maxweight) % (2*maxweight + 1) - maxweight
local hex = string.format("%0"..((maxweight == 127) and "2" or "1").."X", ((weight < 0) and (maxweight + 1) or 0)|math.abs(weight))
weightmap[1 + (x-selrect[1]) + width*(y-selrect[2])] = hex
end
else
for i = 1, arraylen - 2, 2 do
local x, y = array[i], array[i+1]
weightmap[1 + (x-selrect[1]) + width*(y-selrect[2])] = "1"
end
end
local rule = "R"..(width//2)..",C0,S1,B1,NW"..table.concat(weightmap)
g.note("Created rule with weighted Larger than Life neighborhood:\n\n"..rule,false)
g.setrule(rule)
g.setcolors{}
else -- No selection
g.error("") -- Beep without updating status bar
local ans = g.query("Create Weighted Larger than Life neighborhood",
[[There is no square selection to create a neighborhood.
Select your range of weights to convert the rule and layer colors to create a
weighted neighborhood, else press 'Cancel'.]],
"From -7 to 7", "From -127 to 127", "Cancel")
if ans == "Cancel" then g.exit("Script aborted.") end
g.new("")
local colpositive = {255, 210, 0}
local colnegative = {0, 210, 255}
local editcols = {0,0,0,0}
local colstate = {}
local maxweight = (ans == "From -127 to 127") and 127 or 7
local max = math.max
local min = math.min
local floor = math.floor
local minbright = 6
local maxbright = 255
local invert = {false, false, false} -- Stores whether the 3 color channels should start increasing in value instead of decreasing
-- Function to calculate the next color (its not exactly very intuitive but
-- this is used to ensure at least a bare minimum level of distinguishibility for the -127 to 127 range)
local function nextcol(basecol, channel)
local newcol
if invert[channel] then
newcol = min(maxbright, colstate[channel] + 0.5)
else
newcol = max(minbright, colstate[channel] - max(2, (basecol[channel] // (maxweight+1) )))
end
if colstate[channel] <= minbright then
invert[(channel - 1) % 3 + 1] = true
end
colstate[channel] = newcol
end
invert = {false, false, false}
for k = 1, 3 do colstate[k] = colnegative[k] end
for i = maxweight + 1, 2*maxweight do
editcols[4*i+1] = i
for channel = 1, 3 do
editcols[4*i+channel+1] = floor(colstate[channel])
nextcol(colnegative, channel)
end
end
invert = {false, false, false}
for k = 1, 3 do colstate[k] = colpositive[k] end
for i = maxweight, 1, -1 do
editcols[4*i+1] = i
local invert = 0 -- Bitwise storage of whether the 3 channels should start increasing instead of decreasing
for channel = 1, 3 do
editcols[4*i+channel+1] = floor(colstate[channel])
nextcol(colpositive, channel)
end
end
g.setrule("//"..(2*maxweight + 1)) -- Switch to either //15 or //255
g.setcolors(editcols)
end
Currently writing a utility in Lua that may be helpful for faster manual pattern manipulation.