/** A move in 2 different boundaries. */
 private InternalPosition getPositionAfterMove(InternalMove move) {
   InternalPosition newPosition = position.clone();
   InternalRegion region = newPosition.get(move.getRegionIndex());
   InternalBoundary fromBoundary = region.get(move.getFrom().getBoundaryIndex());
   InternalBoundary toBoundary = region.get(move.getTo().getBoundaryIndex());
   // Rename vertices:
   fromBoundary
       .get(move.getFrom().getVertexIndex())
       .setC(
           renameVertex(
               move.getFrom().getVertex().getC(), InternalConstants.TEMP_1, fromBoundary.size()));
   toBoundary
       .get(move.getTo().getVertexIndex())
       .setC(
           renameVertex(
               move.getTo().getVertex().getC(), InternalConstants.TEMP_2, toBoundary.size()));
   InternalBoundary newBoundary =
       InternalBoundary.joinTwoBoundaries(fromBoundary, toBoundary, move);
   region.remove(fromBoundary);
   region.remove(toBoundary);
   region.add(newBoundary);
   return newPosition.recreate();
 }
 private List<ArrayList<VertexInfo>> getVertexInfos() {
   ArrayList<ArrayList<VertexInfo>> result = new ArrayList<ArrayList<VertexInfo>>();
   for (int regionIndex = 0; regionIndex < position.size(); regionIndex++) {
     ArrayList<VertexInfo> regionResult = new ArrayList<VertexInfo>();
     InternalRegion region = position.get(regionIndex);
     int foundZeros = 0;
     for (int boundaryIndex = 0; boundaryIndex < region.size(); boundaryIndex++) {
       InternalBoundary boundary = region.get(boundaryIndex);
       for (int vertexIndex = 0; vertexIndex < boundary.size(); vertexIndex++) {
         Vertex vertex = boundary.get(vertexIndex);
         if (vertex.getLives() >= 3) {
           // A zero
           if (++foundZeros > 2) {
             // Already have 2 zeros in this region, don't add more
             continue;
           }
         }
         regionResult.add(new VertexInfo(vertex, regionIndex, boundaryIndex, vertexIndex));
       }
     }
     result.add(regionResult);
   }
   return result;
 }
  /** A move in the same boundary. */
  private List<InternalPosition> getPositionsAfterMove(InternalMove move) {
    List<InternalPosition> positions = new ArrayList<InternalPosition>();
    InternalPosition partialPosition = position.clone();
    InternalRegion moveRegion = partialPosition.get(move.getRegionIndex());
    InternalBoundary moveBoundary = moveRegion.get(move.getFrom().getBoundaryIndex());
    // Rename vertices:
    if (move.getFrom().getVertexIndex() == move.getTo().getVertexIndex()) {
      // Same vertex:
      moveBoundary
          .get(move.getFrom().getVertexIndex())
          .setC(renameVertexTwice(moveBoundary.get(move.getFrom().getVertexIndex()).getC()));
    } else {
      moveBoundary
          .get(move.getFrom().getVertexIndex())
          .setC(
              renameVertex(
                  moveBoundary.get(move.getFrom().getVertexIndex()).getC(),
                  InternalConstants.TEMP_1,
                  moveBoundary.size()));
      moveBoundary
          .get(move.getTo().getVertexIndex())
          .setC(
              renameVertex(
                  moveBoundary.get(move.getTo().getVertexIndex()).getC(),
                  InternalConstants.TEMP_2,
                  moveBoundary.size()));
    }
    // moveBoundary.compile();
    // Remove current region/boundary
    moveRegion.remove(move.getFrom().getBoundaryIndex());
    partialPosition.remove(move.getRegionIndex());
    // TODO: detect equivalent boundaries and reduce the number of splits?
    Set<List<InternalBoundary>> splits = allPossibleSplits(moveRegion);
    // Output.debug("Number of splits: " + splits.size());
    // Output.debug("Splits: " + splits);
    for (List<InternalBoundary> split : splits) {
      InternalRegion firstRegion = new InternalRegion(split);
      InternalRegion secondRegion = new InternalRegion();
      secondRegion.addAll(moveRegion);
      for (InternalBoundary boundary : firstRegion) {
        secondRegion.remove(boundary);
      }

      int fromId = move.getFrom().getVertexIndex();
      int toId = move.getTo().getVertexIndex();

      InternalBoundary firstBoundary = new InternalBoundary();
      firstBoundary.addAll(moveBoundary.subList(0, fromId + 1));
      firstBoundary.add(new Vertex(InternalConstants.TEMP_NEW, firstBoundary));
      if (moveBoundary.size() > 1) {
        firstBoundary.addAll(moveBoundary.subList(toId, moveBoundary.size()));
      }
      // firstBoundary.compile();

      InternalBoundary secondBoundary = new InternalBoundary();
      secondBoundary.addAll(moveBoundary.subList(fromId, toId + 1));
      secondBoundary.add(new Vertex(InternalConstants.TEMP_NEW, firstBoundary));
      // secondBoundary.compile();

      // Output.debug("First boundary: " + firstBoundary);
      // Output.debug("Second boundary: " + secondBoundary);
      firstRegion.add(firstBoundary);
      secondRegion.add(secondBoundary);

      InternalPosition newPosition = new InternalPosition(partialPosition);
      newPosition.add(firstRegion);
      newPosition.add(secondRegion);
      positions.add(newPosition.recreate());
    }
    return positions;
  }