Configure island settings and press Start (or Spacebar) to begin.
Canvas:
Grid:
⚙️ Controls
ON = Fisher-Yates shuffle → organic shape
OFF = sorted top→left → predictable boxy shape
🕳️ Ocean Pits
Toggle ON to click ocean cells and mark them as pits
(click a pit again to remove it). Pits are too deep for island
growth — the recursion must route around them.
Toggle OFF, then click to place your seed and press Start.
Pits placed: 0
📊 Recursion Cost
✅ Cells added
0
↩️ Backtracks
0
📉 Backtrack ratio
—
🏝️ Islands placed
—
Ratio = backtracks ÷ (adds + backtracks).
Higher ratio = more wasted work = harder path.
🎨 Color Guide
Ocean — open water (light blue)
Trying — current ADD attempt (yellow-green)
Island cells — each island gets its own color
islands 1–8
Candidate hint — legal next moves
Backtrack — cell removed, trying elsewhere
Ocean pit — forbidden zone; island cannot grow here
📋 Recursion Log
🏝️ Island Stage 6 — Multiple Islands
Stage 6 is the closest JavaScript equivalent to the original Java problem.
Instead of growing a single island from a manually-placed seed, the algorithm
now grows multiple islands automatically.
You choose how many islands to attempt and a
minimum and maximum target size;
each island is assigned a random size in that range and a distinct color.
Seeds are placed automatically — no clicking required to start.
What’s New in Stage 6
Island count (1–8) — how many islands the algorithm will attempt to grow on the same ocean grid.
Min / Max size — each island’s target is chosen randomly in this range. If min > max they are automatically swapped.
Auto seed placement — the algorithm picks a random open-water cell that is not orthogonally adjacent to any existing island, so islands are always separated by at least one water cell.
Island colors — a palette of 8 distinct hues cycles through successive islands so each one is visually distinct.
🏝️ Islands placed counter — shows placed / total in the cost card; increments each time an island succeeds.
Cumulative cost — ADD count, BACKTRACK count, and backtrack ratio accumulate across all islands in a run, giving a total picture of algorithmic work.
How a Run Works
Press Start (or Space). The algorithm builds the entire step queue for all islands at once (record phase).
Animation replays the queue island by island. Each island starts with an ISLAND_START event, then plays the familiar ADD / BACKTRACK / SUCCESS cycle.
When an island succeeds (ISLAND_SUCCESS), its cells are archived in color and the next island begins.
If an island cannot be seeded (ocean is full), is unreachable (not enough open water), or the algorithm exhausts all paths (ISLAND_FAIL), it is skipped and the next island is attempted.
After all islands are attempted, ALL_DONE is logged with a final placed count.
The Algorithm (unchanged core)
Each island still uses the same _grow() recursive backtracking
function from earlier stages. The key difference is that
buildAllStepQueues() calls it N times in sequence, and
getValidNeighbors() treats any occupied cell
(from any prior island) as impassable — so islands cannot merge.
🔍 The Recursive Function — Actual Code
The core _grow() function is identical to previous stages.
BASE CASE stops when the island reaches its target.
CALLS ITSELF recurses deeper.
BACKTRACK undoes a failed step.
function_grow(cells, targetSize, useRandom) {
if (cells.length >= targetSize) returntrue; // island is big enough — stop!BASE CASE
// collect all water cells that touch the island’s edge
const candidates = [];
for (const cell of cells) {
for (let d = 0; d < 4; d++) {
const nr = cell.row + DR4[d];
const nc = cell.col + DC4[d];
if (_isValidExpansion(nr, nc) && !_alreadyCandidate(nr, nc, candidates))
candidates.push({ row: nr, col: nc });
}
}
if (candidates.length === 0) returnfalse; // completely surrounded — dead end
// shuffle (organic shapes) or sort (predictable shapes)
if (_grow(cells, targetSize, useRandom)) CALLS ITSELF
returntrue; // deeper call succeeded — bubble success up
cells.pop(); // UNDO: remove from islandBACKTRACK
oceanGrid[row][col] = 0; // mark as water again
}
returnfalse; // all candidates failed — tell the caller to backtrack
}
What the Colors Tell You
Light blue — open ocean.
Yellow-green — cell currently being tried (adds to the ADD counter).
Island color — confirmed cells; hue cycles through the 8-island palette.
Light green tint — valid candidate cells at this moment.
Fading red flash — a backtracked cell (+1 to the BACKTRACK counter).
Dark navy — Ocean Pit; permanently blocked.
Controls
Number of islands — 1–8 islands per run.
Min / Max size — each island is randomly assigned a target in this range.
Speed — 1 (slowest) to 10 (fastest). Slow down at speed 1 to follow each ADD and BACKTRACK individually.
Randomize ON/OFF — organic shapes vs. deterministic; the ratio often differs between modes.
Allow Pit Placement / 🎲 Sprinkle! — add ocean obstacles to increase backtracking and challenge island placement.
Reset — clears all islands and counters while keeping the current pit layout, so you can re-run on the same ocean.
Clear — resets everything including pits. C also works.
⚠️ Too Complex — Browser Safeguard
A very dense pit layout can force the algorithm to explore an exponentially
large number of dead ends. The same 150 000-step limit as earlier stages
applies here: if the total step queue exceeds that limit during the build phase,
the entire run is aborted and “Too Complex.” is displayed.
Reduce pit density, lower the island count or max size, or enable Randomize to recover.
Reading the Recursion Log
🔵 ISLAND START #N — beginning island N with its chosen target size.
▶ ADD (r, c) — algorithm placed this cell and recursed deeper.
✗ BACKTRACK (r, c) — that path failed; the cell was removed.
✓ ISLAND SUCCESS #N — island N reached its target size.
✘ ISLAND FAIL #N — island N could not be seeded, was unreachable, or ran out of paths.
🏝️ ALL DONE — run complete; shows how many islands were successfully placed.
⚠️ TOO COMPLEX — the 150 000-step safety limit was hit.
Stage 5 keeps everything from Stage 4 — the animated recursive
backtracking, the speed control, the recursion log, and Ocean Pits —
and adds one new idea: a live Recursion Cost readout.
Every ADD step and every BACKTRACK step is counted in real time, and a
backtrack ratio is computed as the island grows.
The ratio makes the cost of a difficult path measurable rather than
just visible.
What’s New: Recursion Cost
✅ Cells added — the total number of ADD steps executed so far. Each ADD means the algorithm committed to a new cell and recursed deeper.
↩️ Backtracks — the total number of BACKTRACK steps. Each backtrack means a previously added cell was removed because the path it opened led nowhere.
📉 Backtrack ratio — backtracks ÷ (adds + backtracks), expressed as a percentage.
0 % → the algorithm never needed to backtrack — it picked a winning candidate every time.
50 % → exactly half of all steps were wasted on dead ends.
Near 100 % → almost all of the algorithm’s work was undone before it found a valid path (or it failed entirely).
💡 Try this:
Run the island twice on the same seed: once with no pits, then again
with 20–30 % pits sprinkled around the same area.
Compare the backtrack ratios. Does a more obstacle-filled ocean always cost
more? Try placing pits in a tight ring around the seed to force the algorithm
to search for a gap — then watch the ratio climb.
Ocean Pits (from Stage 4)
Toggle Allow Pit Placement ON to click ocean cells and mark them
as permanently forbidden (dark navy). Press 🎲 Sprinkle! to
scatter a random percentage of the ocean with pits at once.
The higher the pit density, the narrower the corridors the algorithm must thread,
and the higher the backtrack ratio tends to be.
The Algorithm (unchanged from Stage 3)
This is a direct JavaScript port of Island.grow() from the Java source.
It uses recursive backtracking:
Base case: the island already has targetSize cells → done, return true.
Collect candidates: find every cell orthogonally adjacent to the island that is still open water.
Shuffle or sort the candidate list (Randomize ON/OFF).
Try each candidate:
ADD the cell and recurse.
If recursion returns true → success.
If recursion returns false → BACKTRACK: remove the cell and try the next candidate.
If all candidates fail → return false.
🔍 The Recursive Function — Actual Code
Here is the real _grow() function from the sketch, annotated.
BASE CASE stops the recursion when the island is big enough.
CALLS ITSELF is where the recursion happens.
BACKTRACK undoes a failed step and tries the next option.
function_grow(cells, targetSize, useRandom) {
if (cells.length >= targetSize) returntrue; // island is big enough — stop!BASE CASE
// collect all water cells that touch the island's edge
const candidates = [];
for (const cell of cells) {
for (let d = 0; d < 4; d++) {
const nr = cell.row + DR4[d];
const nc = cell.col + DC4[d];
if (_isValidExpansion(nr, nc) && !_alreadyCandidate(nr, nc, candidates))
candidates.push({ row: nr, col: nc });
}
}
if (candidates.length === 0) returnfalse; // completely surrounded — dead end
// shuffle (organic shapes) or sort (predictable shapes)
if (_grow(cells, targetSize, useRandom)) CALLS ITSELF
returntrue; // deeper call succeeded — bubble success up
cells.pop(); // UNDO: remove from islandBACKTRACK
oceanGrid[row][col] = 0; // mark as water again
}
returnfalse; // all candidates failed — tell the caller to backtrack
}
What the Colors Tell You
Light blue — open ocean.
Orange — the seed cell.
Soft green — confirmed island cell.
Yellow-green — the cell currently being tried (contributes +1 to the ADD counter).
Light green tint — valid candidate cells at this moment.
Fading red flash — a backtracked cell (+1 to the BACKTRACK counter).
Dark navy — Ocean Pit; permanently blocked.
Controls
Target size — 1–200 cells. Larger targets give the ratio time to stabilize into a meaningful average.
Speed — 1 (slowest) to 10 (fastest). Slow down to follow each ADD and BACKTRACK individually.
Randomize ON/OFF — organic shapes vs. deterministic; ratio often differs between the two for the same seed and pit layout.
Allow Pit Placement / 🎲 Sprinkle! — increase pit density to drive up the backtrack ratio.
Reset — clears the island, counters, and log while keeping the current pit layout. Use this to run the algorithm again on the same pitted ocean with a new seed, so you can compare costs across placements without re-sprinkling.
Clear — resets everything, including pits. C also works.
⚠️ Too Complex — Browser Safeguard
Very high pit density combined with Randomize OFF can force the algorithm to
explore an exponentially large number of dead-end paths before finding a solution or
confirming there is none. To prevent the browser from stalling, the sketch uses two guards:
Reachability pre-check — before any recursion begins, a fast BFS counts how many open-water cells are reachable from the seed. If fewer cells exist than the target size, the algorithm records an instant FAIL without recursing at all.
Step-count limit — if the recorded step queue reaches 150 000 entries, the build is aborted and the animation shows “Too Complex.” To recover: try fewer pits, a different seed position, or turn Randomize ON to escape the deterministic worst case.
Reading the Recursion Log
▶ ADD (r, c) — algorithm placed this cell and recursed deeper.
✗ BACKTRACK (r, c) — that path failed; the cell was removed.
✓ SUCCESS — the island reached its target size.
✘ FAIL — the seed was completely surrounded before the target was reached.
⚠️ TOO COMPLEX — the 150 000-step safety limit was hit; reduce pit density or enable Randomize.
—— Reset (pits kept) —— — separator marking the start of a new run on the same pit layout.