Behavior Tree v0.3.1 BehaviorTree.Node View Source
A collection of “standard” behavior tree nodes.
By composing these nodes, you should be able to describe almost any behavior you need. The children of each node can be a mix of other nodes to create deeper trees, or any other value to create a leaf (an atom or function is recommended).
These nodes implement BehaviorTree.Node.Protocol
.
Link to this section Summary
Functions
Create an “always_fail” style “decorator” node
Create an “always_succeed” style “decorator” node
Create a “negate” style “decorator” node
Create a “random” style “decorator” node
Create a “random_weighted” style “decorator” node
Create a “repeat_n” style “decorator” node
Create a “repeat_until_fail” style “decorator” node
Create a “repeat_until_succeed” style “decorator” node
Create a “select” style node with the supplied children
Create a “sequence” style node with the supplied children
Link to this section Types
Link to this section Functions
Create an “always_fail” style “decorator” node.
This node takes a single child, and will always fail, regardless of the outcome of the child.
This may be useful when used in combination with the “random” nodes.
Example
iex> tree = Node.sequence([
...> Node.always_fail(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:a
always_succeed(any()) :: BehaviorTree.Node.t()
Create an “always_succeed” style “decorator” node.
This node takes a single child, and will always succeed, regardless of the outcome of the child.
This may be useful when used in combination with the “random” nodes.
Example
iex> tree = Node.sequence([
...> Node.always_succeed(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.value
:b
Create a “negate” style “decorator” node.
This node takes a single child. If the child fails, this node succeeds. If the child succeeds, this node fails.
This may be useful to simplify handlers code.
Example
iex> tree = Node.sequence([
...> Node.negate(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.value
:b
Create a “random” style “decorator” node.
This node takes multiple children, from which it will randomly pick one to run (using :rand.uniform/1
). If that child fails, this node fails, if the child succeeds, this node succeeds.
Example
Node.random([:a, :b, :c]) |> BehaviorTree.start |> BehaviorTree.value # will be one of :a, :b, or :c
iex> tree = Node.sequence([
...> Node.random([:a, :b, :c]),
...> :d
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:d
random_weighted([{any(), pos_integer()}, ...]) :: BehaviorTree.Node.t()
Create a “random_weighted” style “decorator” node.
This node takes multiple children with associated weights, from which it will randomly pick one to run, taking the weighting into account (using :rand.uniform/1
). If that child fails, this node fails, if the child succeeds, this node succeeds.
Note that BehaviorTree.value
will return only the value (the first position of the supplied tuple).
Example
Node.random_weighted([{:a, 2}, {:b, 1}]) |> BehaviorTree.start() |> BehaviorTree.value()
# :a will be returned twice as often as :b
iex> tree = Node.sequence([
...> Node.random_weighted([{:a, 2}, {:b, 1}]),
...> :d
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:d
repeat_n(pos_integer(), any()) :: BehaviorTree.Node.t()
Create a “repeat_n” style “decorator” node.
This node takes an integer greater than 1, and a single child, which it will repeatedly return n times, regardless of if the child fails or succeeds. After that, this node will succeed. This node never fails, and always runs n times.
You may find it useful to nest one of the other nodes under this node if you want a collection of children to repeat.
Example
iex> tree = Node.sequence([
...> Node.repeat_n(2, :a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.value
:a
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.fail |> BehaviorTree.value
:b
repeat_until_fail(any()) :: BehaviorTree.Node.t()
Create a “repeat_until_fail” style “decorator” node.
This node only takes a single child, which it will repeatedly return until the child fails, at which point this node will succeed. This node never fails, but it may run forever if the child never fails.
You may find it useful to nest one of the other nodes under this node if you want a collection of children to repeat.
Example
iex> tree = Node.sequence([
...> Node.repeat_until_fail(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.succeed |> BehaviorTree.value
:a
iex> tree = Node.sequence([
...> Node.repeat_until_fail(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.fail |> BehaviorTree.value
:b
iex> tree = Node.sequence([
...> Node.repeat_until_fail(Node.select([:a, :b])),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.fail |> BehaviorTree.value
:c
repeat_until_succeed(any()) :: BehaviorTree.Node.t()
Create a “repeat_until_succeed” style “decorator” node.
This node only takes a single child, which it will repeatedly return until the child succeeds, at which point this node will succeed. This node never fails, but it may run forever if the child never succeeds.
You may find it useful to nest one of the other nodes under this node if you want a collection of children to repeat.
Example
iex> tree = Node.sequence([
...> Node.repeat_until_succeed(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.fail |> BehaviorTree.value
:a
iex> tree = Node.sequence([
...> Node.repeat_until_succeed(:a),
...> :b
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.succeed |> BehaviorTree.value
:b
iex> tree = Node.sequence([
...> Node.repeat_until_succeed(Node.sequence([:a, :b])),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.succeed |> BehaviorTree.value
:c
Create a “select” style node with the supplied children.
This node always goes from left to right, moving on to the next child when the current one fails. Succeeds immediately if any child succeeds, fails if all children fail.
Example
iex> tree = Node.select([:a, :b])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.value
:b
iex> tree = Node.select([
...> Node.select([:a, :b]),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.fail |> BehaviorTree.value
:c
iex> tree = Node.sequence([
...> Node.select([:a, :b]),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:c
sequence([any(), ...]) :: BehaviorTree.Node.t()
Create a “sequence” style node with the supplied children.
This node always goes from left to right, moving on to the next child when the current one succeeds. Succeeds if all children succeed, fails immediately if any child fails.
Example
iex> tree = Node.sequence([:a, :b])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.value
:b
iex> tree = Node.sequence([
...> Node.sequence([:a, :b]),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.succeed |> BehaviorTree.succeed |> BehaviorTree.value
:c
iex> tree = Node.select([
...> Node.sequence([:a, :b]),
...> :c
...> ])
iex> tree |> BehaviorTree.start |> BehaviorTree.fail |> BehaviorTree.value
:c