
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

public class soldier extends unit implements Runnable {

	Thread soldierThread = null;

	boolean auto;	// trueなら自己判断して行動する。
	soldier target;	// 攻撃目標。

	int direction;	//0なら上。1なら右。2なら下。3なら左。
	boolean walking;	//前に進む(true)？、それとも、止まる(false)？

	int Nationality;	// 敵・味方を識別する。味方なら同じ数字。

	int offensivePower;	// 攻撃力
	int defensivePower;	// 防御力

	int presentSpeed;	// 現在速度
	int maxSpeed;		// 最高速度
	int acceleration;	// 加速度

	public soldier(int x, int y, int direction, int Nationality) {
		this.x = x;
		this.y = y;

		this.direction = direction;
		this.Nationality = Nationality;

		walking = true;

		this.target = null;
		this.auto = false;

		init();
	}
	public soldier(int x, int y, int direction, int Nationality, soldier target, boolean auto) {
		this.x = x;
		this.y = y;

		this.direction = direction;
		this.Nationality = Nationality;

		walking = true;

		this.target = target;
		this.auto = auto;

		init();
	}

	public void init() {
		HP = 100;
		offensivePower = 2;
		defensivePower = 2;

		presentSpeed = 0;
		maxSpeed = 2;
		acceleration = 1;
	}

	public void start() {
		if (soldierThread == null)
			soldierThread = new Thread(this);
		soldierThread.start();
	}

	public void run() {
	 while (checkExistence() && 0 < gameBoard.getSpeed() ) {

		moveAndAttack();	//前進して攻撃範囲に敵がいないかチェック。敵がいれば攻撃。

		if (auto)
			selfJudge();	// なにをすればよいか自己判断させる。(具体的にはtargetを求めて進行方向を変更する。)

		// 現在速度に応じてウエイトをおく。
		// ただし現在速度がゼロなら、とりあえず1ということにしてしまう。
		// ちなみに、歩兵ユニットの場合、いまのところ現在速度は0-1の間の値ではあるが。。。
		try
		{
			if (presentSpeed <= 0)
				soldierThread.sleep( gameBoard.getSpeed() / 1);
			else
				soldierThread.sleep( gameBoard.getSpeed() / presentSpeed);
		}
		catch (InterruptedException e)
		{
		}

	 }
	 soldierThread = null;
	}

	public void show(Graphics g, int x, int y, Component view) {
		UGE.show(g, x,y, this, view);
	}

	protected void moveAndAttack() {

		// walkingが否ならば、停止していろということ。
		if (walking) {
			int dest_x = x;
			int dest_y = y;

			switch (direction) {
				case 0 : dest_y--;
					break;
				case 1 : dest_x++;
					break;
				case 2 : dest_y++;
					break;
				case 3 : dest_x--;
			}

			if ( gameBoard.moveUnit(x,y, dest_x,dest_y) ) {
			 // 移動に成功。
				x = dest_x;
				y = dest_y;

				// 現在速度を修正。
				if ( (presentSpeed += acceleration) > maxSpeed)
					presentSpeed = maxSpeed;

				// 攻撃範囲に敵がいるかいないか
				soldier enemy = searchEnemy();
				if (enemy != null)
					attack(enemy);	// いれば攻撃。
			}
			else {
			// 移動に失敗。
				// 攻撃範囲に敵がいるかいないか
				soldier enemy = searchEnemy();
				if (enemy != null)
					attack(enemy);	// いれば攻撃。

				// 現在速度をゼロに。
				presentSpeed = 0;
			}
		} else {
				// 攻撃範囲に敵がいるかいないか
				soldier enemy = searchEnemy();
				if (enemy != null)
					attack(enemy);	// いれば攻撃。

				// 現在速度をゼロに。
				presentSpeed = 0;
		}

	}

	/** 兵士を自己判断するようにしたり、させなかったりするメソッド。 */
	public void setAuto(boolean auto) { this.auto = auto; }
	public boolean getAuto() { return auto; }

	/** 兵士が現在の状況を自分で判断して行動するためのメソッド。 */
	void selfJudge() {
		direction = getDestDirection(target);
	}

	public void setTarget(soldier target) { this.target = target; }
	public soldier getTarget() { return target; }

	/** 引数として与えられた兵士にたいし攻撃する */
	void attack(soldier enemy) {
		enemy.attacked(this, this.getDestDirection(enemy) );	// 敵を攻撃する。
		this.attacked(enemy, enemy.getDestDirection(this) );	// 敵から反撃される。

		// 現在速度を修正。
		if (--presentSpeed < 0)
			presentSpeed = 0;
	}

	/** 攻撃力を算出するルーチン。兵士のもつ「攻撃力」「現在速力」「体力」「方角」によって求める */
	public int getOffensivePower(int attackDirection) {

		int retOffensivePower = offensivePower + (HP>>2);

		if (direction == attackDirection)
			retOffensivePower += (3+presentSpeed);
		else if ( direction == ((attackDirection+1)&3) )
			retOffensivePower += (2+presentSpeed);
		else if ( direction == ((attackDirection-1)&3) )
			retOffensivePower += (1+presentSpeed);

		return retOffensivePower;
	}
	/** 防御力を算出するルーチン。兵士のもつ「防御力」「現在速力」「方角」によって求める */
	public int getDefensivePower(int attackedDirection) {

		int retDefensivePower = defensivePower + presentSpeed + (HP>>3);

		if (direction == attackedDirection) {
			retDefensivePower += presentSpeed;
		} else if ( direction == ((attackedDirection+1)&3) )
			retDefensivePower += (1+presentSpeed);
		else if ( direction == ((attackedDirection-1)&3) )
			retDefensivePower += (2+presentSpeed);
		else
			retDefensivePower += (3+presentSpeed);

		return retDefensivePower;
	}

	/** 自身の攻撃範囲に敵がいるかどうかを判断するルーチン */
	public soldier searchEnemy() {

		soldier enemy = null;
		int dest_x = x;
		int dest_y = y;

		if (direction == 0) {
			dest_y--;
			enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
			if (enemy == null || !checkEnemy(enemy)) {
				dest_x--;
				enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
				if (enemy == null || !checkEnemy(enemy)) {
					dest_x = dest_x+2;
					enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
					if (!checkEnemy(enemy))
						enemy = null;
				}
			}
		} else if (direction == 1) {
			dest_x++;
			enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
			if (enemy == null || !checkEnemy(enemy)) {
				dest_y--;
				enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
				if (enemy == null || !checkEnemy(enemy)) {
					dest_y = dest_y+2;
					enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
					if (!checkEnemy(enemy))
						enemy = null;
				}
			}
		} else if (direction == 2) {
			dest_y++;
			enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
			if (enemy == null || !checkEnemy(enemy)) {
				dest_x++;
				enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
				if (enemy == null || !checkEnemy(enemy)) {
					dest_x = dest_x-2;
					enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
					if (!checkEnemy(enemy))
						enemy = null;
				}
			}
		} else if (direction == 3) {
			dest_x--;
			enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
			if (enemy == null || !checkEnemy(enemy)) {
				dest_y++;
				enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
				if (enemy == null || !checkEnemy(enemy)) {
					dest_y = dest_y-2;
					enemy = (soldier)gameBoard.getUnit(dest_x, dest_y);
					if (!checkEnemy(enemy))
						enemy = null;
				}
			}
		}

		return enemy;
	}


	/** 敵から攻撃されたときに呼び出されるルーチン。 */
	public void attacked(soldier enemy, int attackedDirection) {
				
		// どれくらいのダメージを受けたか。
		int Damage = enemy.getOffensivePower(attackedDirection) - getDefensivePower(attackedDirection);
		// そのダメージがマイナスになったら、0に補整。
		if (0 < Damage)
			HP -= Damage;

	}

	/** 引数として与えられた兵士が敵か味方かを判別する */
	boolean checkEnemy(soldier unIdentificationSoldier) {
		if (unIdentificationSoldier != null) {
			if (this.getNationality() != unIdentificationSoldier.getNationality())
				return true;
			else
				return false;
		}
		else
			return false;
	}

	public int getNationality() {
		return Nationality;
	}

	public boolean getWalking() {
		return walking;
	}
	public void setWalking(boolean walking) {
		this.walking = walking;
	}

	public int getDirection() {
		return direction;
	}
	public void setDirection(int direction) {
		this.direction = direction;
	}

	/** 引数として与えられた兵士が、自分からみてどの方向にいるかを求めるルーチン */
	public int getDestDirection(soldier destSoldier) {
		if (y < destSoldier.getY()) {
		// 相手ユニットは下かも。。。
			if (x < destSoldier.getX())
				if ( (destSoldier.getY()-y) < (destSoldier.getX()-x) )
					return 1; // 相手ユニットは右。
				else
					return 2; // 相手ユニットは下。
			else
				if ( (destSoldier.getY()-y) < (x-destSoldier.getX()) )
					return 3; // 相手ユニットは左。
				else
					return 2; // 相手ユニットは下。

		}
		else {
		// 相手ユニットは上かも。。。
			if (x < destSoldier.getX())
				if ( (y-destSoldier.getY()) < (destSoldier.getX()-x) )
					return 1; // 相手ユニットは右。
				else
					return 0; // 相手ユニットは上。
			else
				if ( (y-destSoldier.getY()) < (x-destSoldier.getX()) )
					return 3; // 相手ユニットは左。
				else
					return 0; // 相手ユニットは上。
		}
	}

}

