Behave/ReadMe.md

102 lines
3.0 KiB
Markdown
Raw Normal View History

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
}
```
## Decorator Nodes
2017-12-08 04:54:54 +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
```
ManuallyInvertedSomeNode = {
2018-03-16 07:07:40 +00:00
decorator: (result) ->
return not result
SomeNode
}
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,
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
}
```