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
133
134
135
136
137
138
139
140
141
142
143
144 | pico-8 cartridge // http://www.pico-8.com
version 37
__lua__
w,h=100,15 -- constant: size of the adder.
ini=split"32,26,20,14,8,2" -- a lookup table of the x-positions for each of the input bits.
oui=split"91,85,79,73,67,61" -- a mystery line that never got used, left for your amusement.
function bits(n,y,i) -- function: set bits ON for input Y given number N.
-- this travels through each bit in a number and sets
-- the CA cell to an electron if the bit is on.
i=1 -- * start at first bit.
while n>0 do -- * while number is positive.
r=n%2 -- * get modulo 2 of number (even numbers yield 0).
n=(n-r)/2 -- * reduce number by result of above, then halve it.
if r==1 then -- * if number is odd.
x=ini[i] -- * lookup the x position for this bit.
ww[y][x]=12 -- * set electron head.
ww[y][x-1]=7 -- * set electron tail.
end
i+=1 -- * move to next bit.
end
end
function _init() -- program entry.
poke(0x5f5c,30) -- set custom keypress delay to 30 ticks,
poke(0x5f5d,30) -- repeat for key-repeat.
ww={} -- storage for the wireworld cells.
tf={a=12,b=7,c=9} -- there are three states in wireworld:
-- * copper wire (orange:9)
-- * electron tail (white:7)
-- * electron head (blue:12)
-- a fourth color (green:3) is our insulator.
-- next up we have our binary adder in RLE form.
-- the split function returns a table of values
-- split at commas (these demarcate the rows).
r=split"2c4.2c4.2c4.2c4.2c4.2c15.6c,46.c6.c5.2c4.2c4.2c4.2c4.2c4.2c4.2c,37c5.4c2.2c2.4c,37.c3.c5.c2.b.c2.42c,4c2.c.c4.2c3.c.c3.2c5.c4.4c.c3.c.2ca2.4c,.c.c2.c.2c3.2c3.3c4.c5.c4.c2.2c.5c6.c3.c.c.c2.4c3.c.c4.2c3.c.c3.2c5.c,2c.2c.c.2c3.2c5.c4.2c4.c4.4c.c3.c.c4.c4.5c3.c.c3.c.2c3.2c3.3c4.c5.c,37.c3.c5.c3.c5.2c2.c2.2c.2c2.c.2c3.2c5.c4.2c4.c,38c2.3c3.3c.c,38.c2.c5.c2.c,2c4.2c4.2c4.2c4.2c4.2c6.c.c.c3.c.2c,38.c.c.c3.c.c,39.c2.c2.3c,42.c3.c,43.3c"
for y=1,#r do -- this loop decodes the RLE:
ww[y]={} -- add a new row to ww.
d=r[y] -- store this row string in d.
m=""
for x=1,#d do -- process each character in d.
v=d[x]
if tonum(v) then -- concat numbers together.
m..=v
else
p=tonum(m) or 1 -- parse numbers, defaults to 1.
for n=1,p do -- lookup value v in tf (defaults to insulator 3)
add(ww[y],tf[v] or 3) -- then add it p-times to the world.
end
m=""
end
end
end
tm=1 -- set a timer.
fx=1 -- set state (1: wait for button press)
st="" -- clear status text.
end
function _update() -- update loop.
tm-=1/2 -- reduce timer.
if fx==0 and tm<0 then -- test if in running state.
print"\ac1g" -- bip-bip-bip.
tm=btn()>0 and 0 or 1 -- speed up simulation by holding button.
ti+=1 -- step CA generation.
cp={} -- storage for next generation.
for y=1,h do -- evolve each cell in wire world:
cp[y]={} -- * new row.
for x=1,w do -- * next column.
cp[y][x]=tnb(x,y,ww[y][x]) -- * transform and store new cell value via tnb call.
end -- I don't recall what tnb means.
end -- let's go with tasty new bananas. that works.
ww=cp -- persist the new generation.
if ti==66 then -- the calculation is complete, show the answer.
fx=1 -- 66 is the number of generations to solve the problem.
ans="="..a+b
end
elseif btnp()>0 then -- button pressed.
if fx==1 then -- in waiting state.
ans=nil -- reset calculation state.
ti=0 -- ...
fx=2 -- ...
a=flr(rnd(63)) -- pick random number "a".
b=nil -- empty "b".
bits(a,3) -- set a-bits.
st="rolling dice"
elseif fx==2 then
fx=3 -- ...
b=flr(rnd(63)) -- pick random number "b".
bits(b,9) -- set b-bits.
elseif fx==3 then -- end of calculation state.
st="" -- ...
fx=0 -- ...
end
end
end
function _draw() -- render loop.
cls(3) -- ...
print("\^pwireworld",1,1,10)
print("binary adder",74,5,11)
print("\^ipico-1k jam 2022",30,14,15)
print(st,4,122,7)
for y=1,h do -- plot the current state of wire world cells.
for x=1,w do
pset(x+13,y+60,ww[y][x] or 3)
end
end
print(a or "",5,59,14) -- not much else to see here,
if(a)print("+",2,64,14) -- unless you love reading
print(b or "",5,69,14) -- "print" and "or".
print(ans or "",112,61,11)
if fx==0 and flr(time())%2==0 then print("working",4,122,10)end
end
function tnb(x,y,o,c) -- function: evolves a wireworld cell.
-- this is the crux of wireworld, the
-- brevity of this function is exemplary
-- to the simplicity of this CA.
-- the rest of the code is only
-- data-and-state management.
-- the arguments are:
-- * x,y: cell coordinate.
-- * o: current value.
-- * c: not passe1 (variable optimization).
if o==12 then return 7 -- head turns to tail.
elseif o==7 then return 9 -- tail turns to copper.
elseif o~=9 then return o end -- non-copper (insulator) stays as-is.
c=0 -- this code is only reached for copper (9):
for a=-1,1 do -- it counts the number of
for b=-1,1 do -- electron heads in the moore-neighborhood region
if ww[y+a] and ww[y+a][x+b]==12 then
c+=1
end
end
end
return c>0 and c<3 and 12 or o -- turn into electron head if
end -- the cell has 1 or 2 neighbors,
-- otherwise it stays as-is.
|