Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility AI inclusion #97

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*******************************************************************************
* 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.pfa.indexed;

import com.badlogic.gdx.ai.pfa.Connection;
import com.badlogic.gdx.ai.pfa.GraphPath;
import com.badlogic.gdx.ai.pfa.Heuristic;
import com.badlogic.gdx.ai.pfa.PathFinder;
import com.badlogic.gdx.ai.pfa.PathFinderQueue;
import com.badlogic.gdx.ai.pfa.PathFinderRequest;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.BinaryHeap;
import com.badlogic.gdx.utils.TimeUtils;

/**
* Extends IndexedAStarPathFinder
*
* Allows search for a given Node or given termination condition
*
* Example Termination Condition: Node contains 'health' item type
*
* @param <N> Type of node extending {@link IndexedNode}
*
* @author fvolz */
public abstract class IndexedAStarPathFinderWithTerminationCondition<N extends IndexedNode<N>> extends IndexedAStarPathFinder<N> {

public IndexedAStarPathFinderWithTerminationCondition(IndexedGraph<N> graph) {
super(graph, false);
}

public abstract boolean isTerminationConditionSatisfied(N current, N target);

@Override
public boolean searchNodePath (N startNode, N endNode, Heuristic<N> heuristic, GraphPath<N> outPath) {

// Perform AStar
search(startNode, endNode, heuristic);

// We're here if we've either found the goal, or if we've no more nodes to search, find which

//fv: overrode to apply 'equals' operator
if (!current.node.equals(endNode)) {
// We've run out of nodes without finding the goal, so there's no solution
return false;
}

generateNodePath(startNode, outPath);

return true;
}

@Override
protected void search(N startNode, N endNode, Heuristic<N> heuristic) {

initSearch(startNode, endNode, heuristic);

// Iterate through processing each node
do {
// Retrieve the node with smallest estimated total cost from the open list
current = openList.pop();
current.category = IndexedAStarPathFinder.CLOSED;

//Terminate if we reached the goal node/condition
if (isTerminationConditionSatisfied(current.node, endNode)) {
endNode = current.node;

return;
}
;

visitChildren(endNode, heuristic);

} while (openList.size > 0);
}
}

140 changes: 140 additions & 0 deletions gdx-ai/src/com/badlogic/gdx/ai/utility/Action.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.badlogic.gdx.ai.utility;

/** This is the abstract base class of all UtiltiyAI Actions tasks. The {@code Action} a status
*
* @param <E> type of the blackboard object that tasks use to read or modify game state
*
* @author fvolz*/
public abstract class Action<E> {

/** The enumeration of the values that a task's status can have.
*
* @author davebaol */
public enum Status {
/** Means that the task has never run or has been reset. */
FRESH,
/** Means that the task needs to run again. */
RUNNING,
/** Means that the task returned a failure result. */
FAILED,
/** Means that the task returned a success result. */
SUCCEEDED,
/** Means that the task has been terminated by an ancestor. */
CANCELLED;
}

/** The status of this task. */
protected Status status = Status.FRESH;

float cooldown;
float startedTime;
String name;

public Action(String name, float cooldown) {
this.status = Status.FRESH;
setCooldown(cooldown);
this.startedTime = 0; //start in idle mode
this.name = name;
}

public void execute(E context) {
if(canExecute() == false)
return;

if(doTryUpdate(context) == false) {
startedTime = System.currentTimeMillis();
status = Status.RUNNING;
onStart(context);
}
}

public boolean doTryUpdate(E context) {
if(status.equals(Status.RUNNING)) {
onUpdate(context);
return true;
}
return false;
}

protected void endInSuccess(E context) {
if(!status.equals(Status.RUNNING))
return;

status = Status.SUCCEEDED;
finalizeAction(context);
}

protected void onStart(E context) {
endInSuccess(context);
}

protected abstract void onUpdate(E context) ;

protected abstract void onStop(E context);

public boolean canExecute() {
if(isInCooldown()) {
status = Status.FAILED;
return false;
}

return true;
}

void finalizeAction(E context) {
onStop(context);
}

/// <summary>
/// Ends the action and sets its status to <see cref="F:Crystal.ActionStatus.Failure"/>.
/// </summary>
/// <param name="context">The context.</param>
protected void endInFailure(E context) {
if(status != Status.RUNNING)
return;

status = Status.FAILED;
finalizeAction(context);
}

public Status getStatus() {
return status;
}

public void setStatus(Status status) {
this.status = status;
}

public boolean isInCooldown() {

if(status.equals(Status.RUNNING) ||
status.equals(Status.FRESH))
return false;

return System.currentTimeMillis() - startedTime < cooldown;
}

public float getCooldown() {
return cooldown;
}

public void setCooldown(float cooldown) {
this.cooldown = Math.max(0, cooldown);
}

public float getStartedTime() {
return startedTime;
}

public void setStartedTime(float startedTime) {
this.startedTime = startedTime;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
62 changes: 62 additions & 0 deletions gdx-ai/src/com/badlogic/gdx/ai/utility/Behaviour.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.badlogic.gdx.ai.utility;

import com.badlogic.gdx.ai.utility.consideration.CompositeConsideration;
import com.badlogic.gdx.ai.utility.measure.Chebyshev;

import java.util.ArrayList;
import java.util.List;

/**
* Created by felix on 8/6/2017.
*/
/// <summary>
/// An AI behaviour is a set of <see cref="T:Crystal.IOption"/>s. The behaviour itself
/// is a composite consideration and therefore, unless this is the only behaviour in a
/// <see cref="T:Crystal.IUtilityAi"/>, it will be selected only if its considerations
/// "win" against competing behaviours in the AI.
/// </summary>
/// <seealso cref="T:Crystal.CompositeConsideration" />
/// <seealso cref="T:Crystal.IBehaviour" />
public class Behaviour<E> extends CompositeConsideration<E> {

List<Option<E>> options = new ArrayList<Option<E>>();
List<Utility> utilities = new ArrayList<Utility>();
Selector selector;

public Behaviour(String name){
setName(name);
init();
}

public void init(){
setMeasure(new Chebyshev());
selector = new MaxRankAndUtilitySelector();
}


public void addOption(Option option) {
options.add(option);
utilities.add(new Utility(0.0f, 1.0f));
}

/// <summary>
/// Selects the action for execution, given the specified context.
/// </summary>
/// <param name="context">The context.</param>
/// <returns>The action to execute.</returns>
public Action select(E context) {
for(int i = 0, count = options.size(); i < count; i++) {
options.get(i).consider(context);
utilities.set(i,options.get(i).getUtility());
}

return selectAction();
}

protected Action selectAction(){
int idx = selector.select(utilities);
Option option = idx >= 0 ? options.get(idx) : null;
return option != null ? option.action : null;
}

}
8 changes: 8 additions & 0 deletions gdx-ai/src/com/badlogic/gdx/ai/utility/Context.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.badlogic.gdx.ai.utility;

/**
* Created by felix on 8/4/2017.
*/
@Deprecated
public interface Context {
}
Loading