private void generateValidIslandsRecursive(FixedCell fixedCell, Set<Cell> requiredCells,
      Set<Cell> currentCells, Set<Set<Cell>> currentCellsSeen,
      Map<Cell, Set<Cell>> validNeighborsCache, Set<Set<Cell>> result) {
    if (fixedCell.getNumber() == currentCells.size()) {
      // potential valid island
      if (currentCells.containsAll(requiredCells)) {
        // add a copy to result (because the caller might modify currentCells
        result.add(new CellSet(currentCells));
      }
      return;
    }

    if (currentCellsSeen.contains(currentCells)) {
      return;
    }
    else {
      currentCellsSeen.add(new CellSet(currentCells));
    }

    // recurse for each possible "neighbor"
    final Set<Cell> doneNeighbors = new CellSet(fixedCell.getBoard());
    for (final Cell cell : currentCells.toArray(new Cell[currentCells.size()])) {
      for (final Cell neighbor : getValidNeghbors(cell, fixedCell, validNeighborsCache)) {
        if (doneNeighbors.contains(neighbor)) {
          // already seen...
          continue;
        }
        else {
          doneNeighbors.add(neighbor);
        }

        if (!currentCells.contains(neighbor)) {
          // "expand" into neighbor
          currentCells.add(neighbor);
          generateValidIslandsRecursive(fixedCell, requiredCells, currentCells, currentCellsSeen,
              validNeighborsCache, result);
          currentCells.remove(neighbor);
        }
      }
    }
  }