//  package Java.TicTacToe.Game;
/* 
 * Usage : java ComputerPlayer <ORBArgs>
 *         ORBArgs = Arguements for initializing the ORB(i.e -ORBInitialPort 1050)
 * Note  : This computer Player is designed to play the HumanPlayer included in 
 *         this package.  To start the HumanPlayer you must type the following
 *         java HumanPlayer 0 <ORBArgs>
 *         where ORBArgs = the ORBArgs used to start the ComputerPlayer
 */

import RemoteInterface.*;
import java.io.*;

class ComputerPlayer 
    extends Player
{
    
    protected int[] boardState = new int[9];
    
    public static void main(String args[])
    {
	try {
	
	    Player player = new ComputerPlayer();
	       
	    // Establish two way communication with remoteGame
	    player.initialize(args);  

	    // wait for invocations from TicTacToe server
	    java.lang.Object sync = new java.lang.Object();
	    synchronized (sync) {
		sync.wait();
	    }
	    
	}
	catch (Exception e) {
	    System.err.println("Error creating instance of ComputerPlayer: " + e);
	    e.printStackTrace();
	    
	    System.err.print("\nUsage: java ComputerPlayer <ORBArgs>\n");
	    System.err.print("OrbArgs = optional arguments to start the ORB (i.e. -ORBInitialPort 1050)\n");
	    System.exit(1);
	}
	
    }

    public ComputerPlayer( ) 
    {
	// the computer player is always 1, HumanPlayer should be 0
	super("1");

	// Reset the game board
	for(int i = 0; i < boardState.length; i++)
	    boardState[i] = 2;
    }

    public void yourMove(int[] newState)
    {
	setYourTurn(true);
	boardState = newState;
	int newPosition = bestMove();
	setMove( new Move( newPosition, playerNo ) );
    }

    public void wonGame(int[] newState){
	setYourTurn(false);
	setGameStatus(1);  // game won
	boardState = newState;
	System.out.println("The Computer Player has won");
    }
 
    public void lostGame(int[] newState){
	setYourTurn(false);
	setGameStatus(0);  // game lost
	boardState = newState;
	System.out.println("The Computer Player has lost");
    }
    
    public void tieGame(int[] newState){
	setYourTurn(false);
	setGameStatus(2);  // game tied
	boardState = newState;
	System.out.println("The Computer Player has tied the human player");
    }
    
    private boolean isWinningState( int [] state, int player ){
	System.out.println("WinningState:");
	for ( int temp= 0; temp < state.length; temp++ ){
	    System.out.print( " " + temp + ". " + state[temp] );
	}
	System.out.println();
	
	System.out.println("player = " + player );
	if (state[0] == player && state[1] == player && state[2] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[3] == player && state[4] == player && state[5] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[6] == player && state[7] == player && state[8] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[0] == player && state[3] == player && state[6] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[1] == player && state[4] == player && state[7] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[2] == player && state[5] == player && state[8] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[0] == player && state[4] == player && state[8] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	if (state[2] == player && state[4] == player && state[6] == player){
	    System.out.println("WinningState 1");
	    return true;
	}
	
	return false;
    }
 
    public void resetGame() { // nobody calls this right now - jlr
	setYourTurn(false);
	setGameStatus(-1); // game in progress
	// Reset the game board
	for(int i = 0; i < boardState.length; i++)
	    boardState[i] = 2;
    }
    
    
    // PreCondition: Computer player has the token and the 
    //               current boardState is known
    // PostCondition: returns best square (0-8) for 
    //                player 1 (the computer) to move
    //                returns -1 if no more empty Squares left
    private int bestMove(){
	
	final int squares[] // in best move order
	    = {4, 0, 2, 6, 8, 1, 3, 5, 7};
	int bestSquare = -1;
	int firstEmptySquare = -1;
	int square;
	int [] state = new int[boardState.length];
	
    loop:
	for (int i = 0 ; i < boardState.length ; i++) {
	    square = squares[i];  // Try this loop
	    System.out.println("Checking out square" + square );
	    if ( boardState[ square ] == 2) {
		// try this empty square
		System.out.println("square " + square + " is empty" );
		
		System.arraycopy(boardState, 0, state, 0, boardState.length );
		
		System.out.println("State:");
		for ( int temp= 0; temp < state.length; temp++ ){
		    System.out.print( " " + temp + ". " + state[temp] );
		}
		System.out.println();
		
		state[ square ] = 1; // What if player 1 moved to this square
		if (isWinningState(state, 1) ) { // will player 1 win with move
		    // We've won!
		    System.out.println(square + " is a winner");
		    return square;
		}
		
		
		if (firstEmptySquare == -1) {
		    // if we can not find a bestMove then we use this
		    System.out.println(square + " is firstEmptySquare" );
		    firstEmptySquare = square;
		}
		
		// look ahead 1 move
		for (int j = 0 ; j < boardState.length ; j++) {
		    if ( j != square && boardState[j] == 2 ) {
			// What if player 0 moves into empty space j
			System.out.println("What if player 0 moves to " + j );
			state[ j ] = 0;	
			System.out.println("State:");
			for ( int temp= 0; temp < state.length; temp++ ){
			    System.out.print( " " + temp + ". " + state[temp] );
			}
			System.out.println();
			
			if (isWinningState(state, 0) ) {
				// player 0 can win with next turn
			    System.out.println("Can't move to " + square + 
					       "or will loose with move to " + j );
			    continue loop;// lets try another square
			}
			else {
			    state[ j ] = 2;
			}
		    }
		}
		
		if (bestSquare == -1) {
		    // Neither player can win in one move
		    System.out.println("Neither player can win in one move");
		    bestSquare = square;
		}
	    } // end if empty square
	} // end for i
	
	if (bestSquare != -1) {
	    System.out.println("returning bestSquare " + bestSquare );
	    return bestSquare;
	}
	
	System.out.println("returning firstEmptySquare " + firstEmptySquare );
	return firstEmptySquare;
    }
    
    void setMove( Move newMove ){

	if(playerNo == newMove.playerId) {
	    // Player just made a move.
	    // Release the token 
	    setYourTurn(false);
	    //System.out.println("setting move to "+ playerNo +"\n ");
	    remoteGame.setMove(newMove);    
	}
	else {
	    // This should never happen
	    Exception e = new Exception("Illegal value playerID");
	    System.err.println("setMove: " + e);
	    e.printStackTrace();
	    System.exit(1);
	}
    }
	
}

