Stage 6a builds on Stage 5 and answers: “How many islands can
we place in one ocean?” Instead of placing one seed by hand, you specify
a count, a minimum size, and a
maximum size — then press Start.
Seeds are auto-placed in isolated positions, and each island grows to a random size
in [min, max], finishing with its own unique color.
What’s New in Stage 6a
- Auto-placed seeds — no click needed.
findRandomSeedPosition() picks a random open-water cell not
adjacent to any existing island so every island starts separated.
- Per-island colors — a palette of 8 distinct colors is
cycled so each completed island has a unique permanent color.
- Random size per island — each island targets a random
size between Min and Max, creating natural variety.
- Islands placed counter — the Recursion Cost card now
shows how many of the requested islands were successfully grown.
New Step Types
ISLAND_START — seed placed, growth beginning for island N.
ISLAND_SUCCESS — island N reached its target size; cells frozen in final color.
ISLAND_FAIL — island N could not be grown (no valid seed, not enough reachable water, or growth dead-ended).
ALL_DONE — all islands attempted; animation complete.
💡 Try this:
Request 6–8 small islands (max 8–12 cells) and watch them fill the
ocean like an archipelago. Then try 3 large islands (max 30–50 cells) and
observe how the algorithm struggles to find non-adjacent seeds once the ocean fills.
Sprinkle pits first to see how obstacles limit how many islands can fit.
The Algorithm (unchanged from Stage 3)
Each island still uses recursive backtracking in _grow().
The new outer loop in buildAllStepQueues() calls _grow() once
per island and interleaves the results into a single step queue.
- Base case: island has targetSize cells → return
true.
- Collect candidates: orthogonal neighbors that are open water (not pit, not another island).
- Shuffle or sort the candidate list (Randomize ON/OFF).
- Try each candidate: ADD → recurse; if false → BACKTRACK and try next.
- All candidates exhausted → 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) return true; // 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) return false; // completely surrounded — dead end
// shuffle (organic shapes) or sort (predictable shapes)
if (useRandom) _shuffleCandidates(candidates);
else candidates.sort((a, b) => a.row - b.row || a.col - b.col);
// try each candidate neighbor in turn
for (const { row, col } of candidates) {
cells.push({ row, col }); // ADD: claim this cell
oceanGrid[row][col] = 1;
if (_grow(cells, targetSize, useRandom)) CALLS ITSELF
return true; // deeper call succeeded — bubble success up
cells.pop(); // UNDO: remove from island BACKTRACK
oceanGrid[row][col] = 0; // mark as water again
}
return false; // all candidates failed — tell the caller to backtrack
}
What the Colors Tell You
- Light blue — open ocean.
- 8 island colors — each completed island has its own permanent color.
- Yellow-green — the cell currently being tried (ADD).
- Light green tint — valid candidate cells at this moment.
- Fading red flash — a backtracked cell.
- Dark navy — Ocean Pit; permanently blocked.
Controls
- Number of islands — 1–8 islands to grow in one run.
- Min / Max island size — each island targets a random size in [min, max]. If min > max they are swapped automatically.
- Speed — 1 (slowest) to 10 (fastest).
- Randomize ON/OFF — organic shapes vs. deterministic order; affects both shape and backtrack cost.
- Allow Pit Placement / 🎲 Sprinkle! — add obstacles before pressing Start.
- Reset — clears islands and log while keeping the current pit layout.
- Clear — resets everything including pits. C also works.
⚠️ Too Complex — Browser Safeguard
Very high pit density combined with Randomize OFF can produce an exponentially
large search tree. Two guards prevent the browser from stalling:
- Reachability pre-check — BFS counts reachable cells from the seed; instant FAIL if fewer than targetSize.
- Step-count limit — if the queue reaches 150 000 entries, the build aborts and the animation shows “Too Complex.”
Reading the Recursion Log
- >> Island N seed at (r,c) — seed auto-placed, growth starting.
- > ADD (r, c) — algorithm placed this cell and recursed deeper.
- X BACKTRACK (r, c) — that path failed; the cell was removed.
- + Island N complete! — island reached its target size.
- ! Island N FAILED — island could not be grown (no seed / not reachable / dead end).
- -- All done -- — all islands attempted.
- ! TOO COMPLEX — 150 000-step limit hit.
⚠️ Known Limitation — Stage 6b fixes this:
In Stage 6a,
_isValidExpansion() only checks that the candidate
cell is open water. It does
not check diagonal neighbors, so two
different islands can grow until they touch corner-to-corner.
Stage 6b adds the full 8-neighbor separation
rule, guaranteeing every island is completely surrounded by open water on all sides.