mirror of
https://github.com/TangentFoxy/Behave.git
synced 2024-11-15 11:04:21 +00:00
1c05bac30a
* Inverted, Repeat, and Once node types * fixed bug with Decorator * documentation updated
134 lines
2.7 KiB
Plaintext
134 lines
2.7 KiB
Plaintext
local Node, Decorate, Repeat
|
|
|
|
running = setmetatable {}, __tostring: -> return "running"
|
|
|
|
-- produces a callable function from a defined node or full behavior tree
|
|
make = (tab) ->
|
|
if "function" == type tab
|
|
return tab
|
|
elseif tab.decorate
|
|
return Decorate tab
|
|
elseif tab.repeat
|
|
return Repeat tab
|
|
elseif "function" == type tab.type
|
|
return tab.type tab
|
|
else
|
|
return Node tab
|
|
|
|
get_nodes = (tab) ->
|
|
nodes = {}
|
|
for node in *tab
|
|
table.insert nodes, make node
|
|
return nodes
|
|
|
|
-- complex leaf node
|
|
-- state is preserved through calls, optional start/finish functions
|
|
Node = (tab) ->
|
|
state, started = {}, false
|
|
return (...) ->
|
|
local result
|
|
unless started
|
|
result = tab.start state, ... if tab.start
|
|
started = true unless result == false
|
|
result = tab.run state, ... unless result == false
|
|
if result != running
|
|
started = false
|
|
result = tab.finish state, ... if result and tab.finish
|
|
return result
|
|
|
|
-- modifies the result of a node before returning it
|
|
Decorator = (tab) ->
|
|
node = make tab[1]
|
|
return (...) ->
|
|
result = node(...)
|
|
result = tab.decorate result, ... unless result == running
|
|
return result
|
|
|
|
-- inverts the result of a node before returning it
|
|
Inverted = (tab) ->
|
|
node = make tab[1]
|
|
return (...) ->
|
|
result = node(...)
|
|
return not result unless result == running
|
|
|
|
Repeat = (tab) ->
|
|
node = make tab[1]
|
|
i, r = 1, tab.repeat
|
|
return (...) ->
|
|
while i <= r
|
|
return running if running == node(...)
|
|
i += 1
|
|
i = 1
|
|
return true
|
|
|
|
Once = (tab) ->
|
|
node = make tab[1]
|
|
ran = false
|
|
return (...) ->
|
|
return false if ran
|
|
result = node(...)
|
|
unless result == running
|
|
ran = true
|
|
return result
|
|
|
|
-- returns first success/running, or failure
|
|
Selector = (tab) ->
|
|
nodes = get_nodes tab
|
|
length = #nodes
|
|
i = 1
|
|
return (...) ->
|
|
result = nodes[i](...)
|
|
while not result
|
|
i += 1
|
|
if i > length
|
|
i = 1
|
|
return false
|
|
result = nodes[i](...)
|
|
i = 1 if result != running
|
|
return result
|
|
|
|
-- returns first running/failure, or success
|
|
Sequence = (tab) ->
|
|
nodes = get_nodes tab
|
|
length = #nodes
|
|
i = 1
|
|
return (...) ->
|
|
result = nodes[i](...)
|
|
while result and result != running
|
|
i += 1
|
|
if i > length
|
|
i = 1
|
|
return result
|
|
result = nodes[i](...)
|
|
i = 1 unless result
|
|
return result
|
|
|
|
-- returns success/running/failure from random child
|
|
Random = (tab) ->
|
|
nodes = get_nodes tab
|
|
length = #nodes
|
|
local r
|
|
return (...) ->
|
|
unless r
|
|
r = 1 + math.random length
|
|
result = nodes[r](...)
|
|
unless result == running
|
|
r = nil
|
|
return result
|
|
|
|
{
|
|
success: true
|
|
:running
|
|
failure: false
|
|
:Node
|
|
|
|
:Decorator
|
|
:Inverter
|
|
:Repeat
|
|
:Once
|
|
|
|
:Selector
|
|
:Sequence
|
|
:Random
|
|
}
|