capitalex zrewidował ten Gist . Przejdź do rewizji
2 files changed, 322 insertions
main.lua(stworzono plik)
@@ -0,0 +1,230 @@ | |||
1 | + | local PathBag = require "path-bag" | |
2 | + | local the_eye = require "the-eye" | |
3 | + | local pprint = require "pprint" | |
4 | + | -- knowledge base | |
5 | + | local kb = PathBag.new() | |
6 | + | ||
7 | + | for _, pixel in ipairs(the_eye) do | |
8 | + | kb:insert { "image", "eye", pixel[4], pixel[5], pixel[1], pixel[2], pixel[3] } | |
9 | + | end | |
10 | + | ||
11 | + | math.randomseed(os.time()) | |
12 | + | local 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) | |
18 | + | end | |
19 | + | ||
20 | + | local 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 | |
29 | + | end | |
30 | + | ||
31 | + | local 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 | |
41 | + | end | |
42 | + | ||
43 | + | local 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 | |
66 | + | end | |
67 | + | ||
68 | + | local 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 | |
84 | + | end | |
85 | + | ||
86 | + | local 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 | |
102 | + | end | |
103 | + | ||
104 | + | local 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 | |
130 | + | end | |
131 | + | ||
132 | + | local 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 | |
138 | + | end | |
139 | + | ||
140 | + | local 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 | |
150 | + | end | |
151 | + | ||
152 | + | local 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 | |
163 | + | end | |
164 | + | ||
165 | + | local 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 | |
172 | + | end | |
173 | + | ||
174 | + | local 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 | |
183 | + | end | |
184 | + | ||
185 | + | local 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 | + | ||
197 | + | local screen = love.graphics.newCanvas() | |
198 | + | ||
199 | + | ||
200 | + | function 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) | |
205 | + | end | |
206 | + | ||
207 | + | function 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) | |
230 | + | end |
path-bag.lua(stworzono plik)
@@ -0,0 +1,92 @@ | |||
1 | + | love = love or {} | |
2 | + | local 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 | + | --]] | |
20 | + | local PathBag = {} | |
21 | + | PathBag.__mt = {} | |
22 | + | ||
23 | + | function PathBag.new() | |
24 | + | local obj = { root = {children = {}, child_count = 0, count = 0} } | |
25 | + | return setmetatable(obj, {__index = PathBag.__mt}) | |
26 | + | end | |
27 | + | ||
28 | + | function 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 | |
38 | + | end | |
39 | + | ||
40 | + | function 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 | |
54 | + | end | |
55 | + | ||
56 | + | function 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 | |
69 | + | end | |
70 | + | ||
71 | + | function 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 | |
88 | + | end | |
89 | + | ||
90 | + | ||
91 | + | ||
92 | + | return PathBag |
Nowsze
Starsze