How do I measure cleanness (of puffers) in multi-state rules?
update:
I made a such attempt in rule "flashbf8df8". This updated pufferSea3.py now distinguish puffers from burning ones.
Puffers detected by default config:
Code: Select all
#CXRLE Pos=-13,0 Gen=144
x = 25, y = 23, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A2$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=108
x = 25, y = 25, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A4$8.A$7.4A$6.9A$5.6A.2A.2A$6.9A$7.4A$8.A!
#CXRLE Pos=-18,0 Gen=108
x = 30, y = 25, rule = flashbf8df8
21.A$20.4A$19.9A$18.6A.2A.2A$19.9A$20.4A$21.A2$8.A$7.4A$6.9A$5.6A.2A.
2A$6.9A$7.4A$8.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-23,0 Gen=216
x = 35, y = 29, rule = flashbf8df8
26.A$25.4A$24.9A$23.6A.2A.2A$24.9A$25.4A$26.A2$13.A$12.4A$11.9A$10.6A
.2A.2A$11.9A$12.4A$13.A8$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=216
x = 25, y = 26, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A5$5.A$4.4A$3.9A$2.6A.2A.2A$3.9A$4.4A$5.A!
#CXRLE Pos=-15,0 Gen=216
x = 27, y = 26, rule = flashbf8df8
18.A$17.4A$16.9A$15.6A.2A.2A$16.9A$17.4A$18.A2$5.A$4.4A$3.9A$2.6A.2A.
2A$3.9A$4.4A$5.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=180
x = 25, y = 26, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A5$9.A$8.4A$7.9A$6.6A.2A.2A$7.9A$8.4A$9.A!
#CXRLE Pos=-19,0 Gen=144
x = 31, y = 26, rule = flashbf8df8
22.A$21.4A$20.9A$19.6A.2A.2A$20.9A$21.4A$22.A2$9.A$8.4A$7.9A$6.6A.2A.
2A$7.9A$8.4A$9.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-19,0 Gen=108
x = 31, y = 27, rule = flashbf8df8
22.A$21.4A$20.9A$19.6A.2A.2A$20.9A$21.4A$22.A3$9.A$8.4A$7.9A$6.6A.2A.
2A$7.9A$8.4A$9.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-16,0 Gen=180
x = 28, y = 26, rule = flashbf8df8
19.A$18.4A$17.9A$16.6A.2A.2A$17.9A$18.4A$19.A2$6.A$5.4A$4.9A$3.6A.2A.
2A$4.9A$5.4A$6.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=360
x = 25, y = 25, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A4$10.A$9.4A$8.9A$7.6A.2A.2A$8.9A$9.4A$10.A!
#CXRLE Pos=-20,0 Gen=432
x = 32, y = 25, rule = flashbf8df8
23.A$22.4A$21.9A$20.6A.2A.2A$21.9A$22.4A$23.A2$10.A$9.4A$8.9A$7.6A.2A
.2A$8.9A$9.4A$10.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=288
x = 25, y = 24, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A3$6.A$5.4A$4.9A$3.6A.2A.2A$4.9A$5.4A$6.A!
#CXRLE Pos=-16,0 Gen=360
x = 28, y = 24, rule = flashbf8df8
19.A$18.4A$17.9A$16.6A.2A.2A$17.9A$18.4A$19.A2$6.A$5.4A$4.9A$3.6A.2A.
2A$4.9A$5.4A$6.A3$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=1008
x = 25, y = 28, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A7$7.A$6.4A$5.9A$4.6A.2A.2A$5.9A$6.4A$7.A!
#CXRLE Pos=-13,0 Gen=216
x = 25, y = 26, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A5$6.A$5.4A$4.9A$3.6A.2A.2A$4.9A$5.4A$6.A!
#CXRLE Pos=-1051,8
x = 50, y = 20, rule = flashbf8df8
40.A$12.A27.2A4.2A$11.4A27.3A3.A$10.9A.4A14.3A.A.A4.A$9.6A.2A.3A2.A
13.A.A.A2.B.B.A$10.9A.4A14.3A.A.A4.A$11.4A27.3A3.A$12.A21.2A4.2A4.2A$
33.A2.A3.A$34.2A2$31.A$3.A27.2A$2.4A27.4A.2A$.9A.4A14.3A.A.A4.A$6A.2A
.3A2.A13.A.A.A2.B.B.A$.9A.4A14.3A.A.A4.A$2.4A27.3A3.A$3.A27.2A4.2A$
31.A!
#CXRLE Pos=-24,0 Gen=252
x = 36, y = 27, rule = flashbf8df8
27.A$26.4A$25.9A$24.6A.2A.2A$25.9A$26.4A$27.A3$14.A$13.4A$12.9A$11.6A
.2A.2A$12.9A$13.4A$14.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-18,0 Gen=864
x = 30, y = 27, rule = flashbf8df8
21.A$20.4A$19.9A$18.6A.2A.2A$19.9A$20.4A$21.A3$8.A$7.4A$6.9A$5.6A.2A.
2A$6.9A$7.4A$8.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-19,0 Gen=1296
x = 31, y = 26, rule = flashbf8df8
22.A$21.4A$20.9A$19.6A.2A.2A$20.9A$21.4A$22.A3$9.A$8.4A$7.9A$6.6A.2A.
2A$7.9A$8.4A$9.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-21,0 Gen=1296
x = 33, y = 25, rule = flashbf8df8
24.A$23.4A$22.9A$21.6A.2A.2A$22.9A$23.4A$24.A2$11.A$10.4A$9.9A$8.6A.
2A.2A$9.9A$10.4A$11.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-25,0 Gen=288
x = 37, y = 26, rule = flashbf8df8
28.A$27.4A$26.9A$25.6A.2A.2A$26.9A$27.4A$28.A2$15.A$14.4A$13.9A$12.6A
.2A.2A$13.9A$14.4A$15.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=1008
x = 25, y = 28, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A3$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A6$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=432
x = 25, y = 30, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A3$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A8$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-25,0 Gen=2160
x = 37, y = 26, rule = flashbf8df8
28.A$27.4A$26.9A$25.6A.2A.2A$26.9A$27.4A$28.A3$15.A$14.4A$13.9A$12.6A
.2A.2A$13.9A$14.4A$15.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-689,-5
x = 50, y = 39, rule = flashbf8df8
47.3A2$47.A$48.A$45.3A$19.A24.A.A.A$18.5A2.2A16.A.B2.A$17.11A12.2A2.A
3.A$16.7A.A3.A11.2A2.A2.2A$17.11A14.A3.4A$18.5A2.2A9.2A2.A.A5.A$19.A
15.2A3.A.A2.A2.2A$34.3A2.2A2.3A$34.2A3.A4.A$6.A32.2A$5.5A2.2A24.A2.A$
4.11A8.A13.2A.A$3.7A.A3.A5.2A.2A11.2A.A.A$4.11A8.A16.3A$5.5A2.2A$6.A
3$3.A$2.5A2.2A$.11A8.A13.3A4.2A5.2A$7A.A3.A5.2A.2A17.A2.A2.3A$.11A8.A
20.2A5.2A$2.5A2.2A24.2A$3.A28.A3.A$32.A4.A$32.A3.A$33.A2.A$33.3A13.A$
49.A$46.A$45.A.A$45.A.A$46.A!
#CXRLE Pos=-1089,9
x = 50, y = 21, rule = flashbf8df8
14.A23.2A$13.4A20.A2.A$12.9A.4A4.A7.2A$11.6A.2A.3A2.A2.A.A17.A$12.9A.
4A3.2A$13.4A$14.A$47.3A$25.A21.2A$3.A20.A.A22.A$2.4A17.A3.A$.9A.4A8.A
3.A5.2A3.A10.A$6A.2A.3A2.A7.A3.A5.A4.A9.2A$.9A.4A9.A.A12.A8.2A$2.4A
19.A6.2A4.A$3.A28.2A2.B$36.B.A$33.A2.B$33.A4.A$33.A4.A$35.3A!
#CXRLE Pos=-24,0 Gen=864
x = 36, y = 26, rule = flashbf8df8
27.A$26.4A$25.9A$24.6A.2A.2A$25.9A$26.4A$27.A2$14.A$13.4A$12.9A$11.6A
.2A.2A$12.9A$13.4A$14.A5$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=4608
x = 25, y = 28, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A7$9.A$8.4A$7.9A$6.6A.2A.2A$7.9A$8.4A$9.A!
#CXRLE Pos=-13,0 Gen=3240
x = 25, y = 29, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A3$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A7$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
#CXRLE Pos=-13,0 Gen=3240
x = 25, y = 26, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A5$10.A$9.4A$8.9A$7.6A.2A.2A$8.9A$9.4A$10.A!
#CXRLE Pos=-13,0 Gen=108
x = 25, y = 25, rule = flashbf8df8
16.A$15.4A$14.9A$13.6A.2A.2A$14.9A$15.4A$16.A2$3.A$2.4A$.9A$6A.2A.2A$
.9A$2.4A$3.A4$3.A$2.4A$.9A$6A.2A.2A$.9A$2.4A$3.A!
pufferSea3.py
Code: Select all
import golly as g
from glife import *
import random
from time import time
def add_ship(x,y):
g.putcells(ship, x, y, 1, 0, 0, 1, "or")
def add_ships(x_1,y_1,x_2,y_2):
g.select([-10,10,20,20])
g.clear(1)
g.clear(0)
add_ship(0,0)
add_ship(x_1,y_1)
add_ship(x_1+x_2,y_1+y_2)
def custom_run(numstep,delay=0.1):
newsecs=time()
i=0
while time()-newsecs<delay:
g.run(1)
i=i+1
if g.empty(): break
if i==numstep: return True
newsecs=time()
return False
def popcount(rectcoords=g.getrect()):
return int(len(g.getcells(rectcoords))/3)
def headbox():
headbox=g.getrect()
headbox[2]=50
headbox[1]=-40
headbox[3]=80
return(headbox)
def oscillating():
global period,popincr,rate
# return True if the pattern is empty, stable or oscillating
# first get current pattern's bounding box
prect = head
pbox = rect(prect)
if pbox.empty:
g.show("The pattern is empty.")
return True
# get current pattern and create hash of "normalized" version -- ie. shift
# its top left corner to 0,0 -- so we can detect spaceships and knightships
## currpatt = pattern( g.getcells(prect) )
## h = hash( tuple( currpatt(-pbox.left, -pbox.top) ) )
# use Golly's hash command (3 times faster than above code)
h = g.hash(prect)
# check if outer-totalistic rule has B0 but not S8
# rule = g.getrule().split(":")[0]
# hasB0notS8 = rule.startswith("B0") and (rule.find("/") > 1) and not rule.endswith("8")
# determine where to insert h into hashlist
pos = 0
listlen = len(hashlist)
while pos < listlen:
if h > hashlist[pos]:
pos += 1
elif h < hashlist[pos]:
# shorten lists and append info below
del hashlist[pos : listlen]
del genlist[pos : listlen]
del poplist[pos : listlen]
# del boxlist[pos : listlen]
break
else:
# h == hashlist[pos] so pattern is probably oscillating, but just in
# case this is a hash collision we also compare pop count and box size
if (int(popcount(head)) - poplist[pos])==0:
period = int(g.getgen()) - genlist[pos]
bighead=head
bighead[2]=bighead[2]+period
popincr=int(popcount(bighead))-poplist[pos]
rate=float(popincr)/float(period)
if (period % 2 > 0) :
return False
if period == 1:
if True:
g.show("The pattern is stable.")
else:
show_spaceship_speed(1, 0, 0)
elif True:
g.show("Oscillator detected (period = " + str(period) + ")")
return True
else:
# look at next matching hash value or insert if no more
pos += 1
# store hash/gen/pop/box info at same position in various lists
hashlist.insert(pos, h)
genlist.insert(pos, int(g.getgen()))
poplist.insert(pos, int(popcount(head)))
# boxlist.insert(pos, pbox)
return False
def list_reset():
global hashlist,poplist,genlist,boxlist
hashlist=[]
poplist=[]
boxlist=[]
genlist=[]
slist=[]
def fit_if_not_visible():
try:
r = rect(g.getrect())
if (not r.empty) and (not r.visible()): g.fit()
except:
# getrect failed because pattern is too big
g.fit()
g.setrule("flashbf8df8")
trimlim=int(g.getstring("How many trims allowed at most?","3"))
ship=g.parse(g.getstring("RLE string for your seed","3bo$2b4o$b9o$6ob2ob2o$b9o$2b4o$3bo!"))
wd=11
ht=14
wd=13
ht=8
ptn=0
foldername=g.getstring("folder name","temp")
# last=[-9,9,-2,9]
last0=g.getstring("last stopped at?","-50 -50 -50 -50").split()
last=[0]*4
for i in range(4):last[i]=int(last0[i])
# g.note(str(last))
#last=[-9,9,-10,11]
period=0
lowestperiod=int(g.getstring("loweset period to keep?","36"))
slist=[]
def add_section():
global slist,section,slistold,l
slistold=slist
slist+=[0,0,period/2,0]
l=len(slist)/4
def map_sections(slist=slist):
sectionlist=[0]*len(slist)
for i in range(len(slist)/4):
if i==0:
sectionlist[4*i]=head[0]+head[2]
else:
sectionlist[4*i]=sectionlist[4*(i-1)]+period/2
sectionlist[4*i+1]=head[1]
sectionlist[4*i+2]=period/2
sectionlist[4*i+3]=head[3]
return sectionlist
def adjust_head():
old=pattern(g.getcells(g.getrect()))
# COMPARRE FLYING INVARIANCE OF S1
def length_puffer(max=10):
global rate,head
slist=[]
snum=0
add_section()
g.setgen("0")
initial=1
while int(g.getgen())<max*period:
head=headbox()
sections=map_sections()
sirect=sections[4*snum:4*(snum+1)]
# g.note(str(sirect))
sPt=g.getcells(sirect)
try:
hash=g.hash(sirect)
except:
g.note("can't hash %s \n sections=%s"%(str(sirect),str(sections)))
if initial:
initial=0
else:
if snum>=2:
sim1rect=sections[4*(snum-1):4*(snum)]
if g.hash(sirect)==g.hash(sim1rect):
if int(len(g.getcells(sirect))/3)==int(len(g.getcells(sim1rect))/3):
snum=snum-1
rate=float(int(len(g.getcells(sirect))/3))/float(period)
g.select(sirect)
g.show("sections="+str(sections))
# g.exit()
return snum
if hash==hash_old:
if int(len(sPt)/3)==int(len(sPt_old)/3):
snum=snum+1
add_section()
initial=1
continue
sPt_old=sPt
hash_old=hash
g.run(period)
if g.empty():
break
return -1
for x_1 in range(-wd,0):
for y_1 in range(ht,ht*2):
for x_2 in range(-wd,ht):
for y_2 in range(ht,ht*2):
if x_1<=last[0] :
if y_1<=last[1]:
if x_2<=last[2]:
if y_2<=last[3]:
continue
add_ships(x_1,y_1,x_2,y_2)
list_reset()
custom_run(50)
trimnum=0
head=headbox()
osci=oscillating()
while trimnum!=trimlim+1 and not osci :
g.show("%i stored, trimnum=%i, oscillating=%i,period=%i"%(ptn,trimnum,osci,period))
fit_if_not_visible()
before=time()
g.run(2)
after=time()
delay=after-before
if g.empty(): break
head=headbox()
osci=oscillating()
if delay>=0.05:
g.select(head)
temp=g.getcells(head)
g.clear(1)
trimnum=trimnum+1
list_reset()
if trimnum==trimlim+1 or g.empty() or period <lowestperiod:
continue
puffer_len=length_puffer()
if puffer_len!=-1:
filename=g.getdir("patterns")+"/%s/gppPercent%i_puffer%ip_%s_%s_%s_%s_p%i.rle"%(foldername,int(100*rate),puffer_len,x_1,y_1,x_2,y_2,period)
else:
filename=g.getdir("patterns")+"/%s/gppPercent%i_burning_%s_%s_%s_%s_p%i.rle"%(foldername,int(100*rate),x_1,y_1,x_2,y_2,period)
try:
if trimnum==0:
add_ships(x_1,y_1,x_2,y_2)
g.save(filename,"rle",True)
else:
g.store(temp,filename,"rle")
ptn=ptn+1
except:
g.note("can't store")