-
Notifications
You must be signed in to change notification settings - Fork 1
/
luabt.lua
98 lines (96 loc) · 3.35 KB
/
luabt.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
-- create a table for the module
local luabt = {}
-- define the create function
function luabt.create(node)
-- execution node
if type(node) == "function" then
return node
-- control flow node
elseif type(node) == "table" then
local children = {}
-- recursively construct child nodes
for index, child in ipairs(node.children) do
children[index] = luabt.create(child)
end
if node.type == "negate" then
-- return a negate decorator node
return function()
child = children[1]
running, success = child()
if running then
return true
else
return false, not success
end
end
elseif node.type == "sequence" then
-- return a sequence control flow node
return function()
for index, child in ipairs(children) do
running, success = child()
if running then
return true -- child running
elseif success == false then
return false, false -- child not running, failed
end
end
return false, true -- not running, all children succeeded
end
elseif node.type == "sequence*" then
-- return a sequence control flow node with memory
local states = {}
return function()
for index, child in ipairs(children) do
if states[index] == nil then
running, states[index] = child()
if running then
return true -- child running
elseif states[index] == false then
-- child failed, clear states and return the failure
states = {}
return false, false
end
end
end
-- all children succeeded, clear states and return success
states = {}
return false, true
end
elseif node.type == "selector" then
-- return a selector control flow node
return function()
for index, child in ipairs(children) do
running, success = child()
if running then
return true -- child running
elseif success == true then
return false, true -- child not running, succeeded
end
end
return false, false -- not running, all children failed
end
elseif node.type == "selector*" then
-- return a selector control flow node with memory
local states = {}
return function()
for index, child in ipairs(children) do
if states[index] == nil then
running, states[index] = child()
if running then
return true -- child running
elseif states[index] == true then
-- child suceeded, clear states and return the success
states = {}
return false, true -- child not running, succeeded
end
end
end
-- all children failed, clear states and return failure
states = {}
return false, false
end
end
end
end
-- return the module
return luabt;