Skip to content

Instantly share code, notes, and snippets.

@jul
Last active October 14, 2024 13:03
Show Gist options
  • Save jul/c164cf6e3e6cb2376afeb17aa822f9c1 to your computer and use it in GitHub Desktop.
Save jul/c164cf6e3e6cb2376afeb17aa822f9c1 to your computer and use it in GitHub Desktop.
evaluating if an hexagonal patterned game of life can be used as a PRNG (spoiler : NO)
from time import time, sleep
import select
from subprocess import Popen, PIPE
from random import randint
import random
from os import system
import os
ORD=0
SZ=12
DIMX=64
DIMY=64
SSP=50
old_alivep=set()
new_alivep=set()
old_alive=set()
new_alive=set()
dead_alive_percent=50
pause=False
print_board=True
set_alive={ 3, 4, 5}
set_dead={ 3, 4, 5}
old_old_samplep=0
old_samplep=0
samplep = 0
old_old_sample=0
old_sample=0
sample = 0
sample_mask=set([])
plt_pause = False
system("rm *ps output2.mp4 ev*.jpg")
seed=int(time())
print("seed %d" % seed)
random.seed(seed)
save_canvas = True
ORD=1
# let's talk to tk/tcl directly
p = Popen(['wish'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
os.set_blocking(p.stdout.fileno(), False)
os.set_blocking(p.stdin.fileno(), False)
os.set_blocking(p.stderr.fileno(), False)
n=0
def puts(s):
global n
n+=1
for l in s.split("\n"):
select.select([], [p.stdin],[])
p.stdin.write((l + "\n").encode())
if back := p.stderr.read():
print("TCL>" + back.decode())
def gets():
ret=p.stdout.read()
if ret:
print(ret)
exec(ret, globals(), )
puts(f"""
package require Tk
set code [ catch {{
source /usr/share/tcltk/ttkthemes/themes/plastik/plastik.tcl
ttk::style theme use plastik
}} pass ]
set status 0
proc SaveAsC {{}} {{
set out [tk_getSaveFile]
set code [ catch {{.c postscript -file $out }} result ]
if {{$result != ""}} {{
error $result
}}
}}
proc SaveAsC2 {{}} {{
set out [tk_getSaveFile]
set code [ catch {{.c2 postscript -file $out }} result ]
if {{$result != ""}} {{
error $result
}}
}}
proc SaveAsC3 {{}} {{
set out [tk_getSaveFile]
set code [ catch {{.c3 postscript -file $out }} result ]
if {{$result != ""}} {{
error $result
}}
}}
proc SaveAsC4 {{}} {{
set out [tk_getSaveFile]
set code [ catch {{.c4 postscript -file $out }} result ]
if {{$result != ""}} {{
error $result
}}
}}
if {{$code}} {{
puts "print('theme not found, fallback to ugly tcl/tk look')"
puts "print('on debian : apt install tcl-ttkthemes to have ttkthemes installed')"
}}
pack [ ttk::frame .t ]
pack [ ttk::frame .tt1 ] -in .t -anchor s -side left
pack [ ttk::frame .tt2 ] -in .t -anchor s -side left
pack [ ttk::frame .tt3 ] -in .t -anchor s -side left
pack [ ttk::label .ll2 -text "board of the game of life" ] -in .tt1
pack [ canvas .c -width {DIMX*SZ*1.01} -height { DIMY*SZ*.87 } -bg white ] -in .tt1 -anchor s
pack [ttk::button .bc -text "Save as postscript" -command SaveAsC ] -in .tt1 -anchor s
pack [ ttk::label .ll1 -text "x,y = u(n-1),u(n) aka Takens Serie " ] -in .tt2 -anchor s
pack [ canvas .c2 -width {DIMX*SZ*1.01//2} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt2 -anchor s
.c configure -bg white
pack [ttk::button .bc2 -text "Save as postscript" -command SaveAsC2 ] -in .tt2 -anchor s
pack [ ttk::label .ll3 -text "Takens Serie for perturbed serie" ] -in .tt2 -anchor s
pack [ canvas .c3 -width {DIMX*SZ//2*1.01} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt2 -anchor s
pack [ttk::button .bc3 -text "Save as postscript" -command SaveAsC3 ] -in .tt2 -anchor s
pack [ ttk::label .ll4 -text "Takens Serie for random" ] -in .tt3 -anchor s
pack [ canvas .c4 -width {DIMX*SZ//2*1.01} -height { DIMY*SZ*.87//2 } -bg white ] -in .tt3 -anchor s
pack [ttk::button .bc4 -text "Save as postscript" -command SaveAsC4 ] -in .tt3 -anchor s
pack [ ttk::frame .first ] -expand true -fill both -anchor s
pack [ ttk::label .s -textvariable status ] -anchor s -in .first
pack [ ttk::frame .f ] -anchor s -expand true -fill both
pack [ ttk::frame .center ] -anchor s -in .f
ttk::button .r -text Reset -command {{ puts seed() }}
ttk::button .b -text Pause -command {{ puts pause^=True }}
ttk::button .quit -text Quit -command {{ destroy . }}
pack .r .b .quit -in .center -anchor se -side left
pack [ ttk::labelframe .rules -text "rules change" ] -in .f -expand true -fill both -padx 5 -pady 5
pack [ ttk::frame .g ] -anchor s -expand true -fill both -in .rules -padx 5
pack [ ttk::checkbutton .v1 -text 1 -command {{ puts "seed();set_alive^=set({1,})" }}] -in .g -anchor w -side left
pack [ ttk::label .s1 -text " " ] -in .g -anchor w -side left
pack [ ttk::checkbutton .v2 -text 2 -command {{ puts "seed();set_alive^=set({2,})" }}] -in .g -anchor w -side left
pack [ ttk::label .s2 -text " " ] -in .g -anchor w -side left
pack [ ttk::checkbutton .v3 -text 3 -onvalue 1 -variable a -command {{ puts "seed();set_alive^=set({3,})" }}] -in .g -anchor w -side left
set a 1
set b 1
set c 1
set d 1
set e 1
set f 1
pack [ ttk::label .s3 -text " " ] -in .g -anchor w -side left
pack [ ttk::checkbutton .v4 -text 4 -onvalue 1 -variable b -command {{ puts "seed();set_alive^=set({4,})" }}] -in .g -anchor w -side left
pack [ ttk::label .s4 -text " " ] -in .g -anchor w -side left
pack [ ttk::checkbutton .v5 -text 5 -onvalue 1 -variable c -command {{ puts "seed();set_alive^=set({5,})" }}] -in .g -anchor w -side left
pack [ ttk::label .s5 -text " " ] -in .g -anchor w -side left
pack [ ttk::checkbutton .v6 -text 6 -command {{ puts "seed();set_alive^=set({6,})" }}] -in .g -anchor w -side left
pack [ ttk::label .s6 -text " " ] -in .g -anchor w -side left
pack [ ttk::label .v -text "neighbour alive to give life" ] -in .g -anchor w -side left
pack [ ttk::frame .h ] -anchor s -expand true -fill both -in .rules -padx 5
pack [ ttk::checkbutton .d1 -text 1 -command {{ puts "seed();set_dead^=set({1,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t1 -text " " ] -in .h -anchor w -side left
pack [ ttk::checkbutton .d2 -text 2 -command {{ puts "seed();set_dead^=set({2,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t2 -text " " ] -in .h -anchor w -side left
pack [ ttk::checkbutton .d3 -text 3 -onvalue 1 -variable d -command {{ puts "seed();set_dead^=set({3,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t3 -text " " ] -in .h -anchor w -side left
pack [ ttk::checkbutton .d4 -text 4 -onvalue 1 -variable e -command {{ puts "seed();set_dead^=set({4,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t4 -text " " ] -in .h -anchor w -side left
pack [ ttk::checkbutton .d5 -text 5 -onvalue 1 -variable f -command {{ puts "seed();set_dead^=set({5,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t5 -text " " ] -in .h -anchor w -side left
pack [ ttk::checkbutton .d6 -text 6 -command {{ puts "seed();set_dead^=set({6,})" }}] -in .h -anchor w -side left
pack [ ttk::label .t6 -text " " ] -in .h -anchor w -side left
pack [ ttk::label .d -text "neighbour dead to give life" ] -in .h -anchor w -side left
pack [ ttk::frame .l ] -expand true -fill both -in .rules -padx 5 -pady 5
set seed 50
pack [ ttk::spinbox .sc -width 4 -from 0 -to 100 -textvariable seed -command {{
puts "dead_alive_percent=$seed;seed()"
}}
] -in .l -anchor w -side left
pack [ ttk::label .scl -text " re seed session with a different percentage of dead/alive ratio" ] -in .l -anchor w -side left
pack [ ttk::frame .k ] -expand true -fill both
pack [ ttk::checkbutton .tb -text "disable printing of board" -command "puts {{print_board^=True}}" ] -in .k -anchor w -side left -padx 5 -pady 5
#.tb invoke
pack [ ttk::frame .kk ] -expand true -fill both
pack [ ttk::checkbutton .tcv -text "disable saving of canvas" -command "puts {{save_canvas^=True}}" ] -in .kk -anchor w -side left -padx 5 -pady 5
.tcv invoke
""")
def save(name="save"):
global ORD, save_canvas
ORD+=1
puts(f"set status {ORD}")
puts(f""".c postscript -file {name}-{"%04d"% ORD}.ps""")
puts(f""".c2 postscript -file t{name}-{"%04d"% ORD}.ps""")
def cell(x,y, **kw):
hs=0.866 # heigth of an equilateral triangle
px,py=x/2-1/2*(y%2),y-2/3
#px,py=x-(y%2),y-2/3
xr,yr=px*SZ+SZ,py*hs*SZ+SZ
# triangle compliqué à dessiner
r=SZ/2
#from pdb import set_trace; set_trace()
puts(f"""
.c create oval {xr-r} {yr-r} {xr+r} {yr+r} -width 0 -outline "" {["","-fill black "][kw.get("state","dead")=="alive"]} -tags [ list "p:{x//2},{y}" ]\n""")
def get_neighbour(x,y):
ye = [(-1, -1), (1, 0), (0, -1), (-1, 1), (-1,0), (0, 1)]
yo= [(1, 1), (-1, 0), (0, -1), (1, 0), (0, 1), (1, -1) ]
return set( ((dxdy[0]+x)%DIMX,(y+dxdy[1])%DIMY) for dxdy in [yo,ye][y%2])
def clear():
global ORD
ORD=0
system("rm *ps output2.mp4 ev*.jpg")
puts(".c delete all")
puts(".c2 delete all")
puts(".c3 delete all")
puts(".c4 delete all")
pick_sample()
def pick_entropy(board, _from, _to,w=0):
entropy=0
for o,i in enumerate(range(_from, _from+_to*2,2)):
if (w,i) in board:
entropy |= 1<<o
return entropy
def flipbit(board,w):
for i in range(0,10):
board ^= {(pick_entropy(board,i*6,6,w), pick_entropy(board,(i+1)*6,6,w))}
def seed():
global old_alive, dead_alive_percent, old_alivep
clear()
for x in range(0,DIMX*2,2):
for y in range(DIMY):
state = randint(0, 100) >= dead_alive_percent and "alive" or "dead"
if state=="alive":
old_alive|= {(x/2,y),}
cell(
x,
y,
state=state,
outline="black")
old_alivep = old_alive.copy()
for i in range(64):
flipbit(old_alivep,i)
def live_neighbour(x,y,board):
return sum(map(lambda x : x in board,get_neighbour(x,y)))
def pick_sample():
global sample_mask
sample_mask=set([])
for i in range(SSP):
x, y=(randint(0, DIMX),randint(0, DIMY))
sample_mask |= set([( x, y, )])
def plot_sample():
global old_sample, old_old_sample, old_old_samplep, sample_mask, new_alive, ORD, SZ, sample, sample_array, plt_pause, samplep, old_samplep, new_alivep, old_alivep
old_old_sample=old_sample
old_sample = sample
sample = 0
old_old_samplep=old_samplep
old_samplep = samplep
samplep = 0
for i, coord in enumerate(sample_mask):
if coord in new_alive:
sample |= 1<<i
if coord in new_alivep:
samplep |= 1<<i
_max = ((1<<(len(sample_mask))))
r=_max//512
if ORD > 1:
_max = ((1<<(len(sample_mask))) // SZ*2)
cr=.8
x = old_sample
y = sample
puts(f""".c2 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max}""")
x = old_samplep
y = samplep
puts(f""".c3 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max} """)
random.seed(ORD)
x=randint(0,_max*6)
y=randint(0,_max*6)
random.seed(time())
puts(f""".c4 create oval {(x -r)*DIMX*cr//_max} {(y -r )*DIMY*cr//_max} {(x+r)*DIMX*cr//_max} {(y+r)*DIMY*cr//_max} """)
def will_live(x,y, old_board, new_board):
global set_dead, set_alive
ostate = (x,y) not in old_board and 'dead' or "alive"
lively = live_neighbour(x,y, old_board)
#print("%d-%d:%s:%d" % (x,y,ostate,lively))
state = ( ostate == "alive" and lively in set_alive ) or (
ostate == "dead" and lively in set_dead )
if(state):
new_board |= {(x,y),}
return state
seed()
save("ev")
while True:
gets()
sleep(0.0001)
while pause:
sleep(.1)
gets()
for x in range(DIMX):
for y in range(DIMY):
will_live(x,y, old_alivep, new_alivep)
will_live(x,y, old_alive, new_alive)
print_board and puts(f""".c itemconfigure "p:{x},{y}" -fill {["white","lightgray", "darkgray", "black"][((x,y) in new_alive) + 2* ((x,y) in new_alivep)]}""")
flipbit(new_alivep,0)
flipbit(new_alivep,1)
plot_sample()
puts("update")
old_alive=new_alive
old_alivep=new_alivep
new_alive=set()
new_alivep=set()
save("ev")
@jul
Copy link
Author

jul commented Oct 13, 2024

takens2

@jul
Copy link
Author

jul commented Oct 14, 2024

interface2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment