tactree/init.lua

109 lines
2.6 KiB
Lua
Raw Normal View History

2024-06-23 13:13:16 +00:00
local Tactree = {}
2024-06-24 03:53:32 +00:00
Tactree.Nodes = {}
2024-06-23 13:13:16 +00:00
local function NodeStart(node, args)
-- abort if started
if node.data then return end
node.data = node.parent and node.parent.data or args
2024-06-24 03:53:32 +00:00
node.data[node] = {}
2024-06-23 13:13:16 +00:00
node:_start()
end
local function NodeUpdate(node)
-- abort if not started
if not node.data then return end
local result = node:_tick()
if type(result) == 'boolean' then
node:_finish()
node.data = nil
end
return result
end
2024-06-24 03:53:32 +00:00
local function NodePrivateData(node)
return node.data[node]
end
2024-06-23 13:13:16 +00:00
local function default_impl(node) end
2024-06-24 03:53:32 +00:00
function Tactree.Leaf(name)
2024-06-23 13:13:16 +00:00
return function(t)
2024-06-24 03:53:32 +00:00
if Tactree.Nodes[name] then
2024-06-23 13:13:16 +00:00
error('node with name \'' .. name .. '\' already exists.', 2)
else
2024-06-24 03:53:32 +00:00
Tactree.Nodes[name] = {}
2024-06-23 13:13:16 +00:00
end
2024-06-24 03:53:32 +00:00
local node_type = Tactree.Nodes[name]
2024-06-23 13:13:16 +00:00
local tick = t.tick or t[1]
if type(tick) ~= 'function' then error('no tick function supplied', 2) end
node_type._tick = tick
node_type._start = type(t.start) == 'function' and t.start or default_impl
node_type._finish = type(t.finish) == 'function' and t.finish or default_impl
end
end
2024-06-24 03:53:32 +00:00
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_type = Tactree.Nodes[name]
node_type.children = {}
for _, child in ipairs(children) do
if type(child) ~= 'string' then error('invalid child node', 2) end
table.insert(node_type.children, child)
end
end
end
end
2024-06-23 13:13:16 +00:00
function Tactree.Tree(name)
2024-06-24 03:53:32 +00:00
if not Tactree.Nodes[name] then error('no such node \'' .. name .. '\'', 2) end
2024-06-23 13:13:16 +00:00
2024-06-24 03:53:32 +00:00
local node = {}
2024-06-23 13:13:16 +00:00
node.children = {}
node.start = NodeStart
node.update = NodeUpdate
2024-06-24 03:53:32 +00:00
node.private = NodePrivateData
2024-06-23 13:13:16 +00:00
2024-06-24 03:53:32 +00:00
if Tactree.Nodes[name].children then
for _, child in ipairs(Tactree.Nodes[name].children) do
table.insert(node.children, Tactree.Tree(child))
2024-06-23 13:13:16 +00:00
end
end
2024-06-24 03:53:32 +00:00
return setmetatable(node, { __index = Tactree.Nodes[name] })
2024-06-23 13:13:16 +00:00
end
--[[
2024-06-24 03:53:32 +00:00
Example usage
-------------
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' }
2024-06-23 13:13:16 +00:00
2024-06-24 03:53:32 +00:00
local tr = Tactree.Tree 'Pick up nearest object'
2024-06-23 13:13:16 +00:00
2024-06-24 03:53:32 +00:00
tr:start{ ... } ( or, if you already have a table, tr:start(existing_table) )
2024-06-23 13:13:16 +00:00
t:update()
]]--
return Tactree