From fa96a38a1d73eeb64acb396b4c57a7d091e407f3 Mon Sep 17 00:00:00 2001 From: Shylie Date: Sun, 23 Jun 2024 23:53:32 -0400 Subject: [PATCH] Allow reuse of composite nodes --- init.lua | 78 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/init.lua b/init.lua index 869f09c..a26d388 100644 --- a/init.lua +++ b/init.lua @@ -1,11 +1,12 @@ local Tactree = {} -local Registry = {} +Tactree.Nodes = {} local function NodeStart(node, args) -- abort if started if node.data then return end node.data = node.parent and node.parent.data or args + node.data[node] = {} node:_start() end @@ -24,16 +25,20 @@ local function NodeUpdate(node) return result end +local function NodePrivateData(node) + return node.data[node] +end + local function default_impl(node) end -function Tactree.Node(name) +function Tactree.Leaf(name) return function(t) - if Registry[name] then + if Tactree.Nodes[name] then error('node with name \'' .. name .. '\' already exists.', 2) else - Registry[name] = {} + Tactree.Nodes[name] = {} end - local node_type = Registry[name] + local node_type = Tactree.Nodes[name] local tick = t.tick or t[1] if type(tick) ~= 'function' then error('no tick function supplied', 2) end @@ -44,40 +49,59 @@ function Tactree.Node(name) end end -function Tactree.Tree(name) - if not Registry[name] then error('no such node \'' .. name .. '\'', 2) end +function Tactree.Composite(name) + return function(parent_type_name) + return function(children) + if Tactree.Nodes[name] then + error('node with name \'' .. name .. '\' already exists.', 2) + else + if not Tactree.Nodes[parent_type_name] then error('no such node \'' .. name .. '\'', 2) end + Tactree.Nodes[name] = setmetatable({}, Tactree.Nodes[parent_type_name]) + end - local node = setmetatable({}, { __index = Registry[name] }) - node.children = {} - node.start = NodeStart - node.update = NodeUpdate + local node_type = Tactree.Nodes[name] + + node_type.children = {} - return function(children) - if type(children) == 'table' then for _, child in ipairs(children) do - if type(child) == 'string' then - child = Tactree.Tree(child) - elseif type(child) ~= 'table' then - error('invalid child type: ' .. type(child), 2) - end + if type(child) ~= 'string' then error('invalid child node', 2) end - child.parent = node - table.insert(node.children, child) + table.insert(node_type.children, child) end end - - return node end end +function Tactree.Tree(name) + if not Tactree.Nodes[name] then error('no such node \'' .. name .. '\'', 2) end + + local node = {} + node.children = {} + node.start = NodeStart + node.update = NodeUpdate + node.private = NodePrivateData + + if Tactree.Nodes[name].children then + for _, child in ipairs(Tactree.Nodes[name].children) do + table.insert(node.children, Tactree.Tree(child)) + end + end + + return setmetatable(node, { __index = Tactree.Nodes[name] }) +end + --[[ - Tactree.Node 'Find nearest object' { function (node) ... end } - Tactree.Node 'Pick up object' { function (node) ... end} - Tactree.Node 'Move' { function (node) return node.data.creature:move(node.data.tx, node.data.ty, dt) end } + Example usage + ------------- - local t = Tactree.Tree 'Sequence' { 'Find nearest object', 'Move', 'Pick up object' } + Tactree.Leaf 'Find nearest object' { function (node) ... end } + Tactree.Leaf 'Pick up object' { function (node) ... end} + Tactree.Leaf 'Move' { function (node) return node.data.creature:move(node.data.tx, node.data.ty, dt) end } + Tactree.Composite 'Pick up nearest object' 'Sequence' { 'Find nearest object', 'Move', 'Pick up object' } - t:start(...) + local tr = Tactree.Tree 'Pick up nearest object' + + tr:start{ ... } ( or, if you already have a table, tr:start(existing_table) ) t:update() ]]--