/*
 * Created on Apr 12, 2004
 *
 * @author: Owen Astrachan
 */
package ooga;

class ABMove extends Move
{
    public ABMove(int r, int c){
    	super(r,c);	
    }
    public int score;
}

public class AIPlayer implements IPlayer 
{

	
	private int[][] myBoard;

	   private static final int DRAW = 0;
	   private static final int COMPUTER_WIN = 10;
	   private static final int HUMAN_WIN = -10;

	   private ABMove[] myPossibleMoves;

	   public AIPlayer(){

		   myPossibleMoves = new ABMove[9];
		   int count = 0;
		   for(int j=0; j < 3; j++){
			   for(int k=0; k < 3; k++){
				   myPossibleMoves[count++] = new ABMove(j,k);
			   }
		   }
		   myBoard = new int[3][3];
	   }

		public Move getMove(IGameModel model) {
			IGrid grid = model.getGrid();
			for(int j=0; j < 3; j++){
				for(int k=0; k < 3; k++){
					myBoard[j][k] = grid.getValue(j,k);
				}
			}
			ABMove move = bestComputerMove(HUMAN_WIN,COMPUTER_WIN);
			return new Move(move.myRow,move.myCol);
		}

		public String getName() {
			return "AIPlayer";
		}
	   public boolean isDraw(){
		   for(int j=0; j < 3; j++){
			   for(int k=0; k < 3; k++){
				   if (myBoard[j][k] == 0) return false;
			   }
		   }
		   return true;
	   }
    
	   public boolean isWin(char ch){

		   for(int k=0; k < 3; k++){
                        
			   if (myBoard[k][0] == ch &&
				   myBoard[k][0] == myBoard[k][1] &&
				   myBoard[k][0] == myBoard[k][2]) return true;
			   if (myBoard[0][k] == ch &&
				   myBoard[0][k] == myBoard[1][k] &&
				   myBoard[0][k] == myBoard[2][k]) return true;
		   }
		   if (myBoard[0][0] == ch &&
			   myBoard[0][0] == myBoard[1][1] &&
			   myBoard[0][0] == myBoard[2][2]) return true;
		   if (myBoard[0][2] == ch && 
			   myBoard[0][2] == myBoard[1][1] &&
			   myBoard[1][1] == myBoard[2][0]) return true;
        
		   return false;   
	   }

	   public ABMove bestComputerMove(int alpha, int beta)
	   {

		   int bestScore = alpha;                 // best so far (human)
		   int score;
		   ABMove retmove = null;
        
		   for(int k=0; k < myPossibleMoves.length && bestScore < beta; k++){

			   ABMove m = myPossibleMoves[k];
			   if (myBoard[m.myRow][m.myCol] == 0){

				   myBoard[m.myRow][m.myCol] = 'X';
                
				   if (isWin('X')){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = COMPUTER_WIN;
					   return move;
				   }
				   if (isWin('O')){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = HUMAN_WIN;
					   return move;
				   }               
				   if (isDraw()){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = DRAW;
					   return move;                    
				   }

				   ABMove oppMove = bestHumanMove(bestScore,beta);
				   myBoard[m.myRow][m.myCol] = 0; // unplace
				   if (oppMove.score > bestScore)
				   {
					   bestScore = oppMove.score;
					   retmove = m;
				   }
			   }
		   }
		   retmove = new ABMove(retmove.myRow,retmove.myCol);
		   retmove.score = bestScore;
		   return retmove;
	   }

	   public ABMove bestHumanMove(int alpha, int beta)
	   {

		   int bestScore = beta;                 // best so far (computer)
		   int score;
		   ABMove retmove = null;
        
		   for(int k=0; k < myPossibleMoves.length && bestScore > alpha; k++){

			   ABMove m = myPossibleMoves[k];
			   if (myBoard[m.myRow][m.myCol] == 0){

				   myBoard[m.myRow][m.myCol] = 'O';
                
				   if (isWin('O')){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = HUMAN_WIN;
					   return move;
				   }
				   if (isWin('X')){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = COMPUTER_WIN;
					   return move;                    
				   }
				   if (isDraw()){
					   myBoard[m.myRow][m.myCol] = 0; // unplace
					   ABMove move = new ABMove(m.myRow,m.myCol);
					   move.score = DRAW;
					   return move;                    
				   }

				   ABMove oppMove = bestComputerMove(alpha,bestScore);
				   myBoard[m.myRow][m.myCol] = 0; // unplace
				   if (oppMove.score < bestScore) {
					   bestScore = oppMove.score;
					   retmove = m;
				   }
			   }
		   }
		   retmove = new ABMove(retmove.myRow,retmove.myCol);
		   retmove.score = bestScore;
		   return retmove;
	   }
	   }
