diff --git a/init.lua b/init.lua index 8b5c178..9852991 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,11 @@ local Tactree = {} local Nodes = {} +local function NodeReset(node) + node:_finish() + node._started = false +end + local function NodeStart(node, args) -- don't start again if started if node._started then return end @@ -14,14 +19,27 @@ end local function NodeUpdate(node, ...) -- automatically start if not started - if not node._started then NodeStart(node) end + if not node._started then + NodeStart(node) + end + + -- mark node as run and unmark children + node._ran = true + for _, child in ipairs(node.children) do + child._ran = false + end local result = node:_tick(...) - if type(result) == 'boolean' then - node:_finish() + if result ~= nil then + NodeReset(node) + end - node._started = false + -- reset unrun children + for _, child in ipairs(node.children) do + if not child._ran and child._started then + NodeReset(child) + end end return result @@ -85,8 +103,8 @@ local function tree_by_name(name, depth) node.update = NodeUpdate node.private = NodePrivateData - -- this will crash if there is a recursive structure - -- find a way to prevent this? + -- this will crash if there is a recursive structure; find a way to prevent this? + -- does my API even allow declaring recursive structures? if Nodes[name].children then for _, child in ipairs(Nodes[name].children) do local cn = tree_by_name(child, depth + 1) @@ -137,6 +155,20 @@ function Tactree.Tree(name) end Tactree.Leaf 'Sequence' +{ + function(node, ...) + local child = 1 + local result + repeat + result = node.children[child]:update(...) + child = child + 1 + until (not result) or (child > #node.children) + + return result + end +} + +Tactree.Leaf 'StepSequence' { start = function(node) node:private().current_child = 1 @@ -145,9 +177,7 @@ Tactree.Leaf 'Sequence' local result repeat result = node.children[node:private().current_child]:update(...) - if result then - node:private().current_child = node:private().current_child + 1 - end + if result ~= nil then node:private().current_child = node:private().current_child + 1 end until (not result) or (node:private().current_child > #node.children) return result @@ -155,6 +185,20 @@ Tactree.Leaf 'Sequence' } Tactree.Leaf 'Selector' +{ + function(node, ...) + local child = 1 + local result + repeat + result = node.children[child]:update(...) + child = child + 1 + until (result ~= false) or (child > #node.children) + + return result + end +} + +Tactree.Leaf 'StepSelector' { start = function(node) node:private().current_child = 1 @@ -163,9 +207,7 @@ Tactree.Leaf 'Selector' local result repeat result = node.children[node:private().current_child]:update(...) - if result == false then - node:private().current_child = node:private().current_child + 1 - end + if result ~= nil then node:private().current_child = node:private().current_child + 1 end until (result ~= false) or (node:private().current_child > #node.children) return result @@ -174,30 +216,11 @@ Tactree.Leaf 'Selector' Tactree.Leaf 'Inverter' { - start = function(node) - node.children[1]:start() - end, - tick = function(node, ...) + function(node, ...) local result = node.children[1]:update(...) - if type(result) == 'boolean' then return not result end + if result ~= nil then return not result end end } ---[[ - 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' } - - local tr = Tactree.Tree 'Pick up nearest object' - - tr:start{ ... } ( or, if you already have a table, tr:start(existing_table) ) - - t:update() -]]-- - return Tactree \ No newline at end of file