import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Othello extends Applet implements MouseListener,Runnable{
	private Dimension d;
	private Image offscreen;
	private Graphics grf;
	//画像用の変数
	private Image title_bar;
	private Image [] slime_img = new Image[2];
	private Image [] number_img = new Image[10];
	private Image startbutton;
	private Image passbutton;
	private Image sankaku;
	private MediaTracker mt;
	//マスの大きさ
	private int masuWidth = 25;
	private int masuHeight = 25;
	//マスの外枠の大きさ
	private int masuframeWidth = 2;
	private int masuframeHeight = 2;
	//その他の場所の外枠の大きさ
	private int otherframeWidth = 5;
	private int otherframeHeight = 5;
	//メッセージボックスの大きさ
	private int messageboxWidth = 218;
	private int messageboxHeight = 80;
	//メッセージの種類
	private String message1 = "プレイヤーは赤く光るマスに置きました。";
	private String message2 = "プレイヤーはパスしました。";
	private String message3 = "ゲームは終了しました。";
	private String message4 = "青色に光るマスが着手可能なマスです。";
	private String message5 = "置けるマスがありません。パスしてください。";
	//プレイヤー画面
	private String [] playerKind = {"Human","Comp_0","Comp_1","Comp_2"};
	private int [] pl = {0,0};
	private boolean [] player_henka = {false,false};
	//色の設定
	private Color backgroundColor;
	private Color frameColor;
	private Color messageboxColor;
	private Color textColor;
	private Color masuColor;
	//座標格納変数
	private int [][] indx;
	private int [][] indy;
	//状態用変数
	private boolean pass;
	private boolean start = false;
	private Kyokumen kyokumen;
	private Tactics tactics[] = {null,null};
	private Thread thread = null;
	private Thread thread2 = null;
	private AudioClip au1,au2;
	public int su = 0;
	//初期処理initメソッド
	public void init(){
		//ダブルスクリーンのための処理
		d = getSize();
		offscreen = createImage(d.width,d.height);
		grf = offscreen.getGraphics();
		indx = new int[8][8];
		indy = new int[8][8];
		kyokumen = new Kyokumen();
		for(int i = 0;i < 8;i++){
			for(int j = 0;j < 8;j++){
				indx[i][j] = 77 + (masuframeWidth + masuWidth) * j;
				indy[i][j] = 62 + (masuframeHeight + masuHeight) * i;
			}
		}
		//色の設定
		backgroundColor = new Color(0,128,0);
		frameColor = new Color(128,128,128);
		messageboxColor = Color.white;
		textColor = Color.black;
		masuColor = Color.white;
		//画像読み込み設定
		mt = new MediaTracker(this);
		title_bar = getImage(getCodeBase(),"titlebar.png");
		mt.addImage(title_bar,0);
		startbutton = getImage(getCodeBase(),"startbutton.png");
		mt.addImage(startbutton,0);
		passbutton = getImage(getCodeBase(),"passbutton.png");
		mt.addImage(passbutton,0);
		sankaku = getImage(getCodeBase(),"sankaku.png");
		mt.addImage(sankaku,0);
		for(int i = 0;i < 2;i++){
			slime_img[i] = getImage(getCodeBase(),"slime_" + (i + 1) + ".png");
			mt.addImage(slime_img[i],0);
		}
		for(int i = 0;i < 10;i++){
			number_img[i] = getImage(getCodeBase(),i + ".gif");
			mt.addImage(number_img[i],0);
		}
		//音読み込み設定
		au1 = getAudioClip(getDocumentBase(),"piko1.wav");
		au2 = getAudioClip(getDocumentBase(),"cancel1.wav");
		addMouseListener(this);
	}
	public void paint(Graphics g){
		update(g);
	}
	public void update(Graphics g){
	    if(!mt.checkID(0)){
			g.setColor(Color.black);
			g.drawString("Please wait...",d.width / 4,d.height / 2);
			return;
		}
		grf.setColor(backgroundColor);
		grf.fillRect(0,0,d.width,d.height);
		grf.drawImage(title_bar,75,10,this);
		grf.setColor(frameColor);
		for(int i = 0;i < 9;i++){
			grf.fillRect(75 + (masuframeHeight + masuHeight) * i,60,masuframeHeight,(masuframeWidth + masuWidth) * 8 + masuframeWidth);
			grf.fillRect(75,60 + (masuframeWidth + masuWidth) * i,(masuframeHeight + masuHeight) * 8 + masuframeHeight,masuframeWidth);
		}
		for(int i = 0;i < 2;i++){
			int y = 60 + i * 90;
			for(int j = 0;j < 2;j++){
				grf.setColor(frameColor);
				grf.fillRect(308,y + 30 * j,masuWidth + otherframeWidth * 2,otherframeHeight);
				grf.fillRect(308 + 30 * j,y,otherframeWidth,masuHeight + otherframeHeight * 2);
			}
			grf.drawImage(slime_img[i],313,65 + 90 * i,this);
			if((i + 1) == kyokumen.getTurn()){
				grf.setColor(Color.red);
				grf.fillRect(313,65 + 90 * i,3,3);
			}
			if(player_henka[i]){
				pl[i] = pl[i] + 1;
				if(pl[i] == playerKind.length){
					pl[i] = 0;
				}
				player_henka[i] = false;
			}
			grf.drawImage(sankaku,308,y + 45,this);
			grf.setColor(textColor);
			grf.setFont(new Font("ＭＳ　ゴシック",Font.BOLD,12));
			grf.drawString(playerKind[pl[i]],329,y + 56);
		}
		
		for(int i = 0;i < 2;i++){
			grf.drawImage(number_img[kyokumen.stoneCount(i) / 10],343,66 + i * 90,this);
			grf.drawImage(number_img[kyokumen.stoneCount(i) % 10],362,66 + i * 90,this);
			grf.fillRect(75 + 213 * i,309,otherframeWidth,70);
		}
		for(int i = 0;i < 2;i++){
			grf.setColor(frameColor);
			grf.fillRect(75,309 + 65 * i,218,otherframeHeight);
			grf.fillRect(75 + 213 * i,309,otherframeWidth,70);
		}
		grf.drawImage(startbutton,317,240,this);
		grf.drawImage(passbutton,317,290,this);
		grf.setColor(messageboxColor);
		grf.fillRect(80,314,208,60);
		
		for(int i = 0;i < 8;i++){
			for(int j = 0;j < 8;j++){
				grf.setColor(masuColor);
				if(kyokumen.specialgetMasu(i,j,0) == 0){
					grf.fillRect(indx[i][j],indy[i][j],masuWidth,masuHeight);
				}else{
					grf.drawImage(slime_img[kyokumen.specialgetMasu(i,j,0) - 1],indx[i][j],indy[i][j],this);
				}
				grf.setColor(Color.red);
				if(kyokumen.specialgetMasu(i,j,1) == 1){
					grf.fillRect(indx[i][j],indy[i][j],3,3);
				}
				grf.setColor(Color.blue);
				if(kyokumen.masuPlaceCheck(i,j,kyokumen.getTurn())){
					grf.fillRect(indx[i][j] + 10,indy[i][j] + 10 ,5,5);
				}
			}
		}
		grf.setColor(textColor);
		grf.setFont(new Font("ＭＳ　ゴシック",Font.PLAIN,10));
		if(gameEnd()){
			grf.drawString(message3,80,340);
			start = false;
		}else{
			if(pass){
				grf.drawString(message2,80,325);
				grf.drawString(message4,80,355);
			}else{
				if(!(kyokumen.stoneCount(0) == 2 && kyokumen.stoneCount(1) == 2)){
					grf.drawString(message1,80,325);
					if(kyokumen.noPlaceCheck(kyokumen.getTurn())){
						grf.drawString(message5,80,355);
					}else{
						grf.drawString(message4,80,355);
					}
				}
			}
		}
		g.drawImage(offscreen,0,0,this);
	}
	public void mousePressed(MouseEvent e){
	}
	public void mouseReleased(MouseEvent e){
	}
	public void mouseExited(MouseEvent e){
	}
	public void mouseEntered(MouseEvent e){
	}
	public void mouseClicked(MouseEvent e){
		int x = e.getX();
		int y = e.getY();
		if(start){
			if(pl[kyokumen.getTurn() - 1] == 0){
				for(int i = 0;i < 8;i++){
					for(int j = 0;j < 8;j++){
						if(x >= indx[i][j] && x < indx[i][j] + masuWidth && y >= indy[i][j] && y <= indy[i][j] + masuHeight){
							if(kyokumen.masuPlaceCheck(i,j,kyokumen.getTurn())){
								for(int k = 0;k < 9;k++){
									if(k != 4){
										int [] check = kyokumen.placeAbleCheck(i,j,k / 3 - 1,k % 3 - 1,kyokumen.getTurn());
										if(check[0] == 1){
											kyokumen.henkan(i * 10 + j,check[1],k / 3 - 1,k % 3 - 1,kyokumen.getTurn());
										}
									}
								}
								kyokumen.placeSyori(i,j);
								au1.play();
								kyokumen.othersidesetTurn();
								pass = false;
								compCheck();
								repaint();
							}else{
								
							}
						}
					}
				}
			}
		}
		if(x >= 317 && x < 372 && y >= 240 && y < 270){
			stop();
			init();
			start = true;
			tactics[0] = tactics[1] = null;
			for(int i = 0;i < 2; i++){
				if(pl[i] != 0){
					if(pl[i] == 1){
						tactics[i] = new RandomTactics(this);
					}else{
						if(pl[i] == 2){
							tactics[i] = new MostTactics(this);
						}else{
							tactics[i] = new Two_Thinking_Tactics();
						}
					}
				}
			}
			compCheck();
			repaint();
		}
		if(start){
			if(x >= 317 && x < 372 && y >= 290 && y < 320){
				if(kyokumen.noPlaceCheck(kyokumen.getTurn())){
					pass = true;
					kyokumen.othersidesetTurn();
					repaint();
					compCheck();
				}
			}
		}
		if(!start){
			for(int i = 0; i < 2;i++){
				if(x >= 308 && x < 324 && y >= (105 + i * 90) && y < (121 + i * 90)){
					player_henka[i] = true;
					repaint();
				}
			}
		}
	}
	public boolean gameEnd(){
		for(int a = 1; a < 3;a++){
			if(!kyokumen.noPlaceCheck(a)){
				return false;
			}
		}
		return true;
	}
	public void computer(){
		int ct = tactics[kyokumen.getTurn() - 1].where(kyokumen);
		if(ct == -1){
			pass = true;
			kyokumen.othersidesetTurn();
			repaint();
			compCheck();
			return;
		}
		int i = ct / 10;
		int j = ct % 10;
		for(int k = 0;k < 9;k++){
			if(k != 4){
				int [] check = kyokumen.placeAbleCheck(i,j,k / 3 - 1,k % 3 - 1,kyokumen.getTurn());
				if(check[0] == 1){
					kyokumen.henkan(i * 10 + j,check[1],k / 3 - 1,k % 3 - 1,kyokumen.getTurn());
				}
			}
		}
		kyokumen.placeSyori(i,j);
		au1.play();
		kyokumen.othersidesetTurn();
		pass = false;
		if(!gameEnd()){
			compCheck();
		}
		repaint();
	}
	public void compCheck(){
		if(pl[kyokumen.getTurn() - 1] != 0){
			ComputerThinking ct = new ComputerThinking(this);
			thread2 = new Thread(ct);
			thread2.start();
		}
	}
	public void start(){
		if(thread == null){
			thread = new Thread(this);
			thread.start();
		}
	}
	public void stop(){
		if(thread != null){
			thread.stop();
			thread = null;
		}
		if(thread2 != null){
			thread2.stop();
			thread2 = null;
		}
	}
	public void run(){
		try{
			mt.waitForID(0);
		}
		catch(InterruptedException e){
			return;
		}
		repaint();
	}
}