forked from zeroflag/punyforth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample-game-of-life-ws2812.forth
132 lines (115 loc) · 3.2 KB
/
example-game-of-life-ws2812.forth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
GPIO load
\ 8x8 pixel ws2812 led matrix game of life written in Punyforth
\ see it in action: https://youtu.be/XMPZt5o3QAc
64 array: world
5 constant: PIN ( data pin of ws2812 )
16r000000 constant: DEAD
16r250025 constant: DYING
16r08040C constant: LIVE
16r000C00 constant: BORN
: clamp ( n -- n ) 7 and ;
: north ( x y -- x' y' ) 1- clamp ;
: south ( x y -- x' y' ) 1+ clamp ;
: west ( x y -- x' y' ) swap 1- clamp swap ;
: east ( x y -- x' y' ) swap 1+ clamp swap ;
: north-east ( x y -- x' y' ) swap 1+ clamp swap 1- clamp ;
: south-east ( x y -- x' y' ) swap 1+ clamp swap 1+ clamp ;
: south-west ( x y -- x' y' ) swap 1- clamp swap 1+ clamp ;
: north-west ( x y -- x' y' ) swap 1- clamp swap 1- clamp ;
: >i ( x y -- idx ) 3 lshift + ;
: set! ( x y state -- ) -rot >i world ! ;
: at ( x y -- n ) >i world @ ;
: live? ( x y -- bool ) at LIVE = ;
: dead? ( x y -- bool ) at DEAD = ;
: kill ( x y -- ) 2dup live? if DYING set! else 2drop then ;
: live ( x y -- ) 2dup dead? if BORN set! else 2drop then ;
: status ( x y -- 0/1 ) at dup LIVE = swap DYING = or 1 and ;
: xyover ( x y n -- x y n x y ) >r 2dup r> -rot ;
: neighbours ( x y -- n )
2dup north status
xyover north-east status +
xyover east status +
xyover south-east status +
xyover south status +
xyover south-west status +
xyover west status +
-rot north-west status + ;
: evolve ( -- )
8 0 do
8 0 do
i j status i j neighbours or 3 = \ newstatus = (oldstatus | #neighbors) == 3.
if i j live else i j kill then
loop
loop ;
: finalize ( -- )
64 0 do i world @
case
DYING of DEAD i world ! endof
BORN of LIVE i world ! endof
drop
endcase
loop ;
: paint ( color -- ) PIN ws2812rgb ;
: show ( -- ) os-enter-critical 64 0 do i world @ paint loop os-exit-critical ;
: generations ( n -- ) 0 do evolve show 100 ms finalize show 100 ms loop ;
: seed ( -- ) random clamp random clamp live ;
: randomize ( n -- ) 0 do seed loop ;
: destroy ( -- ) 64 0 do 0 i world ! loop ;
: load ( buffer -- ) 64 0 do dup i cells + @ i world ! loop drop ;
: # LIVE , ;
: _ DEAD , ;
create: INFINITE
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ # # # _ _
_ _ # _ _ # _ _
_ _ # # # _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
create: ACORN
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ # _ _ _ _ _
_ _ _ _ # _ _ _
_ # # _ _ # # #
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
create: GLIDER
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ # _ _ _ _
_ _ _ _ # _ _ _
_ _ # # # _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
create: CALLAHANS
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ # # # _ # _ _
_ # _ _ _ _ _ _
_ _ _ _ # # _ _
_ _ # # _ # _ _
_ # _ # _ # _ _
_ _ _ _ _ _ _ _
PIN GPIO_OUT gpio-mode
wifi-stop ( ws2812 requires precise timing )
: curtain ( -- )
destroy show
8 0 do
8 0 do
i j 16r1F0212 set!
loop
show 50 ms
loop
destroy show 50 ms ;
: demo ( -- )
curtain
INFINITE load 50 generations 100 ms
ACORN load 29 generations 100 ms
GLIDER load 30 generations 100 ms
15 randomize 10 generations 100 ms
CALLAHANS load 13 generations 100 ms
curtain ;