Stage 8 inherits everything from Stage 7
— the same recursive island growth, the same SWIsland and
Coordinates classes, the same controls. It adds one new feature:
after all islands are placed you can press
🌊 Apply Fractal Coastline to redraw them with
organic, realistic borders instead of blocky grid edges.
The coastline paradox (Benoit Mandelbrot, 1967):
“How long is the coast of Britain?”
Answer: it depends on your ruler length. A finer ruler
catches more inlets and peninsulas, giving a longer measurement.
Real coastlines are fractal — they look
equally jagged no matter how much you zoom in.
Two phases inside SWFractalIsland.js
- Build a
Set of island cell keys for O(1) lookup.
- For each cell, identify which of its 4 edges faces a non-island cell.
- Direct each border edge for CCW winding (island stays on your left as you walk the border).
- Chain edges into a single closed polygon by following end→start connections.
- Convert cell-corner coordinates to screen pixels via
grid.userToScreen().
For each subdivision pass:
- For each edge A→B, find midpoint M.
- Compute the unit perpendicular to the edge.
- Displace M sideways by a random amount.
disp = rand(±1) × |AB| × scale
- Insert displaced M between A and B.
The polygon now has 2× as many vertices.
Repeat for the next pass.
How roughness is controlled
The displacement scale shrinks each iteration using the
Hurst exponent H:
scale = roughness × 0.5iter × H
— where H = 0.7 (natural coastlines ≈ 0.6–0.8)
Iteration 0: scale = roughness (largest bumps)
Iteration 1: scale ≈ roughness × 0.616
Iteration 2: scale ≈ roughness × 0.379
… each pass gives finer, proportionally smaller details.
Multiplying by |AB| (edge length) keeps the roughness
visually consistent: long edges get bigger absolute bumps, short ones
get smaller ones — so every part of the coastline looks equally jagged.
Seeded PRNG — why random but reproducible?
SWFractalIsland uses a
Linear Congruential Generator (LCG) instead of
Math.random():
// LCG constants from Knuth's Numerical Recipes
state = (Math.imul(state, 1664525) + 1013904223) | 0;
// → reproducible [-1, 1] float from 32-bit int
Each island gets a unique seed:
seed + islandIndex × 7919
(7919 is prime — keeps seeds well-spread).
This means clicking the button twice with the
same roughness and passes still gives a different coastline
(new random seed each click), but the same seed always produces the
exact same shape — useful for reproducible demos.
Why outline extraction is safe for these islands
A polygon outline algorithm can fail at a pinch point
— a grid corner where two diagonally opposite cells are island
but the other two diagonal neighbors are not, creating an ambiguous
branching vertex.
Our island growth algorithm prevents this: every cell is added by
orthogonal adjacency, and SWIsland.isValidExpansion()
requires all 8 neighbors of a new cell to be either water or this
island. Together these rules guarantee that if two cells in a
finished island touch diagonally, at least one of the two
“rook” cells (sharing an edge with both) is also in
the island — so no pinch points are possible.
Controls — Stage 8 additions
- Roughness — 0.10 (gentle, rolling hills)
to 0.80 (sharp, jagged cliffs). 0.45 is a good natural default.
- Subdivision passes — each pass doubles the
vertex count and adds a finer level of detail. 3 passes gives
8× the original vertices (good for most island sizes);
5 passes can give thousands of vertices for very large islands.
- 🌊 Apply Fractal Coastline — enabled only
when at least one island has been placed. Clicking again generates
a fresh random coastline with the same settings.
- Reset / Clear — both return to the normal
grid view and disable the button until the next run completes.
Inherited from Stage 7 (unchanged)
- Full island growth algorithm inside
SWIsland.grow().
- All 8-direction diagonal separation rules.
- Auto-placed seeds, BFS reachability pre-check, step-count safety limit.
- Candidate hint overlay, backtrack flashes, recursion log.
- Ocean pits, sprinkle, speed slider, randomize toggle.
SWIsland.toString() logged on island completion.