<file_sep>package ca.ubc.ece.cpen221.mp4.ai;

import java.util.Set;

import ca.ubc.ece.cpen221.mp4.Location;
import ca.ubc.ece.cpen221.mp4.Util;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.chessPieces.ChessPiece;
import ca.ubc.ece.cpen221.mp4.chessPieces.Queen;
import ca.ubc.ece.cpen221.mp4.commands.Command;
import ca.ubc.ece.cpen221.mp4.commands.MoveCommand;
import ca.ubc.ece.cpen221.mp4.commands.WaitCommand;

/**
 * An artificial intelligence that allows a ChessPiece with the
 * potentialLocations of a Pawn to behave as a Pawn would in a game of chess.
 * Once reaching the end of the world Pawn isDead and a Queen spawns in its
 * place.
 *
 */
public class PawnAI implements ChessAI {

	@Override
	public Command getNextAction(World world, ChessPiece piece) {

		Set<Location> possibleMoves = piece.potentialLocations();

		// When the Pawn reaches the top or bottom of the World, remove the pawn
		// and spawn a new Queen
		if ((piece.getLocation().getY() == 0 || piece.getLocation().getY() == world.getHeight() - 1)
				&& !piece.isDead()) {
			Location loc = piece.getLocation();
			piece.loseEnergy(100);
			world.step();
			promotionPawn(world, loc);
			return new WaitCommand();

		}

		// Move into one of the Pawn's possible Locations if Empty and Valid
		for (Location loc : possibleMoves) {
			if (Util.isLocationEmpty(world, loc)) {
				return new MoveCommand(piece, loc);
			}
		}

		return new WaitCommand();
	}

	/**
	 * Spawns a new Queen in a location that a pawn previously existed
	 * 
	 * @param world
	 *            the World in which the Queen is to be spawned
	 * @param loc
	 *            the Location in which to spawn a new Queen, must be Valid and
	 *            Empty
	 * 
	 */
	private void promotionPawn(World world, Location loc) {
		QueenAI queenAI = new QueenAI();
		Queen queen = new Queen(queenAI, loc);
		world.addItem(queen);
		world.addActor(queen);
	}

}
<file_sep>package ca.ubc.ece.cpen221.mp4.ai;

import ca.ubc.ece.cpen221.mp4.ArenaWorld;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.chessPieces.ChessPiece;
import ca.ubc.ece.cpen221.mp4.commands.Command;

/**
 * The AI interface for all ChessPieces. Each ChessPiece possess a unique
 * implementation of this interface
 *
 */
public interface ChessAI {
	/**
	 * Returns the next Command that the ChessPiece will perform based on its
	 * unique behavior
	 * 
	 * @param world
	 *            the World in which the ChessPiece exists
	 * @param piece
	 *            a chessPiece, preferably matched to its corresponding AI
	 * @return the next Command for the piece to perform
	 */
	public Command getNextAction(World world, ChessPiece piece);
}
<file_sep>package ca.ubc.ece.cpen221.mp4.chessPieces;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import javax.swing.ImageIcon;

import ca.ubc.ece.cpen221.mp4.Location;
import ca.ubc.ece.cpen221.mp4.Util;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.ai.ChessAI;
import ca.ubc.ece.cpen221.mp4.commands.Command;

/**
 * A Knight implementation of a ChessPieces has potential locations in a
 * distance 3 L shape around its current location. It is assigned a random
 * colour "black" or "white"
 *
 */
public class Knight implements ChessPiece {
	// Arbitrary
	private static final int INITIAL_ENERGY = 40;
	// Arbitrary
	private static final int STRENGTH = 200;
	// Slower COOLDOWN time
	private static final int COOLDOWN = 4;
	// Knight moves 3 spaces in its L pattern
	private static final int MOVING_RANGE = 3;
	private static final ImageIcon knightImage = Util.loadImage("knight.gif");

	// Recommended KnightAI
	private final ChessAI ai;

	private Location location;
	private int energy;
	// Generate a random number to determine colour
	private final int random = new Random().nextInt(10);

	public Knight(ChessAI knightAI, Location initialLocation) {
		ai = knightAI;
		location = initialLocation;
		energy = INITIAL_ENERGY;
	}

	@Override
	public void moveTo(Location targetLocation) {
		location = targetLocation;
	}

	@Override
	public int getMovingRange() {
		return MOVING_RANGE;
	}

	@Override
	public ImageIcon getImage() {
		return knightImage;
	}

	@Override
	public String getName() {
		return "knight";
	}

	@Override
	public Location getLocation() {
		return this.location;
	}

	@Override
	public int getStrength() {
		return STRENGTH;
	}

	@Override
	public void loseEnergy(int energyLost) {
		energy -= energyLost;
	}

	@Override
	public boolean isDead() {
		return energy <= 0;
	}

	@Override
	public int getPlantCalories() {
		return 0;
	}

	@Override
	public int getMeatCalories() {
		return 0;
	}

	@Override
	public int getCoolDownPeriod() {
		return COOLDOWN;
	}

	@Override
	public Command getNextAction(World world) {
		Command nextAction = ai.getNextAction(world, this);
		return nextAction;
	}

	/**
	 * Knight moves in a distance 3 "L" shape in any direction. A set of all the
	 * locations a Knight could move if they are Valid and Empty
	 * 
	 * @return a set of all the possible Locations a knight could move if
	 *         Locations are Valid and Empty
	 */
	@Override
	public Set<Location> potentialLocations() {
		Set<Location> locations = new HashSet<Location>();
		locations.add(new Location(location.getX() + 2, location.getY() + 1));
		locations.add(new Location(location.getX() + 2, location.getY() - 1));
		locations.add(new Location(location.getX() - 2, location.getY() + 1));
		locations.add(new Location(location.getX() - 2, location.getY() - 1));
		locations.add(new Location(location.getX() + 1, location.getY() + 2));
		locations.add(new Location(location.getX() - 1, location.getY() + 2));
		locations.add(new Location(location.getX() + 1, location.getY() - 2));
		locations.add(new Location(location.getX() - 1, location.getY() - 2));
		return locations;
	}

	@Override
	public String colour() {

		if (this.random % 2 == 1) {
			return "white";
		}
		return "black";
	}

}
<file_sep>package ca.ubc.ece.cpen221.mp4.items.animals;

import javax.swing.ImageIcon;

import ca.ubc.ece.cpen221.mp4.Food;
import ca.ubc.ece.cpen221.mp4.Location;
import ca.ubc.ece.cpen221.mp4.Util;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.ai.AI;
import ca.ubc.ece.cpen221.mp4.ai.ArenaAnimalAI;
import ca.ubc.ece.cpen221.mp4.ai.PredatorAI;
import ca.ubc.ece.cpen221.mp4.commands.Command;
import ca.ubc.ece.cpen221.mp4.items.LivingItem;

/**
 *The {@link Tiger} is an {@link ArenaAnimal} that uses the {@link PredatorAI}.
 */
public class Tiger implements ArenaAnimal {
	// Constant attributes of the Tiger implementation of Animal
	private static final int INITIAL_ENERGY = 20;
	private static final int MAX_ENERGY = 200;
	private static final int STRENGTH = 400;
	private static final int VIEW_RANGE = 5;
	private static final int MIN_BREEDING_ENERGY = 100;
	private static final int COOLDOWN = 2;
	private static final int MOVING_RANGE = 1;
	private static final ImageIcon tigerImage = Util.loadImage("tiger.gif");

	private final AI ai;

	private Location location;
	private int energy;

	/**
	 * Constructs a new Tiger at a certain initialLocation
	 * 
	 * @param initialLocation
	 *            the location in which the Tiger is created
	 */
	public Tiger(Location initialLocation) {
		// Tiger uses the PredatorAI
		this.ai = new PredatorAI();
		this.location = initialLocation;

		this.energy = INITIAL_ENERGY;
	}

	@Override
	public LivingItem breed() {
		Tiger child = new Tiger(location);
		child.energy = energy / 2;
		this.energy = energy / 2;
		return child;
	}

	@Override
	public void eat(Food food) {
		energy = Math.min(MAX_ENERGY, energy + food.getMeatCalories());
	}

	@Override
	public int getCoolDownPeriod() {
		return COOLDOWN;
	}

	@Override
	public int getEnergy() {
		return energy;
	}

	@Override
	public ImageIcon getImage() {
		return tigerImage;
	}

	@Override
	public Location getLocation() {
		return location;
	}

	@Override
	public int getMaxEnergy() {
		return MAX_ENERGY;
	}

	@Override
	public int getMeatCalories() {
		// The amount of meat calories it provides is equal to its current
		// energy.
		return energy;
	}

	@Override
	public int getMinimumBreedingEnergy() {
		return MIN_BREEDING_ENERGY;
	}

	@Override
	public int getMovingRange() {
		return MOVING_RANGE; // Can only move to adjacent locations.
	}

	@Override
	public String getName() {
		return "Tiger";
	}

	@Override
	public Command getNextAction(World world) {
		Command nextAction = ai.getNextAction(world, this);
		this.energy--; // Loses 1 energy regardless of action.
		return nextAction;
	}

	@Override
	public int getPlantCalories() {
		return 0;
	}

	@Override
	public int getStrength() {
		return STRENGTH;
	}

	@Override
	public int getViewRange() {
		return VIEW_RANGE;
	}

	@Override
	public boolean isDead() {
		return energy <= 0;
	}

	@Override
	public void loseEnergy(int energyLoss) {
		this.energy = this.energy - energyLoss;
	}

	@Override
	public void moveTo(Location targetLocation) {
		location = targetLocation;
	}
}
<file_sep>package ca.ubc.ece.cpen221.mp4.ai;

import ca.ubc.ece.cpen221.mp4.Direction;
import ca.ubc.ece.cpen221.mp4.Location;
import ca.ubc.ece.cpen221.mp4.Util;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.commands.Command;
import ca.ubc.ece.cpen221.mp4.commands.DestroyCommand;
import ca.ubc.ece.cpen221.mp4.commands.MoveCommand;
import ca.ubc.ece.cpen221.mp4.commands.WaitCommand;
import ca.ubc.ece.cpen221.mp4.items.Item;
import ca.ubc.ece.cpen221.mp4.vehicles.copy.Vehicle;

/**
 * A simple vehicle AI
 */
public class VehicleAI {
	protected Vehicle veh;
	protected World world;
	
	
	public VehicleAI() {
	}
	
	/** 
	 * Decides the next action to be taken, given the state of the World and the
	 * vehicle.
	 *
	 * @param world
	 *            the current World
	 * @param animal
	 *            the vehicle waiting for the next action
	 * @return the next action for vehicle
	 */
	public Command getNextAction(World world, Vehicle veh) {
		this.veh = veh;
		this.world = world;
		Command com = null;
		
		//vehicle always tries to speed up
		veh.speedUp();
		
		//vehicle always maintains direction unless a wall is infront of it
		Direction dir = veh.getDirection();
		
		Location targetLocation = new Location(veh.getLocation(), dir);
		if (Util.isValidLocation(world, targetLocation) && Util.isLocationEmpty(world, targetLocation)) {
			return new MoveCommand(veh, targetLocation);
		}
		
		//if the position is not empty the vehicle attempts to run over the object
		else{
			com = destroyCheck(targetLocation);
		}
		
		if (com != null){
			return com;
		}
		
		//otherwise it must be against a wall so it will turn to a random direction along the wall
		//this slows the vehicle down
		else {
			if (dir == Direction.EAST) {
				int temp = (Math.random() <= 0.5) ? 1 : 2;
				if (temp == 1 && !veh.getLocation().equals(new Location(world.getWidth(), world.getHeight()))){
					dir = Direction.SOUTH;
				}
				else if(!veh.getLocation().equals(new Location(world.getWidth(),0))) {
					dir = Direction.NORTH;
				}
				else {
					dir = Direction.WEST;
				}
				targetLocation = new Location(veh.getLocation(), dir);
				
				com = destroyCheck(targetLocation);
				
				if (com != null){
					return com;
				}
				
				if (Util.isValidLocation(world, targetLocation) && Util.isLocationEmpty(world, targetLocation)) {
					return new MoveCommand(veh, targetLocation);
				}
				
			}
			
			if (dir == Direction.WEST) {
				int temp = (Math.random() <= 0.5) ? 1 : 2;
				if (temp == 1 && !veh.getLocation().equals(new Location(0, world.getHeight()))){
					dir = Direction.SOUTH;
				}
				else if (!veh.getLocation().equals(new Location(0,0))){
					dir = Direction.NORTH;
				}
				else {
					dir = Direction.EAST;
				}
				targetLocation = new Location(veh.getLocation(), dir);
				
				com = destroyCheck(targetLocation);
				
				if (com != null){
					return com;
				}
				
				if (Util.isValidLocation(world, targetLocation) && Util.isLocationEmpty(world, targetLocation)) {
					return new MoveCommand(veh, targetLocation);
				}
			}
			
			if (dir == Direction.SOUTH) {
				int temp = (Math.random() <= 0.5) ? 1 : 2;
				if (temp == 1 && !veh.getLocation().equals(new Location(world.getWidth(), world.getHeight()))){
					dir = Direction.EAST;
				}
				else if (!veh.getLocation().equals(new Location(0, world.getHeight()))) {
					dir = Direction.WEST;
				}
				else {
					dir = Direction.NORTH;
				}
				targetLocation = new Location(veh.getLocation(), dir);
				
				com = destroyCheck(targetLocation);
				
				if (com != null){
					return com;
				}
				
				if (Util.isValidLocation(world, targetLocation) && Util.isLocationEmpty(world, targetLocation)) {
					return new MoveCommand(veh, targetLocation);
				}
			}
			
			if (dir == Direction.NORTH) { 
				int temp = (Math.random() <= 0.5) ? 1 : 2;
				if (temp == 1 && !veh.getLocation().equals(new Location(world.getWidth(), 0))){
					dir = Direction.EAST;
				}
				else if (!veh.getLocation().equals(new Location(0,0))){
					dir = Direction.WEST;
				}
				else {
					dir = Direction.SOUTH;
				}
				targetLocation = new Location(veh.getLocation(), dir);
				
				com = destroyCheck(targetLocation);
				
				if (com != null){
					return com;
				}
				
				if (Util.isValidLocation(world, targetLocation) && Util.isLocationEmpty(world, targetLocation)) {
					return new MoveCommand(veh, targetLocation);
				}
			}
		}
		return veh.stop();
	}
	
	/**
	 * checks whether or not the vehicle is in a collision 
	 * 
	 * @param targetLocation the location directly in front of the vehicle
	 * @return either a command to destroy the vehicle, the item at the targetLocation or null
	 */
	public Command destroyCheck(Location targetLocation) {
		if (Util.isValidLocation(world, targetLocation) && !Util.isLocationEmpty(world, targetLocation)){
			for (Item i : world.getItems()) { 
				if (i.getLocation().equals(targetLocation)) {
					return new DestroyCommand(veh, i); 
				}
			}
		}
		return null;
	}
}<file_sep>package ca.ubc.ece.cpen221.mp4.items.animals;

import javax.swing.ImageIcon;

import ca.ubc.ece.cpen221.mp4.Food;
import ca.ubc.ece.cpen221.mp4.Location;
import ca.ubc.ece.cpen221.mp4.Util;
import ca.ubc.ece.cpen221.mp4.World;
import ca.ubc.ece.cpen221.mp4.ai.AI;
import ca.ubc.ece.cpen221.mp4.ai.ArenaAnimalAI;
import ca.ubc.ece.cpen221.mp4.ai.PredatorAI;
import ca.ubc.ece.cpen221.mp4.commands.Command;
import ca.ubc.ece.cpen221.mp4.items.LivingItem;

/**
 * The {@link Bear} is an {@link ArenaAnimal} that uses the {@link PredatorAI}.
 */
public class Bear implements ArenaAnimal {
	// Constant attributes of the Bear implementation of ArenaAnimal
	private static final int INITIAL_ENERGY = 20;
	private static final int MAX_ENERGY = 200;
	private static final int STRENGTH = 400;
	private static final int VIEW_RANGE = 5;
	private static final int MIN_BREEDING_ENERGY = 100;
	private static final int COOLDOWN = 5;
	private static final int MOVING_RANGE = 1;
	private static final ImageIcon bearImage = Util.loadImage("bear.gif");

	private final AI ai;

	private Location location;
	private int energy;

	/**
	 * Constructs a new Bear at a certain initialLocation
	 * 
	 * @param initialLocation
	 *            the location in which the Bear is created
	 */
	public Bear(Location initialLocation) {

		this.ai = new PredatorAI();
		this.location = initialLocation;

		this.energy = INITIAL_ENERGY;
	}

	@Override
	public LivingItem breed() {
		Bear child = new Bear(location);
		child.energy = energy / 2;
		this.energy = energy / 2;
		return child;
	}

	@Override
	public void eat(Food food) {
		energy = Math.min(MAX_ENERGY, energy + food.getMeatCalories());
	}

	@Override
	public int getCoolDownPeriod() {
		return COOLDOWN;
	}

	@Override
	public int getEnergy() {
		return energy;
	}

	@Override
	public ImageIcon getImage() {
		return bearImage;
	}

	@Override
	public Location getLocation() {
		return location;
	}

	@Override
	public int getMaxEnergy() {
		return MAX_ENERGY;
	}

	@Override
	public int getMeatCalories() {
		return energy;
	}

	@Override
	public int getMinimumBreedingEnergy() {
		return MIN_BREEDING_ENERGY;
	}

	@Override
	public int getMovingRange() {
		return MOVING_RANGE;
	}

	@Override
	public String getName() {
		return "Bear";
	}

	@Override
	public Command getNextAction(World world) {
		Command nextAction = ai.getNextAction(world, this);
		this.energy--;
		return nextAction;
	}

	@Override
	public int getPlantCalories() {
		return 0;
	}

	@Override
	public int getStrength() {
		return STRENGTH;
	}

	@Override
	public int getViewRange() {
		return VIEW_RANGE;
	}

	@Override
	public boolean isDead() {
		return energy <= 0;
	}

	@Override
	public void loseEnergy(int energyLoss) {
		this.energy = this.energy - energyLoss;
	}

	@Override
	public void moveTo(Location targetLocation) {
		location = targetLocation;
	}

}
