Skip to content

Commit d79a2fa

Browse files
committed
Added Game of Life implementations.
1 parent 8e7d54f commit d79a2fa

File tree

4 files changed

+231
-7
lines changed

4 files changed

+231
-7
lines changed

gol-tiny.lua

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
local component = require("component")
2+
local event = require("event")
3+
local keyboard = require("keyboard")
4+
local term = require("term")
5+
local unicode = require("unicode")
6+
7+
print("Left click: mark a cell as 'alive'.")
8+
print("Right click: mark a cell as 'dead'.")
9+
print("Space: toggle pause of the simulation.")
10+
print("Q: exit the program.")
11+
print("Press any key to begin.")
12+
os.sleep(0.1)
13+
event.pull("key")
14+
15+
local off = " "
16+
local off2on = unicode.char(0x2593)
17+
local on = unicode.char(0x2588)
18+
local on2off = unicode.char(0x2592)
19+
20+
local gpu = component.gpu
21+
local ow, oh = gpu.getResolution()
22+
gpu.setResolution(27, 15)
23+
local w, h = gpu.getResolution()
24+
gpu.setBackground(0x000000)
25+
gpu.setForeground(0xFFFFFF)
26+
gpu.fill(1, 1, w, h, off)
27+
28+
local function isAlive(x, y)
29+
x = (x + w - 1) % w + 1
30+
y = (y + h - 1) % h + 1
31+
local char = gpu.get(x, y)
32+
return char == on or char == on2off
33+
end
34+
local function setAlive(x, y, alive)
35+
if isAlive(x, y) == alive then
36+
return
37+
end
38+
if alive then
39+
gpu.set(x, y, off2on)
40+
else
41+
gpu.set(x, y, on2off)
42+
end
43+
end
44+
local function flush()
45+
for y = 1, h do
46+
local row = ""
47+
for x = 1, w do
48+
row = row .. gpu.get(x, y)
49+
end
50+
final = row:gsub(on2off, off):gsub(off2on, on)
51+
if final ~= row then
52+
gpu.set(1, y, final)
53+
end
54+
end
55+
end
56+
57+
local function count(x, y)
58+
local n = 0
59+
for rx = -1, 1 do
60+
local nx = x + rx
61+
for ry = -1, 1 do
62+
local ny = y + ry
63+
if (rx ~= 0 or ry ~= 0) and isAlive(nx, ny) then
64+
n = n + 1
65+
end
66+
end
67+
end
68+
return n
69+
end
70+
local function map(x, y)
71+
local n = count(x, y)
72+
return n == 2 and isAlive(x, y) or n == 3
73+
end
74+
local function step()
75+
for y = 1, h do
76+
for x = 1, w do
77+
setAlive(x, y, map(x, y))
78+
end
79+
end
80+
flush()
81+
end
82+
83+
local running = false
84+
while true do
85+
local e = table.pack(event.pull(0.25))
86+
if e[1] == "key_down" then
87+
local _, _, _, code = table.unpack(e)
88+
if code == keyboard.keys.space then
89+
running = not running
90+
elseif code == keyboard.keys.q then
91+
gpu.setResolution(ow, oh)
92+
term.clear()
93+
return
94+
end
95+
elseif e[1] == "touch" then
96+
local _, _, x, y, button = table.unpack(e)
97+
gpu.set(x, y, button == 0 and on or off)
98+
end
99+
if running then
100+
step()
101+
end
102+
end

gol.lua

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
local component = require("component")
2+
local event = require("event")
3+
local keyboard = require("keyboard")
4+
local term = require("term")
5+
local unicode = require("unicode")
6+
7+
print("Left click: mark a cell as 'alive'.")
8+
print("Right click: mark a cell as 'dead'.")
9+
print("Space: toggle pause of the simulation.")
10+
print("Q: exit the program.")
11+
print("Press any key to begin.")
12+
os.sleep(0.1)
13+
event.pull("key")
14+
15+
local off = " "
16+
local on = unicode.char(0x2588)
17+
18+
local gpu = component.gpu
19+
local ow, oh = gpu.getResolution()
20+
gpu.setResolution(27, 15)
21+
local w, h = gpu.getResolution()
22+
gpu.setBackground(0x000000)
23+
gpu.setForeground(0xFFFFFF)
24+
gpu.fill(1, 1, w, h, off)
25+
26+
local buffers = {{}, {}}
27+
local dirty = {}
28+
for y = 1, h do
29+
buffers[1][y] = {}
30+
buffers[2][y] = {}
31+
dirty[y] = false
32+
for x = 1, w do
33+
buffers[1][y][x] = off
34+
buffers[2][y][x] = off
35+
end
36+
end
37+
38+
local function isAlive(x, y)
39+
x = (x + w - 1) % w + 1
40+
y = (y + h - 1) % h + 1
41+
return buffers[1][y][x] == on
42+
end
43+
local function setAlive(x, y, alive)
44+
buffers[2][y][x] = alive and on or off
45+
if isAlive(x, y) ~= alive then
46+
dirty[y] = true
47+
end
48+
end
49+
local function flush()
50+
buffers[1], buffers[2] = buffers[2], buffers[1]
51+
for y = 1, h do
52+
if dirty[y] then
53+
gpu.set(1, y, table.concat(buffers[1][y]))
54+
end
55+
dirty[y] = false
56+
end
57+
end
58+
59+
local function count(x, y)
60+
local n = 0
61+
for rx = -1, 1 do
62+
local nx = x + rx
63+
for ry = -1, 1 do
64+
local ny = y + ry
65+
if (rx ~= 0 or ry ~= 0) and isAlive(nx, ny) then
66+
n = n + 1
67+
end
68+
end
69+
end
70+
return n
71+
end
72+
local function map(x, y)
73+
local n = count(x, y)
74+
return n == 2 and isAlive(x, y) or n == 3
75+
end
76+
local function step()
77+
for y = 1, h do
78+
for x = 1, w do
79+
setAlive(x, y, map(x, y))
80+
end
81+
end
82+
flush()
83+
end
84+
85+
local running = false
86+
while true do
87+
local e = table.pack(event.pull(0.25))
88+
if e[1] == "key_down" then
89+
local _, _, _, code = table.unpack(e)
90+
if code == keyboard.keys.space then
91+
running = not running
92+
elseif code == keyboard.keys.q then
93+
gpu.setResolution(ow, oh)
94+
term.clear()
95+
return
96+
end
97+
elseif e[1] == "touch" then
98+
local _, _, x, y, button = table.unpack(e)
99+
local char = button == 0 and on or off
100+
buffers[1][y][x] = char
101+
gpu.set(x, y, char)
102+
end
103+
if running then
104+
step()
105+
end
106+
end

programs.cfg

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
{
22
["geo2holo"] = {
33
files = {
4-
["master/geo2holo.lua"] = "/bin"
4+
["master/geo2holo.lua"] = "/bin"
55
},
66
name = "Terrain Visualizer",
77
description = "Will plot the terrain surrounding the Geolyzer to the Hologram.",
88
authors = "Sangar",
99
note = "Requires a Geolyzer and a Hologram Projector.",
1010
},
11+
["gol"] = {
12+
files = {
13+
["master/gol.lua"] = "/bin",
14+
["master/gol-tiny.lua"] = "/bin"
15+
},
16+
name = "Conway's Game of Life",
17+
description = "Simple implementations of the well-known cellular automaton Game of Life.",
18+
authors = "Sangar",
19+
note = "The 'tiny' version requires much less RAM, but also runs a lot slower."
20+
},
1121
["holo-demos"] = {
1222
files = {
13-
["master/holo-flow.lua"] = "/bin",
14-
["master/holo-text.lua"] = "/bin"
23+
["master/holo-flow.lua"] = "/bin",
24+
["master/holo-text.lua"] = "/bin"
1525
},
1626
dependencies = {
17-
["libnoise"] = "/lib"
27+
["libnoise"] = "/lib"
1828
},
1929
name = "Hologram Demos",
2030
description = "Useful example programs for the Hologram block.",
@@ -23,7 +33,7 @@
2333
},
2434
["midi"] = {
2535
files = {
26-
["master/midi.lua"] = "/bin"
36+
["master/midi.lua"] = "/bin"
2737
},
2838
name = "Crappy MIDI Player",
2939
description = "Can be used to play real MIDI files using either Note Blocks or the built-in speakers.",
@@ -32,7 +42,7 @@
3242
},
3343
["libnoise"] = {
3444
files = {
35-
["master/noise.lua"] = "/lib"
45+
["master/noise.lua"] = "/lib"
3646
},
3747
name = "Perlin Noise Library",
3848
description = "This package provides a library for generating Perlin noise, and some utility methods.",
@@ -41,7 +51,7 @@
4151
},
4252
["derp"] = {
4353
files = {
44-
["master/idontexist.lua"] = "/bin"
54+
["master/idontexist.lua"] = "/bin"
4555
},
4656
name = "Missing File Test",
4757
description = "Test for OPPM's behavior if files are missing.",

programs.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
geo-scan:
22
/blob/master/geo-scan.lua
33
Creates a holographic image of the surrounding area.
4+
gol:
5+
/blob/master/gol.lua
6+
Conway's Game of Life.
7+
gol-tiny:
8+
/blob/master/gol-tiny.lua
9+
Also Conway's Game of Life, but should run on a toaster (uses the screen for state storage). Less performant as a direct result.
410
holo-flow:
511
/blob/master/holo-flow.lua
612
Creates a scrolling, terrain like hologram.

0 commit comments

Comments
 (0)