package player.gamer.statemachine.sadna;

import java.io.IOException;
import java.util.Random;

/**
 * Train two Connect Four players. 
 * Uges: GameTrainer <player1 starting weights file name> <player2 starting weights file name> <number of games to run> <random beginner (boolean)>
 */
public class GameTrainer {

	private static Random rand = new Random();
	
	public static void main(String[] args) throws IOException {

		// read user parameters
		String player1WeightsFileName;
		String player2WeightsFileName;
		int numberOfGames;
		boolean randomBeginner;
		try {
			player1WeightsFileName = args[0];
			player2WeightsFileName = args[1];
			numberOfGames = Integer.valueOf(args[2]);
			randomBeginner = Boolean.valueOf(args[3]); // true if the beginner should be chosen randomly 
		} catch (Exception e) {
			System.out.println("Uges: GameTrainer <player1 starting weights file name> <player2 starting weights file name> <number of games to run> <random beginner (boolean)>");
			return;
		}
		
		TrainingPlayer player1 = new TrainingPlayer(Utils.readWeights(player1WeightsFileName)); 
		TrainingPlayer player2 = new TrainingPlayer(Utils.readWeights(player2WeightsFileName)); 

		int counter1 = 0;
		int counter2 = 0;
		int tie = 0;

		try {
			// play numberOfGames games
			for (int i = 0; i < numberOfGames ; i++) {
				System.out.println(i);
				
				player1 = new TrainingPlayer(player1.getWeights(), 5);
				player2 = new TrainingPlayer(player2.getWeights(), 5);

				// play one game
				if (!randomBeginner || rand.nextInt(2) == 0) {
					// player 1 begin
					int result = playGame(player1, player2);
					if (result == 1) {
						System.out.println("1 begin, 1 won");
						counter1++;
					} else if (result == 2) {
						System.out.println("1 begin, 2 won");
						counter2++;
					} else {
						System.out.println("1 begin, tie");
						tie++;
					}
				} else {
					// player 2 begin
					int result = playGame(player2, player1);
					if (result == 1) {
						System.out.println("2 begin, 2 won");
						counter2++;
					} else if (result == 2) {
						System.out.println("2 begin, 1 won");
						counter1++;
					} else {
						System.out.println("2 begin, tie");
						tie++;
					}
				}
	
				// save intermediate results
				if (i % 5000 == 0 && i > 0) {
					Utils.writeWeights(player1.getWeights(), "player1_train_" + i + ".txt");
					Utils.writeWeights(player2.getWeights(), "player2_train_" + i + ".txt");
					
					System.out.println("Tie: " + tie + ", 1 own: " + counter1 + ", 2 won: " + counter2);
				}
			}
		} finally {
			System.out.println("Tie: " + tie + ", 1 own: " + counter1 + ", 2 won: " + counter2);

			// save final results
			Utils.writeWeights(player1.getWeights(), "player1_after_trian.txt");
			Utils.writeWeights(player2.getWeights(), "player2_after_trian.txt");
		}
		
	} 

	/**
	 * Play one Connect Four game
	 * @return 1 if first player won, 2 if second player won, 3 if tie.
	 */
	public static int playGame(TrainingPlayer player1, TrainingPlayer player2) {
		int counter = 0;
		int action = -1;
		
		while (counter != Board.HEIGHT*Board.WIDTH/2) {
			counter++;
			
			action = player1.playMove(action);
			if (player1.didWin()) {
				player2.opponentWon(action);
				return 1;
			}
			action = player2.playMove(action);
			if (player2.didWin()) {
				player1.opponentWon(action);
				return 2;
			}
		}
		return 3; // tie
	}
}
