Step Types

From ABL
Revision as of 07:54, 22 August 2006 by Sooraj (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

ABL has seven basic step types: primitive acts, mental acts, subgoal steps, spawn goal steps, fail steps, succeed steps, and wait steps.

A step is a statement in a behavior; conversely, a behavior can be viewed as a sequence of steps. Abstractly a behavior may be viewed as follows:

sequential behavior B() {
    <math>Step_1</math>;
    <math>Step_2</math>;
    ...
    <math>Step_n</math>;
}

It is possible to annotate any step; see ABL Step and Behavior Annotations.

Act

Intuitively, an act corresponds to a physical act performed in the world of the ABL agent. For example, it might be the movement of an arm to pick up an object, or the shooting of a gun at another agent.

Writing an Act

Concretely, several things must happen to implement and use an act.

  1. Implement a subclass of abl.compiler.runtime.PrimitiveAction. This involves implementing void execute(Object[] args) and possibly void abort().

    The body of execute(Object[] args) should execute the act "physically" in the virtual world of the agent. The body of abort() should terminate the execution of the physical act (if it is executing) and clean up any resources it holds.
  2. Optionally, override void decisionCycleCallback() if you need to do some processing every decision cycle.
  3. Register an act signature with a PrimitiveAction subclass.


See Implementing Primitive Actions.

Execution

When an act step is chosen for execution by the ABL Decision Cycle, the ABL runtime first creates an instance of the action class associated with the act signature and calls the execute(Object[]) method on this object with the act arguments. The state of the act step changes to executing; the decision cycle continues to execute other steps while the primtive act executes in the world. For a complete discussion of how an act interacts with the decision cycle, read decision cycle execution. For a discussion of how action classes are defined as part of connecting ABL to a particular world, see Asynchronous Sensory Motor Systems. For a discussion of how to associate an act signature with an action class, see Action Registration.

Acts & Atomicity

Depending on the implementation of a particular act, it may or may not execute atomically with respect to the ABL Decision Cycle. Specifically, if an act marks itself as complete immediately on execution, then it is atomic (with respect to the ABL Decision Cycle).

Otherwise, an act is not atomic. The ABL runtime system may call abort() on the step node in the ABT if it decides to preempt the act.

For example, the ABL runtime may call RunAFewFeet.abort() while executing the steps in the following parallel behavior:

parallel behavior RunAndShootUntilDead() {
    with (persistent) subgoal Aim();
    with (effect_only) act RunAFewFeet();
    with (persistent) act Fire();
    // ...
}

Suppose that RunAFewFeet is executing in parallel with the other acts. Then, Aim and Fire succeed; at this point, if RunAFewFeet is still executing, it will be forcibly aborted.

In general the decision cycle may decide to abort an act for any number of reasons.

Mental Act

A mental act is an atomic piece of arbitrary Java code.<ref>Because of parser limitations, currently only a large subset of the Java language is supported in mental acts. However, the plan is to to conform to what is specified above.</ref>

Typical uses of mental acts include: numerical computations, updating working memory.

Syntax

mental_act { // Java code }

Example Behavior

    sequential behavior CreateItWME() {
        mental_act {
            ItWME itWME = new ItWME(PLAYER_REALNAME);
            BehavingEntity.getBehavingEntity().addWME(itWME);
        }
    }

Execution

When a mental act is chosen for execution by the ABL Decision Cycle, the code inside the mental act is executed in the decision cycle thread, blocking the decision cycle<ref>This is one reason why one shouldn't write lengthy mental acts.</ref>. When the mental act has finished, the associated node in the Active Behavior Tree is succeeded, potentially causing cascading effects in the tree (e.g. if the mental act was the last step in a behavior, then the behavior succeeds, causing the parent subgoal to succeed, etc.) and the decision cycle starts over to select another step for execution.

Subgoal

A subgoal is the main high-level control-flow structure.

You should not think of a subgoal step like a method call in Java. There are surface similarities, to be sure, but you will probably be very confused if you think the two are alike in more ways than that. When a subgoal is to be pursued, the actual code run to pursue the goal can only be decided dynamically -- in other words, behavior selection cannot be performed at compile time.

For example, if the following subgoal is found in the code:

subgoal TakeADrag(cig);

there may be arbitrarily many behaviors which conform to the preceding signature. Thus any one of them could be chosen at run-time to pursue the goal. The discriminating factors for choosing among candidate behaviors is discussed in ABL Behavior Selection.

Syntax

subgoal GoalName(arg1, ..., argn)

Execution

When a subgoal is chosen for execution by the ABL Decision Cycle, the following steps occur:

  1. Behavior selection occurs to choose a behavior to accomplish the subgoal. In the event that there is no matching behavior, the subgoal immediately fails.
  2. The behavior is rooted at the subgoal in the Active Behavior Tree.
  3. For sequential behaviors, the first step of the behavior is rooted at the behavior in the Active Behavior Tree. For parallel behaviors, all the steps of the behavior are rooted at the behavior in the Active Behavior Tree.

Then the ABL Decision Cycle starts again at the beginning, choosing a new step to execute. Note that the behavior's first step was not executed during the same decision cycle in which the the subgoal was choosen for execution; the step may not be executed until much later, depending on the priorities of the executable steps in the Active Behavior Tree (the steps in the leaves of the tree).

Suppose a step inside a subgoal behavior is executed, and fails. The original subgoal will then repeat step 1 of the list above until there's no matching behavior (as specified in step 1 of the list above).

Below is an example of a simple ABT before and after one decision cycle executing a subgoal.

Error creating thumbnail: Unable to save thumbnail to destination

Spawn Goal

The spawngoal step allows one to spawn a subgoal to pursue concurrently with the current goal; the spawned subgoal will continue to be pursued even after the behavior which spawned the goal has completed.


Fail

A naked fail_step will automatically cause the lexically enclosing behavior to fail and return.

Syntax

fail_step;

Example Behavior

    sequential behavior RunGoodPath(List navPoints, NavPointWME bestPoint, float bestAngle) {
        precondition {
            (navPoints.size() == 0)
            ((bestPoint == null) || (bestAngle > 100))
        }
        fail_step;
    }

Execution

When a fail_step is executed, the ABL Decision Cycle fails the current step, and recursively propagates failure as appropriate.

See Also

Fail step coding idioms.

Succeed

A succeed_step immediately succeeds the enclosing behavior.

Syntax

succeed_step;

Example Behavior

    sequential behavior RunGoodPath(List navPoints, NavPointWME bestPoint, float bestAngle) {
        precondition {
            (navPoints.size() == 0)
            ((bestPoint == null) || (bestAngle > 100))
        }
        succeed_step;
    }

Execution

When a succeed_step is executed, the ABL Decision Cycle succeeds the current step, and recursively propagates success as appropriate.


Wait

A wait is a blocking step. A naked wait in a sequential behavior will inhibit all further progress in that behavior. A wait in a parallel behavior doesn't make much sense: it won't inhibit progress in that behavior (because other steps will continue to be pursued), and is therefore a no-op.

In a sequential behavior, when a wait is annotated with a success test, it becomes a guard for the lexically following code. Thus, a wait is typically associated with a success test in a sequential behavior. A sequential behavior of the following form

with (success_test { SuccessTestBody }) wait;

is an instance of the common daemon pattern. Any code written after the line above will not be executed until SuccessTestBody is satisfied.

Example

sequential behavior ImIt() {
    with ( success_test { (ItWME itPlayerName :: itAgent)
                          (MY_REALNAME.equalsIgnoreCase(itAgent)) } ) wait;
    subgoal DoItBehavior();
}

This means when the itPlayerName becomes my name, then pursue the DoItBehavior() subgoal. DoItBehavior() will not be pursued until the success test passes.

Execution

A wait step is never chosen for execution.


Anonymous Behavior

...

Footnotes

<references/>