package Game;

import java.io.IOException;
import java.util.Random;

import javax.microedition.lcdui.Image;

/**
 * NPC
 * 
 * @author Cynosure7
 * @version 1.5.0
 */
public class NPC extends Role {
	/**
	 * NPC策略
	 */
	private final int ENEMY_RANDOM = 0;
	private final int ENEMY_ATTACK = 1;
	private final int ENEMY_ELIMINATE = 2;
	private int ENEMY_STATE = ENEMY_RANDOM;
	Random random;
	private int dir;

	/**
	 * 寻径算法变量
	 */
	private int[][][] openList;
	private boolean[][] closeList;
	private int openListLength = 0;
	private int closeListLength = 0;
	private int mWidth = Global.COL, mHeight = Global.ROW;
	private boolean canReach;
	int[] selectedNum = { 1, 2, 3, 4 };

	private int step = 0;
	private int stepsPC = 0;

	/**
	 * structure method
	 * 
	 * @param image
	 * @param width
	 * @param Height
	 */

	private NPC(Image image, int width, int Height, Game game) {
		super(image, width, Height, game);
	}

	/**
	 * 静态方法创建NPC对象
	 * 
	 * @param game
	 * @param row
	 * @param col
	 * @return
	 */
	public static NPC createNPC(Game game, int row, int col) {
		NPC npc = null;
		try {
			npc = new NPC(Image.createImage("/Character/John.png"),
					Global.MAP_CELL, Global.JOHN_HEIGHT, game);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		npc.row = row;
		npc.col = col;
		npc.game = game;

		npc.random = new Random();

		npc.status = Global.BORN;
		npc.height = Global.JACK_HEIGHT;
		npc.width = Global.MAP_CELL;
		npc.speed = 5;
		npc.stepsPC = 20 / npc.speed;
		npc.dir = 9;

		npc.power = Global.JACK_POWER;
		npc.power = 3;
		npc.bombNums = 3;

		npc.xCoodinate = Global.MAP_CELL * col;
		npc.yCoodinate = Global.MAP_CELL * (row + 1) - npc.height;
		npc.setPosition(npc.xCoodinate, npc.yCoodinate);
		npc.setFrame(6);
		return npc;
	}

	public void updateRole() {

		if (this.characterClock < 10000) {
			this.characterClock++;
		} else {
			this.characterClock = 100;
		}

		int row = this.getRow();
		int col = this.getCol();

		if (this.isAlive) {
			int tool = this.game.map.getToolLayer().getCell(col, row);
			if (tool > 0) {
				this.pickUptool(tool);
				this.game.map.getToolLayer().setCell(col, row, 0);
			}

			if (this.game.map.hasFeature(row, col, Global.DEADLY)) {
				this.isAlive = false;
				return;
			}

			if (this.status == Global.BORN
					&& this.characterClock > Global.BORN_TIME) {
				this.status = Global.SOUTH;
				this.setFrame(Global.SOUTH * 6);
				this.isCanOperate = true;
			}

			if (this.status == Global.BORN) {
				if (this.characterClock % 2 == 0)
					this.setFrame(Global.BORN * 6 + (this.getFrame() - 1) % 4);
				return;
			}
		} else {
			this.isCanOperate = false;
			if (this.deadTime <= 20) {
				this.deadTime++;
			} else {
				this.setVisible(false);
				return;
			}

			if (this.characterClock % 2 == 0) {
				if (this.getFrame() < Global.DEAD * 6) {
					this.setFrame(Global.DEAD * 6);
				} else {
					if (this.getFrame() < 29) {
						this.setFrame(this.getFrame() + 1);
					} else {
						if (this.characterClock % 4 == 0) {
							this.setFrame(29);
							this.setVisible(true);
						} else {
							this.setVisible(false);
						}
					}
				}
			}
		}
		// this.stepsPC = 20 / this.speed;
		if (step % stepsPC != 0 && dir != 9) {
			walk(dir);
			if (dir != 9)
				this.step++;
			return;
		}

		// this.eliminateAction();
		// this.randomAction();
		// this.attackAction();
		this.decisionMaking();
	}

	public void pickUptool(int tool) {
		if (!this.isAlive || !this.isCanOperate)
			return;
		switch ((tool - 1) / 3) {
		case Global.SHOES_INC:
			if (this.speed < 5) {
				// this.speed++;
			}
			break;
		case Global.SUPER_SHOES:
			// this.speed = 5;
			break;
		case Global.POWER_INC:
			if (this.power < 6)
				this.power++;
			break;
		case Global.BOMB_INC:
			increaseBomb();
			break;
		case Global.SUPER_POWER:
			this.power = 6;
			break;
		case Global.SUPER_BOMB:
			this.bombNums = 9;
			break;
		}
	}

	/**
	 * 获取道具（可达性，安全性）
	 * 
	 * @return
	 */
	private boolean walkToGetTool() {
		for (int i = 1; i < 2; i++) {

			if (this.getRow() + i < Global.ROW
					&& this.getCol() < Global.COL
					&& this.game.map.getToolLayer().getCell(this.getCol(),
							this.getRow() + i) > 0) {
				this.dir = 1;
				walk(dir);
				this.step++;
				return true;
			}

			if (this.getRow() - i >= 0
					&& this.getCol() < Global.COL
					&& this.game.map.getToolLayer().getCell(this.getCol(),
							this.getRow() - i) > 0) {
				this.dir = 0;
				walk(dir);
				this.step++;
				return true;
			}

			if (this.getRow() < Global.ROW
					&& this.getCol() + i < Global.COL
					&& this.game.map.getToolLayer().getCell(this.getCol() + i,
							this.getRow()) > 0) {
				this.dir = 3;
				walk(dir);
				this.step++;
				return true;
			}

			if (this.getRow() < Global.ROW
					&& this.getCol() - i >= 0
					&& this.game.map.getToolLayer().getCell(this.getCol() - i,
							this.getRow()) > 0) {
				this.dir = 2;
				walk(dir);
				this.step++;
				return true;
			}
		}
		return false;
	}

	/**
	 * 获得数据并作出反应
	 */
	private void decisionMaking() {

		checkTarget();

		if (random.nextInt(3) == 1) { // 目标导向
			// this.attackAction();
			// return;
		}

		for (int n = 0; n < 4; n++) {
			int ran = Math.abs(random.nextInt(selectedNum.length));
			int ran2 = 0;
			while (true) {
				ran2 = Math.abs(random.nextInt(selectedNum.length));
				if (ran2 != ran) {
					break;
				}
			}
			int i = selectedNum[ran];
			selectedNum[ran] = selectedNum[ran2];
			selectedNum[ran2] = i;
		}

		switch (ENEMY_STATE) {
		case ENEMY_RANDOM:
			randomAction();
			break;
		case ENEMY_ATTACK:
			attackAction();
			break;
		case ENEMY_ELIMINATE:
			eliminateAction();
			break;
		}

		return;

	}

	/**
	 * 检测目标
	 * 
	 * @param r
	 * @param m
	 */
	private void checkTarget() {
		// if (this.findPath(this.game.hero.getCol(), this.game.hero.getRow(),
		// this.game.map))// 如果可以到达目标则进入进攻模式
		// this.ENEMY_STATE = this.ENEMY_ATTACK;
		// else
		// if (this.setVirtualBomb(0) && this.virtualShunBomb()) {//
		// 如果不在危险区且可以放置炸弹则进入清场模式
		// this.ENEMY_STATE = this.ENEMY_ELIMINATE;
		// this.setVirtualBomb(1);
		// } else
		// this.ENEMY_STATE = this.ENEMY_RANDOM;// 如果不在危险区域且无法放置炸弹，则进入随机模式

		if (!this.eliminateActionTest())
			this.ENEMY_STATE = this.ENEMY_ELIMINATE;
	}

	/**
	 * 攻击动作
	 * 
	 * @param r
	 */
	private void attackAction() {
		if (this.game.player.isAlive) {
			this.findPath(this.game.player.getCol(), this.game.player.getRow(),
					this.game.map);
			walk(dir);
			if (dir != 9)
				this.step++;
		}
	}

	/**
	 * 清场动作
	 */
	private void eliminateAction() {

		if (walkToGetTool())
			return;
		if (this.game.map.hasFeature(this.getRow(), this.getCol(),
				Global.DangerArea)
				|| this.game.map.hasFeature(this.getRow(), this.getCol(),
						Global.EXCDANGERAREA)) {
			// this.randomSelect();
			this.setVirtualBomb(0);
			if (this.virtualRandomShunBomb()
					&& this.characterClock > Global.BORN_TIME
					&& this.bombNums > 0
					&& this.game.map.hasFeature(this.getRow(), this.getCol(),
							Global.MID_DANGER) && random.nextInt(10) == 1) { // 随机数
				this.setBomb(this.getRow(), this.getCol());
				this.setVirtualBomb(1);
			} else {
				this.setVirtualBomb(1);
			}
			if (!this.randomSelect())
				this.randomSelectNMID();
			walk(dir);
			if (dir != 9)
				this.step++;
		} else {
			this.setVirtualBomb(0);
			if (this.virtualRandomShunBomb()
					&& this.characterClock > Global.BORN_TIME
					&& this.bombNums > 0) {
				this.setBomb(this.getRow(), this.getCol());
				walk(dir);
				if (dir != 9)
					this.step++;
				this.setVirtualBomb(1);
			} else {
				this.setVirtualBomb(1);
			}

		}
	}

	/**
	 * 清场模式测试
	 */
	private boolean eliminateActionTest() {
		int temS = this.dir;
		boolean sign = true;
		if (this.game.map.hasFeature(this.getRow(), this.getCol(),
				Global.DangerArea)
				|| this.game.map.hasFeature(this.getRow(), this.getCol(),
						Global.EXCDANGERAREA)) {
			// this.randomSelect();
			sign = false;
		} else {
			this.setVirtualBomb(0);
			if (this.virtualRandomShunBomb()
					&& this.characterClock > Global.BORN_TIME
					&& this.bombNums > 0) {
				this.setVirtualBomb(1);
				sign = false;
			} else {
				this.setVirtualBomb(1);
			}
		}
		dir = temS;
		return sign;
	}

	/**
	 * 放置虚拟炸弹
	 * 
	 * @param setOrClear
	 * @return
	 */
	private boolean setVirtualBomb(int setOrClear) {
		boolean canSet = false;
		int mapCols = Global.COL;
		int mapRows = Global.ROW;
		if (setOrClear == 0) {
			this.game.map.addFeature(this.getRow(), this.getCol(),
					Global.VIRTUAL_DANGERAREA);
		} else {
			this.game.map.removeFeature(this.getRow(), this.getCol(),
					Global.VIRTUAL_DANGERAREA);
		}

		for (int i = 1; i <= this.power; i++) {
			if (this.getCol() + i < mapCols) {
				if (this.game.map.hasFeature(this.getRow(), this.getCol() + i,
						Global.CAN_PASS)) {
					if (setOrClear == 0)
						this.game.map.addFeature(this.getRow(), this.getCol()
								+ i, Global.VIRTUAL_DANGERAREA);
					else
						this.game.map.removeFeature(this.getRow(), this
								.getCol()
								+ i, Global.VIRTUAL_DANGERAREA);
				} else {
					canSet = true;
					break;
				}
			}
		}

		for (int i = 1; i <= this.power; i++) {
			if (this.getCol() - i >= 0) {
				if (this.game.map.hasFeature(this.getRow(), this.getCol() - i,
						Global.CAN_PASS)) {
					if (setOrClear == 0)
						this.game.map.addFeature(this.getRow(), this.getCol()
								- i, Global.VIRTUAL_DANGERAREA);
					else
						this.game.map.removeFeature(this.getRow(), this
								.getCol()
								- i, Global.VIRTUAL_DANGERAREA);
				} else {
					canSet = true;
					break;
				}
			}
		}

		for (int i = 1; i <= this.power; i++) {
			if (this.getRow() - i >= 0) {
				if (this.game.map.hasFeature(this.getRow() - i, this.getCol(),
						Global.CAN_PASS)) {
					if (setOrClear == 0)
						this.game.map.addFeature(this.getRow() - i, this
								.getCol(), Global.VIRTUAL_DANGERAREA);
					else
						this.game.map.removeFeature(this.getRow() - i, this
								.getCol(), Global.VIRTUAL_DANGERAREA);
				} else {
					canSet = true;
					break;
				}
			}
		}

		for (int i = 1; i <= this.power; i++) {
			if (this.getRow() + i < mapRows) {
				if (this.game.map.hasFeature(this.getRow() + i, this.getCol(),
						Global.CAN_PASS)) {
					if (setOrClear == 0)
						this.game.map.addFeature(this.getRow() + i, this
								.getCol(), Global.VIRTUAL_DANGERAREA);
					else
						this.game.map.removeFeature(this.getRow() + i, this
								.getCol(), Global.VIRTUAL_DANGERAREA);
				} else {
					canSet = true;
					break;
				}
			}
		}
		return canSet;
	}

	/**
	 * 随机移动
	 */
	private void randomAction() {

		out: for (int num = 0; num < 4; num++) {

			switch (selectedNum[num]) {
			case 1:
				if (randomS1())
					break out;
			case 2:
				if (randomS2())
					break out;
			case 3:
				if (randomS3())
					break out;
			case 4:
				if (randomS4())
					break out;
			}

		}

	}

	public boolean randomS1() {
		if (this.getRow() + 1 < Global.ROW
				&& this.getCol() < Global.COL
				&& (this.game.map.hasFeature(this.getRow() + 1, this.getCol(),
						Global.CAN_PASS))) {
			this.dir = 1;
			walk(dir);
			this.step++;
			return true;
		}
		return false;
	}

	public boolean randomS2() {
		if (this.getRow() - 1 >= 0
				&& this.getCol() < Global.COL
				&& (this.game.map.hasFeature(this.getRow() - 1, this.getCol(),
						Global.CAN_PASS))) {
			this.dir = 0;
			walk(dir);
			this.step++;
			return true;
		}
		return false;
	}

	public boolean randomS3() {
		if (this.getRow() < Global.ROW
				&& this.getCol() + 1 < Global.COL
				&& (this.game.map.hasFeature(this.getRow(), this.getCol() + 1,
						Global.CAN_PASS))) {
			this.dir = 3;
			walk(dir);
			this.step++;
			return true;
		}
		return false;
	}

	public boolean randomS4() {
		if (this.getRow() < Global.ROW
				&& this.getCol() - 1 >= 0
				&& (this.game.map.hasFeature(this.getRow(), this.getCol() - 1,
						Global.CAN_PASS))) {
			this.dir = 2;
			walk(dir);
			this.step++;
			return true;
		}
		return false;
	}

	/**
	 * 随机虚拟躲避
	 * 
	 * @return
	 */
	private boolean virtualRandomShunBomb() {
		boolean result = false;
		int testRow = this.getRow();
		int testCol = this.getCol();

		out: for (int i = 1; i < 6; i++) {
			for (int num = 0; num < 4; num++) {

				switch (selectedNum[num]) {
				case 1:
					if (virtualShun1(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 2:
					if (virtualShun2(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 3:
					if (virtualShun3(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 4:
					if (virtualShun4(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				}

			}
		}
		return result;
	}

	private boolean virtualShun1(int testRow, int testCol, int i) {
		for (int n = 0; n <= i; n++) {
			if (-1 < testRow - n
					&& -1 < testCol - (i - n)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.VIRTUAL_DANGERAREA)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - n, testCol - (i - n),
							Global.CAN_PASS)
					&& findPath(testCol - (i - n), testRow - n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean virtualShun2(int testRow, int testCol, int i) {
		for (int n = 0; n <= i; n++) {
			if (Global.ROW > testRow + n
					&& Global.COL > testCol + (i - n)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.VIRTUAL_DANGERAREA)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + n, testCol + (i - n),
							Global.CAN_PASS)
					&& findPath(testCol + (i - n), testRow + n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean virtualShun3(int testRow, int testCol, int i) {
		for (int m = 0; m <= i; m++) {
			if (Global.ROW > testRow + m
					&& -1 < testCol - (i - m)
					&& !this.game.map.hasFeature(testRow + m,
							testCol - (i - m), Global.VIRTUAL_DANGERAREA)
					&& !this.game.map.hasFeature(testRow + m,
							testCol - (i - m), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow + m,
							testCol - (i - m), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + m, testCol - (i - m),
							Global.CAN_PASS)
					&& findPath(testCol - (i - m), testRow + m, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean virtualShun4(int testRow, int testCol, int i) {
		for (int m = 0; m <= i; m++) {
			if (-1 < testRow - m
					&& Global.COL > testCol + (i - m)
					&& !this.game.map.hasFeature(testRow - m,
							testCol + (i - m), Global.VIRTUAL_DANGERAREA)
					&& !this.game.map.hasFeature(testRow - m,
							testCol + (i - m), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow - m,
							testCol + (i - m), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - m, testCol + (i - m),
							Global.CAN_PASS)
					&& findPath(testCol + (i - m), testRow - m, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 随机选取安全区域
	 * 
	 * @return
	 */
	private boolean randomSelect() {
		boolean result = false;
		int testRow = this.getRow();
		int testCol = this.getCol();

		out: for (int i = 1; i < 6; i++) {
			for (int num = 0; num < 4; num++) {

				switch (selectedNum[num]) {
				case 1:
					if (search1(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 2:
					if (search2(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 3:
					if (search3(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 4:
					if (search4(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				}

			}
		}
		return result;
	}

	private boolean search1(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (-1 < testRow - n
					&& -1 < testCol - (i - n)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - n, testCol - (i - n),
							Global.CAN_PASS)
					&& findPath(testCol - (i - n), testRow - n, this.game.map)) {
				return true;
			}
		}
		return false;

	}

	private boolean search2(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (Global.ROW > testRow + n
					&& Global.COL > testCol + (i - n)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + n, testCol + (i - n),
							Global.CAN_PASS)
					&& findPath(testCol + (i - n), testRow + n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean search3(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (Global.ROW > testRow + n
					&& -1 < testCol - (i - n)
					&& !this.game.map.hasFeature(testRow + n,
							testCol - (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow + n,
							testCol - (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + n, testCol - (i - n),
							Global.CAN_PASS)
					&& findPath(testCol - (i - n), testRow + n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean search4(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (-1 < testRow - n
					&& Global.COL > testCol + (i - n)
					&& !this.game.map.hasFeature(testRow - n,
							testCol + (i - n), Global.DangerArea)
					&& !this.game.map.hasFeature(testRow - n,
							testCol + (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - n, testCol + (i - n),
							Global.CAN_PASS)
					&& findPath(testCol + (i - n), testRow - n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 随机选取中等危险区域
	 * 
	 * @return
	 */
	private boolean randomSelectNMID() {
		boolean result = false;
		int testRow = this.getRow();
		int testCol = this.getCol();

		out: for (int i = 1; i < 6; i++) {
			for (int num = 0; num < 4; num++) {

				switch (selectedNum[num]) {
				case 1:
					if (searchM1(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 2:
					if (searchM2(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 3:
					if (searchM3(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				case 4:
					if (searchM4(testRow, testCol, i)) {
						result = true;
						break out;
					} else
						break;
				}

			}
		}
		return result;
	}

	private boolean searchM1(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (-1 < testRow - n
					&& -1 < testCol - (i - n)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.MID_DANGER)
					&& !this.game.map.hasFeature(testRow - n,
							testCol - (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - n, testCol - (i - n),
							Global.CAN_PASS)
					&& findPath(testCol - (i - n), testRow - n, this.game.map)) {
				return true;
			}
		}
		return false;

	}

	private boolean searchM2(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (Global.ROW > testRow + n
					&& Global.COL > testCol + (i - n)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.MID_DANGER)
					&& !this.game.map.hasFeature(testRow + n,
							testCol + (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + n, testCol + (i - n),
							Global.CAN_PASS)
					&& findPath(testCol + (i - n), testRow + n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean searchM3(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (Global.ROW > testRow + n
					&& -1 < testCol - (i - n)
					&& !this.game.map.hasFeature(testRow + n,
							testCol - (i - n), Global.MID_DANGER)
					&& !this.game.map.hasFeature(testRow + n,
							testCol - (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow + n, testCol - (i - n),
							Global.CAN_PASS)
					&& findPath(testCol - (i - n), testRow + n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	private boolean searchM4(int testRow, int testCol, int i) {

		for (int n = 0; n <= i; n++) {
			if (-1 < testRow - n
					&& Global.COL > testCol + (i - n)
					&& !this.game.map.hasFeature(testRow - n,
							testCol + (i - n), Global.MID_DANGER)
					&& !this.game.map.hasFeature(testRow - n,
							testCol + (i - n), Global.EXCDANGERAREA)
					&& this.game.map.hasFeature(testRow - n, testCol + (i - n),
							Global.CAN_PASS)
					&& findPath(testCol + (i - n), testRow - n, this.game.map)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 寻找路径
	 * 
	 * @param m
	 * @param tx
	 *            = r.getCol();
	 * @param ty
	 *            = r.getRow();
	 */
	private boolean findPath(int tx, int ty, Map m) {
		this.canReach = false;
		int by = this.getRow();
		int bx = this.getCol();
		closeList = null;
		openList = null;
		closeList = new boolean[mHeight][mWidth];
		openList = new int[mHeight][mWidth][5];
		closeListLength = 0;
		openListLength = 0;
		dir = 9;
		for (int i = 0; i < mHeight; i++) {
			for (int j = 0; j < mWidth; j++) {
				openList[i][j][0] = 0;
				if ((m.mapArray[0][i][j] & 1) != 0) {
					openList[i][j][1] = 1;
				} else {
					openList[i][j][1] = 9;
				}
				openList[i][j][2] = Math.abs(i - ty) + Math.abs(j - tx);
				openList[i][j][3] = openList[i][j][1] + openList[i][j][2];
				openList[i][j][4] = 0;
			}
		}

		addInOpenList(bx, by);

		if (!isBalk(bx + 1, by, m)) {
			addInOpenList(bx + 1, by);
			setFather(bx + 1, by, 3);
			getGHF(bx + 1, by, tx, ty, m);
		}

		if (!isBalk(bx - 1, by, m)) {
			addInOpenList(bx - 1, by);
			setFather(bx - 1, by, 4);
			getGHF(bx - 1, by, tx, ty, m);
		}

		if (!isBalk(bx, by + 1, m)) {
			addInOpenList(bx, by + 1);
			setFather(bx, by + 1, 1);
			getGHF(bx, by + 1, tx, ty, m);
		}

		if (!isBalk(bx, by - 1, m)) {
			addInOpenList(bx, by - 1);
			setFather(bx, by - 1, 2);
			getGHF(bx, by - 1, tx, ty, m);
		}

		removeFromOpenList(bx, by);
		addInCloseList(bx, by);

		int ttx = bx, tty = by, minf = 255;
		for (int i = 0; i < mHeight; i++) {
			for (int j = 0; j < mWidth; j++) {
				if (openList[i][j][0] == 1) {
					if (minf > openList[i][j][3]) {
						minf = openList[i][j][3];
						ttx = j;
						tty = i;
					}
				}
			}
		}

		AAsterisk_t(ttx, tty, tx, ty, m);
		walkFromTo(this.getCol(), this.getRow(), tx, ty, openList, closeList);
		return this.canReach;
	}

	private void AAsterisk_t(int ttx, int tty, int tx, int ty, Map m) {

		if ((ttx == tx && tty == ty) || openListLength == 0)
			return;

		removeFromOpenList(ttx, tty);
		addInCloseList(ttx, tty);

		if (!isBalk(ttx + 1, tty, m)) {
			if (openList[tty][ttx + 1][0] == 0) {
				addInOpenList(ttx + 1, tty);
				setFather(ttx + 1, tty, 3);
				getGHF(ttx + 1, tty, tx, ty, m);
			} else

			if (openList[tty][ttx + 1][0] == 1) {
				if ((m.mapArray[0][tty][ttx + 1] & 1) != 0) {
					if (openList[tty][ttx][1] + 1 < openList[tty][ttx + 1][1]) {
						setFather(ttx + 1, tty, 3);
						getGHF(ttx + 1, tty, tx, ty, m);
					}
				} else {
					if (openList[tty][ttx][1] + 9 < openList[tty][ttx + 1][1]) {
						setFather(ttx + 1, tty, 3);
						getGHF(ttx + 1, tty, tx, ty, m);
					}
				}
			}
		}

		if (!isBalk(ttx - 1, tty, m)) {
			if (openList[tty][ttx - 1][0] == 0) {
				addInOpenList(ttx - 1, tty);
				setFather(ttx - 1, tty, 4);
				getGHF(ttx - 1, tty, tx, ty, m);
			} else

			if (openList[tty][ttx - 1][0] == 1) {
				if ((m.mapArray[0][tty][ttx - 1] & 1) != 0) {
					if (openList[tty][ttx][1] + 1 < openList[tty][ttx - 1][1]) {
						setFather(ttx - 1, tty, 4);
						getGHF(ttx - 1, tty, tx, ty, m);
					}
				} else {
					if (openList[tty][ttx][1] + 9 < openList[tty][ttx - 1][1]) {
						setFather(ttx - 1, tty, 4);
						getGHF(ttx - 1, tty, tx, ty, m);
					}
				}
			}
		}

		if (!isBalk(ttx, tty + 1, m)) {
			if (openList[tty + 1][ttx][0] == 0) {
				addInOpenList(ttx, tty + 1);
				setFather(ttx, tty + 1, 1);
				getGHF(ttx, tty + 1, tx, ty, m);
			} else

			if (openList[tty + 1][ttx][0] == 1) {
				if ((m.mapArray[0][tty + 1][ttx] & 1) != 0) {
					if (openList[tty][ttx][1] + 1 < openList[tty + 1][ttx][1]) {
						setFather(ttx, tty + 1, 1);
						getGHF(ttx, tty + 1, tx, ty, m);
					}
				} else {
					if (openList[tty][ttx][1] + 9 < openList[tty + 1][ttx][1]) {
						setFather(ttx, tty + 1, 1);
						getGHF(ttx, tty + 1, tx, ty, m);
					}
				}
			}
		}

		if (!isBalk(ttx, tty - 1, m)) {
			if (openList[tty - 1][ttx][0] == 0) {
				addInOpenList(ttx, tty - 1);
				setFather(ttx, tty - 1, 2);
				getGHF(ttx, tty - 1, tx, ty, m);
			} else

			if (openList[tty - 1][ttx][0] == 1) {
				if ((m.mapArray[0][tty - 1][ttx] & 1) != 0) {
					if (openList[tty][ttx][1] + 1 < openList[tty - 1][ttx][1]) {
						setFather(ttx, tty - 1, 2);
						getGHF(ttx, tty - 1, tx, ty, m);
					}
				} else {
					if (openList[tty][ttx][1] + 9 < openList[tty - 1][ttx][1]) {
						setFather(ttx, tty - 1, 2);
						getGHF(ttx, tty - 1, tx, ty, m);
					}
				}
			}

		}

		int bx = ttx, by = tty, minf = 255;
		for (int i = 0; i < mHeight; i++) {
			for (int j = 0; j < mWidth; j++) {
				if (openList[i][j][0] == 1) {
					if (minf > openList[i][j][3]) {
						minf = openList[i][j][3];
						bx = j;
						by = i;
					}
				}
			}
		}

		AAsterisk_t(bx, by, tx, ty, m);
	}

	private void addInOpenList(int x, int y) {
		openList[y][x][0] = 1;
		openListLength++;
	}

	private void removeFromOpenList(int x, int y) {
		openList[y][x][0] = 0;
		openListLength--;
	}

	private void getGHF(int x, int y, int tx, int ty, Map m) {
		openList[y][x][1] = getG(x, y, m);
		openList[y][x][2] = getH(x, y, tx, ty);
		openList[y][x][3] = openList[y][x][1] + openList[y][x][3];
	}

	private int getG(int x, int y, Map m) {
		switch (openList[y][x][4]) {
		default:
			if ((m.mapArray[0][y][x] & 1) != 0) {
				return 1;
			} else
				return 9;
		case 1:
			if ((m.mapArray[0][y][x] & 1) != 0)
				return openList[y - 1][x][1] + 1;
			else
				return openList[y - 1][x][1] + 9;
		case 2:
			if ((m.mapArray[0][y][x] & 1) != 0)
				return openList[y + 1][x][1] + 1;
			else
				return openList[y + 1][x][1] + 9;
		case 3:
			if ((m.mapArray[0][y][x] & 1) != 0)
				return openList[y][x - 1][1] + 1;
			else
				return openList[y][x - 1][1] + 9;
		case 4:
			if ((m.mapArray[0][y][x] & 1) != 0)
				return openList[y][x + 1][1] + 1;
			else
				return openList[y][x + 1][1] + 9;
		}
	}

	private int getH(int x, int y, int tx, int ty) {
		return Math.abs(x - tx) + Math.abs(y - ty);
	}

	private boolean isBalk(int x, int y, Map m) {
		if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) {
			return true;
		}
		if (closeList[y][x])
			return true;
		if ((m.mapArray[0][y][x] & 1) == 0
				// || this.game.map.hasFeature(y, x, Global.DangerArea)
				|| this.game.map.hasFeature(y, x, Global.EXCDANGERAREA)
				|| this.game.map.hasFeature(y, x, Global.DEADLY)
		// || this.game.map.hasFeature(y, x, Global.VIRTUAL_DANGERAREA)) {//
		// 可能要加入危险区域
		) {
			return true;
		}
		return false;
	}

	private void setFather(int x, int y, int f) {
		openList[y][x][4] = f;
	}

	private void addInCloseList(int x, int y) {
		closeList[y][x] = true;
		closeListLength++;
	}

	private void walkFromTo(int begin_x, int begin_y, int x, int y,
			int[][][] openList, boolean[][] closeList) {

		if ((x == begin_x && y == begin_y)) {
			this.canReach = true;
			return;
		}

		switch (openList[y][x][4]) {
		case 1:
			walkFromTo(begin_x, begin_y, x, y - 1, openList, closeList);
			addInDir(Global.SOUTH);
			break;
		case 2:
			walkFromTo(begin_x, begin_y, x, y + 1, openList, closeList);
			addInDir(Global.NORTH);
			break;
		case 3:
			walkFromTo(begin_x, begin_y, x - 1, y, openList, closeList);
			addInDir(Global.EAST);
			break;
		case 4:
			walkFromTo(begin_x, begin_y, x + 1, y, openList, closeList);
			addInDir(Global.WEST);
			break;
		default: {
			this.canReach = false;
			break;
		}
		}
	}

	private void addInDir(int dira) {
		if (dir == 9) {
			dir = dira;
		}

	}

	public void collisionCheck(int direction) {
		switch (direction) {
		case Global.NORTH:

			this.yCoodinate -= speed;

			break;
		case Global.SOUTH:

			this.yCoodinate += speed;

			break;
		case Global.WEST:

			this.xCoodinate -= speed;

			break;
		case Global.EAST:

			this.xCoodinate += speed;

		}

	}

	public void pickupTool(int tool) {
		if (!this.isAlive || !this.isCanOperate)
			return;
		switch ((tool - 1) / 3) {
		case Global.SHOES_INC:
			if (this.speed < 5) {
				// this.speed++;
			}
			break;
		case Global.SUPER_SHOES:
			// this.speed = 5;
			break;
		case Global.POWER_INC:
			if (this.power < 6)
				this.power++;
			break;
		case Global.BOMB_INC:
			increaseBomb();
			break;
		case Global.SUPER_POWER:
			this.power = 6;
			break;
		case Global.SUPER_BOMB:
			this.bombNums = 9;
			break;
		}

	}

	public void setBomb(int row, int col) {
		if (!this.isAlive || !this.isCanOperate || this.bombNums == 0
				|| this.game.map.hasFeature(row, col, Global.BOMB))
			return;
		String key = row * 10 + "" + col;
		this.game.bombTable.put(key, new SingleGameBomb(this.game,this));		
		this.game.map.removeFeature(row, col, Global.CAN_PASS);
		this.game.map.addFeature(row, col, Global.BOMB);
		this.bombNums--;
	}

}
