AI – Behavior Trees
In AI a behavior tree can be considered among most to be the best data structure to use when it comes to
achieving different states among an Artificial Intelligence.
What is a behavior tree?
It allows the programmer to stack up different behaviors with actions and conditions at the heart of
the behavior tree. It uses sequences and selectors that are complements of each other because a
sequence will bail out on success and a selector will bail out of the tree on failure.
A behavior tree has a root that branches off into a list of behaviors that each contain a selector.
A selector can be a priority selector or a dynamic selector. Each selector will contain a list of nodes that contain a decorator object.
There can also be a node that just contains an assertion check that only checks if a certain condition is true.
A decorator is an object that adds new functionality to an object without creating a new object.
There are many types of decorators that can be created and the designers will love then because you will
find them using decorators for just about anything.
Some different types of decorators include:
Semaphore: For resource allocation so that two animations or more than one of anything will not be played at the same time.
Wait: Signals the tree that a sub tree is not accessible yet until a time in seconds has passed.
Loop: tells a sub tree to keep executing.
Continue: Everything that is not a selector will return success, otherwise failure.
The decorator object will contain an action and a condition. An action is something that the AI will do like ‘throw grenade’
and a condition is something that must pass like ‘can I throw a grenade’ in order to succeed.
For each behavior one could answer the question of “What happens if…”
What happens if patrolling
-> I am walking/moving
-> I am …
With all of this logic put together one can easily create a simple solution to the complex problem of behavior trees.
The Behavior Tree can also contain a Parallel node that basically run every sub tree and list of assertions at the same time.
If just one fails then the entire parallel node fails.
A behavior can be created like this for those of you who know C++:
Behavior<AIGuard>* combatBehavior = new Behavior<AIGuard>(“Combat”);
—-//Create a priority selector for the combat behavior
—-Selector<AIGuard>* combatBehaviorSelector = new PrioritySelector<AIGuard>();
——–//SEQUENCE 1 (ATTACK)
——–//Create a sequence for the combat behavior that the priority selector will select
——–Sequence<AIGuard>* combatBehaviorAttack = new Sequence<AIGuard>();
————//Create a node for the attack sequence
————Node<AIGuard>* combatBehaviorAttackNode = new TaskNode<AIGuard>();
—————-//Create a decorator the the combatBehaviorAttackNode
—————-Decorator<AIGuard>* combatBehaviorAttackDecorator = new Decorator<AIGuard>();
——————–//Now create a action for the decorator
——————–Task<AIGuard>* attackAction = new Task<AIGuard>(“ATTACK”);
——————–Delegate<AIGuard, Status>* attackDelegate = new Delegate<AIGuard, Status>(guard, &AIGuard::doAttack);
——————–//Now create a condition for the decorator
——————–Delegate<AIGuard, bool>* attackCondition = new Delegate<AIGuard, bool>(guard, &AIGuard::canAttack);
—————-//Finally we can add the decorator to the node
————//Add the attack node to the attack sequence
——–//Add the attack sequence to the priority selector for combat attack
——–//SEQUENCE 2 …
—-//Add the combat attack priority selector to the combat behavior
//Finally Insert the combat behavior into the behavior tree
mBehaviorTree->InsertBehavior( combatBehavior );
If you want to know more about behavior trees see aigamedev.com
Alex j. champandard is the main person there that talks about behavior trees.
More on AI will soon follow.