Stage 6b is identical to Stage 6a with one critical fix: island cells
are now diagonally separated as well as orthogonally separated.
In Stage 6a two different islands could grow until their cells touched
corner-to-corner (or even side-to-side), because _isValidExpansion()
only checked whether a candidate cell was water — it never looked at the
cell’s diagonal neighbors. Stage 6b mirrors the exact rule enforced by
Island.isValidExpansion() in the Java source.
The New Rule — All 8 Neighbors
A candidate cell is valid only if none of its 8 surrounding
neighbors (orthogonal and diagonal) is land that belongs to a
different island. Land from the current island is
fine — that is how U-shapes and L-shapes form.
▦ ▦ ▦
▦ ? ▦ ← all 8 neighbors must be water or same-island
▦ ▦ ▦
What Changed in Stage 6b
DR8 / DC8 arrays added — the 8 surrounding directions
(orthogonal + diagonal), mirroring Island.java’s constants.
_isValidExpansion(row, col, cells) updated — now accepts the
current island’s cell list and adds Rule 3: scan all 8 neighbors;
reject if any neighbor is land from a different island.
findRandomSeedPosition() updated — now checks all 8 directions
(not just 4) for existing land before accepting a seed, matching
Island.buildIsland() Step 3 in Java.
- Candidate hints updated —
getValidNeighbors() applies the same
8-neighbor rule so the green hint tiles are always accurate.
💡 Compare with Stage 6a: Run both stages with the same
settings (3 islands, max 12 cells, Randomize ON). In 6a you will often
see islands touching at corners; in 6b every island is completely surrounded by
open water on all sides. You will also notice higher backtrack counts in
Stage 6b because the stricter rule cuts off more expansion paths.
Inherited from Stage 6a (unchanged)
- Auto-placed seeds —
findRandomSeedPosition() picks an open cell
not adjacent (in any of the 8 directions) to any existing island.
- Per-island colors — a palette of 8 distinct hues cycles so each completed island has a unique permanent color.
- Random size per island — each island targets a random size between Min and Max.
- New step types —
ISLAND_START, ISLAND_SUCCESS, ISLAND_FAIL, ALL_DONE, TOOSLOW.
The Algorithm (unchanged from Stage 3)
Each island still uses recursive backtracking in _grow().
The outer loop in buildAllStepQueues() calls _grow() once
per island and interleaves all results into a single step queue.
- Base case: island has targetSize cells → return
true.
- Collect candidates: orthogonal neighbors that pass the new
_isValidExpansion() — open water with no diagonal or orthogonal foreign-island neighbor.
- 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 Key Change — _isValidExpansion()
This is the real _isValidExpansion() from Stage 6b, annotated.
NEW IN 6b marks the Rule 3 addition that enforces diagonal separation.
function _isValidExpansion(row, col, cells) {
// Rule 1: bounds check
if (row < 0 || row >= OCEAN_ROWS || col < 0 || col >= OCEAN_COLS) return false;
// Rule 2: must be open water (not pit, not land)
if (oceanGrid[row][col] !== 0) return false;
// Rule 3 (NEW): scan all 8 neighbors for FOREIGN island land NEW IN 6b
for (let d = 0; d < 8; d++) {
const nr = row + DR8[d];
const nc = col + DC8[d];
if (nr >= 0 && nr < OCEAN_ROWS && nc >= 0 && nc < OCEAN_COLS) {
if (oceanGrid[nr][nc] === 1 &&
!cells.some(c => c.row === nr && c.col === nc))
return false; // foreign island land nearby — reject
}
}
return true; // all three rules passed
}
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.