Stage 7 produces exactly the same visual output as Stage 6b —
the same rules, the same controls, the same animation.
The difference is architectural: the island algorithm has been lifted out of the
sketch and encapsulated into two reusable JavaScript classes that
mirror the Java source one-to-one.
Two New Classes
Mirrors Coordinates.java exactly:
- Stores a single
(row, col) position.
- Validates that row and col are ≥ 0 (throws on negative input).
- Immutable after construction — no setters.
getRow(), getCol(), toString()
Mirrors Island.java with one addition:
- Cells stored as
Coordinates instances.
- Same methods:
contains(), isValidExpansion(), grow(), buildIsland().
- Same DR4/DC4 and DR8/DC8 direction arrays (now static class constants).
- JS addition:
grow() records every ADD / BACKTRACK into an internal step queue; getStepQueue() returns it.
What Moved from the Sketch into SWIsland
| Stage 6b sketch function |
Stage 7 equivalent (in SWIsland) |
_grow(cells, target, useRandom) | island.grow(target, ocean, rows, cols, useRandom) |
_isValidExpansion(row, col, cells) | island.isValidExpansion(row, col, ocean, rows, cols) |
_alreadyCandidate(row, col, candidates) | island._alreadyCandidate(row, col, candidates) |
_shuffleCandidates(list) | island._shuffleCandidates(list) |
findRandomSeedPosition() | Inside SWIsland.buildIsland() |
countReachableCells(seed, ...) | SWIsland.countReachableCells(seed, ocean, ...) |
How the Sketch Uses the Classes
The sketch’s buildAllStepQueues() function became dramatically
simpler. Instead of calling several standalone functions, it now asks the
SWIsland class to build each island, then splices the recorded steps
into the global animation queue:
// Stage 6b: scattered standalone functions
const seed = findRandomSeedPosition();
oceanGrid[seed.row][seed.col] = 1;
const reachable = countReachableCells(seed.row, seed.col);
const success = _grow(cells, targetSize, useRandom);
// Stage 7: one clean call to the SWIsland class STAGE 7
const island = SWIsland.buildIsland(
oceanGrid, targetSize, OCEAN_ROWS, OCEAN_COLS, useRandom, MAX_QUEUE_STEPS
);
if (island !== null && !island.wasAborted()) { STAGE 7
// splice island's recorded steps into the global queue
for (const step of island.getStepQueue()) {
stepQueue.push(step);
}
}
toString() in the Recursion Log
When an island completes, Stage 7 calls island.toString() and
logs the result — matching the console output you see when running
Island.java. Look for lines like:
+ Island 2 complete! (8 cells)
SWIsland [size=8]: (3, 4) -> (3, 5) -> (4, 5) -> (5, 5) -> ...
Hint Overlay
The green candidate hint tiles are now computed by calling
SWIsland.isValidExpansion() through a transient
hint island built from the current animation cells.
This means the hint overlay uses exactly the same validity logic
as the algorithm itself — no separate inline check.
Inherited from Stage 6b (unchanged)
- Full diagonal separation — no two islands may touch, even at a corner (
SWIsland.isValidExpansion() Rule 3).
- Auto-placed seeds — handled inside
SWIsland.buildIsland().
- Per-island colors — 8-hue palette, one per island slot.
- Random size per island — each island targets a random size in [min, max].
- All controls — island count, size range, speed, randomize, pits, sprinkle, reset.
The Algorithm (unchanged, now inside SWIsland.grow())
- Base case: island has targetSize cells → return
true.
- Collect candidates: orthogonal neighbors that pass
isValidExpansion().
- Shuffle or sort the candidate list.
- Try each candidate: ADD → recurse; if false → BACKTRACK.
- All candidates exhausted → return
false.
What the Colors Tell You
- Light blue — open ocean.
- 8 island colors — each completed island has its own permanent color.
- Yellow-green — cell currently being tried (ADD).
- Light green tint — valid candidate cells (from
SWIsland.isValidExpansion()).
- 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.
- 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
- Reachability pre-check — inside
SWIsland.buildIsland(); BFS fast-fails seeds with too few reachable cells.
- Step-count limit —
SWIsland.grow() aborts if its internal queue exceeds 150 000 entries; 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.
- SWIsland [size=N]: (r,c) -> ... — Stage 7 addition: the island’s
toString(), matching Java console output.
- ! Island N FAILED — island could not be placed.
- -- All done -- — all islands attempted.