Add wireworld!

main
mat ess 2022-09-14 23:05:05 -04:00
parent 212948b1c4
commit 1ffa545f60
4 changed files with 235 additions and 8 deletions

View File

@ -80,14 +80,6 @@ function love.load(args)
drawGlider(80, 80)
end
local function wrap(n, high)
n = n % high
if n < 0 then
n = n + high
end
return n
end
local function neighbors(x, y)
local lowX = x - UNITS
local highX = x + UNITS

View File

@ -21,3 +21,11 @@ end
function round2even(num)
return 2 * math.floor(num / 2)
end
function wrap(n, high)
n = n % high
if n < 0 then
n = n + high
end
return n
end

5
wireworld/conf.lua Normal file
View File

@ -0,0 +1,5 @@
function love.conf(t)
t.window.highdpi = true
t.window.vsync = true
t.window.title = "wireworld"
end

222
wireworld/main.lua Normal file
View File

@ -0,0 +1,222 @@
require "util"
local function initColors()
local colorbrewer = require("colorbrewer")
COLORS = colorbrewer.random(4)
BLACK = { 0, 0, 0, 1 }
end
local function initScreen()
local width, height = love.graphics.getDimensions()
WIDTH, HEIGHT = round2even(width), round2even(height)
local color = COLORS[#COLORS]
color[4] = 0.9
love.graphics.setBackgroundColor(color)
end
local function initFont()
FONT = love.graphics.newFont(16)
love.graphics.setFont(FONT)
FONT_HEIGHT = FONT:getHeight()
PLAYING_WIDTH = FONT:getWidth("playing")
PAUSED_WIDTH = FONT:getWidth("paused")
end
local function initGrid()
GRID = {}
GRID.mt = {}
setmetatable(GRID, GRID.mt)
GRID.mt.__index = function(table, key)
table[key] = {}
table[key].mt = {}
setmetatable(table[key], table[key].mt)
table[key].mt.__index = function(innerTable, innerKey)
innerTable[innerKey] = 1
return innerTable[innerKey]
end
return table[key]
end
end
local function cloneGrid()
local grid = {}
for x, v in pairs(GRID) do
grid[x] = {}
for y, set in pairs(v) do
grid[x][y] = set
end
setmetatable(grid[x], grid[x].mt)
end
setmetatable(grid, grid.mt)
return grid
end
function love.load(args)
UNITS = args[1] or 16
STEPS_PER_FRAME = args[2] or 1
PAUSED = false
initColors()
initScreen()
initFont()
initGrid()
end
local function neighbors(x, y)
local lowX = x - UNITS
local highX = x + UNITS
local lowY = y - UNITS
local highY = y + UNITS
local count = 0
for i = lowX, highX do
for j = lowY, highY do
i = wrap(i, WIDTH)
j = wrap(j, HEIGHT)
if (i ~= x or j ~= y) and GRID[i][j] == 2 then
count = count + 1
end
end
end
return count
end
local function clear(grid, x, y)
grid[x][y] = 1
end
local function setHead(grid, x, y)
grid[x][y] = 2
end
local function setTail(grid, x, y)
grid[x][y] = 3
end
local function setConductor(grid, x, y)
grid[x][y] = 4
end
local function setSpark(grid, x, y)
local n = neighbors(x, y)
if n == 1 or n == 2 then
setHead(grid, x, y)
end
end
local function updater(state)
local match = {
-- noop
[1] = function(x, y) end,
[2] = setTail,
[3] = setConductor,
[4] = setSpark,
}
return match[state]
end
local function stepCell(grid, x, y)
local state = GRID[x][y]
local update = updater(state)
update(grid, x, y)
end
function love.keypressed(key, _, isrepeat)
if key == "space" and not isrepeat then
PAUSED = not PAUSED
if PAUSED then
print("pausing")
else
print("unpausing")
end
end
end
function love.mousepressed(x, y, button)
x = (x - (x % UNITS))
y = (y - (y % UNITS))
local state = GRID[x][y]
if button == 1 then
if state == 1 then
print("setting conductor")
setConductor(GRID, x, y)
else
print("clearing")
clear(GRID, x, y)
end
elseif button == 2 then
if state == 4 then
print("setting head")
setHead(GRID, x, y)
elseif state == 2 then
print("setting conductor")
setConductor(GRID, x, y)
end
end
end
FRAMELOCK_COUNTER = 0
FRAMELOCK_FPS = 10
function love.update(dt)
pcall(function()
require("lurker").update()
end)
if not PAUSED then
FRAMELOCK_COUNTER = FRAMELOCK_COUNTER + dt
if FRAMELOCK_COUNTER < (1 / FRAMELOCK_FPS) then
return
end
FRAMELOCK_COUNTER = 0
local grid = cloneGrid()
for x = 0, WIDTH, UNITS do
for y = 0, HEIGHT, UNITS do
local state = GRID[x][y]
if state ~= 1 then
stepCell(grid, x, y)
end
end
end
GRID = grid
end
end
local function paintPlayPause()
local status, width
if PAUSED then
status, width = "paused", PAUSED_WIDTH
else
status, width = "playing", PLAYING_WIDTH
end
love.graphics.setColor(COLORS[1])
love.graphics.rectangle("fill", -10, HEIGHT - FONT_HEIGHT - 20, width + 30, FONT_HEIGHT + 10, 5, 5)
love.graphics.setColor(BLACK)
love.graphics.print(status, 10, HEIGHT - FONT_HEIGHT - 15)
end
local function paintFPS()
local fps = tostring(love.timer.getFPS()) .. " FPS"
local width = FONT:getWidth(fps)
love.graphics.setColor(COLORS[1])
love.graphics.rectangle("fill", WIDTH - width - 10, HEIGHT - FONT_HEIGHT - 20, width + 30, FONT_HEIGHT + 10,
5, 5)
love.graphics.setColor(BLACK)
love.graphics.print(fps, WIDTH - width - 5, HEIGHT - FONT_HEIGHT - 15)
end
function love.draw()
for x, v in pairs(GRID) do
if x ~= "mt" then
for y, state in pairs(v) do
if y ~= "mt" then
local color = COLORS[#COLORS - state + 1]
love.graphics.setColor(color)
love.graphics.rectangle("fill", x, y, UNITS, UNITS)
if state ~= 1 then
love.graphics.setColor(BLACK)
love.graphics.rectangle("line", x, y, UNITS, UNITS)
end
end
end
end
end
paintFPS()
paintPlayPause()
end