//  package Java.TicTacToe.Game;
/*
 * Usage : java TicTacToe <ORBArgs>
 *	   	ORBArgs => options for initializing the Corba ORB
 *	   	   i.e. -ORBInitialPort 1050
 */

import RemoteInterface.*;

class TicTacToe
    extends Game
{
    protected RemotePlayer remotePlayer0 = null;
    protected RemotePlayer remotePlayer1 = null;
    final static int gamePositions = 9;
    protected int[] gameState = new int[gamePositions];
    static boolean[] won = new boolean[1 << gamePositions];
    static final int DONE = (1 << gamePositions) - 1;
    protected int player0, player1;

    public static void hasWon(int pos)
    {
	// All the different possible winning scenarios
	for(int i = 0; i < DONE; i++) {
	    if((i & pos) == pos) {
		won[i] = true;
	    }
	}
    }

	public boolean isTieGame(){
		if(!( (won[player0] == true) || (won[player1] == true) )  ){
			boolean flag = true;
			for(int i = 0; i<gameState.length; i++){
				if(!(gameState[i] == 1 || gameState[i] == 0)){
					flag = false;
				}
			}	
			return flag;
		}
		return false;
	}

    static {
	hasWon((1 << 0) | (1 << 1) | (1 << 2));
	hasWon((1 << 3) | (1 << 4) | (1 << 5));
	hasWon((1 << 6) | (1 << 7) | (1 << 8));
	hasWon((1 << 0) | (1 << 3) | (1 << 6));
	hasWon((1 << 1) | (1 << 4) | (1 << 7));
	hasWon((1 << 2) | (1 << 5) | (1 << 8));
	hasWon((1 << 0) | (1 << 4) | (1 << 8));
	hasWon((1 << 2) | (1 << 4) | (1 << 6));
    }


    // PreCondition: The Game.connect() method has been
    //               succesfully executed
    // PostCondition: obtains the Corba servent for 
    //                remotePlayer0 and remotePlayer1
    public void setRemotePlayers()
    {
	
	remotePlayer0 = getRemotePlayer("Player0");
	remotePlayer1 = getRemotePlayer("Player1");
    }

    public void play()
    {
	try {
	    remotePlayer0.yourMove(gameState);
	}
	catch (Exception e) {
		e.printStackTrace();
	 }
    }


    // take out part and create connect() method
    public static void main(String args[])
    {
	try { 

	    TicTacToe game = new TicTacToe();
	    game.connect(args);
	    game.setRemotePlayers();

	    game.play();

	    // wait for invocations from clients
	    java.lang.Object sync = new java.lang.Object();
	    synchronized (sync) {
		sync.wait();
	    }

	}
	catch (Exception e) {
	    System.out.println("Error in main loop" + e);
	    System.exit(1);
	}
    }

    public void resetGame()
    {
	
	try {
	    // reset game and remove token from play
	    remotePlayer0.resetGame();
	    remotePlayer1.resetGame();
	}
	catch (Exception e) { }

	player1 = 0;
	player0 = 0;

	// Reset the game board
	for(int i = 0; i < gameState.length; i++)
	    gameState[i] = 2;

	play();
    }

    public TicTacToe()
    {
	player0 = 0;
	player1 = 0;

	// Reset the game board
	for(int i = 0; i < gameState.length; i++)
	    gameState[i] = 2;
    }

    public int[] getCurrentState()
    {
	return gameState;
    }

    public void setMove(RemoteInterface.Move newMove) 
    {

	java.lang.Object sync = new java.lang.Object();
	
	gameState[(int)newMove.newPosition] = (int)newMove.playerId;
	try {
	    if(newMove.playerId == 1) {
		// Player with id 1 has won
		player1 |= 1 << newMove.newPosition;
		if(won[player1] == true) {
		    remotePlayer1.wonGame(gameState);
		    remotePlayer0.lostGame(gameState);
		    synchronized (sync) {sync.wait(5000);  }
		    resetGame();
		}
		else if (this.isTieGame()){
		    remotePlayer1.tieGame(gameState);
		    remotePlayer0.tieGame(gameState);	
		    synchronized (sync) {sync.wait(5000);  }
		    resetGame();
		}
		else {
		    remotePlayer0.yourMove(gameState);
		}
	    }
	    else if(newMove.playerId == 0) {
		// Player with id 0 has won
		player0 |= 1 << newMove.newPosition;
		if(won[player0] == true) {
		    remotePlayer0.wonGame(gameState);
		    remotePlayer1.lostGame(gameState);
		    synchronized (sync) {sync.wait(5000);  }
		    resetGame();
		}
		else if (this.isTieGame()){
		    remotePlayer1.tieGame(gameState);
		    remotePlayer0.tieGame(gameState);	
		    synchronized (sync) {sync.wait(5000);  }
		    resetGame();
		}
		else {
		    remotePlayer1.yourMove(gameState);

		}
	    }
	}
	catch(Exception e){
	    // interupt exception from wait
	    // or corba exception from remotePlayer
	}
    }
}








