moving-stuff-kinda.lua
· 8.6 KiB · Lua
Неформатований
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
Неформатований
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
Неформатований
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() |