2017-12-08 04:54:54 +00:00
|
|
|
# Behave
|
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
A simple implementation of behavior trees in MoonScript / Lua. Define behaviors
|
|
|
|
as functions or small tables, then call `behave.make` on them to get a function
|
|
|
|
you can call repeatedly to execute behaviors.
|
|
|
|
|
|
|
|
A node should return a truthy or falsy value to indicate success or failure, or
|
|
|
|
`behave.running` to indicate that the node needs to be called again to continue
|
|
|
|
running.
|
|
|
|
|
|
|
|
Examples are in MoonScript, but shouldn't be too difficult to understand even if
|
|
|
|
you are unfamiliar with its syntax.
|
2017-12-08 04:54:54 +00:00
|
|
|
|
|
|
|
## Example
|
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
```
|
|
|
|
TODO
|
|
|
|
```
|
|
|
|
|
|
|
|
## Leaf Nodes
|
|
|
|
|
|
|
|
The easiest node is just a function that will be passed all arguments sent to a
|
|
|
|
behavior tree it is part of. There is a slightly more complex leaf node for
|
|
|
|
maintaining an internal state, and optional `start`/`finish` functions only
|
|
|
|
called at the beginning and end of processing.
|
2017-12-08 04:54:54 +00:00
|
|
|
|
|
|
|
```
|
2018-03-16 07:07:40 +00:00
|
|
|
WalkPath = {
|
|
|
|
start: (state, entity) ->
|
|
|
|
state.path = findPath(entity, entity.target)
|
|
|
|
return state.path
|
|
|
|
run: (state, entity) ->
|
|
|
|
-- this will not run if start fails
|
|
|
|
state.path.step!
|
|
|
|
finish: (state, entity) ->
|
|
|
|
-- this will run only if run returns a truthy value besides behave.running
|
|
|
|
state.path = nil
|
2017-12-08 04:54:54 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-03-16 07:30:40 +00:00
|
|
|
## Decorator Nodes
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:30:40 +00:00
|
|
|
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.
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
```
|
2018-03-16 07:30:40 +00:00
|
|
|
ManuallyInvertedSomeNode = {
|
2018-03-16 07:07:40 +00:00
|
|
|
decorator: (result) ->
|
|
|
|
return not result
|
|
|
|
SomeNode
|
|
|
|
}
|
2018-03-16 07:30:40 +00:00
|
|
|
InvertedSomeNode = {
|
|
|
|
type: behave.Inverted
|
|
|
|
SomeNode
|
|
|
|
}
|
|
|
|
SomeNodeRepeated = {
|
|
|
|
repeat: 20
|
|
|
|
SomeNode
|
|
|
|
}
|
|
|
|
SomeNodeOnce = {
|
|
|
|
type: behave.Once
|
|
|
|
SomeNode
|
|
|
|
}
|
2018-03-16 07:07:40 +00:00
|
|
|
```
|
2017-12-08 04:54:54 +00:00
|
|
|
|
|
|
|
## Composite Nodes
|
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
Selector skips any failures and returns on the first node that returns a truthy
|
|
|
|
value (or returns `false` if nothing succeeds). Sequence continues until there
|
|
|
|
is a failure or returns success. Random executes a random node underneath it.
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
```
|
|
|
|
Behaviors = {
|
|
|
|
type: behave.Random
|
|
|
|
WalkRandomly, LookAtPhone, LeaveArea
|
|
|
|
}
|
|
|
|
```
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
## Custom Nodes
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
You can create custom nodes and easily use them. Rather than explaining how to,
|
2018-03-16 07:30:40 +00:00
|
|
|
here's an example inverter (note: `behave.Inverted` offers this feature):
|
2017-12-08 04:54:54 +00:00
|
|
|
|
2018-03-16 07:07:40 +00:00
|
|
|
```
|
|
|
|
-- defining the node type:
|
|
|
|
Invert = (tab) -> -- your fn will be passed a table describing the node
|
|
|
|
node = behave.make tab[1] -- call make on any sub-nodes that you will be using, save the result
|
|
|
|
return (...) -> -- use variable arguments, so sub-nodes can
|
|
|
|
result = node(...) -- get what they need
|
|
|
|
unless result == behave.running -- running nodes should not be interrupted
|
|
|
|
result = not result -- and finally we invert the result before
|
|
|
|
return result -- returning it
|
|
|
|
|
|
|
|
-- using the node type:
|
|
|
|
SomeInvertedNode = {
|
|
|
|
type: Invert -- this is how the library knows what function to call
|
|
|
|
SomeNode -- this is the node that will be inverted
|
|
|
|
}
|
|
|
|
```
|