/*
* Copyright 2007-2013
* Licensed under GNU Lesser General Public License
*
* This file is part of EpochX: genetic programming software for research
*
* EpochX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EpochX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with EpochX. If not, see <http://www.gnu.org/licenses/>.
*
* The latest version is available from: http://www.epochx.org
*/
package org.epochx.tools.ant;
import static org.epochx.tools.ant.Orientation.*;
import java.awt.Point;
/**
* An Ant represents an artificial ant which exists within and can move about
* and perform other actions on an <code>AntLandscape</code>.
*/
public class Ant {
// The landscape that this ant exists within.
private AntLandscape landscape;
// The compass direction the ant is currently facing to travel.
private Orientation orientation;
// How many time steps have passed for the ant.
private int timesteps;
// The maximum number of time steps that this ant is allowed to make.
private int maxTimesteps;
// Location of the ant within its landscape.
private int xLocation;
private int yLocation;
// How many food pellets this ant has eaten.
private int foodEaten;
/**
* Constructs an Ant object on the given landscape.
*
* @param timeSteps the maximum number of time steps the ant is allowed to
* move. Turning, moving and skipping all count as one time step.
* @param landscape the landscape the ant will move through.
*/
public Ant(final int timeSteps, final AntLandscape landscape) {
// Initialise the ant.
reset(timeSteps, landscape);
}
/**
* Resets this ant, setting it up with a new number of time steps allocated
* and a new <code>AntLandscape</code>.
*
* @param maxTimeSteps the maximum number of time steps the ant is allowed
* to
* move. Turning, moving and skipping all count as one time step.
* @param landscape the landscape this ant will move through.
*/
public void reset(final int maxTimeSteps, final AntLandscape landscape) {
setMaxTimeSteps(maxTimeSteps);
setAntLandscape(landscape);
// Initialise the ant.
reset();
}
/**
* Sets the maximum number of timesteps this ant is allowed to move.
* Turning,
* moving and skipping all count as one time step.
*
* @param maxTimeSteps the maximum number of time steps the ant is allowed
* to
* move.
*/
public void setMaxTimeSteps(final int maxTimeSteps) {
maxTimesteps = maxTimeSteps;
}
/**
* Sets the landscape this ant will navigate.
*
* @param landscape the landscape this ant will move through.
*/
public void setAntLandscape(final AntLandscape landscape) {
this.landscape = landscape;
landscape.setAnt(this);
}
/**
* Resets this ant using the same number of time steps and on the same
* <code>AntLandscape</code>.
*/
public void reset() {
orientation = EAST;
timesteps = 0;
xLocation = 0;
yLocation = 0;
foodEaten = 0;
}
/**
* Turns this ant to the left relative to its current orientation. For
* example, if calling getOrientation() returns EAST before calling this
* method it will return NORTH after calling this method. If the ant
* has reached its maximum number of allowed time steps then this method
* will do nothing.
*/
public void turnLeft() {
// Don't allow the turn if the ant has reached its maximum.
if (timesteps >= maxTimesteps) {
return;
}
// Set the ant's new orientation.
if (orientation == EAST) {
orientation = NORTH;
} else if (orientation == NORTH) {
orientation = WEST;
} else if (orientation == WEST) {
orientation = SOUTH;
} else if (orientation == SOUTH) {
orientation = EAST;
}
timesteps++;
}
/**
* Turns this ant to the right relative to its current orientation. For
* example, if calling getOrientation() returns EAST before calling this
* method it will return SOUTH after calling this method. If the ant
* has reached its maximum number of allowed time steps then this method
* will do nothing.
*/
public void turnRight() {
// Don't allow the turn if the ant has reached its maximum.
if (timesteps >= maxTimesteps) {
return;
}
// Set the ant's new orientation.
if (orientation == EAST) {
orientation = SOUTH;
} else if (orientation == SOUTH) {
orientation = WEST;
} else if (orientation == WEST) {
orientation = NORTH;
} else if (orientation == NORTH) {
orientation = EAST;
}
timesteps++;
}
/**
* Moves this ant's position one place in the direction it is currently
* facing based upon its orientation. If the ant's new location on the
* landscape contains a food pellet then the ant will attempt to eat it.
* If the ant has reached its maximum number of allowed time steps then
* this method will do nothing.
*/
public void move() {
// Don't allow the move if the ant has reached its maximum.
if (timesteps >= maxTimesteps) {
return;
}
// Update the ant's location according to its orientation.
if (orientation == EAST) {
if (xLocation < 31) {
xLocation++;
} else {
xLocation = 0;
}
} else if (orientation == NORTH) {
if (yLocation > 0) {
yLocation--;
} else {
yLocation = 31;
}
} else if (orientation == WEST) {
if (xLocation > 0) {
xLocation--;
} else {
xLocation = 31;
}
} else if (orientation == SOUTH) {
if (yLocation < 31) {
yLocation++;
} else {
yLocation = 0;
}
}
// If the new location has food then eat it.
if (landscape.isFoodLocation(getLocation())) {
eatFood();
landscape.removeFoodLocation(getLocation());
}
timesteps++;
}
/**
* Increments the number of food pellets the ant has eaten.
*/
public void eatFood() {
foodEaten++;
}
/**
* Returns the current location of Ant as a point in the x/y-coordinate
* system that represents the landscape.
*
* @return the current location of the ant as a <code>Point</code>.
*/
public Point getLocation() {
return new Point(xLocation, yLocation);
}
/**
* Sets the location of the ant on its landscape using an x/y co-ordinate
* system.
*
* @param x the x axis location of the ant.
* @param y the Y axis location of the ant.
*/
public void setLocation(final int x, final int y) {
xLocation = x;
yLocation = y;
}
/**
* Gets the number of time steps the ant has completed. Turning, moving and
* skipping all count as one time step.
*
* @return The number of time steps the ant has gone through.
*/
public int getTimesteps() {
return timesteps;
}
/**
* Returns the number of food pellets the ant has eaten.
*
* @return The number of food pellets the ant has eaten.
*/
public int getFoodEaten() {
return foodEaten;
}
/**
* Returns the direction the Ant is currently facing and travelling.
*
* @return a compass orientation indicating the direction the ant is
* currently facing.
*/
public Orientation getOrientation() {
return orientation;
}
/**
* Sets the orientation the Ant is to face. This is the direction the
* ant will proceed in if the move method is called next.
*
* @param orientation The new orientation the ant is to face.
*/
public void setOrientation(final Orientation orientation) {
this.orientation = orientation;
}
/**
* Tests whether the next location for the ant, in its current orientation
* on its current landscape, contains a food pellet or not.
*
* @return true if the position in front of the ant contains a food pellet
* and false otherwise.
*/
public boolean isFoodAhead() {
final Point ahead = landscape.getNextLocation(getLocation(), getOrientation());
return landscape.isFoodLocation(ahead);
}
/**
* Skipping will cause the ant to fill one timestep without moving in its
* ant landscape. This is required for the skip algorithm to prevent the
* ant falling into dead ends.
*/
public void skip() {
timesteps++;
}
/**
* Returns the maximum number of time steps the ant is allowed to
* move. Turning, moving and skipping all count as one time step.
*
* @return the maximum number of time steps the ant is allowed to
* move
*/
public int getMaxMoves() {
return maxTimesteps;
}
}