Skip to content

Instantly share code, notes, and snippets.

@jul
Last active September 24, 2024 09:19
Show Gist options
  • Save jul/37f418aefd27b69bb213fe1e2a563bfd to your computer and use it in GitHub Desktop.
Save jul/37f418aefd27b69bb213fe1e2a563bfd to your computer and use it in GitHub Desktop.
experiment #1543 making a cellular automata on hexagonal network of stuff falling (black) with obstacles (red)
import FreeSimpleGUI as sg
SZ=15
DIMX=50
DIMY=85
can = sg.Canvas(size=(DIMX*SZ*1.01,DIMY*SZ*.87))
status=sg.Text('status')
win = sg.Window("titre",[[can,],[status,],], finalize=True)
c = can.TKCanvas
from time import sleep, time
from random import randint, shuffle
from os import system
system("rm *ps output2.mp4 ev*.jpg")
seed=int(time())
seen=set()
old_filled=set()
new_filled=set()
obstacle=set()
ORD=1
def save(canvas, name="save"):
global ORD
with open("%s-%04d.ps"% (name, ORD), "w") as f:
ORD+=1
status.update("%4d" % ORD)
f.write(canvas.postscript())
def filled(x,y,c=c):
global old_filled, to_remove,new_filled, obstacle
if (x,y) in obstacle:
return False
if not (x,y) in old_filled:
#free fall
for nx, ny in get_top_neighbour(x,y)[::(1,-1)[randint(0,1)]]:
if (nx,ny) in old_filled and not (nx,ny) in obstacle:
new_filled |= {(x,y)}
old_filled -= {(nx,ny)}
return True
else:
# blocked by an obstacle
new_filled |= { (x,y)}
return True
return False
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
r=SZ/2
i=c.create_oval(xr-r,yr-r,xr+r,yr+r,
fill=["","black"][kw.get("state","empty")=="filled"], outline="",
tags=("p:%d,%d" % (x/2,y),))
return i
def get_top_neighbour(x,y):
ye = [ (0,-1),(-1,-1) ]
yo = [ (0,-1),(1,-1) ]
to_ret= list( ((dxdy[0]+x)%DIMX,(y+dxdy[1])%DIMY) for dxdy in [yo,ye][y%2] )
return to_ret[::-1]
def randrange(*x):
c=list(range(*x))
shuffle(c)
return c
c.configure(bg="green")
for y in range(DIMY):
for x in range(0,DIMX*2,2):
state="empty"
if (x+y > DIMX and x-y<DIMX):
if y%7==0 and y+30<DIMY:
if x %8 in { 0,2} :
obstacle |= {(x/2,y)}
if y%7==3 and y+30<DIMY:
if x %8 in {4,6} :
obstacle |= {(x/2,y)}
if y+30>DIMY:
if x%3==1:
obstacle |= {(x/2,y)}
if y+1==DIMY:
obstacle |= {(x/2,y)}
elt=cell(
x,
y,
state=state,
outline="black")
c.itemconfigure("p:%d,%d" % (x/2,y),fill="red" if (x/2,y) in obstacle else '')
seen.update(((x,y),),)
def randrange(*x):
c = list(range(*x))
shuffle(c)
return c
ORD=0
save(c, "ev")
for i in range(350):
if i%2==0 and i < 200:
for x in range((DIMX//2)-1, (DIMX//2)+2):
old_filled |= {(x,0)}
for y in range(DIMY,0,-1):
for x in randrange(DIMX):
if filled(x,y):
c.itemconfigure("p:%d,%d" % (x,y),fill="black")
else:
c.itemconfigure("p:%d,%d" % (x,y),fill="red" if (x,y) in obstacle else "")
c.update()
old_filled=new_filled
to_remove=set()
save(c, "ev")
new_filled=set()
@jul
Copy link
Author

jul commented May 6, 2024

rev 5 Stop being a left leaning coder (bolchevik) and be a centrist. Now all Galton are belong to us

output2.mp4

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