public void plantTrees() {
   ArrayList<Position> treeList = new ArrayList<Position>();
   for (int x = 0; x < m_width; x++) {
     for (int y = 0; y < m_height; y++) {
       boolean tooClose = false;
       for (Position p : treeList) {
         double distance = Math.sqrt(Math.pow(p.getX() - x, 2) + Math.pow(p.getY() - y, 2));
         if (distance < 30) tooClose = true;
       }
       if (!tooClose) {
         if (m_random.nextInt(100) <= 5) {
           for (int z = m_depth - 1; z > 0; z--) {
             if ((m_blocks[x][y][z] == BlockConstants.DIRT
                     || m_blocks[x][y][z] == BlockConstants.GRASS)
                 && m_blocks[x][y][z + 1] == BlockConstants.AIR) {
               plantTree(x, y, z);
               treeList.add(new Position(x, y, z));
               break;
             } else if (z < m_depth - 1 && m_blocks[x][y][z + 1] != BlockConstants.AIR) {
               break;
             }
           }
         }
       }
     }
   }
 }
  private void carveLake(int x, int y, ArrayList<Position> visited, int distance, int depth) {
    if (distance == 0) return;
    if (x < 0 || y < 0 || x >= m_width || y >= m_height) return;
    if (depth <= 0) return;
    Position cur = new Position(x, y, 0);
    for (Position p : visited) if (p.equals(cur)) return;
    visited.add(cur);

    int delta = m_random.nextInt(depth);

    carveLake(x + 1, y, visited, distance - 1, delta);
    carveLake(x - 1, y, visited, distance - 1, delta);
    carveLake(x, y + 1, visited, distance - 1, delta);
    carveLake(x, y - 1, visited, distance - 1, delta);
    sculptHill(x, y, -depth, distance);
  }
 public void raiseTerrain() {
   boolean[][] prevContour = new boolean[m_width][m_height];
   boolean[][] curContour = new boolean[m_width][m_height];
   for (int x = 0; x < m_width; x++) {
     for (int y = 0; y < m_height; y++) {
       curContour[x][y] = (m_random.nextInt(100) <= 48);
     }
   }
   for (int count = 0; count < 4; count++) {
     System.arraycopy(curContour, 0, prevContour, 0, curContour.length);
     for (int x = 0; x < m_width; x++) {
       for (int y = 0; y < m_width; y++) {
         curContour[x][y] = simulateCell(prevContour, x, y);
       }
     }
   }
   int x = 0;
   int y = 0;
   boolean[][] visited = new boolean[m_width][m_height];
   while (y < m_height) {
     LinkedList<Position> path = new LinkedList<Position>();
     if (curContour[x][y]) {
       Position pos = new Position(x, y, 0);
       path.offer(pos);
     } else {
       m_contour[x][y] = -3;
     }
     int height = m_random.nextInt(6);
     PATH:
     while (path.size() > 0) {
       Position cur = path.remove();
       if (visited[cur.getX()][cur.getY()]) continue PATH;
       if (!curContour[cur.getX()][cur.getY()]) continue PATH;
       visited[cur.getX()][cur.getY()] = true;
       m_contour[cur.getX()][cur.getY()] = height;
       if (cur.getX() > 0 && cur.getX() < m_width - 1) {
         path.offer(new Position(cur.getX() - 1, cur.getY(), 0));
         path.offer(new Position(cur.getX() + 1, cur.getY(), 0));
       }
       if (cur.getY() > 0 && cur.getY() < m_width - 1) {
         path.offer(new Position(cur.getX(), cur.getY() - 1, 0));
         path.offer(new Position(cur.getX(), cur.getY() + 1, 0));
       }
     }
     x++;
     if (x == m_height) {
       x = 0;
       y++;
     }
   }
   for (x = 0; x < m_width; x++) {
     for (y = 0; y < m_height; y++) {
       if (curContour[x][y]) averageArea(x, y, 2);
     }
   }
 }