SWIsland Recursion Saga

“How many islands can the ocean hold?” — Stage

...loading...

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

    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

    💡 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:

    1. Base case: the island already has targetSize cells → done, return true.
    2. Collect candidates: find every cell orthogonally adjacent to the island that is still open water.
    3. Shuffle or sort the candidate list (Randomize ON/OFF).
    4. Try each candidate:
      • ADD the cell and recurse.
      • If recursion returns truesuccess.
      • If recursion returns falseBACKTRACK: remove the cell and try the next candidate.
    5. 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) 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

    Controls

    ⚠️ 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:

    Reading the Recursion Log