Allow reuse of composite nodes
This commit is contained in:
parent
d3e1c8e711
commit
fa96a38a1d
78
init.lua
78
init.lua
@ -1,11 +1,12 @@
|
|||||||
local Tactree = {}
|
local Tactree = {}
|
||||||
local Registry = {}
|
Tactree.Nodes = {}
|
||||||
|
|
||||||
local function NodeStart(node, args)
|
local function NodeStart(node, args)
|
||||||
-- abort if started
|
-- abort if started
|
||||||
if node.data then return end
|
if node.data then return end
|
||||||
|
|
||||||
node.data = node.parent and node.parent.data or args
|
node.data = node.parent and node.parent.data or args
|
||||||
|
node.data[node] = {}
|
||||||
node:_start()
|
node:_start()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,16 +25,20 @@ local function NodeUpdate(node)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function NodePrivateData(node)
|
||||||
|
return node.data[node]
|
||||||
|
end
|
||||||
|
|
||||||
local function default_impl(node) end
|
local function default_impl(node) end
|
||||||
function Tactree.Node(name)
|
function Tactree.Leaf(name)
|
||||||
return function(t)
|
return function(t)
|
||||||
if Registry[name] then
|
if Tactree.Nodes[name] then
|
||||||
error('node with name \'' .. name .. '\' already exists.', 2)
|
error('node with name \'' .. name .. '\' already exists.', 2)
|
||||||
else
|
else
|
||||||
Registry[name] = {}
|
Tactree.Nodes[name] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local node_type = Registry[name]
|
local node_type = Tactree.Nodes[name]
|
||||||
|
|
||||||
local tick = t.tick or t[1]
|
local tick = t.tick or t[1]
|
||||||
if type(tick) ~= 'function' then error('no tick function supplied', 2) end
|
if type(tick) ~= 'function' then error('no tick function supplied', 2) end
|
||||||
@ -44,40 +49,59 @@ function Tactree.Node(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Tactree.Tree(name)
|
function Tactree.Composite(name)
|
||||||
if not Registry[name] then error('no such node \'' .. name .. '\'', 2) end
|
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] })
|
local node_type = Tactree.Nodes[name]
|
||||||
node.children = {}
|
|
||||||
node.start = NodeStart
|
node_type.children = {}
|
||||||
node.update = NodeUpdate
|
|
||||||
|
|
||||||
return function(children)
|
|
||||||
if type(children) == 'table' then
|
|
||||||
for _, child in ipairs(children) do
|
for _, child in ipairs(children) do
|
||||||
if type(child) == 'string' then
|
if type(child) ~= 'string' then error('invalid child node', 2) end
|
||||||
child = Tactree.Tree(child)
|
|
||||||
elseif type(child) ~= 'table' then
|
|
||||||
error('invalid child type: ' .. type(child), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
child.parent = node
|
table.insert(node_type.children, child)
|
||||||
table.insert(node.children, child)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return node
|
|
||||||
end
|
end
|
||||||
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 }
|
Example usage
|
||||||
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 }
|
|
||||||
|
|
||||||
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()
|
t:update()
|
||||||
]]--
|
]]--
|
||||||
|
Loading…
Reference in New Issue
Block a user