new node types, bugfix, ReadMe update

* Inverted, Repeat, and Once node types
* fixed bug with Decorator
* documentation updated
This commit is contained in:
Paul Liverman III 2018-03-16 00:30:40 -07:00
parent 6455230334
commit 1c05bac30a
3 changed files with 124 additions and 32 deletions

View File

@ -38,17 +38,31 @@ WalkPath = {
}
```
## The Decorator Node
## Decorator Nodes
A very basic extension to the result of a leaf node, allowing you to alter the
result it returns. Note: You cannot alter a `behave.running` return.
Basic extensions to leaf nodes. Decorator allows you to specify a function to
modify returned results (except for `behave.running`). Inverted inverts the
result of its node. Repeat allows you to repeatedly call a node a specified
number of times. Once allows you to make a node only get called once.
```
InvertSomeNode = {
ManuallyInvertedSomeNode = {
decorator: (result) ->
return not result
SomeNode
}
InvertedSomeNode = {
type: behave.Inverted
SomeNode
}
SomeNodeRepeated = {
repeat: 20
SomeNode
}
SomeNodeOnce = {
type: behave.Once
SomeNode
}
```
## Composite Nodes
@ -67,7 +81,7 @@ Behaviors = {
## Custom Nodes
You can create custom nodes and easily use them. Rather than explaining how to,
here's an example:
here's an example inverter (note: `behave.Inverted` offers this feature):
```
-- defining the node type:

View File

@ -1,9 +1,23 @@
local make, Node, Decorate
local Node, Decorate, Repeat
local running = setmetatable({ }, {
__tostring = function()
return "running"
end
})
local make
make = function(tab)
if "function" == type(tab) then
return tab
elseif tab.decorate then
return Decorate(tab)
elseif tab["repeat"] then
return Repeat(tab)
elseif "function" == type(tab.type) then
return tab.type(tab)
else
return Node(tab)
end
end
local get_nodes
get_nodes = function(tab)
local nodes = { }
@ -13,17 +27,6 @@ get_nodes = function(tab)
end
return nodes
end
make = function(tab)
if "function" == type(tab) then
return tab
elseif "function" == type(tab.type) then
return tab.type(tab)
elseif tab.decorate then
return Decorate(tab)
else
return Node(tab)
end
end
Node = function(tab)
local state, started = { }, false
return function(...)
@ -52,13 +55,52 @@ local Decorator
Decorator = function(tab)
local node = make(tab[1])
return function(...)
local result = node(object, ...)
local result = node(...)
if not (result == running) then
result = tab.decorate(result, ...)
end
return result
end
end
local Inverted
Inverted = function(tab)
local node = make(tab[1])
return function(...)
local result = node(...)
if not (result == running) then
return not result
end
end
end
Repeat = function(tab)
local node = make(tab[1])
local i, r = 1, tab["repeat"]
return function(...)
while i <= r do
if running == node(...) then
return running
end
i = i + 1
end
i = 1
return true
end
end
local Once
Once = function(tab)
local node = make(tab[1])
local ran = false
return function(...)
if ran then
return false
end
local result = node(...)
if not (result == running) then
ran = true
end
return result
end
end
local Selector
Selector = function(tab)
local nodes = get_nodes(tab)
@ -123,6 +165,9 @@ return {
failure = false,
Node = Node,
Decorator = Decorator,
Inverter = Inverter,
Repeat = Repeat,
Once = Once,
Selector = Selector,
Sequence = Sequence,
Random = Random

View File

@ -1,24 +1,26 @@
local make, Node, Decorate
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
-- produces a callable function from a defined node or full behavior tree
make = (tab) ->
if "function" == type tab
return tab
elseif "function" == type tab.type
return tab.type tab
elseif tab.decorate
return Decorate tab
else
return Node tab
-- complex leaf node
-- state is preserved through calls, optional start/finish functions
Node = (tab) ->
@ -38,10 +40,37 @@ Node = (tab) ->
Decorator = (tab) ->
node = make tab[1]
return (...) ->
result = node object, ...
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
@ -91,9 +120,13 @@ Random = (tab) ->
success: true
:running
failure: false
:Node
:Decorator
:Inverter
:Repeat
:Once
:Selector
:Sequence
:Random