AI Capture the Flag

Find Gist Here

Java, Searching Algorithms, AI design.

Project for an Artificial Intelligence class. We were tasked with creating an “Agent” that would successfully capture and return an enemy flag to our base while simultaneously try to protect our own flag from capture. We were provided the Java environment our Agents would travel in.

The project utilized proprietary software from UTD, so I am unable to post said environment for you to try out the agent yourself, but here are some GIFs of the project in action.

Red team is mine, the Green team is the enemy.

Some example GIFs

JavaCTF2
JavaCTF3

Red: Me, Green: Computer.

The computer uses a “Random” Agent class to determine its movements. The left arena is labeled as “traps”, the right as “simple”.

/*
* Tomer Braff
* May 10, 2017
* txb130030Agent
*
* This is the code for my own Agent for an AI class project.
* An applet runs that displays an NxN sized arena where two teams, Red and Green, are placed
* on opposite sides of eachother. Each team has a team base and a team flag on the far left/right
* sides of the arena. Agents can only do certain actions: Move North, South, East, West, Place a Bomb, or do Nothing.
* The agents must interface with code that was provided to me in the class. All the code in this file
* was created with those limitations, which were the following:
*
* LIMITATIONS
*
* Agents can only see what is directly north, south, east, and west of their current position.
* AgentEnvironment provided functions to see what is directly north/south/east/west (NSEW) of the agent's
* current position, as well as if an enemy/base/friend/etc… was in the general NSEW direction.
* AgentAction is a class that provides the integer representations of certain actions an Agent can take
* As limited by the environment, an Agent can only do one of these moves: Move NSEW, Plant a Bomb, or do nothing
* Agents do not know their locations and cannot access the arena except by AgentEnvironment functions.
*
* Because of these limitations and more, I had to create several methods of having the Agents know where they are
* in the map, whether they've respawned, what general direction they should go in, etc…
*
* Comments in the code should provide insight as to what I needed to create for the Agents and how it is used.
*
* The main portion of code is that to figure out which direction to go in next. As the Agent moves around
* the environment they build up a 10×10 map and take note of which nodes are obstacles, enemies, etc…
* Then the Agent takes their current position and uses the A* search algorithm to find a path to the enemy or
* team base (depending on if they have the flag or not) and they go in that direction.
*
*
*/
package ctf.agent;
import java.util.*;
import ctf.common.*;
// Enum of the various types of obstacles that can occur in the environment.
// The Nodes on the map the agents use all indicate what type of Node they are
enum ObsType
{
Null(-1), None(0), Obstacle(1), Friend(2), Foe(3), TeamFlag(4), EnemFlag(5), TeamBase(6), EnemBase(7);
private int value;
private ObsType(int val){
this.value = val;
}
}
// A Wrapper Key Object
// Source:
// https://stackoverflow.com/questions/14677993/how-to-create-a-hashmap-with-two-keys-key-pair-value
// For the HashMap that contains X and Y coordinates since HashMaps can't contain two keys for a value.
// This way I can just do Map<Key, Node> and to get a specific value I do map.get(new Key(x,y)) instead
// of doing a roundabout, convoluted way of, say, having a Map with they Key being the X coordinate
// and a value of another Map has a Key being the Y value with a value of the environment state.
// ( Map<int xCoordinate, Map<int yCoordinate>> )
class Key
{
private final int x;
private final int y;
public Key(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key key = (Key) o;
return x == key.x && y == key.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
// Class that populates the map
//
class Node
{
public double value = 1; // Heuristic value for nodes in A* search
public Node prevNode = null; // Used to keep track of the path back to the root node when searching
public ObsType type = ObsType.Null; // The type of obstacle this node is (none, obstacle, team base, etc…)
public int xCoord = 10000; // X Coordinate of the Node in the map
public int yCoord = 10000; // Y Coordinate of the Node in the map
// Constructors
Node()
{
type = ObsType.Null;
}
Node(ObsType t, int x, int y)
{
type = t;
SetXY(x,y);
}
Node(ObsType t, int x, int y, double val)
{
type = t;
SetXY(x,y);
value = val;
}
// Sets the X and Y coordinates
public void SetXY(int x, int y)
{
xCoord = x;
yCoord = y;
}
// Compares the X,Y coordinate values of this node to the pass node
public boolean CompareXY(Node n)
{
return (xCoord == n.xCoord && yCoord == n.yCoord);
}
// Creates a string representation of the X and Y coordinates
public String XY()
{
return "X: " + xCoord + ", Y: " + yCoord;
}
// Returns a Key object created from the Node's X,Y coordinates
public Key getKey()
{
return new Key(xCoord, yCoord);
}
// Gets the Node that is North/South/East/West from the this Node
// NSEW goes – 0:North, 1:South, 2:East, 3:West
// Possibly could be easier with an enum for NSEW?
public Key GetNSEWKey(int NSEW)
{
switch(NSEW){
case 0:
return new Key(xCoord, yCoord+1);
case 1:
return new Key(xCoord, yCoord1);
case 2:
return new Key(xCoord+1, yCoord);
case 3:
return new Key(xCoord1, yCoord);
}
return new Key(xCoord, yCoord+1);
}
// Distance formulas to certain nodes, mostly used to determine value heuristic
public double Distance(Node other)
{
return Math.sqrt(Math.pow(other.xCoord xCoord, 2) Math.pow(other.yCoord yCoord, 2));
}
public double Distance(int x, int y)
{
return Math.sqrt(Math.pow(x xCoord, 2) Math.pow(y yCoord, 2));
}
}
// Main Agent code
public class txb130030Agent extends Agent
{
// A static HashMap that all txb130030Agent's have access to
// This map contains Nodes with a Key (from the Key class) as a key value (new Key(x,y)).
// The map is updated continually as Agents traverse the environment, making note of which
// nodes are obstacles and which nodes aren't.
public static Map<Key, Node> map = new HashMap<Key, Node>();
// The X and Y positions the Agent is currently in
int xPos = 0, yPos = 0;
// The Nodes that contain the Enemy/Team bases respectively
public static Node enemyBase = null, teamBase = null;
// The current node the Agent is on as well as the initial node they spawned at
Node currentNode = null, spawnNode = null;
// If the Agent first spawned at the top left/right or bottom left/right corner of the arena
public boolean botLeftAgent = false, botRightAgent = false, topLeftAgent = false, topRightAgent = false;
// Obstacle Types of NSEW, as well as if the team/enemy bases are NSEW of the Agent
ObsType nType, sType, eType, wType;
boolean nBase, sBase, eBase, wBase;
boolean nBaseEnem, sBaseEnem, eBaseEnem, wBaseEnem;
public int ID = 0;
public static int numAgents = 0;
// Couldn't use constructors like I wanted to, had to use a boolean flag to indicate if the Agent was created yet
public boolean initialized = false;
public static List<Agent> agents = new ArrayList<Agent>();
public boolean IsDefender()
{
return ID == 0;
}
// Couldn't use a constructor for the project, so I used a boolean to switch off when initialized
public void Initialize()
{
initialized = true;
ID = numAgents;
numAgents++;
// Determines if an agent will go for the enemy flag or "defend" the team base
if(numAgents % 2 != 0)
map.clear();
agents.add(this);
// Initialize a 10×10 map
if(map.isEmpty())
for(int x=1; x<=10; x++)
for(int y=1; y<=10; y++)
{
// Border obstacle
if(x == 1 || x == 10 || y == 1 || y == 10)
map.put(new Key(x,y), new Node(ObsType.Obstacle, x, y));
else
map.put(new Key(x,y), new Node(ObsType.None, x, y));
}
// If this Agent started in the bottom/top corner on the left/right side
// This is done by seeing if the enemy base is either North or South of the agent, and either East or West of the agent
if(nBaseEnem && wBaseEnem)
{
botRightAgent = true;
currentNode = spawnNode = map.get(new Key(9,0));
xPos = 9;
yPos = 0;
map.get(new Key(9,4)).type = ObsType.TeamBase;
map.get(new Key(0,4)).type = ObsType.EnemBase;
teamBase = map.get(new Key(9,4));
enemyBase = map.get(new Key(0,4));
}
else if(sBaseEnem && wBaseEnem)
{
topRightAgent = true;
currentNode = spawnNode = map.get(new Key(9,9));
xPos = 9;
yPos = 9;
map.get(new Key(9,4)).type = ObsType.TeamBase;
map.get(new Key(0,4)).type = ObsType.EnemBase;
teamBase = map.get(new Key(9,4));
enemyBase = map.get(new Key(0,4));
}
else if(nBaseEnem && eBaseEnem)
{
botLeftAgent = true;
currentNode = spawnNode = map.get(new Key(0,0));
xPos = 0;
yPos = 0;
map.get(new Key(0,4)).type = ObsType.TeamBase;
map.get(new Key(9,4)).type = ObsType.EnemBase;
teamBase = map.get(new Key(0,4));
enemyBase = map.get(new Key(9,4));
}
else
{
topLeftAgent = true;
currentNode = spawnNode = map.get(new Key(0,9));
xPos = 0;
yPos = 9;
map.get(new Key(0,4)).type = ObsType.TeamBase;
map.get(new Key(9,4)).type = ObsType.EnemBase;
teamBase = map.get(new Key(0,4));
enemyBase = map.get(new Key(9,4));
}
// Create heuristic values for the nodes
for(int x=0; x<9; x++)
for(int y=0; y<9; y++)
map.get(new Key(x,y)).value = enemyBase.Distance(map.get(new Key(x,y)));
}
// Check if the Agent has respawned to its original location
// This is needed because if an Agent contacts an enemy they are repositioned, not reinstantiated.
// Therefore, the Agent needs to check if it is in the same state as it's original spawning position
public void CheckIfRespawned()
{
// If the base is directly north/south of the agent
// Reset the currentNode to be the agent's spawn node
// Each statement asks if the agent is a top right/left or bottom right/left agent.
// Then it checks if the situation now is the same as if it had spawned.
// For example, if the Agent initially spawned at the bottom right corner, then we
// need to check if the enemy base is NorthEast of the Agent, AND we need the team
// base to be DIRECTLY North of the agent and NEITHER East or West of the Agent.
// We also check if the Southern Node is an obstacle as that determines if it is a corner.
// (No obstacles can be on the far east/west sides of the arena, and when we initialized the map
// we made the outside borders impenetrable obstacles)
// If all of that is true, then the Agent has respawned, so let's do what we need to do.
if(botRightAgent && nBaseEnem && wBaseEnem && nBase && !wBase && !eBase && sType == ObsType.Obstacle)
{
currentNode = map.get(spawnNode.getKey());
xPos = spawnNode.xCoord;
yPos = spawnNode.yCoord;
}
else if(topRightAgent && sBaseEnem && wBaseEnem && sBase && !wBase && !eBase && nType == ObsType.Obstacle)
{
currentNode = map.get(spawnNode.getKey());
xPos = spawnNode.xCoord;
yPos = spawnNode.yCoord;
}
else if(botLeftAgent && nBaseEnem && eBaseEnem && nBase && !wBase && !eBase && sType == ObsType.Obstacle)
{
currentNode = map.get(spawnNode.getKey());
xPos = spawnNode.xCoord;
yPos = spawnNode.yCoord;
}
else if(topLeftAgent && sBaseEnem && eBaseEnem && nBase && !wBase && !eBase && nType == ObsType.Obstacle)
{
currentNode = map.get(spawnNode.getKey());
xPos = spawnNode.xCoord;
yPos = spawnNode.yCoord;
}
}
public int getMove(AgentEnvironment env)
{
// Clamp the X and Y positions of the Agent
if(xPos > 9)
xPos = 9;
if(xPos < 0)
xPos = 0;
if(yPos > 9)
yPos = 9;
if(yPos < 0)
yPos = 0;
// Check the obstacle types of the NSEW nodes
nType = CheckType(env, 0);
sType = CheckType(env, 1);
eType = CheckType(env, 2);
wType = CheckType(env, 3);
// Check if the team base is in the general NSEW direction of the Agent
nBase = env.isBaseNorth(AgentEnvironment.OUR_TEAM, false);
sBase = env.isBaseSouth(AgentEnvironment.OUR_TEAM, false);
eBase = env.isBaseEast(AgentEnvironment.OUR_TEAM, false);
wBase = env.isBaseWest(AgentEnvironment.OUR_TEAM, false);
// Check if the Enemy base is in the general NSEW direction of the Agent
nBaseEnem = env.isBaseNorth(AgentEnvironment.ENEMY_TEAM, false);
sBaseEnem = env.isBaseSouth(AgentEnvironment.ENEMY_TEAM, false);
eBaseEnem = env.isBaseEast(AgentEnvironment.ENEMY_TEAM, false);
wBaseEnem = env.isBaseWest(AgentEnvironment.ENEMY_TEAM, false);
// Initialize the Agent if they haven't been already.
if(!initialized)
Initialize();
// Check if the agent has respawned
if(!env.hasFlag())
CheckIfRespawned();
// Checks if the team/enemy flag (depending on the situation) is directly NSEW of the Agent
// This is so we don't go through all the searching just for a simple direction
int foundFlagDir = UpdateCurrentNode(nType, sType, eType, wType, env.hasFlag());
// Is this agent a "defender"? If not, just do the normal algorithm
if(IsDefender())
{
// If the enemy team has our flag, go towards the enemy base
// Otherwise, just go to the team base
if(env.hasFlag(AgentEnvironment.ENEMY_TEAM))
return GetNextAction(currentNode, enemyBase);
else
return GetNextAction(currentNode, teamBase);
}
else
{
// If the agent doesn't have the flag, go towards the predicted enemy base
if( !env.hasFlag() )
{
// If we had found the flag earlier, move up to that flag
if(foundFlagDir > 1)
{
switch(foundFlagDir){
case AgentAction.MOVE_NORTH:
xPos++;
break;
case AgentAction.MOVE_SOUTH:
xPos;
break;
case AgentAction.MOVE_EAST:
yPos++;
break;
case AgentAction.MOVE_WEST:
yPos;
break;
}
return foundFlagDir;
}
else
return GetNextAction(currentNode, enemyBase);
}
else
return GetNextAction(currentNode, teamBase);
}
}
// A* Search
// Will start at the root, search through the nodes for a potential path to the goal
// Once it gets a path, returns the action that will take it to the next node on that path
private int GetNextAction(Node root, Node goal)
{
// Keep track of the nodes we've already been to
List<Key> expanded = new ArrayList<Key>();
Queue<Node> Q = new LinkedList<Node>();
root.prevNode = null;
Q.add(root);
// So long as the Queue is not empty, keep searching
while (!Q.isEmpty())
{
// Take the next node in the queue
Node n = Q.peek();
Q.remove();
// Have we reached the goal? Let's go the direction the next node wants us to go in
if (n.CompareXY(goal))
return ReturnAction(root, n);
// Otherwise, have we already visited this node? Don't bother if we have
if(!expanded.contains(n.getKey()))
{
expanded.add(n.getKey());
List<Node> children = new ArrayList<Node>();
// Go through NSEW children nodes. If a node is null, an obstacle, or an Enemy, don't add to the list.
Node nNode = map.get(n.GetNSEWKey(0));
Node sNode = map.get(n.GetNSEWKey(1));
Node eNode = map.get(n.GetNSEWKey(2));
Node wNode = map.get(n.GetNSEWKey(3));
if(nNode != null && !expanded.contains(nNode.getKey()) && nNode.type != ObsType.Obstacle && nNode.type != ObsType.Foe)
{
nNode.prevNode = n;
children.add(nNode);
}
if(sNode != null && !expanded.contains(sNode.getKey()) && sNode.type != ObsType.Obstacle && sNode.type != ObsType.Foe)
{
sNode.prevNode = n;
children.add(sNode);
}
if(eNode != null && !expanded.contains(eNode.getKey()) && eNode.type != ObsType.Obstacle && eNode.type != ObsType.Foe)
{
eNode.prevNode = n;
children.add(eNode);
}
if(wNode != null && !expanded.contains(wNode.getKey()) && wNode.type != ObsType.Obstacle && wNode.type != ObsType.Foe)
{
wNode.prevNode = n;
children.add(wNode);
}
//children = SortChildren(children, team);
// Add the children to the queue if there are any
for (int i = 0; i < children.size(); i++)
Q.add(children.get(i));
}
}
// If we went through all of that and somehow didn't find a path, then something is wrong with the map
// An agent probably listed a node as an obstacle by mistake, blocking off half of the map
// Let's clear the map and reinitialize it. Not the most ideal way, but it works
map.clear();
for(int x=1; x<=10; x++)
for(int y=1; y<=10; y++)
{
// Border obstacle
if(x == 1 || x == 10 || y == 1 || y == 10)
map.put(new Key(x,y), new Node(ObsType.Obstacle, x, y));
else
map.put(new Key(x,y), new Node(ObsType.None, x, y));
}
return 1;
}
// Return the integer value of the next action we should take
public int ReturnAction(Node root, Node n)
{
Node checkNode = n;
// Go up the node's prevNode values until it hits the root node.
// This will let us see what the next direction should be
while (checkNode.prevNode != null)
{
if(checkNode.prevNode.CompareXY(root))
break;
checkNode = checkNode.prevNode;
}
int action = 0;
// Check this next node with the root's NSEW nodes and see which direction it should go.
// Probably could be done so that the nodes keep track of which direction the prevNode came from.
if(map.get(root.GetNSEWKey(0)) == map.get(checkNode.getKey()))
{
yPos++;
action = AgentAction.MOVE_NORTH;
}
else if(map.get(root.GetNSEWKey(1)) == map.get(checkNode.getKey()))
{
yPos;
action = AgentAction.MOVE_SOUTH;
}
else if(map.get(root.GetNSEWKey(2)) == map.get(checkNode.getKey()))
{
xPos++;
action = AgentAction.MOVE_EAST;
}
else if(map.get(root.GetNSEWKey(3)) == map.get(checkNode.getKey()))
{
xPos;
action = AgentAction.MOVE_WEST;
}
else
action = AgentAction.DO_NOTHING;
return action;
}
// Sorts the nodes from least to greaatest depending on the passed boolean
public List<Node> SortChildren(List<Node> l, boolean asc)
{
List<Node> list = l;
Node min;
for (int x=0; x < list.size(); x++)
{
min = list.get(x);
int loc = x;
for (int k = x + 1; k < list.size(); k++)
{
if (asc && min.value > list.get(k).value)
{
min = list.get(k);
loc = k;
}
else if (!asc && min.value < list.get(k).value)
{
min = list.get(k);
loc = k;
}
}
Node temp, temp2;
temp = list.get(x);
temp2 = list.get(loc);
list.remove(x);
list.add(x, temp2);
list.remove(loc);
list.add(loc, temp);
}
return list;
}
// Updates the current node the Agent is on.
// Updates the NSEW nodes of the current node the Agent is on.
private int UpdateCurrentNode(ObsType n, ObsType s, ObsType e, ObsType w, boolean hasFlag)
{
currentNode = map.get(new Key(xPos, yPos));
Node nNode = map.get(new Key(xPos, yPos+1));
Node sNode = map.get(new Key(xPos, yPos1));
Node eNode = map.get(new Key(xPos+1, yPos));
Node wNode = map.get(new Key(xPos1, yPos));
// We check if the retrieved node is null just in case.
// Otherwise, we update the node type UNLESS it is an Obstacle (there can't magically be no obstacle anymore)
if(nNode == null)
nNode = new Node(n, xPos, yPos+1, enemyBase.Distance(xPos, yPos+1));
else if(nNode.type != ObsType.Obstacle)
nNode.type = n;
if(sNode == null)
sNode = new Node(s, xPos, yPos1, enemyBase.Distance(xPos, yPos1));
else if(sNode.type != ObsType.Obstacle)
sNode.type = s;
if(eNode == null)
eNode = new Node(e, xPos+1, yPos, enemyBase.Distance(xPos+1, yPos));
else if(eNode.type != ObsType.Obstacle)
eNode.type = e;
if(wNode == null)
wNode = new Node(w, xPos1, yPos, enemyBase.Distance(xPos1, yPos));
else if(wNode.type != ObsType.Obstacle)
wNode.type = w;
// Put the
map.put(currentNode.getKey(), currentNode);
map.put(nNode.getKey(), nNode);
map.put(sNode.getKey(), sNode);
map.put(eNode.getKey(), eNode);
map.put(wNode.getKey(), wNode);
// This is to check if any of the NSEW nodes that we just updated are actually the
// enemy or team bases. Used to bypass searaching if we can just go immediately to the flag
// Should probably decouple this from the function, but it works for now.
if(!hasFlag)
{
if(nNode.type == ObsType.EnemFlag || nNode.type == ObsType.EnemBase)
return AgentAction.MOVE_NORTH;
if(sNode.type == ObsType.EnemFlag || sNode.type == ObsType.EnemBase)
return AgentAction.MOVE_SOUTH;
if(eNode.type == ObsType.EnemFlag || eNode.type == ObsType.EnemBase)
return AgentAction.MOVE_EAST;
if(wNode.type == ObsType.EnemFlag || wNode.type == ObsType.EnemBase)
return AgentAction.MOVE_WEST;
else
return 100;
}
// Otherwise, if we do have the flag, return if our own base is within reach
else
{
if(nNode.type == ObsType.TeamFlag || nNode.type == ObsType.TeamBase)
return AgentAction.MOVE_NORTH;
if(sNode.type == ObsType.TeamFlag || sNode.type == ObsType.TeamBase)
return AgentAction.MOVE_SOUTH;
if(eNode.type == ObsType.TeamFlag || eNode.type == ObsType.TeamBase)
return AgentAction.MOVE_EAST;
if(wNode.type == ObsType.TeamFlag || wNode.type == ObsType.TeamBase)
return AgentAction.MOVE_WEST;
else
return 100;
}
}
// Checks what type the NSEW node is from the current position using the AgentEnvironment
// NSEW tells us in what direction relative to the Agent the node we're checking is
// 0:N, 1:S, 2:E, 3:W
private ObsType CheckType(AgentEnvironment env, int NSEW)
{
if(checkAgentAdjacent(env, NSEW, false))
return ObsType.Friend;
if(checkAgentAdjacent(env, NSEW, true))
return ObsType.Foe;
if(checkFlagAdjacent(env, NSEW, false))
return ObsType.TeamFlag;
if(checkFlagAdjacent(env, NSEW, true))
return ObsType.EnemFlag;
if(checkBaseAdjacent(env, NSEW, false))
return ObsType.TeamBase;
if(checkBaseAdjacent(env, NSEW, true))
return ObsType.EnemBase;
if(checkObsAdjacent(env, NSEW))
return ObsType.Obstacle;
return ObsType.None;
}
// Checks if there is an Agent (either friend or enemy) adjacent to the current position
// NSEW tells us in what direction relative to the Agent the node we're checking is
// 0:N, 1:S, 2:E, 3:W
private boolean checkAgentAdjacent(AgentEnvironment e, int NSEW, boolean enemTeam)
{
if(enemTeam){
switch(NSEW){
case 0:
return e.isAgentNorth(AgentEnvironment.ENEMY_TEAM, true);
case 1:
return e.isAgentSouth(AgentEnvironment.ENEMY_TEAM, true);
case 2:
return e.isAgentEast(AgentEnvironment.ENEMY_TEAM, true);
case 3:
return e.isAgentWest(AgentEnvironment.ENEMY_TEAM, true);
}
}
else{
switch(NSEW){
case 0:
return e.isAgentNorth(AgentEnvironment.OUR_TEAM, true);
case 1:
return e.isAgentSouth(AgentEnvironment.OUR_TEAM, true);
case 2:
return e.isAgentEast(AgentEnvironment.OUR_TEAM, true);
case 3:
return e.isAgentWest(AgentEnvironment.OUR_TEAM, true);
}
}
return enemTeam;
}
// Checks if there is a Flag (enemy or team) adjacent to the Agent
// NSEW tells us in what direction relative to the Agent the node we're checking is
// 0:N, 1:S, 2:E, 3:W
private boolean checkFlagAdjacent(AgentEnvironment e, int NSEW, boolean enemTeam)
{
if(enemTeam){
switch(NSEW){
case 0:
return e.isFlagNorth(AgentEnvironment.ENEMY_TEAM, true);
case 1:
return e.isFlagSouth(AgentEnvironment.ENEMY_TEAM, true);
case 2:
return e.isFlagEast(AgentEnvironment.ENEMY_TEAM, true);
case 3:
return e.isFlagWest(AgentEnvironment.ENEMY_TEAM, true);
}
}
else{
switch(NSEW){
case 0:
return e.isFlagNorth(AgentEnvironment.OUR_TEAM, true);
case 1:
return e.isFlagSouth(AgentEnvironment.OUR_TEAM, true);
case 2:
return e.isFlagEast(AgentEnvironment.OUR_TEAM, true);
case 3:
return e.isFlagWest(AgentEnvironment.OUR_TEAM, true);
}
}
return false;
}
// Checks if there is an obstacle directly adjacent to the Agent
// NSEW tells us in what direction relative to the Agent the node we're checking is
// 0:N, 1:S, 2:E, 3:W
private boolean checkObsAdjacent(AgentEnvironment e, int NSEW)
{
switch(NSEW){
case 0:
return e.isObstacleNorthImmediate();
case 1:
return e.isObstacleSouthImmediate();
case 2:
return e.isObstacleEastImmediate();
case 3:
return e.isObstacleWestImmediate();
}
return false;
}
// Checks if there is a base (enemy or team) directly aadjacent to the agent
// NSEW tells us in what direction relative to the Agent the node we're checking is
// 0:N, 1:S, 2:E, 3:W
private boolean checkBaseAdjacent(AgentEnvironment e, int NSEW, boolean enemTeam)
{
if(enemTeam){
switch(NSEW){
case 0:
return e.isBaseNorth(AgentEnvironment.ENEMY_TEAM, true);
case 1:
return e.isBaseSouth(AgentEnvironment.ENEMY_TEAM, true);
case 2:
return e.isBaseEast(AgentEnvironment.ENEMY_TEAM, true);
case 3:
return e.isBaseWest(AgentEnvironment.ENEMY_TEAM, true);
}
}
else{
switch(NSEW){
case 0:
return e.isBaseNorth(AgentEnvironment.OUR_TEAM, true);
case 1:
return e.isBaseSouth(AgentEnvironment.OUR_TEAM, true);
case 2:
return e.isBaseEast(AgentEnvironment.OUR_TEAM, true);
case 3:
return e.isBaseWest(AgentEnvironment.OUR_TEAM, true);
}
}
return enemTeam;
}
}
view raw txb130030Agent.java hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s