Last active
September 24, 2024 09:19
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
rev 5 Stop being a left leaning coder (bolchevik) and be a centrist. Now all Galton are belong to us
output2.mp4