Última actividad 1738990209

Revisión 9ccd39ff6488cbe0df32e6eae698fb7ad0ba30d1

main.lua Sin formato Playground
1local PathBag = require "path-bag"
2local the_eye = require "the-eye"
3local pprint = require "pprint"
4-- knowledge base
5local kb = PathBag.new()
6
7for _, pixel in ipairs(the_eye) do
8 kb:insert { "image", "eye", pixel[4], pixel[5], pixel[1], pixel[2], pixel[3] }
9end
10
11math.randomseed(os.time())
12local function uuid()
13 local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
14 return string.gsub(template, '[xy]', function (c)
15 local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
16 return string.format('%x', v)
17 end)
18end
19
20local function io_add(kb)
21 local node, b = kb:get_and_bind {
22 "@add", "eval", "$id", "$x", "$y"
23 }
24 if not node then return false end
25
26 kb:remove_node(node)
27 kb:insert { "@add", "success", b.id, b.x + b.y }
28 return true
29end
30
31local function io_put_pixel(kb)
32 local node, b = kb:get_and_bind {
33 "@put", "pixel", "$r", "$g", "$b", "$x", "$y"
34 }
35 if not node then return false end
36 kb:remove_node(node)
37
38 love.graphics.setColor(b.r, b.g, b.b, 1.0)
39 love.graphics.points(b.x, b.y)
40 return true
41end
42
43local function put_pixel(kb)
44 local put_pixel, b1 = kb:get_and_bind {
45 "put", "pixel", "$r", "$g", "$b", "at", "$px_result", "$py_result"
46 }
47 if not put_pixel then return false end
48
49 local px, b2 = kb:get_and_bind {
50 "@add", "success", b1.px_result, "$px"
51 }
52 if not px then return false end
53
54
55 local py, b3 = kb:get_and_bind {
56 "@add", "success", b1.py_result, "$py"
57 }
58 if not py then return false end
59
60 kb:remove_node(put_pixel)
61 kb:remove_node(px)
62 kb:remove_node(py)
63
64 kb:insert { "@put", "pixel", b1.r, b1.g, b1.b, b2.px, b3.py }
65 return true
66end
67
68local function next_cursor_down_1(kb)
69 local next_cursor, b1 = kb:get_and_bind {
70 "next", "cursor", "down", "$down_id"
71 }
72 if not next_cursor then return false end
73
74 local add_success, b2 = kb:get_and_bind {
75 "@add", "success", b1.down_id, "$cy"
76 }
77 if not add_success then return false end
78
79 kb:remove_node(next_cursor)
80 kb:remove_node(add_success)
81
82 kb:insert { "cursor", 0, b2.cy }
83 return true
84end
85
86local function next_cursor_right_1(kb)
87 local next_cursor, b1 = kb:get_and_bind {
88 "next", "cursor", "right", "$right_id", "$cy"
89 }
90 if not next_cursor then return false end
91
92 local add_success, b2 = kb:get_and_bind {
93 "@add", "success", b1.right_id, "$cx"
94 }
95 if not add_success then return false end
96
97 kb:remove_node(next_cursor)
98 kb:remove_node(add_success)
99
100 kb:insert { "cursor", b2.cx, b1.cy }
101 return true
102end
103
104local function draw_image_1(kb)
105 local draw_image, b1 = kb:get_and_bind {
106 "draw", "image", "$image", "$x", "$y"
107 }
108 if not draw_image then return end
109
110 local cursor, b2 = kb:get_and_bind {
111 "cursor", "$cx", "$cy"
112 }
113 if not cursor then return end
114
115 local image, b3 = kb:get_and_bind {
116 "image", "$image", b2.cx, b2.cy, "$r", "$g", "$b"
117 }
118 if not image then return end
119
120 kb:remove_node(cursor)
121
122 local px_id = uuid()
123 local py_id = uuid()
124
125 kb:insert { "put", "pixel", b3.r, b3.g, b3.b, "at", px_id, py_id }
126 kb:insert { "advance", "cursor", b2.cx, b2.cy }
127 kb:insert { "@add", "eval", px_id, b1.x, b2.cx }
128 kb:insert { "@add", "eval", py_id, b1.y, b2.cy }
129 return true
130end
131
132local function advance_cursor_1(kb)
133 local node, b = kb:get_and_bind { "advance", "cursor", 249, 165 }
134 if not node then return false end
135
136 kb:remove_node(node)
137 return true
138end
139
140local function advance_cursor_2(kb)
141 local node, b = kb:get_and_bind { "advance", "cursor", 249, "$cy" }
142 if not node then return false end
143
144 kb:remove_node(node)
145
146 local down_id = uuid()
147 kb:insert { "next", "cursor", "down", down_id }
148 kb:insert { "@add", "eval", down_id, 1, b.cy }
149 return true
150end
151
152local function advance_cursor_3(kb)
153 local node, b = kb:get_and_bind { "advance", "cursor", "$cx", "$cy" }
154 if not node then return false end
155
156
157 kb:remove_node(node)
158
159 local right_id = uuid()
160 kb:insert { "next", "cursor", "right", right_id, b.cy }
161 kb:insert { "@add", "eval", right_id, 1, b.cx }
162 return true
163end
164
165local function draw_image_2(kb)
166 local node, b = kb:get_and_bind { "draw", "image", "$image", "$x", "$y" }
167 if not node then return false end
168
169 kb:remove_node(node)
170
171 return true
172end
173
174local function tick(kb)
175 local node, b = kb:get_and_bind { "tick", "$dt" }
176 if not node then return false end
177
178 kb:remove_node(node)
179
180 kb:insert { "draw", "image", "eye", 0, 0 }
181 kb:insert { "cursor", 0, 0 }
182 return true
183end
184
185local rules =
186 { io_add
187 , io_put_pixel
188 , put_pixel
189 , next_cursor_down_1
190 , next_cursor_right_1
191 , draw_image_1
192 , advance_cursor_1, advance_cursor_2, advance_cursor_3
193 , draw_image_2
194 , tick
195 }
196
197local screen = love.graphics.newCanvas()
198
199
200function love.draw()
201 love.graphics.setColor(1, 1, 1)
202 love.graphics.draw(screen, 0, 0)
203 love.graphics.setColor(1, 0, 0)
204 love.graphics.print(tostring(love.timer.getFPS()) .. " fps", 0, 0)
205end
206
207function love.update(dt)
208 local dt_fact = tostring(dt)
209 local now = os.time()
210 love.graphics.setCanvas(screen)
211 love.graphics.clear(0, 0, 0, 0)
212 kb:insert { "tick", dt }
213 local rewrite = true
214 -- pprint("--- START ---")
215 -- pprint(kb)
216 while rewrite do
217 rewrite = false
218 for i, rule in ipairs(rules) do
219 if rule(kb) then
220 -- print("--- MATCH ---")
221 -- pprint(kb)
222 rewrite = true
223 break
224 end
225 end
226 end
227 love.graphics.setCanvas()
228 local later = os.time()
229 print(later - now)
230end
path-bag.lua Sin formato Playground
1love = love or {}
2local pprint = require "pprint"
3
4--[[
5 If you are familiar with jargon, then a "path bag" is
6 a muliset that is implemented as a prefix tree.
7
8 this is a path
9 this is another path
10 this is a final path
11 this is a path
12 |
13 V
14 this <-> is <-> a <-> path {2}
15 | |
16 | + <-> final path {1}
17 |
18 + <-> another <-> path {1}
19--]]
20local PathBag = {}
21PathBag.__mt = {}
22
23function PathBag.new()
24 local obj = { root = {children = {}, child_count = 0, count = 0} }
25 return setmetatable(obj, {__index = PathBag.__mt})
26end
27
28function PathBag.__mt:insert(path)
29 local root = self.root
30 for _, step in ipairs(path) do
31 if not root.children[step] then
32 root.children[step] = { value = step, children = {}, child_count = 0, count = 0, parent = root }
33 root.child_count = root.child_count + 1
34 end
35 root = root.children[step]
36 end
37 root.count = root.count + 1
38end
39
40function PathBag.__mt:get(path)
41 local root = self.root
42 for _, step in ipairs(path) do
43 if step == "*" then
44 _, root = next(root.children)
45 if not root then return end
46 elseif not root.children[step] then
47 return nil
48 else
49 root = root.children[step]
50 end
51 end
52
53 return root.count ~= 0 and root or nil
54end
55
56function PathBag.__mt:remove_node(node)
57 local leaf = node
58 while leaf.parent do
59 leaf.count = leaf.count - 1
60 if leaf.count <= 0 and leaf.child_count <= 0 then
61 local path = leaf.value
62 leaf = leaf.parent
63 leaf.children[path] = nil
64 leaf.child_count = leaf.child_count - 1
65 else
66 return
67 end
68 end
69end
70
71function PathBag.__mt:get_and_bind(path)
72 local bindings, root = {}, self.root
73 for _, step in ipairs(path) do
74 if type(step) == "string" and step:find("^%$") then
75 key, root = next(root.children)
76 if not root then return end
77 bindings[step:sub(2)] = key
78 elseif not root.children[step] then
79 return nil
80 else
81 root = root.children[step]
82 end
83 end
84
85 if root.count ~= 0 then
86 return root, bindings
87 end
88end
89
90
91
92return PathBag