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

Link to this function always_fail(child) View Source
always_fail(any()) :: BehaviorTree.Node.t()

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
Link to this function always_succeed(child) View Source
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
Link to this function random(children) View Source
random([any(), ...]) :: BehaviorTree.Node.t()

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
Link to this function random_weighted(children) View Source
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

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
Link to this function repeat_until_fail(child) View Source
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
Link to this function repeat_until_succeed(child) View Source
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
Link to this function select(children) View Source
select([any(), ...]) :: BehaviorTree.Node.t()

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
Link to this function sequence(children) View Source
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