long alphaBeta(Board board, long limit, long alpha, long beta) {
    long result;

    //last 1 turn -> evaluate + flip count (not exec board.put)
    if (board.getTurn() == Board.MAX_TURNS - 1) {
      CopyOnWriteArraySet<Disc> movables = board.getMovablePos();
      if (!movables.isEmpty()) {
        Disc disc = (Disc)movables.toArray()[0];
        int[] cf = board.getCountFlip(disc.getPos(), board.getCurrentColor());
        result = cf[0] * 2 + 1 + evaluate(board);
        return result;
      }
    }

    if (limit == 0 || board.isGameOver()) {
      result = evaluate(board);
      return result;
    }

    CopyOnWriteArraySet<Disc> movables = board.getMovablePos();

    if (movables.isEmpty()) {
      board.pass();
      result = -(alphaBeta(board, limit, -(beta), -(alpha)));
      board.undo();
      return result;
    }

    Iterator<Disc> it = movables.iterator();
    while (it.hasNext()) {
      Disc disc = it.next();
      board.autoPut(disc.getPos(), disc.color, disc.flipFlg);
      long eval = -(alphaBeta(board, limit, -(beta), -(alpha)));
      board.undo();
      alpha = Math.max(alpha, eval);
      if (alpha >= beta) { return alpha;}
    }
    return alpha;
  }