moving-stuff-kinda.lua
· 8.6 KiB · Lua
Eredeti
Playground
local pprint = require "pprint"
love.graphics.setDefaultFilter("nearest", "nearest")
local read, write = 1, 1
local active_buffer, back_buffer, rule_book = {}, {}, {}
local function parse(str)
local symbols = {}
for symbol in str:gmatch("%S+") do
table.insert(symbols, symbol)
end
return symbols
end
local function queue_up(string)
for _, symbol in ipairs(parse(string)) do
table.insert(active_buffer, symbol)
end
end
local function add_rule(wants)
return function(gives)
table.insert(rule_book, {parse(wants), type(gives) == "string" and parse(gives) or gives})
end
end
local function match(wants)
for i = 1, #wants do
if wants[i] ~= active_buffer[i + read - 1] then return false end
end
return true
end
local function consume(n)
read = read + n
end
local function peek(n)
local symbols = {}
for i = 0, n - 1 do
table.insert(symbols, active_buffer[read + i])
end
return symbols
end
local function take_next(n)
n = n or 1
local symbol = active_buffer[read]
read = read + 1
return symbol
end
local function produce(gives)
for _, symbol in ipairs(gives) do
back_buffer[write] = symbol
write = write + 1
end
end
local function advance()
back_buffer[write], active_buffer[read] = active_buffer[read], nil
write, read = write + 1, read + 1
end
local function run_cycle()
local rule_matched = false
repeat
local rule_fired = false
for _, rule in ipairs(rule_book) do
local wants, gives = rule[1], rule[2]
if match(wants) then
consume(#wants)
if type(gives) == "function" then
gives(active_buffer, read)
else
produce(gives)
end
rule_fired, rule_matched = true, true
break
end
end
if not rule_fired then advance() end
until not active_buffer[read]
return rule_matched
end
local function exchange_buffers()
active_buffer, back_buffer = back_buffer, {}
read, write = 1, 1
end
local cycles, MAX_CYCLES = 0, 10000
local function run()
while run_cycle() and cycles < MAX_CYCLES do
print(table.concat(back_buffer, " "))
exchange_buffers()
cycles = cycles + 1
end
exchange_buffers()
end
local current_sprite
local sprites, state = {}, {}
local screen = love.graphics.newCanvas()
add_rule "@ sprite [" (function()
current_sprite = { data = {{}} }
produce {"sprite>"}
end)
add_rule "sprite> name is" (function()
current_sprite.name = take_next()
produce { "sprite>" }
end)
add_rule "sprite> symbol is" (function()
current_sprite.symbol = take_next()
produce { "sprite>" }
end)
add_rule "sprite> ;" (function()
table.insert(current_sprite.data, {})
produce { "sprite>" }
end)
add_rule "sprite> ]" (function()
-- find longest row in data
local longest_row = -1
for _, row in ipairs(current_sprite.data) do
if #row > longest_row then longest_row = #row end
end
-- pad out other rows
for _, row in ipairs(current_sprite.data) do
while #row < longest_row do
table.insert(row, ".")
end
end
-- construct a canvas for our sprite
local sprite = love.graphics.newCanvas(longest_row, #current_sprite.data)
love.graphics.setCanvas(sprite)
local x, y = 0, 0
for _, row in ipairs(current_sprite.data) do
for _, data in ipairs(row) do
if data == "#" then
love.graphics.points(x + 0.5, y + 0.5)
end
x = x + 1
end
x, y = 0, y + 1
end
love.graphics.setCanvas()
sprites[current_sprite.symbol] = sprite
produce {"@"}
end)
add_rule "sprite>" (function()
table.insert(current_sprite.data[#current_sprite.data], take_next())
produce { "sprite>" }
end)
add_rule "@ draw sprite [" (function()
local symbol = take_next()
consume(2)
local x = tonumber(take_next())
consume(1)
local y = tonumber(take_next())
consume(1)
love.graphics.setCanvas(screen)
love.graphics.draw(sprites[symbol], x * 16, y * 16)
love.graphics.setCanvas()
produce {"@"}
end)
add_rule "@ clear screen" (function()
love.graphics.setCanvas(screen)
love.graphics.clear()
love.graphics.setCanvas()
produce {"@"}
end)
-- @ set <field> to <value>
add_rule "@ set" (function ()
-- <field>
local field = {}
local symbol = take_next()
print(symbol)
while symbol ~= "to" do
table.insert(field, symbol)
symbol = take_next()
end
pprint(symbol)
-- <value>
local value = take_next()
-- try casting value to a number
if value:sub(1,1) == "#" then
local numerical_part = tonumber(value:sub(2))
value = numerical_part or value
end
print()
state[table.concat(field, " ")] = value
produce {"@"}
end)
queue_up [[
@ sprite [
symbol is p
. . . . . # # # # # . . . . . . ;
. . . . . . . . . . . . . . . . ;
. . . . . # # # # # . . . . . . ;
. . # # # # # # . # # . . . . . ;
. . . . # # # # . # # # # # . . ;
. . . . . # # # # # # # # # . . ;
. . . . . . # # # # . . . . . . ;
. . . . . # # # # # # . . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ]
sprite [
symbol is w
. . # # # # # # # # # # # # . . ;
. # . # . # . # . # . # . # # . ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
. # # . # . # . # . # . # . # . ;
. . # # # # # # # # # # # # . . ]
set player x to #5
set player y to #4
]]
local function draw_map()
queue_up [[
draw sprite [ w at x 5 y 5 ]
draw sprite [ w at x 4 y 6 ]
draw sprite [ w at x 5 y 6 ]
draw sprite [ w at x 6 y 6 ]
draw sprite [ w at x 3 y 7 ]
draw sprite [ w at x 4 y 7 ]
draw sprite [ w at x 5 y 7 ]
draw sprite [ w at x 6 y 7 ]
draw sprite [ w at x 7 y 7 ]
draw sprite [ w at x 2 y 8 ]
draw sprite [ w at x 3 y 8 ]
draw sprite [ w at x 4 y 8 ]
draw sprite [ w at x 5 y 8 ]
draw sprite [ w at x 6 y 8 ]
draw sprite [ w at x 7 y 8 ]
draw sprite [ w at x 8 y 8 ]
draw sprite [ w at x 1 y 9 ]
draw sprite [ w at x 2 y 9 ]
draw sprite [ w at x 3 y 9 ]
draw sprite [ w at x 4 y 9 ]
draw sprite [ w at x 5 y 9 ]
draw sprite [ w at x 6 y 9 ]
draw sprite [ w at x 7 y 9 ]
draw sprite [ w at x 8 y 9 ]
draw sprite [ w at x 9 y 9 ]
draw sprite [ w at x 0 y 10 ]
draw sprite [ w at x 1 y 10 ]
draw sprite [ w at x 2 y 10 ]
draw sprite [ w at x 3 y 10 ]
draw sprite [ w at x 4 y 10 ]
draw sprite [ w at x 5 y 10 ]
draw sprite [ w at x 6 y 10 ]
draw sprite [ w at x 7 y 10 ]
draw sprite [ w at x 8 y 10 ]
draw sprite [ w at x 9 y 10 ]
draw sprite [ w at x 10 y 10 ]
]]
end
run()
local function draw_player()
local draw_command = ("draw sprite [ p at x %d y %d ]"):format(state["player x"], state["player y"])
queue_up(draw_command)
end
function love.draw()
queue_up "clear screen"
draw_player()
pprint(active_buffer)
run()
love.graphics.draw(screen, 0, 0, 0, 4, 4)
love.graphics.print(tostring(love.timer.getFPS()), 10, 10)
end
function love.keypressed(_, scancode)
local move_x_command = "set player x to #%d"
local move_y_command = "set player y to #%d"
if scancode == "w" then
queue_up(move_y_command:format(state["player y"] - 1))
elseif scancode == "s" then
queue_up(move_y_command:format(state["player y"] + 1))
end
if scancode == "a" then
queue_up(move_x_command:format(state["player x"] - 1))
elseif scancode == "d" then
queue_up(move_x_command:format(state["player x"] + 1))
end
end
| 1 | local pprint = require "pprint" |
| 2 | love.graphics.setDefaultFilter("nearest", "nearest") |
| 3 | local read, write = 1, 1 |
| 4 | local active_buffer, back_buffer, rule_book = {}, {}, {} |
| 5 | local function parse(str) |
| 6 | local symbols = {} |
| 7 | for symbol in str:gmatch("%S+") do |
| 8 | table.insert(symbols, symbol) |
| 9 | end |
| 10 | return symbols |
| 11 | end |
| 12 | |
| 13 | local function queue_up(string) |
| 14 | for _, symbol in ipairs(parse(string)) do |
| 15 | table.insert(active_buffer, symbol) |
| 16 | end |
| 17 | end |
| 18 | local function add_rule(wants) |
| 19 | return function(gives) |
| 20 | table.insert(rule_book, {parse(wants), type(gives) == "string" and parse(gives) or gives}) |
| 21 | end |
| 22 | end |
| 23 | |
| 24 | local function match(wants) |
| 25 | for i = 1, #wants do |
| 26 | if wants[i] ~= active_buffer[i + read - 1] then return false end |
| 27 | end |
| 28 | return true |
| 29 | end |
| 30 | |
| 31 | local function consume(n) |
| 32 | read = read + n |
| 33 | end |
| 34 | |
| 35 | local function peek(n) |
| 36 | local symbols = {} |
| 37 | for i = 0, n - 1 do |
| 38 | table.insert(symbols, active_buffer[read + i]) |
| 39 | end |
| 40 | return symbols |
| 41 | end |
| 42 | |
| 43 | local function take_next(n) |
| 44 | n = n or 1 |
| 45 | local symbol = active_buffer[read] |
| 46 | read = read + 1 |
| 47 | return symbol |
| 48 | end |
| 49 | |
| 50 | |
| 51 | local function produce(gives) |
| 52 | for _, symbol in ipairs(gives) do |
| 53 | back_buffer[write] = symbol |
| 54 | write = write + 1 |
| 55 | end |
| 56 | end |
| 57 | |
| 58 | local function advance() |
| 59 | back_buffer[write], active_buffer[read] = active_buffer[read], nil |
| 60 | write, read = write + 1, read + 1 |
| 61 | end |
| 62 | |
| 63 | local function run_cycle() |
| 64 | local rule_matched = false |
| 65 | repeat |
| 66 | local rule_fired = false |
| 67 | for _, rule in ipairs(rule_book) do |
| 68 | local wants, gives = rule[1], rule[2] |
| 69 | if match(wants) then |
| 70 | consume(#wants) |
| 71 | if type(gives) == "function" then |
| 72 | gives(active_buffer, read) |
| 73 | else |
| 74 | produce(gives) |
| 75 | end |
| 76 | rule_fired, rule_matched = true, true |
| 77 | break |
| 78 | end |
| 79 | end |
| 80 | if not rule_fired then advance() end |
| 81 | until not active_buffer[read] |
| 82 | return rule_matched |
| 83 | end |
| 84 | |
| 85 | |
| 86 | local function exchange_buffers() |
| 87 | active_buffer, back_buffer = back_buffer, {} |
| 88 | read, write = 1, 1 |
| 89 | end |
| 90 | |
| 91 | local cycles, MAX_CYCLES = 0, 10000 |
| 92 | local function run() |
| 93 | while run_cycle() and cycles < MAX_CYCLES do |
| 94 | print(table.concat(back_buffer, " ")) |
| 95 | exchange_buffers() |
| 96 | cycles = cycles + 1 |
| 97 | end |
| 98 | exchange_buffers() |
| 99 | end |
| 100 | |
| 101 | local current_sprite |
| 102 | local sprites, state = {}, {} |
| 103 | local screen = love.graphics.newCanvas() |
| 104 | |
| 105 | add_rule "@ sprite [" (function() |
| 106 | current_sprite = { data = {{}} } |
| 107 | produce {"sprite>"} |
| 108 | end) |
| 109 | |
| 110 | add_rule "sprite> name is" (function() |
| 111 | current_sprite.name = take_next() |
| 112 | produce { "sprite>" } |
| 113 | end) |
| 114 | |
| 115 | add_rule "sprite> symbol is" (function() |
| 116 | current_sprite.symbol = take_next() |
| 117 | produce { "sprite>" } |
| 118 | end) |
| 119 | |
| 120 | |
| 121 | add_rule "sprite> ;" (function() |
| 122 | table.insert(current_sprite.data, {}) |
| 123 | produce { "sprite>" } |
| 124 | end) |
| 125 | |
| 126 | add_rule "sprite> ]" (function() |
| 127 | -- find longest row in data |
| 128 | local longest_row = -1 |
| 129 | for _, row in ipairs(current_sprite.data) do |
| 130 | if #row > longest_row then longest_row = #row end |
| 131 | end |
| 132 | |
| 133 | -- pad out other rows |
| 134 | for _, row in ipairs(current_sprite.data) do |
| 135 | while #row < longest_row do |
| 136 | table.insert(row, ".") |
| 137 | end |
| 138 | end |
| 139 | |
| 140 | -- construct a canvas for our sprite |
| 141 | local sprite = love.graphics.newCanvas(longest_row, #current_sprite.data) |
| 142 | love.graphics.setCanvas(sprite) |
| 143 | local x, y = 0, 0 |
| 144 | for _, row in ipairs(current_sprite.data) do |
| 145 | for _, data in ipairs(row) do |
| 146 | if data == "#" then |
| 147 | love.graphics.points(x + 0.5, y + 0.5) |
| 148 | end |
| 149 | x = x + 1 |
| 150 | end |
| 151 | x, y = 0, y + 1 |
| 152 | end |
| 153 | love.graphics.setCanvas() |
| 154 | sprites[current_sprite.symbol] = sprite |
| 155 | produce {"@"} |
| 156 | end) |
| 157 | |
| 158 | add_rule "sprite>" (function() |
| 159 | table.insert(current_sprite.data[#current_sprite.data], take_next()) |
| 160 | produce { "sprite>" } |
| 161 | end) |
| 162 | |
| 163 | add_rule "@ draw sprite [" (function() |
| 164 | local symbol = take_next() |
| 165 | consume(2) |
| 166 | local x = tonumber(take_next()) |
| 167 | consume(1) |
| 168 | local y = tonumber(take_next()) |
| 169 | consume(1) |
| 170 | love.graphics.setCanvas(screen) |
| 171 | love.graphics.draw(sprites[symbol], x * 16, y * 16) |
| 172 | love.graphics.setCanvas() |
| 173 | produce {"@"} |
| 174 | end) |
| 175 | |
| 176 | add_rule "@ clear screen" (function() |
| 177 | love.graphics.setCanvas(screen) |
| 178 | love.graphics.clear() |
| 179 | love.graphics.setCanvas() |
| 180 | produce {"@"} |
| 181 | end) |
| 182 | |
| 183 | -- @ set <field> to <value> |
| 184 | add_rule "@ set" (function () |
| 185 | -- <field> |
| 186 | local field = {} |
| 187 | local symbol = take_next() |
| 188 | print(symbol) |
| 189 | while symbol ~= "to" do |
| 190 | table.insert(field, symbol) |
| 191 | symbol = take_next() |
| 192 | end |
| 193 | pprint(symbol) |
| 194 | -- <value> |
| 195 | local value = take_next() |
| 196 | -- try casting value to a number |
| 197 | if value:sub(1,1) == "#" then |
| 198 | local numerical_part = tonumber(value:sub(2)) |
| 199 | value = numerical_part or value |
| 200 | end |
| 201 | print() |
| 202 | state[table.concat(field, " ")] = value |
| 203 | produce {"@"} |
| 204 | end) |
| 205 | |
| 206 | |
| 207 | |
| 208 | queue_up [[ |
| 209 | @ sprite [ |
| 210 | symbol is p |
| 211 | . . . . . # # # # # . . . . . . ; |
| 212 | . . . . . . . . . . . . . . . . ; |
| 213 | . . . . . # # # # # . . . . . . ; |
| 214 | . . # # # # # # . # # . . . . . ; |
| 215 | . . . . # # # # . # # # # # . . ; |
| 216 | . . . . . # # # # # # # # # . . ; |
| 217 | . . . . . . # # # # . . . . . . ; |
| 218 | . . . . . # # # # # # . . . . . ; |
| 219 | . . . . # . # # # # . # . . . . ; |
| 220 | . . . . # . # # # # . # . . . . ; |
| 221 | . . . . # . # # # # . # . . . . ; |
| 222 | . . . . . . # . . # . . . . . . ; |
| 223 | . . . . . . # . . # . . . . . . ; |
| 224 | . . . . . . # . . # . . . . . . ; |
| 225 | . . . . . . # . . # . . . . . . ; |
| 226 | . . . . . . # . . # . . . . . . ] |
| 227 | |
| 228 | sprite [ |
| 229 | symbol is w |
| 230 | . . # # # # # # # # # # # # . . ; |
| 231 | . # . # . # . # . # . # . # # . ; |
| 232 | # . # . # . # . # . # . # . # # ; |
| 233 | # # . # . # . # . # . # . # . # ; |
| 234 | # . # . # . # . # . # . # . # # ; |
| 235 | # # . # . # . # . # . # . # . # ; |
| 236 | # . # . # . # . # . # . # . # # ; |
| 237 | # # . # . # . # . # . # . # . # ; |
| 238 | # . # . # . # . # . # . # . # # ; |
| 239 | # # . # . # . # . # . # . # . # ; |
| 240 | # . # . # . # . # . # . # . # # ; |
| 241 | # # . # . # . # . # . # . # . # ; |
| 242 | # . # . # . # . # . # . # . # # ; |
| 243 | # # . # . # . # . # . # . # . # ; |
| 244 | . # # . # . # . # . # . # . # . ; |
| 245 | . . # # # # # # # # # # # # . . ] |
| 246 | |
| 247 | set player x to #5 |
| 248 | set player y to #4 |
| 249 | ]] |
| 250 | |
| 251 | local function draw_map() |
| 252 | queue_up [[ |
| 253 | draw sprite [ w at x 5 y 5 ] |
| 254 | |
| 255 | draw sprite [ w at x 4 y 6 ] |
| 256 | draw sprite [ w at x 5 y 6 ] |
| 257 | draw sprite [ w at x 6 y 6 ] |
| 258 | |
| 259 | draw sprite [ w at x 3 y 7 ] |
| 260 | draw sprite [ w at x 4 y 7 ] |
| 261 | draw sprite [ w at x 5 y 7 ] |
| 262 | draw sprite [ w at x 6 y 7 ] |
| 263 | draw sprite [ w at x 7 y 7 ] |
| 264 | |
| 265 | draw sprite [ w at x 2 y 8 ] |
| 266 | draw sprite [ w at x 3 y 8 ] |
| 267 | draw sprite [ w at x 4 y 8 ] |
| 268 | draw sprite [ w at x 5 y 8 ] |
| 269 | draw sprite [ w at x 6 y 8 ] |
| 270 | draw sprite [ w at x 7 y 8 ] |
| 271 | draw sprite [ w at x 8 y 8 ] |
| 272 | |
| 273 | draw sprite [ w at x 1 y 9 ] |
| 274 | draw sprite [ w at x 2 y 9 ] |
| 275 | draw sprite [ w at x 3 y 9 ] |
| 276 | draw sprite [ w at x 4 y 9 ] |
| 277 | draw sprite [ w at x 5 y 9 ] |
| 278 | draw sprite [ w at x 6 y 9 ] |
| 279 | draw sprite [ w at x 7 y 9 ] |
| 280 | draw sprite [ w at x 8 y 9 ] |
| 281 | draw sprite [ w at x 9 y 9 ] |
| 282 | |
| 283 | draw sprite [ w at x 0 y 10 ] |
| 284 | draw sprite [ w at x 1 y 10 ] |
| 285 | draw sprite [ w at x 2 y 10 ] |
| 286 | draw sprite [ w at x 3 y 10 ] |
| 287 | draw sprite [ w at x 4 y 10 ] |
| 288 | draw sprite [ w at x 5 y 10 ] |
| 289 | draw sprite [ w at x 6 y 10 ] |
| 290 | draw sprite [ w at x 7 y 10 ] |
| 291 | draw sprite [ w at x 8 y 10 ] |
| 292 | draw sprite [ w at x 9 y 10 ] |
| 293 | draw sprite [ w at x 10 y 10 ] |
| 294 | ]] |
| 295 | |
| 296 | end |
| 297 | run() |
| 298 | local function draw_player() |
| 299 | local draw_command = ("draw sprite [ p at x %d y %d ]"):format(state["player x"], state["player y"]) |
| 300 | queue_up(draw_command) |
| 301 | end |
| 302 | |
| 303 | function love.draw() |
| 304 | queue_up "clear screen" |
| 305 | draw_player() |
| 306 | pprint(active_buffer) |
| 307 | run() |
| 308 | love.graphics.draw(screen, 0, 0, 0, 4, 4) |
| 309 | love.graphics.print(tostring(love.timer.getFPS()), 10, 10) |
| 310 | end |
| 311 | |
| 312 | function love.keypressed(_, scancode) |
| 313 | local move_x_command = "set player x to #%d" |
| 314 | local move_y_command = "set player y to #%d" |
| 315 | if scancode == "w" then |
| 316 | queue_up(move_y_command:format(state["player y"] - 1)) |
| 317 | elseif scancode == "s" then |
| 318 | queue_up(move_y_command:format(state["player y"] + 1)) |
| 319 | end |
| 320 | if scancode == "a" then |
| 321 | queue_up(move_x_command:format(state["player x"] - 1)) |
| 322 | elseif scancode == "d" then |
| 323 | queue_up(move_x_command:format(state["player x"] + 1)) |
| 324 | end |
| 325 | end |
| 326 | |
| 327 |
pixels.lua
· 6.9 KiB · Lua
Eredeti
Playground
local pprint = require "pprint"
love.graphics.setDefaultFilter("nearest", "nearest")
local read, write = 1, 1
local active_buffer, back_buffer, rule_book = {}, {}, {}
local function parse(str)
local symbols = {}
for symbol in str:gmatch("%S+") do
table.insert(symbols, symbol)
end
return symbols
end
local function queue_up(string)
for _, symbol in ipairs(parse(string)) do
table.insert(active_buffer, symbol)
end
end
local function add_rule(wants)
return function(gives)
table.insert(rule_book, {parse(wants), type(gives) == "string" and parse(gives) or gives})
end
end
local function match(wants)
for i = 1, #wants do
if wants[i] ~= active_buffer[i + read - 1] then return false end
end
return true
end
local function consume(n)
read = read + n
end
local function peek(n)
local symbols = {}
for i = 0, n - 1 do
table.insert(symbols, active_buffer[read + i])
end
return symbols
end
local function take_next(n)
n = n or 1
local symbol = active_buffer[read]
read = read + 1
return symbol
end
local function produce(gives)
for _, symbol in ipairs(gives) do
back_buffer[write] = symbol
write = write + 1
end
end
local function advance()
back_buffer[write], active_buffer[read] = active_buffer[read], nil
write, read = write + 1, read + 1
end
local function run_cycle()
local rule_matched = false
repeat
local rule_fired = false
for _, rule in ipairs(rule_book) do
local wants, gives = rule[1], rule[2]
if match(wants) then
consume(#wants)
if type(gives) == "function" then
gives(active_buffer, read)
else
produce(gives)
end
rule_fired, rule_matched = true, true
break
end
end
if not rule_fired then advance() end
until not active_buffer[read]
return rule_matched
end
local function exchange_buffers()
active_buffer, back_buffer = back_buffer, {}
read, write = 1, 1
end
local cycles, MAX_CYCLES = 0, 10000
local function run()
while run_cycle() and cycles < MAX_CYCLES do
print(table.concat(back_buffer, " "))
exchange_buffers()
cycles = cycles + 1
end
end
local current_sprite
local sprites = {}
local screen = love.graphics.newCanvas()
add_rule "@ sprite [" (function()
current_sprite = { data = {{}} }
produce {"sprite>"}
end)
add_rule "sprite> name is" (function()
current_sprite.name = take_next()
produce { "sprite>" }
end)
add_rule "sprite> symbol is" (function()
current_sprite.symbol = take_next()
produce { "sprite>" }
end)
add_rule "sprite> ;" (function()
table.insert(current_sprite.data, {})
produce { "sprite>" }
end)
add_rule "sprite> ]" (function()
-- find longest row in data
local longest_row = -1
for _, row in ipairs(current_sprite.data) do
if #row > longest_row then longest_row = #row end
end
-- pad out other rows
for _, row in ipairs(current_sprite.data) do
while #row < longest_row do
table.insert(row, ".")
end
end
-- construct a canvas for our sprite
print(#current_sprite.data)
local sprite = love.graphics.newCanvas(longest_row, #current_sprite.data)
love.graphics.setCanvas(sprite)
local x, y = 0, 0
for _, row in ipairs(current_sprite.data) do
for _, data in ipairs(row) do
if data == "#" then
love.graphics.points(x + 0.5, y + 0.5)
end
x = x + 1
end
x, y = 0, y + 1
end
love.graphics.setCanvas()
sprites[current_sprite.symbol] = sprite
produce {"@"}
end)
add_rule "sprite>" (function()
table.insert(current_sprite.data[#current_sprite.data], take_next())
produce { "sprite>" }
end)
add_rule "@ draw sprite [" (function()
local symbol = take_next()
consume(2)
local x = tonumber(take_next())
consume(1)
local y = tonumber(take_next())
consume(1)
love.graphics.setCanvas(screen)
love.graphics.draw(sprites[symbol], x * 16, y * 16)
love.graphics.setCanvas()
produce {"@"}
end)
queue_up [[
@ sprite [
symbol is p
. . . . . # # # # # . . . . . . ;
. . . . . . . . . . . . . . . . ;
. . . . . # # # # # . . . . . . ;
. . # # # # # # . # # . . . . . ;
. . . . # # # # . # # # # # . . ;
. . . . . # # # # # # # # # . . ;
. . . . . . # # # # . . . . . . ;
. . . . . # # # # # # . . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . # . # # # # . # . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ;
. . . . . . # . . # . . . . . . ]
sprite [
symbol is w
. . # # # # # # # # # # # # . . ;
. # . # . # . # . # . # . # # . ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
# . # . # . # . # . # . # . # # ;
# # . # . # . # . # . # . # . # ;
. # # . # . # . # . # . # . # . ;
. . # # # # # # # # # # # # . . ]
draw sprite [ p at x 5 y 4 ]
draw sprite [ w at x 5 y 5 ]
draw sprite [ w at x 4 y 6 ]
draw sprite [ w at x 5 y 6 ]
draw sprite [ w at x 6 y 6 ]
draw sprite [ w at x 3 y 7 ]
draw sprite [ w at x 4 y 7 ]
draw sprite [ w at x 5 y 7 ]
draw sprite [ w at x 6 y 7 ]
draw sprite [ w at x 7 y 7 ]
draw sprite [ w at x 2 y 8 ]
draw sprite [ w at x 3 y 8 ]
draw sprite [ w at x 4 y 8 ]
draw sprite [ w at x 5 y 8 ]
draw sprite [ w at x 6 y 8 ]
draw sprite [ w at x 7 y 8 ]
draw sprite [ w at x 8 y 8 ]
draw sprite [ w at x 1 y 9 ]
draw sprite [ w at x 2 y 9 ]
draw sprite [ w at x 3 y 9 ]
draw sprite [ w at x 4 y 9 ]
draw sprite [ w at x 5 y 9 ]
draw sprite [ w at x 6 y 9 ]
draw sprite [ w at x 7 y 9 ]
draw sprite [ w at x 8 y 9 ]
draw sprite [ w at x 9 y 9 ]
draw sprite [ w at x 0 y 10 ]
draw sprite [ w at x 1 y 10 ]
draw sprite [ w at x 2 y 10 ]
draw sprite [ w at x 3 y 10 ]
draw sprite [ w at x 4 y 10 ]
draw sprite [ w at x 5 y 10 ]
draw sprite [ w at x 6 y 10 ]
draw sprite [ w at x 7 y 10 ]
draw sprite [ w at x 8 y 10 ]
draw sprite [ w at x 9 y 10 ]
draw sprite [ w at x 10 y 10 ]
]]
run()
function love.draw()
love.graphics.draw(screen, 0, 0, 0, 4, 4)
end
| 1 | local pprint = require "pprint" |
| 2 | love.graphics.setDefaultFilter("nearest", "nearest") |
| 3 | local read, write = 1, 1 |
| 4 | local active_buffer, back_buffer, rule_book = {}, {}, {} |
| 5 | local function parse(str) |
| 6 | local symbols = {} |
| 7 | for symbol in str:gmatch("%S+") do |
| 8 | table.insert(symbols, symbol) |
| 9 | end |
| 10 | return symbols |
| 11 | end |
| 12 | |
| 13 | local function queue_up(string) |
| 14 | for _, symbol in ipairs(parse(string)) do |
| 15 | table.insert(active_buffer, symbol) |
| 16 | end |
| 17 | end |
| 18 | local function add_rule(wants) |
| 19 | return function(gives) |
| 20 | table.insert(rule_book, {parse(wants), type(gives) == "string" and parse(gives) or gives}) |
| 21 | end |
| 22 | end |
| 23 | |
| 24 | local function match(wants) |
| 25 | for i = 1, #wants do |
| 26 | if wants[i] ~= active_buffer[i + read - 1] then return false end |
| 27 | end |
| 28 | return true |
| 29 | end |
| 30 | |
| 31 | local function consume(n) |
| 32 | read = read + n |
| 33 | end |
| 34 | |
| 35 | local function peek(n) |
| 36 | local symbols = {} |
| 37 | for i = 0, n - 1 do |
| 38 | table.insert(symbols, active_buffer[read + i]) |
| 39 | end |
| 40 | return symbols |
| 41 | end |
| 42 | |
| 43 | local function take_next(n) |
| 44 | n = n or 1 |
| 45 | local symbol = active_buffer[read] |
| 46 | read = read + 1 |
| 47 | return symbol |
| 48 | end |
| 49 | |
| 50 | |
| 51 | local function produce(gives) |
| 52 | for _, symbol in ipairs(gives) do |
| 53 | back_buffer[write] = symbol |
| 54 | write = write + 1 |
| 55 | end |
| 56 | end |
| 57 | |
| 58 | local function advance() |
| 59 | back_buffer[write], active_buffer[read] = active_buffer[read], nil |
| 60 | write, read = write + 1, read + 1 |
| 61 | end |
| 62 | |
| 63 | local function run_cycle() |
| 64 | local rule_matched = false |
| 65 | repeat |
| 66 | local rule_fired = false |
| 67 | for _, rule in ipairs(rule_book) do |
| 68 | local wants, gives = rule[1], rule[2] |
| 69 | if match(wants) then |
| 70 | consume(#wants) |
| 71 | if type(gives) == "function" then |
| 72 | gives(active_buffer, read) |
| 73 | else |
| 74 | produce(gives) |
| 75 | end |
| 76 | rule_fired, rule_matched = true, true |
| 77 | break |
| 78 | end |
| 79 | end |
| 80 | if not rule_fired then advance() end |
| 81 | until not active_buffer[read] |
| 82 | return rule_matched |
| 83 | end |
| 84 | |
| 85 | |
| 86 | local function exchange_buffers() |
| 87 | active_buffer, back_buffer = back_buffer, {} |
| 88 | read, write = 1, 1 |
| 89 | end |
| 90 | |
| 91 | local cycles, MAX_CYCLES = 0, 10000 |
| 92 | local function run() |
| 93 | while run_cycle() and cycles < MAX_CYCLES do |
| 94 | print(table.concat(back_buffer, " ")) |
| 95 | exchange_buffers() |
| 96 | cycles = cycles + 1 |
| 97 | end |
| 98 | end |
| 99 | |
| 100 | local current_sprite |
| 101 | local sprites = {} |
| 102 | local screen = love.graphics.newCanvas() |
| 103 | |
| 104 | add_rule "@ sprite [" (function() |
| 105 | current_sprite = { data = {{}} } |
| 106 | produce {"sprite>"} |
| 107 | end) |
| 108 | |
| 109 | add_rule "sprite> name is" (function() |
| 110 | current_sprite.name = take_next() |
| 111 | produce { "sprite>" } |
| 112 | end) |
| 113 | |
| 114 | add_rule "sprite> symbol is" (function() |
| 115 | current_sprite.symbol = take_next() |
| 116 | produce { "sprite>" } |
| 117 | end) |
| 118 | |
| 119 | |
| 120 | add_rule "sprite> ;" (function() |
| 121 | table.insert(current_sprite.data, {}) |
| 122 | produce { "sprite>" } |
| 123 | end) |
| 124 | |
| 125 | add_rule "sprite> ]" (function() |
| 126 | -- find longest row in data |
| 127 | local longest_row = -1 |
| 128 | for _, row in ipairs(current_sprite.data) do |
| 129 | if #row > longest_row then longest_row = #row end |
| 130 | end |
| 131 | |
| 132 | -- pad out other rows |
| 133 | for _, row in ipairs(current_sprite.data) do |
| 134 | while #row < longest_row do |
| 135 | table.insert(row, ".") |
| 136 | end |
| 137 | end |
| 138 | |
| 139 | -- construct a canvas for our sprite |
| 140 | print(#current_sprite.data) |
| 141 | local sprite = love.graphics.newCanvas(longest_row, #current_sprite.data) |
| 142 | love.graphics.setCanvas(sprite) |
| 143 | local x, y = 0, 0 |
| 144 | for _, row in ipairs(current_sprite.data) do |
| 145 | for _, data in ipairs(row) do |
| 146 | if data == "#" then |
| 147 | love.graphics.points(x + 0.5, y + 0.5) |
| 148 | end |
| 149 | x = x + 1 |
| 150 | end |
| 151 | x, y = 0, y + 1 |
| 152 | end |
| 153 | love.graphics.setCanvas() |
| 154 | sprites[current_sprite.symbol] = sprite |
| 155 | produce {"@"} |
| 156 | end) |
| 157 | |
| 158 | add_rule "sprite>" (function() |
| 159 | table.insert(current_sprite.data[#current_sprite.data], take_next()) |
| 160 | produce { "sprite>" } |
| 161 | end) |
| 162 | |
| 163 | add_rule "@ draw sprite [" (function() |
| 164 | local symbol = take_next() |
| 165 | consume(2) |
| 166 | local x = tonumber(take_next()) |
| 167 | consume(1) |
| 168 | local y = tonumber(take_next()) |
| 169 | consume(1) |
| 170 | love.graphics.setCanvas(screen) |
| 171 | love.graphics.draw(sprites[symbol], x * 16, y * 16) |
| 172 | love.graphics.setCanvas() |
| 173 | produce {"@"} |
| 174 | end) |
| 175 | |
| 176 | |
| 177 | |
| 178 | queue_up [[ |
| 179 | @ sprite [ |
| 180 | symbol is p |
| 181 | . . . . . # # # # # . . . . . . ; |
| 182 | . . . . . . . . . . . . . . . . ; |
| 183 | . . . . . # # # # # . . . . . . ; |
| 184 | . . # # # # # # . # # . . . . . ; |
| 185 | . . . . # # # # . # # # # # . . ; |
| 186 | . . . . . # # # # # # # # # . . ; |
| 187 | . . . . . . # # # # . . . . . . ; |
| 188 | . . . . . # # # # # # . . . . . ; |
| 189 | . . . . # . # # # # . # . . . . ; |
| 190 | . . . . # . # # # # . # . . . . ; |
| 191 | . . . . # . # # # # . # . . . . ; |
| 192 | . . . . . . # . . # . . . . . . ; |
| 193 | . . . . . . # . . # . . . . . . ; |
| 194 | . . . . . . # . . # . . . . . . ; |
| 195 | . . . . . . # . . # . . . . . . ; |
| 196 | . . . . . . # . . # . . . . . . ] |
| 197 | |
| 198 | sprite [ |
| 199 | symbol is w |
| 200 | . . # # # # # # # # # # # # . . ; |
| 201 | . # . # . # . # . # . # . # # . ; |
| 202 | # . # . # . # . # . # . # . # # ; |
| 203 | # # . # . # . # . # . # . # . # ; |
| 204 | # . # . # . # . # . # . # . # # ; |
| 205 | # # . # . # . # . # . # . # . # ; |
| 206 | # . # . # . # . # . # . # . # # ; |
| 207 | # # . # . # . # . # . # . # . # ; |
| 208 | # . # . # . # . # . # . # . # # ; |
| 209 | # # . # . # . # . # . # . # . # ; |
| 210 | # . # . # . # . # . # . # . # # ; |
| 211 | # # . # . # . # . # . # . # . # ; |
| 212 | # . # . # . # . # . # . # . # # ; |
| 213 | # # . # . # . # . # . # . # . # ; |
| 214 | . # # . # . # . # . # . # . # . ; |
| 215 | . . # # # # # # # # # # # # . . ] |
| 216 | |
| 217 | draw sprite [ p at x 5 y 4 ] |
| 218 | |
| 219 | draw sprite [ w at x 5 y 5 ] |
| 220 | |
| 221 | draw sprite [ w at x 4 y 6 ] |
| 222 | draw sprite [ w at x 5 y 6 ] |
| 223 | draw sprite [ w at x 6 y 6 ] |
| 224 | |
| 225 | draw sprite [ w at x 3 y 7 ] |
| 226 | draw sprite [ w at x 4 y 7 ] |
| 227 | draw sprite [ w at x 5 y 7 ] |
| 228 | draw sprite [ w at x 6 y 7 ] |
| 229 | draw sprite [ w at x 7 y 7 ] |
| 230 | |
| 231 | draw sprite [ w at x 2 y 8 ] |
| 232 | draw sprite [ w at x 3 y 8 ] |
| 233 | draw sprite [ w at x 4 y 8 ] |
| 234 | draw sprite [ w at x 5 y 8 ] |
| 235 | draw sprite [ w at x 6 y 8 ] |
| 236 | draw sprite [ w at x 7 y 8 ] |
| 237 | draw sprite [ w at x 8 y 8 ] |
| 238 | |
| 239 | draw sprite [ w at x 1 y 9 ] |
| 240 | draw sprite [ w at x 2 y 9 ] |
| 241 | draw sprite [ w at x 3 y 9 ] |
| 242 | draw sprite [ w at x 4 y 9 ] |
| 243 | draw sprite [ w at x 5 y 9 ] |
| 244 | draw sprite [ w at x 6 y 9 ] |
| 245 | draw sprite [ w at x 7 y 9 ] |
| 246 | draw sprite [ w at x 8 y 9 ] |
| 247 | draw sprite [ w at x 9 y 9 ] |
| 248 | |
| 249 | draw sprite [ w at x 0 y 10 ] |
| 250 | draw sprite [ w at x 1 y 10 ] |
| 251 | draw sprite [ w at x 2 y 10 ] |
| 252 | draw sprite [ w at x 3 y 10 ] |
| 253 | draw sprite [ w at x 4 y 10 ] |
| 254 | draw sprite [ w at x 5 y 10 ] |
| 255 | draw sprite [ w at x 6 y 10 ] |
| 256 | draw sprite [ w at x 7 y 10 ] |
| 257 | draw sprite [ w at x 8 y 10 ] |
| 258 | draw sprite [ w at x 9 y 10 ] |
| 259 | draw sprite [ w at x 10 y 10 ] |
| 260 | ]] |
| 261 | |
| 262 | run() |
| 263 | |
| 264 | function love.draw() |
| 265 | |
| 266 | love.graphics.draw(screen, 0, 0, 0, 4, 4) |
| 267 | end |
string-rewriter.lua
· 2.1 KiB · Lua
Eredeti
Playground
local read, write = 1, 1
local active_buffer, back_buffer, rule_book = {}, {}, {}
local function parse(str)
local symbols = {}
for symbol in str:gmatch("%S+") do
table.insert(symbols, symbol)
end
return symbols
end
local function queue_up(string)
for _, symbol in ipairs(parse(string)) do
table.insert(active_buffer, symbol)
end
end
local function add_rule(wants)
return function(gives)
table.insert(rule_book, {parse(wants), parse(gives)})
end
end
local function match(wants)
for i = 1, #wants do
if wants[i] ~= active_buffer[i + read - 1] then return false end
end
return true
end
local function consume(n)
read = read + n
end
local function produce(gives)
for _, symbol in ipairs(gives) do
back_buffer[write] = symbol
write = write + 1
end
end
local function advance()
back_buffer[write], active_buffer[read] = active_buffer[read], nil
write, read = write + 1, read + 1
end
local function run_cycle()
local rule_matched = false
repeat
local rule_fired = false
for _, rule in ipairs(rule_book) do
local wants, gives = rule[1], rule[2]
if match(wants) then
consume(#wants)
produce(gives)
rule_fired, rule_matched = true, true
break
end
end
if not rule_fired then advance() end
until not active_buffer[read]
return rule_matched
end
local function exchange_buffers()
active_buffer, back_buffer = back_buffer, {}
read, write = 1, 1
end
local cycles, MAX_CYCLES = 0, 10000
local function run()
while run_cycle() and cycles < MAX_CYCLES do
print(table.concat(back_buffer, " "))
exchange_buffers()
cycles = cycles + 1
end
end
add_rule "D D" "M"
add_rule "C C C C C" "D"
add_rule "L L" "C"
add_rule "X X X X X" "L"
add_rule "V V" "X"
add_rule "I I I I I" "V"
add_rule "I I I I" "I V"
add_rule "V I V" "I X"
add_rule "X X X X" "X L"
add_rule "L X L" "X C"
add_rule "C C C C" "C D"
add_rule "D C D" "C M"
queue_up(("I"):rep(1950, " "))
run()
| 1 | local read, write = 1, 1 |
| 2 | local active_buffer, back_buffer, rule_book = {}, {}, {} |
| 3 | local function parse(str) |
| 4 | local symbols = {} |
| 5 | for symbol in str:gmatch("%S+") do |
| 6 | table.insert(symbols, symbol) |
| 7 | end |
| 8 | return symbols |
| 9 | end |
| 10 | |
| 11 | local function queue_up(string) |
| 12 | for _, symbol in ipairs(parse(string)) do |
| 13 | table.insert(active_buffer, symbol) |
| 14 | end |
| 15 | end |
| 16 | local function add_rule(wants) |
| 17 | return function(gives) |
| 18 | table.insert(rule_book, {parse(wants), parse(gives)}) |
| 19 | end |
| 20 | end |
| 21 | |
| 22 | local function match(wants) |
| 23 | for i = 1, #wants do |
| 24 | if wants[i] ~= active_buffer[i + read - 1] then return false end |
| 25 | end |
| 26 | return true |
| 27 | end |
| 28 | |
| 29 | local function consume(n) |
| 30 | read = read + n |
| 31 | end |
| 32 | |
| 33 | local function produce(gives) |
| 34 | for _, symbol in ipairs(gives) do |
| 35 | back_buffer[write] = symbol |
| 36 | write = write + 1 |
| 37 | end |
| 38 | end |
| 39 | |
| 40 | local function advance() |
| 41 | back_buffer[write], active_buffer[read] = active_buffer[read], nil |
| 42 | write, read = write + 1, read + 1 |
| 43 | end |
| 44 | |
| 45 | local function run_cycle() |
| 46 | local rule_matched = false |
| 47 | repeat |
| 48 | local rule_fired = false |
| 49 | for _, rule in ipairs(rule_book) do |
| 50 | local wants, gives = rule[1], rule[2] |
| 51 | if match(wants) then |
| 52 | consume(#wants) |
| 53 | produce(gives) |
| 54 | rule_fired, rule_matched = true, true |
| 55 | break |
| 56 | end |
| 57 | end |
| 58 | if not rule_fired then advance() end |
| 59 | until not active_buffer[read] |
| 60 | return rule_matched |
| 61 | end |
| 62 | |
| 63 | |
| 64 | local function exchange_buffers() |
| 65 | active_buffer, back_buffer = back_buffer, {} |
| 66 | read, write = 1, 1 |
| 67 | end |
| 68 | |
| 69 | local cycles, MAX_CYCLES = 0, 10000 |
| 70 | local function run() |
| 71 | while run_cycle() and cycles < MAX_CYCLES do |
| 72 | print(table.concat(back_buffer, " ")) |
| 73 | exchange_buffers() |
| 74 | cycles = cycles + 1 |
| 75 | end |
| 76 | end |
| 77 | |
| 78 | add_rule "D D" "M" |
| 79 | add_rule "C C C C C" "D" |
| 80 | add_rule "L L" "C" |
| 81 | add_rule "X X X X X" "L" |
| 82 | add_rule "V V" "X" |
| 83 | add_rule "I I I I I" "V" |
| 84 | |
| 85 | add_rule "I I I I" "I V" |
| 86 | add_rule "V I V" "I X" |
| 87 | add_rule "X X X X" "X L" |
| 88 | add_rule "L X L" "X C" |
| 89 | add_rule "C C C C" "C D" |
| 90 | add_rule "D C D" "C M" |
| 91 | |
| 92 | queue_up(("I"):rep(1950, " ")) |
| 93 | |
| 94 | run() |