public GameMove getMove(GameState state, String lastMove) {
    DomineeringState board = (DomineeringState) state;
    homeSym = board.homeSym;
    awaySym = board.awaySym;
    emptySym = board.emptySym;
    isHome = state.who == GameState.Who.HOME; // HOME: true, AWAY: false

    if (isHome) {
      MAX_DEPTH = 6;
      if (board.numMoves >= 6) MAX_DEPTH = 8;
      if (board.numMoves >= 12) MAX_DEPTH = 10;
      if (board.numMoves >= 14) MAX_DEPTH = 12;
    } else {
      MAX_DEPTH = 7;
      if (board.numMoves >= 6) MAX_DEPTH = 9;
      if (board.numMoves >= 12) MAX_DEPTH = 11;
      if (board.numMoves >= 14) MAX_DEPTH = 13;
    }

    Move[] stack = new Move[MAX_DEPTH + 1];
    init(stack);

    if (isHome == true) {
      if (board.numMoves == 0) {
        Move[] temp = new Move[4];
        temp[0] = new Move(1, 2, 1, 3);
        temp[1] = new Move(1, 4, 1, 5);
        temp[2] = new Move(6, 2, 6, 3);
        temp[3] = new Move(6, 4, 6, 5);
        Random rnd = new Random();
        return temp[rnd.nextInt(4)];
      } else if (board.numMoves == 2) {
        Map map = new HashMap();
        Scanner sc;
        try {
          sc = new Scanner(new File("home3.txt"));
          while (sc.hasNextLine()) {
            String s = sc.nextLine();
            String[] sp = s.split("\\s+");
            long key = Long.parseLong(sp[0]);
            Move value =
                new Move(
                    Integer.parseInt(sp[1]),
                    Integer.parseInt(sp[2]),
                    Integer.parseInt(sp[3]),
                    Integer.parseInt(sp[4]));
            map.put(key, value);
          }
          long hash = new Board(board.board, isHome, "alphabetatt").getHashKey();
          Move rtn = (Move) map.get(hash);
          if (rtn != null) return rtn;
        } catch (FileNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    } else {
      if (board.numMoves == 1) {
        Map map = new HashMap();
        Scanner sc;
        try {
          sc = new Scanner(new File("away2.txt"));
          while (sc.hasNextLine()) {
            String s = sc.nextLine();
            String[] sp = s.split("\\s+");
            long key = Long.parseLong(sp[0]);
            Move value =
                new Move(
                    Integer.parseInt(sp[1]),
                    Integer.parseInt(sp[2]),
                    Integer.parseInt(sp[3]),
                    Integer.parseInt(sp[4]));
            map.put(key, value);
          }
          long hash = new Board(board.board, isHome, "alphabetatt").getHashKey();
          Move rtn = (Move) map.get(hash);
          if (rtn != null) return rtn;
        } catch (FileNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }

    long start = System.currentTimeMillis();
    alphabetaTT(board.board, 0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, isHome, stack);
    long end = System.currentTimeMillis();

    total += (end - start);
    System.out.printf(
        "%s %3d Time: %-4d Total:%d\n", stack[0], (int) stack[0].score, (end - start), total);
    tt.print();

    System.out.println("Move: " + board.numMoves);

    return stack[0];
  }
  public void alphabetaTT(char[][] map, int d, double a, double b, boolean isHome, Move[] stack) {
    double ev_tem = 0;
    ev_tem = ev2(map, isHome);
    if (d == MAX_DEPTH || Math.abs(ev_tem) == MAX_SCORE) {
      stack[d].score = ev_tem;
      return;
    }
    Board board = new Board(map, isHome, "alphabetatt");
    TTEntry tte = tt.getEntry(board.getHashKey());
    if (tte != null && tte.getDepth() <= d) {
      if (tte.getType() == TTEntry.NT.EXACT) {
        stack[d].score = tte.getScore();
        return;
      }
      if (tte.getType() == TTEntry.NT.LOWERBOUND && tte.getScore() > a) a = tte.getScore();
      else if (tte.getType() == TTEntry.NT.UPPERBOUNT && tte.getScore() < b) b = tte.getScore();
      if (a >= b) {
        stack[d].score = tte.getScore();
        return;
      }
    }

    if (board.getSize() == 0) System.out.println(isHome + "\t" + d);
    Move move;
    if (isHome) {
      double v = Double.NEGATIVE_INFINITY;
      while (board.hasNext()) {
        if (FIRST_LAYER_DEBUG == 1 && d == 0)
          System.out.println("Home: 0 Total: " + board.getSize());
        move = board.next();
        map[move.row1][move.col1] = homeSym;
        map[move.row2][move.col2] = homeSym;
        if (d + 1 == MAX_DEPTH) {
          stack[d + 1].set(move.row1, move.col1, move.row2, move.col2);
        }
        alphabetaTT(map, d + 1, a, b, false, stack);
        if (stack[d + 1].score > v) {
          v = stack[d + 1].score;
          stack[d].set(move.row1, move.col1, move.row2, move.col2, v);
        }
        map[move.row1][move.col1] = emptySym;
        map[move.row2][move.col2] = emptySym;
        a = Math.max(a, stack[d].score);

        if (stack[d].score >= b || stack[d].score == MAX_SCORE) return;
      }
      if (stack[d].score < a)
        tt.store(new TTEntry(board.getHashKey(), stack[d].score, TTEntry.NT.LOWERBOUND, d));
      else if (stack[d].score > b)
        tt.store(new TTEntry(board.getHashKey(), stack[d].score, TTEntry.NT.UPPERBOUNT, d));

      return;
    } else {
      double v = Double.POSITIVE_INFINITY;
      while (board.hasNext()) {
        if (FIRST_LAYER_DEBUG == 1 && d == 0)
          System.out.println("Away: 0 Total: " + board.getSize());
        move = board.next();
        map[move.row1][move.col1] = awaySym;
        map[move.row2][move.col2] = awaySym;
        if (d + 1 == MAX_DEPTH) {
          stack[d + 1].set(move.row1, move.col1, move.row2, move.col2);
        }
        alphabetaTT(map, d + 1, a, b, true, stack);
        if (stack[d + 1].score < v) {
          v = stack[d + 1].score;
          stack[d].set(move.row1, move.col1, move.row2, move.col2, v);
        }
        map[move.row1][move.col1] = emptySym;
        map[move.row2][move.col2] = emptySym;
        b = Math.min(b, stack[d].score);

        if (stack[d].score <= a || stack[d].score == -MAX_SCORE) return;
      }
      if (stack[d].score < a)
        tt.store(new TTEntry(board.getHashKey(), stack[d].score, TTEntry.NT.LOWERBOUND, d));
      else if (stack[d].score > b)
        tt.store(new TTEntry(board.getHashKey(), stack[d].score, TTEntry.NT.UPPERBOUNT, d));
      return;
    }
  }