public void createEnd(int x, int y) {
    if (elementList.getTypeAt(x, y) != DungeonElementType.ROOM)
      throw new IllegalStateException("Cannot create end, invalid dungeon element!");

    Set<DungeonElement> connected = elementList.getGrouped(elementList.getAt(x, y));
    if (connected.size() != 4)
      throw new IllegalStateException("Cannot create end, invalid dungeon element size!");

    List<DungeonElement> endElements = new ArrayList<>();

    for (DungeonElement element : connected) {
      elementList.remove(element);

      DungeonElement newElement = new DungeonElement(element.x, element.y, DungeonElementType.END);
      elementArray[element.x][element.y] = DungeonElementType.END;
      endElements.add(newElement);
      elementList.add(newElement);

      for (DungeonDir dir : DungeonDir.values) {
        if (element.checkConnection(dir)) newElement.connect(dir);
      }
    }

    for (DungeonElement endElement : endElements) {
      for (DungeonDir dir : DungeonDir.values) {
        if (elementList.getTypeAt(endElement.x + dir.addX * 2, endElement.y + dir.addY * 2)
            == DungeonElementType.END) {
          endElement.connect(dir);
        }
      }
    }
  }
 public void createEntrance(int x, int y) {
   if (this.entranceX != -1 || this.entranceY != -1)
     throw new IllegalStateException("Created entrance twice!");
   this.entranceX = this.x = (byte) x;
   this.entranceY = this.y = (byte) y;
   elementArray[x][y] = DungeonElementType.ENTRANCE;
   elementList.add(new DungeonElement(x, y, DungeonElementType.ENTRANCE));
 }
  private void addRoomAt(int x, int y) {
    for (int xx = x - 1; xx <= x + 1; xx++) {
      for (int yy = y - 1; yy <= y + 1; yy++) {
        elementArray[xx][yy] = DungeonElementType.ROOM;
      }
    }

    elementList.add(new DungeonElement(x, y, DungeonElementType.ROOM));
  }
  public boolean addHallway(DungeonDir dir) {
    int amount = elementArray[x][y] == DungeonElementType.ROOM ? 2 : 1;
    int prevX = x, prevY = y;

    if (move(dir, amount)) {
      if (elementArray[x][y] == DungeonElementType.EMPTY) {
        elementArray[x][y] = DungeonElementType.HALLWAY;
        elementList.add(
            new DungeonElement(x, y, DungeonElementType.HALLWAY).connect(dir.reversed()));
        if (elementList.getAt(prevX, prevY) != null) elementList.getAt(prevX, prevY).connect(dir);
        return true;
      } else move(dir.reversed(), amount);
    }

    return false;
  }
  public void createDescend(int x, int y) {
    if (elementList.getTypeAt(x, y) != DungeonElementType.ROOM)
      throw new IllegalStateException("Cannot create descend, invalid dungeon element!");

    DungeonElement descend;
    elementArray[x][y] = DungeonElementType.DESCEND;
    elementList.add(descend = new DungeonElement(x, y, DungeonElementType.DESCEND));

    for (DungeonDir dir : DungeonDir.values) {
      DungeonElement element = elementList.getAt(x + dir.addX * 2, y + dir.addY * 2);

      if (element != null) {
        descend.connect(dir);
        element.connect(dir.reversed());
      }
    }
  }
 public void createDescendBottom(int x, int y) {
   this.entranceX = this.x = (byte) x;
   this.entranceY = this.y = (byte) y;
   elementArray[x][y] = DungeonElementType.DESCENDBOTTOM;
   elementList.add(new DungeonElement(x, y, DungeonElementType.DESCENDBOTTOM));
 }