Cellular automata
from collections import defaultdict | |
import sys | |
from svg import * | |
def log(*a, **k): | |
print(*a, **k, file=sys.stderr) | |
ROWS = 16 | |
STOP_AFTER = ROWS | |
COLS = ROWS*2-1 | |
BOXSIZE = 16 | |
HEADER_HEIGHT = BOXSIZE * ROWS * (3/4) | |
NOM_WIDTH = COLS * BOXSIZE + 1 + 20 | |
NOM_HEIGHT = NOM_WIDTH // 2 ** 0.5 | |
NOM_YBIAS = NOM_HEIGHT - (ROWS * BOXSIZE + 10) | |
IMG_HEIGHT = 1024 | |
IMG_WIDTH = IMG_HEIGHT / NOM_HEIGHT * NOM_WIDTH | |
RULE_GAP = 2 | |
RULE_MGAP = 3 | |
RULE_MARGIN = 2 | |
if len(sys.argv) > 1: | |
rule = int(sys.argv[1]) | |
else: | |
rule = 30 | |
# Basic header | |
svg_header() | |
svg_open(width=IMG_WIDTH, height=IMG_HEIGHT, | |
x_bias=-(NOM_WIDTH-1)/2-1, y_bias=-NOM_YBIAS+12, | |
xw=NOM_WIDTH+1, yh=NOM_HEIGHT+1) | |
def draw_box(x, y, value=None, scale=1): | |
svg_rect((x*scale, y*scale), scale*BOXSIZE, scale*BOXSIZE, | |
fill="black" if value else "white", | |
stroke="grey", stroke_width=scale) | |
def draw_cell(row, col, value=None, scale=1): | |
draw_box(BOXSIZE*(col-0.5), BOXSIZE*row, | |
value=value, scale=scale) | |
#def draw_rule(x, y, n): | |
# scale = COLS / (4*3 + 3*RULE_GAP + 2*RULE_MARGIN) | |
# draw_box((x - 1.5)*BOXSIZE, y * BOXSIZE , n & 4 != 0 , scale) | |
# draw_box((x - 0.5)*BOXSIZE, y * BOXSIZE , n & 2 != 0 , scale) | |
# draw_box((x + 0.5)*BOXSIZE, y * BOXSIZE , n & 1 != 0 , scale) | |
# draw_box((x - 0.5)*BOXSIZE, (y + 1) * BOXSIZE, rule & (1 << n) != 0, scale) | |
# | |
#draw_rule(-(3 + RULE_MGAP)/2 - 3 - RULE_GAP, -7, 7) | |
#draw_rule(-(3 + RULE_MGAP)/2 , -7, 6) | |
#draw_rule( (3 + RULE_MGAP)/2 , -7, 5) | |
#draw_rule( (3 + RULE_MGAP)/2 + 3 + RULE_GAP, -7, 4) | |
#draw_rule(-(3 + RULE_MGAP)/2 - 3 - RULE_GAP, -3, 3) | |
#draw_rule(-(3 + RULE_MGAP)/2 , -3, 2) | |
#draw_rule( (3 + RULE_MGAP)/2 , -3, 1) | |
#draw_rule( (3 + RULE_MGAP)/2 + 3 + RULE_GAP, -3, 0) | |
def draw_rule(row, col, n): | |
draw_cell(row, col - 1, n & 4 != 0) | |
draw_cell(row, col, n & 2 != 0) | |
draw_cell(row, col + 1, n & 1 != 0) | |
draw_cell(row + 1, col, rule & (1 << n) != 0) | |
draw_rule(-4, -14, 7) | |
draw_rule(-4, -10, 6) | |
draw_rule(-4, -6, 5) | |
draw_rule(-4, -2, 4) | |
draw_rule(-4, 2, 3) | |
draw_rule(-4, 6, 2) | |
draw_rule(-4, 10, 1) | |
draw_rule(-4, 14, 0) | |
cells = defaultdict(lambda: False) | |
cells[(0,0)] = True | |
draw_cell(0, 0, cells[(0,0)]) | |
for j in range(1, ROWS): | |
if j >= STOP_AFTER: | |
for i in range(-j, j+1): | |
draw_cell(j, i, False) | |
continue | |
for i in range(-j, j+1): | |
prev = 4 * cells[(j-1, i-1)] | |
prev += 2 * cells[(j-1, i )] | |
prev += 1 * cells[(j-1, i+1)] | |
cells[(j,i)] = rule & (1 << prev) != 0 | |
draw_cell(j, i, cells[(j,i)]) | |
# Footer | |
svg_close() |
def xml(tag, _xml_tag_is_a_singleton=True, **options): | |
s = f'<{tag}' | |
kw_attrib = lambda x: x.replace('_', '-') | |
if options: | |
s += ' ' | |
s += ' '.join(f'{kw_attrib(k)}="{str(v)}"' for k, v in options.items()) | |
if _xml_tag_is_a_singleton: | |
s += ' />' | |
else: | |
s += '>' | |
print(s) | |
def xml_open(*args, **kwargs): | |
xml(*args, **kwargs, _xml_tag_is_a_singleton=False) | |
def xml_close(tag): | |
print(f'</{tag}>') | |
def svg_header(): | |
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>' | |
def svg_open(width, height, x_bias, y_bias, xw, yh): | |
vb = f'{x_bias} {y_bias} {xw} {yh}' | |
ns = 'http://www.w3.org/2000/svg' | |
xml_open('svg', width=width, height=height, viewBox=vb, xmlns=ns) | |
def svg_close(): | |
xml_close('svg') | |
def svg_poly(*points, **opts): | |
point_str = ' '.join(f'{x},{y}' for x, y in points) | |
xml('polyline', points=point_str, **opts) | |
def svg_circle(point, radius, **opts): | |
xml('circle', cx=point[0], cy=point[1], r=radius, **opts) | |
def svg_line(p1, p2, **opts): | |
xml('line', x1=p1[0], y1=p1[1], x2=p2[0], y2=p2[1], **opts) | |
def svg_rect(p, width, height, x_radius=0, y_radius=0, **opts): | |
xml('rect', x=p[0], y=p[1], width=width, height=height, | |
rx=x_radius, ry=y_radius, **opts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment