import java.util.*;

public class Agent {

	private PDStrategy strategy;
	private Agent competitor;
	private int fitness = 0;
	private int numGames = 0;
	// memory:
	private Map<Agent, Boolean> lastMoves = new Hashtable<Agent, Boolean>();
	private Set<Agent> defectors = new HashSet<Agent>();


	public void setStrategy(PDStrategy s) {
		strategy = s;
		strategy.setMyAgent(this);
	}

	public PDStrategy getStrategy() {
		return strategy;
	}

	public Agent getCompetitor() {
		return competitor;
	}

	public void setCompetitor(Agent other) {
		competitor = other;
	}

	public int getFitness() {
		return fitness;
	}

	public int getNumGames() {
		return numGames;
	}

	public boolean hasDefected(Agent other) {
		return defectors.contains(other);
	}

	public boolean getLastMove(Agent other) {
		Boolean b = lastMoves.get(other);
		if (b == null) return true; // assume agents are born cooperative
		return b;
	}

	public boolean willCooperate() {
		return strategy.willCooperate();
	}

	public void updateFitness(boolean myMove, boolean otherMove) {
		numGames++;
		if (myMove) {
			if (otherMove) {
				fitness += 3;
			} else {
				fitness += 0;
			}
		} else {
			if (otherMove) {
				fitness += 5;
			} else {
				fitness += 1;
			}
		}
	}

	public void updateMemory(boolean otherMove) {
		lastMoves.put(competitor, otherMove);
		if (!otherMove) {
			defectors.add(competitor);
		}
	}

	public void compete(Agent other) {
		competitor = other;
		other.setCompetitor(this);
		boolean myMove = willCooperate();
		boolean otherMove = other.willCooperate();
		updateFitness(myMove, otherMove);
		other.updateFitness(otherMove, myMove);
		updateMemory(otherMove);
		other.updateMemory(myMove);
	}

	public String toString() {
		return "Agent: fittness = " + fitness + " numGames = " + numGames + " strategy = " + strategy;
	}

}