import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.io.*;

public class player5c_edg extends Applet
{


        OthelloBoard board;
        OthelloPlayer whitePlayer;
        OthelloPlayer blackPlayer;


	static final int NOWHERE = -1;
	
	static final int BLACK = 2;
	static final int WHITE = 1;
	static final int EMPTY = 0;
	static final int OKMOVE = 3;
	
	static final int USER = BLACK;
	static final int COMPUTER = WHITE;
	
	static final int CHANGED = 16;
	
	static final int BOARD_WIDTH = 400;
	static final int BOARD_HEIGHT = 260;
	static final int APPLET_HEIGHT = 345;
	static final int STATUS_BOX_HEIGHT = 120;
	
	static final int ICON_TOP = BOARD_HEIGHT + 30;
	static final int SOUND_LEFT = BOARD_WIDTH - 37;
	static final int RESTART_LEFT = 70;	
	
    //static final int A_SPLIT_SECOND = 180;
    static final int A_SPLIT_SECOND = 0;
        static final int EDGAR_FAKE_THINK_TIME = 0;

	int xpos[][], ypos[];

	
	// keep track of where the legal move indicator is
	// also, keep the last one so that it can be redrawn
	int okMoveColumn = NOWHERE;
	int okMoveRow = NOWHERE;
	
	// the zero column is not used, board is 8x8

	// This is the "learning" that was done and will be used
        // to decide what to do in a particular situation

        boolean FirstTime = true;
        boolean NowReady = false;


	Image emptyBoard;
	Image blackBoard;
	Image whiteBoard;
	Image moveBoard;
	
	boolean soundIsTurnedOn = false;
	AudioClip userMoveSound;
	AudioClip computerMoveSound;
	AudioClip pieceFlipSound;
	AudioClip illegalMoveSound;

	Image soundOnIcon;
	Image soundOffIcon;
	Image gameRestartIcon;
	String statusMessage;
	
    URL url;

	/**
	 * Set up the board, load everything in so it's speedy
	 */
	public void init()
	{
		// codebase used multiple times, start a new mediatracker
		url = getCodeBase();
		MediaTracker tracker = new MediaTracker(this);
			
		// Suck in the images.
		blackBoard = getImage(url, "images/blackboard-B.gif");
		tracker.addImage(blackBoard, 0);
		whiteBoard = getImage(url, "images/whiteboard-B.gif");
		tracker.addImage(whiteBoard, 0);
		emptyBoard = getImage(url, "images/emptyboard-B.gif");
		tracker.addImage(emptyBoard, 0);
		moveBoard = getImage(url, "images/moveboard-B.gif");
		tracker.addImage(moveBoard, 0);
		soundOnIcon = getImage(url, "images/soundon.gif");
		tracker.addImage(soundOnIcon, 0);
		soundOffIcon = getImage(url, "images/soundoff.gif");
		tracker.addImage(soundOffIcon, 0);
		gameRestartIcon = getImage(url, "images/restart.gif");
		tracker.addImage(gameRestartIcon, 0);
		try {
			tracker.waitForAll();
		}
		catch (InterruptedException e) {
		}
		// Snatch the audio
		userMoveSound = getAudioClip(url, "audio/pock.au");
		computerMoveSound = getAudioClip(url, "audio/shortlowpock.au");
		pieceFlipSound = getAudioClip(url, "audio/tick.au");
		illegalMoveSound = getAudioClip(url, "audio/bozo.au");
		
		// Setup board regions
		xpos = new int[9][9];
		double left = 50.0;
		double right = 349.0;
		
		for (double j = 0.0; j < 9.0; j++) {
			for (double i = 0.0; i <= 8.0; i++) {
				xpos[(int) i][(int) j] = (int) ((left + (right - left) * (i / 8.0)));
			}
			left -= 5.5;
			right += 5.5;
		}
		
		ypos = new int[9];
		//ypos = { 10, 33, 58, 84, 111, 142, 175, 210, 247 };
		ypos[0] = 10;
		ypos[1] = 33;
		ypos[2] = 58;
		ypos[3] = 84;
		ypos[4] = 111;
		ypos[5] = 142;
		ypos[6] = 175;
		ypos[7] = 210;
		ypos[8] = 247;
		beginGame();
	}



  // This finction is where the game and players get defined.
	public void beginGame()
	{
	  board = new OthelloBoard();

	  statusMessage = "Your turn.";
	  paint(this.getGraphics());
	  
	  
	  if (FirstTime)
	    {

	      whitePlayer = new OthelloEdgar(true, url);

	      blackPlayer = new MyPlayer(BLACK,
					 " ( /   me_near_corners  ( /  ( *   me_near_corners  ( *  ( /  me_near_corners me_edges )  me_change )) ( -   me_edges  ( *  ( -   row_from_center  ( -  me_corners_gain   me_edges )) ( -   10  ( *   me_corners_gain   me_change )))))) ");

	      FirstTime = false;
	    }
	}
	
	public void waitFor(long duration)
	{
		long stopTime = System.currentTimeMillis() + duration;
		
		do {
		} while (System.currentTimeMillis() < stopTime);
	}




	/**
	 * Draw the board, update, whatever
	 */
	public void paint(Graphics g)
	{
		g.clipRect(0, 0, BOARD_WIDTH, APPLET_HEIGHT);
		g.drawImage(emptyBoard, 0, 0, this);
		
		g.setColor(Color.black);
		g.fillRect(0, BOARD_HEIGHT, BOARD_WIDTH, APPLET_HEIGHT - BOARD_HEIGHT);
		
		g.setColor(Color.black);
		g.fillRect(60, BOARD_HEIGHT+20, BOARD_WIDTH-120, STATUS_BOX_HEIGHT);
	
		paintIcons(g);
		paintMessage(g);
		
		// draw everyone
		for (int row = 1; row < 9; row++)
			for (int col = 1; col < 9; col++)
				paintPiece(g, col, row);
	}
	
	public void paintIcons(Graphics g)
	{
		// show sound icon
/*		if (soundIsTurnedOn)
			g.drawImage(soundOnIcon, SOUND_LEFT, ICON_TOP, this );
		else
			g.drawImage(soundOffIcon, SOUND_LEFT, ICON_TOP, this ); */
		// show restart icon
		g.drawImage(gameRestartIcon, SOUND_LEFT, ICON_TOP, this );
	}
	
	
	public void updateIcons()
	{
		Graphics g = this.getGraphics();
		g.clipRect(0, 0, BOARD_WIDTH, APPLET_HEIGHT);
		paintIcons(g);
	}
	
	
	public void paintMessage(Graphics g)
	{
		g.setColor(Color.black);
		g.fillRect(0, BOARD_HEIGHT+20, BOARD_WIDTH-45, STATUS_BOX_HEIGHT);
		
		g.setColor(Color.red);
                g.setFont(new Font("TimesRoman",Font.BOLD,18));
		g.drawString(statusMessage, 225, BOARD_HEIGHT+50);
		g.setColor(Color.white);
		g.drawString("WHITE : "+board.score[WHITE], 10, BOARD_HEIGHT+50);
		g.drawString("BLACK : "+board.score[BLACK], 125, BOARD_HEIGHT+50);
	}
	
	
	public void updateMessage(String message)
	{
		Graphics g = this.getGraphics();
		g.clipRect(0, 0, BOARD_WIDTH, APPLET_HEIGHT);
		
		statusMessage = message;
		paintMessage(g);
	}	



  // Draw the pieces that were flipped and need to be updated.

        public void paintPieces() {
	  
	  Move piece;

	  while (board.paintPieces.size()>0) {
	    
	    piece = (Move)board.paintPieces.elementAt(0);
	    paintPiece(piece.col(),piece.row());
	    board.paintPieces.removeElementAt(0);

	  }
	}


	/**
	 * draw an individual piece
	 */
	public void paintPiece(int col, int row)
	{
		paintPiece(this.getGraphics(), col, row);
	}
	
	
	public void paintPiece(Graphics g, int col, int row)
	{
		boolean pieceFlipped = false;
		
		// changed piece? play flipping sound before redrawing
		if ((board.board[col][row] & CHANGED) > 0) {
			if (soundIsTurnedOn)
				pieceFlipSound.play();
			board.board[col][row] -= CHANGED;
			pieceFlipped = true;
		}
 
		// draw graphics for piece based on its status
		g = this.getGraphics();
		g.clipRect(xpos[col-1][row-1], ypos[row-1],
		           xpos[col][row-1] - xpos[col-1][row-1], ypos[row] - ypos[row-1]);
		switch (board.board[col][row]) {
			case EMPTY:
				g.drawImage(emptyBoard, 0, 0, this );
				break;
			case WHITE:
				g.drawImage(whiteBoard, 0, 0, this );
				break;
			case BLACK:
				g.drawImage(blackBoard, 0, 0, this );
				break;
			case OKMOVE:
				g.drawImage(moveBoard, 0, 0, this );
				break;
		}

		if (pieceFlipped) 
			waitFor(A_SPLIT_SECOND);

	}



  // Main loop that plays game.
        public void playGame() {
	  
	  Move currentMove;

	  while(!board.gameOver()) {

	    if (board.gameTurn==BLACK) {

	    waitFor(EDGAR_FAKE_THINK_TIME*1);
	    currentMove = blackPlayer.bestMove(board);
	    board.makeMove(BLACK, currentMove.col(), currentMove.row());
	    //System.out.println("Black Move: Col = " + currentMove.col() + "Row = " + currentMove.row());
	    //board.PrintBoard();
	    paintPieces();
	    } else {
	    waitFor(EDGAR_FAKE_THINK_TIME*1);
	    currentMove = whitePlayer.bestMove(board);
	    board.makeMove(WHITE, currentMove.col(), currentMove.row());
	    //System.out.println("White Move: Col = " + currentMove.col() + "Row = " + currentMove.row());
	    //board.PrintBoard();
	    paintPieces();
	    }
	  }
	    if (board.gameOver())
	      endGame();
	}

  // I left the following functions commented out for you so you can easily add
  // playing against the players yourself.  I leave that to you to do it.
  // Look at the file "Othello.java" for the original code and how it works there.
  // Note that we now paint peices using the "paintPieces" function because the peices
  // are flipped in a different file (OthelloBoard.java).

  /*	public boolean mouseMove (Event evt, int x, int y)
	{
		int row = 0, col = 0;
		for (int j = 0; j < 8; j++) {
			if (y > ypos[j] && y < ypos[j+1]) {
				row = j + 1;
				double left = 50 - (row * 5.5);
				double right = 349 + (row * 5.5);
				col = (int) ((x - left) / (right - left) * 8) + 1;
			}
		}

		if (col>8 || row>8 || col<1 || row<1)
			return false;
		
		if (col != okMoveColumn || row != okMoveRow) {
			if (okMoveColumn != NOWHERE) {					// un-mark old piece
				board[okMoveColumn][okMoveRow] = EMPTY;
				paintPiece(okMoveColumn, okMoveRow);
				okMoveColumn = NOWHERE;
				okMoveRow = NOWHERE;
			}
			if (isLegalMove(USER, col, row)) {				// mark the new legal piece
				board[col][row] = OKMOVE;
				paintPiece(col, row);
				okMoveColumn = col;
				okMoveRow = row;
			}
		}
		return true;
	}*/


  /*	public boolean mouseUp (Event evt, int x, int y)
	{
	    if (NowReady)
              {
		  waitFor(EDGAR_FAKE_THINK_TIME*1);
		  doComputerMove();
		  NowReady = false;
	      }
	    return true;
	}
	*/
	/**
	 * make the user's move, based on the mouse click
	 */
	public boolean mouseDown (Event evt, int x, int y)
	{
	  /*int row = 0, col = 0;
		for (int j = 0; j < 8; j++) {
			if (y > ypos[j] && y < ypos[j+1]) {
				row = j + 1;
				double left = 50 - (row * 5.5);
				double right = 349 + (row * 5.5);
				col = (int) ((x - left) / (right - left) * 8) + 1;
			}
		}
		*/
	  //if (col>8 || row>8 || col<1 || row<1) {

	  // This is the only uncommented region in this function.
	  // I stripped out everything except for starting games over and
	  // starting games from the begining.

			if (y > ICON_TOP && y < ICON_TOP+32) {
				if (x > SOUND_LEFT && x < SOUND_LEFT+24) {
				    FirstTime = false;
				    beginGame();
				} 
			}
			//return true;
			//}
			else {
			  playGame();
			}
			return true;
	
		/*
		if (isLegalMove(USER, col, row)) {
 			if (soundIsTurnedOn)
				userMoveSound.play();
		
			// update the old 'ok move' piece
			if (okMoveColumn != NOWHERE)	{
				board[okMoveColumn][okMoveRow] = EMPTY;
				okMoveColumn = okMoveRow = NOWHERE;
			}
			makeMove(USER, col, row);
			NowReady = true;

		} else {
			// not a legal move
			if ( board[col][row] == EMPTY )	{
				if ( soundIsTurnedOn )
					illegalMoveSound.play();
				updateMessage("  Illegal!");
			}
		}
		*/
			//return true;
	}



	void endGame ()
	{
		// COMPUTER has won
		if ( board.score[WHITE] > board.score[BLACK] )	{
			if ( soundIsTurnedOn )
				play( getCodeBase(), "audio/iwin.au");
			updateMessage("White Wins!");
		}
	
		// USER has won
		else if ( board.score[BLACK] > board.score[WHITE] )	{
			if ( soundIsTurnedOn )
				play( getCodeBase(), "audio/youwin.au");
			updateMessage("Black Wins!");
		}
		
		// It is a tie
		else	{
			if ( soundIsTurnedOn )
				play( getCodeBase(), "audio/itsatie.au");
			updateMessage("A TIE!");
		}
	}
}



