/******************************************************************************* * 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.decorator; import com.badlogic.gdx.ai.btree.LoopDecorator; import com.badlogic.gdx.ai.btree.Task; import com.badlogic.gdx.ai.btree.annotation.TaskAttribute; import com.badlogic.gdx.ai.utils.random.ConstantIntegerDistribution; import com.badlogic.gdx.ai.utils.random.IntegerDistribution; /** A {@code Repeat} decorator will repeat the wrapped task a certain number of times, possibly infinite. This task always succeeds * when reaches the specified number of repetitions. * * @param <E> type of the blackboard object that tasks use to read or modify game state * * @author implicit-invocation */ public class Repeat<E> extends LoopDecorator<E> { /** Optional task attribute specifying the integer distribution that determines how many times the wrapped task must be * repeated. Defaults to {@link ConstantIntegerDistribution#NEGATIVE_ONE} which indicates an infinite number of repetitions. * * @see #start() */ @TaskAttribute public IntegerDistribution times; private int count; /** Creates an infinite repeat decorator with no child task. */ public Repeat () { this(null); } /** Creates an infinite repeat decorator that wraps the given task. * * @param child the task that will be wrapped */ public Repeat (Task<E> child) { this(ConstantIntegerDistribution.NEGATIVE_ONE, child); } /** Creates a repeat decorator that executes the given task the number of times (possibly infinite) determined by the given * distribution. The number of times is drawn from the distribution by the {@link #start()} method. Any negative value means * forever. * * @param times the integer distribution specifying how many times the child must be repeated. * @param child the task that will be wrapped */ public Repeat (IntegerDistribution times, Task<E> child) { super(child); this.times = times; } /** Draws a value from the distribution that determines how many times the wrapped task must be repeated. Any negative value * means forever. * <p> * This method is called when the task is entered. */ @Override public void start () { count = times.nextInt(); } @Override public boolean condition () { return loop && count != 0; } @Override public void childSuccess (Task<E> runningTask) { if (count > 0) count--; if (count == 0) { super.childSuccess(runningTask); loop = false; } else loop = true; } @Override public void childFail (Task<E> runningTask) { childSuccess(runningTask); } @Override protected Task<E> copyTo (Task<E> task) { Repeat<E> repeat = (Repeat<E>)task; repeat.times = times; // no need to clone since it is immutable return super.copyTo(task); } }