package cecj.app.othello;

import ec.EvolutionState;
import ec.Individual;
import ec.util.Parameter;
import ec.vector.DoubleVectorIndividual;
import games.BoardGame;
import games.Player;
import cecj.eval.TDLImprover;
import games.scenarios.SelfPlayTDLScenario;

public class OthelloTDLImprover implements TDLImprover {

	private static final int WPC_LENGTH = 64;

	private static final String P_REPEATS = "repeats";
	private static final String P_RANDOMNESS = "randomness";
	private static final String P_LEARNING_RATE = "learning-rate";

	private int repeats;
	private double randomness;
	private double learningRate;

	public void setup(EvolutionState state, Parameter base) {
		Parameter randomnessParam = base.push(P_RANDOMNESS);
		randomness = state.parameters.getDoubleWithDefault(randomnessParam, null, 0.1);

		Parameter learningRateParam = base.push(P_LEARNING_RATE);
		learningRate = state.parameters.getDoubleWithDefault(learningRateParam, null, 0.01);

		Parameter repeatsParam = base.push(P_REPEATS);
		repeats = state.parameters.getIntWithDefault(repeatsParam, null, 10);
	}

	public void improve(EvolutionState state, Individual ind) {
		Player player = new OthelloPlayer(getWPC(state, ind));
		BoardGame game = new OthelloGame(new OthelloBoard());
		SelfPlayTDLScenario selfPlayScenario = new SelfPlayTDLScenario(state.random[0], player,
			randomness, learningRate);

		for (int r = 0; r < repeats; r++) {
			game.reset();
			selfPlayScenario.play(game);
		}
	}

	public void prepareForImproving(EvolutionState state, Individual ind) {
		double[] wpc = getWPC(state, ind);
		for (int i = 0; i < WPC_LENGTH; i++) {
			wpc[i] = 0.0;
		}
	}

	private double[] getWPC(EvolutionState state, Individual ind) {
		if (!(ind instanceof DoubleVectorIndividual)) {
			state.output.error("Othello players should be represented by floats vectors\n");
		}

		double[] wpc = ((DoubleVectorIndividual) ind).genome;
		if (wpc.length != WPC_LENGTH) {
			state.output.error("Players WPC vectors length should be 64\n");
		}

		return wpc;
	}
}
