capitalex ha revisionato questo gist 10 months ago. Vai alla revisione
2 files changed, 322 insertions
main.lua(file creato)
| @@ -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(file creato)
| @@ -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 | |
Più nuovi
Più vecchi