@Override protected boolean sprout() { boolean endRiver = child != null; if (garden.isWater(location.x, location.y)) { // There is already water here; end the river here // TODO: grow lake? endRiver = true; } if (parent != null) { drawLine( parent.location, location, (int) Math.round(Math.sqrt(crossSectionalArea)), false, category); } if (endRiver) { return (parent != null); } // Find coordinates of lowest point on a surrounding circle // Midpoint circle ("Bresenham's") algorithm final boolean[] lowerPointFound = new boolean[1]; final int[] lowestHeightCoords = new int[2]; int radius = 0; for (int r = 3; (!lowerPointFound[0]) && (r <= 9); r += 2) { radius = r; final float[] lowestHeight = {garden.getHeight(location.x, location.y)}; GeometryUtil.visitCircle( r, new GeometryVisitor() { @Override public boolean visit(int dx, int dy, float d) { float height = garden.getHeight(location.x + dx, location.y + dy); if (height < lowestHeight[0]) { lowestHeight[0] = height; lowestHeightCoords[0] = location.x + dx; lowestHeightCoords[1] = location.y + dy; lowerPointFound[0] = true; } return true; } }); } if (lowerPointFound[0]) { // Find existing nodes to connect with (not belonging to the same // river) List<RiverNode> nearbyNodes = garden.findSeeds(RiverNode.class, lowestHeightCoords[0], lowestHeightCoords[1], radius); int ownNodesEncountered = 0; for (RiverNode riverNode : nearbyNodes) { if (riverNode.getOrigin() == getOrigin()) { // Another node of same river ownNodesEncountered++; if (ownNodesEncountered < 2) { continue; } else { // We seem to be circing the drain. Abort! Abort! return true; } } if (riverNode.child != null) { garden.plantSeed(new RiverNode(garden, this, riverNode.location, riverNode.child)); addCrossSectionalArea(riverNode.child, crossSectionalArea); } else { garden.plantSeed(new RiverNode(garden, this, riverNode.location)); } return true; } garden.plantSeed( new RiverNode( garden, this, new Point3i(lowestHeightCoords[0], lowestHeightCoords[1], -1))); return true; } else { // No lower point around; end the river here // TODO: start a lake? return (parent != null); } }