com.badlogic.gdx.ai.btree.branch.Parallel Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2014 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.ai.btree.branch;
import com.badlogic.gdx.ai.btree.BranchTask;
import com.badlogic.gdx.ai.btree.Task;
import com.badlogic.gdx.ai.btree.annotation.TaskAttribute;
import com.badlogic.gdx.utils.Array;
/** A {@code Parallel} is a special branch task that starts or resumes all children every single time. The actual behavior of
* parallel task depends on its {@link #policy}:
*
* - {@link Policy#Sequence}: the parallel task fails as soon as one child fails; if all children succeed, then the parallel
* task succeeds. This is the default policy.
* - {@link Policy#Selector}: the parallel task succeeds as soon as one child succeeds; if all children fail, then the parallel
* task fails.
*
*
* The typical use case: make the game entity react on event while sleeping or wandering.
*
* @param type of the blackboard object that tasks use to read or modify game state
*
* @author implicit-invocation
* @author davebaol */
public class Parallel extends BranchTask {
/** Optional task attribute specifying the parallel policy (defaults to {@link Policy#Sequence}) */
@TaskAttribute public Policy policy;
private boolean noRunningTasks;
private Boolean lastResult;
private int currentChildIndex;
/** Creates a parallel task with sequence policy and no children */
public Parallel () {
this(new Array>());
}
/** Creates a parallel task with sequence policy and the given children
* @param tasks the children */
public Parallel (Task... tasks) {
this(new Array>(tasks));
}
/** Creates a parallel task with sequence policy and the given children
* @param tasks the children */
public Parallel (Array> tasks) {
this(Policy.Sequence, tasks);
}
/** Creates a parallel task with the given policy and no children
* @param policy the policy */
public Parallel (Policy policy) {
this(policy, new Array>());
}
/** Creates a parallel task with the given policy and children
* @param policy the policy
* @param tasks the children */
public Parallel (Policy policy, Task... tasks) {
this(policy, new Array>(tasks));
}
/** Creates a parallel task with the given policy and children
* @param policy the policy
* @param tasks the children */
public Parallel (Policy policy, Array> tasks) {
super(tasks);
this.policy = policy;
noRunningTasks = true;
}
@Override
public void run () {
noRunningTasks = true;
lastResult = null;
for (currentChildIndex = 0; currentChildIndex < children.size; currentChildIndex++) {
Task child = children.get(currentChildIndex);
if (child.getStatus() != Status.RUNNING) {
child.setControl(this);
child.start();
}
child.run();
if (lastResult != null) {
cancelRunningChildren(noRunningTasks ? currentChildIndex + 1 : 0);
if (lastResult)
success();
else
fail();
return;
}
}
running();
}
@Override
public void childRunning (Task task, Task reporter) {
noRunningTasks = false;
}
@Override
public void childSuccess (Task runningTask) {
lastResult = policy.onChildSuccess(this);
}
@Override
public void childFail (Task runningTask) {
lastResult = policy.onChildFail(this);
}
@Override
public void reset () {
super.reset();
noRunningTasks = true;
}
@Override
protected Task copyTo (Task task) {
Parallel parallel = (Parallel)task;
parallel.policy = policy; // no need to clone since it is immutable
return super.copyTo(task);
}
/** The enumeration of the policies supported by the {@link Parallel} task. */
public enum Policy {
/** The sequence policy makes the {@link Parallel} task fail as soon as one child fails; if all children succeed, then the
* parallel task succeeds. This is the default policy. */
Sequence() {
@Override
public Boolean onChildSuccess (Parallel> parallel) {
return parallel.noRunningTasks && parallel.currentChildIndex == parallel.children.size - 1 ? Boolean.TRUE : null;
}
@Override
public Boolean onChildFail (Parallel> parallel) {
return Boolean.FALSE;
}
},
/** The selector policy makes the {@link Parallel} task succeed as soon as one child succeeds; if all children fail, then the
* parallel task fails. */
Selector() {
@Override
public Boolean onChildSuccess (Parallel> parallel) {
return Boolean.TRUE;
}
@Override
public Boolean onChildFail (Parallel> parallel) {
return parallel.noRunningTasks && parallel.currentChildIndex == parallel.children.size - 1 ? Boolean.FALSE : null;
}
};
/** Called by parallel task each time one of its children succeeds.
* @param parallel the parallel task
* @return {@code Boolean.TRUE} if parallel must succeed, {@code Boolean.FALSE} if parallel must fail and {@code null} if
* parallel must keep on running. */
public abstract Boolean onChildSuccess (Parallel> parallel);
/** Called by parallel task each time one of its children fails.
* @param parallel the parallel task
* @return {@code Boolean.TRUE} if parallel must succeed, {@code Boolean.FALSE} if parallel must fail and {@code null} if
* parallel must keep on running. */
public abstract Boolean onChildFail (Parallel> parallel);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy