Beispiel #1
0
  protected OrderedSet<Coord> removeAdjacent(OrderedSet<Coord> coll, Coord pt) {
    for (Coord temp :
        new Coord[] {
          Coord.get(pt.x + 1, pt.y),
          Coord.get(pt.x - 1, pt.y),
          Coord.get(pt.x, pt.y + 1),
          Coord.get(pt.x, pt.y - 1)
        }) {
      if (coll.contains(temp) && !(temp.x == pt.x && temp.y == pt.y)) coll.remove(temp);
    }

    return coll;
  }
Beispiel #2
0
  private char[][] innerGenerate(char[][] map) {
    OrderedSet<Coord> doorways;
    OrderedSet<Coord> hazards = new OrderedSet<>();
    Coord temp;
    boolean doubleDoors = false;
    int floorCount = DungeonUtility.countCells(map, '.'),
        doorFill = 0,
        waterFill = 0,
        grassFill = 0,
        trapFill = 0,
        boulderFill = 0,
        islandSpacing = 0;
    if (fx.containsKey(FillEffect.DOORS)) {
      doorFill = fx.get(FillEffect.DOORS);
      if (doorFill < 0) {
        doubleDoors = true;
        doorFill *= -1;
      }
    }
    if (fx.containsKey(FillEffect.GRASS)) {
      grassFill = fx.get(FillEffect.GRASS);
    }
    if (fx.containsKey(FillEffect.WATER)) {
      waterFill = fx.get(FillEffect.WATER);
    }
    if (fx.containsKey(FillEffect.BOULDERS)) {
      boulderFill = fx.get(FillEffect.BOULDERS) * floorCount / 100;
    }
    if (fx.containsKey(FillEffect.ISLANDS)) {
      islandSpacing = fx.get(FillEffect.ISLANDS);
    }
    if (fx.containsKey(FillEffect.TRAPS)) {
      trapFill = fx.get(FillEffect.TRAPS);
    }

    doorways = viableDoorways(doubleDoors, map);

    OrderedSet<Coord> obstacles = new OrderedSet<>(doorways.size() * doorFill / 100);
    if (doorFill > 0) {
      int total = doorways.size() * doorFill / 100;

      BigLoop:
      for (int i = 0; i < total; i++) {
        Coord entry = rng.getRandomElement(doorways);
        if (map[entry.x][entry.y] == '<' || map[entry.x][entry.y] == '>') continue;
        if (map[entry.x - 1][entry.y] != '#' && map[entry.x + 1][entry.y] != '#') {
          map[entry.x][entry.y] = '+';
        } else {
          map[entry.x][entry.y] = '/';
        }
        obstacles.add(entry);
        Coord[] adj =
            new Coord[] {
              Coord.get(entry.x + 1, entry.y),
              Coord.get(entry.x - 1, entry.y),
              Coord.get(entry.x, entry.y + 1),
              Coord.get(entry.x, entry.y - 1)
            };
        for (Coord near : adj) {
          if (doorways.contains(near)) {
            map[near.x][near.y] = '#';
            obstacles.add(near);
            doorways.remove(near);
            i++;
            doorways.remove(entry);
            continue BigLoop;
          }
        }
        doorways.remove(entry);
      }
    }
    if (boulderFill > 0.0) {
      /*
      short[] floor = pack(map, '.');
      short[] viable = retract(floor, 1, width, height, true);
      ArrayList<Coord> boulders = randomPortion(viable, boulderFill, rng);
      for (Coord boulder : boulders) {
          map[boulder.x][boulder.y] = '#';
      }
      */
      Coord[] boulders = new GreasedRegion(map, '.').retract8way(1).randomPortion(rng, boulderFill);
      Coord t;
      for (int i = 0; i < boulders.length; i++) {
        t = boulders[i];
        map[t.x][t.y] = '#';
      }
    }

    if (trapFill > 0) {
      for (int x = 1; x < map.length - 1; x++) {
        for (int y = 1; y < map[x].length - 1; y++) {
          temp = Coord.get(x, y);
          if (map[x][y] == '.' && !obstacles.contains(temp)) {
            int ctr = 0;
            if (map[x + 1][y] != '#') ++ctr;
            if (map[x - 1][y] != '#') ++ctr;
            if (map[x][y + 1] != '#') ++ctr;
            if (map[x][y - 1] != '#') ++ctr;
            if (map[x + 1][y + 1] != '#') ++ctr;
            if (map[x - 1][y + 1] != '#') ++ctr;
            if (map[x + 1][y - 1] != '#') ++ctr;
            if (map[x - 1][y - 1] != '#') ++ctr;
            if (ctr >= 5) hazards.add(Coord.get(x, y));
          }
        }
      }
    }
    short[] floors = pack(map, '.'), working;
    floorCount = count(floors);
    float waterRate = waterFill / 100.0f, grassRate = grassFill / 100.0f;
    if (waterRate + grassRate > 1.0f) {
      waterRate /= (waterFill + grassFill) / 100.0f;
      grassRate /= (waterFill + grassFill) / 100.0f;
    }
    int targetWater = Math.round(floorCount * waterRate),
        targetGrass = Math.round(floorCount * grassRate),
        sizeWaterPools = targetWater / rng.between(3, 6),
        sizeGrassPools = targetGrass / rng.between(2, 5);

    Coord[] scatter;
    int remainingWater = targetWater, remainingGrass = targetGrass;
    if (targetWater > 0) {
      scatter = fractionPacked(floors, 7);
      scatter = rng.shuffle(scatter, new Coord[scatter.length]);
      ArrayList<Coord> allWater = new ArrayList<>(targetWater);
      for (int i = 0; i < scatter.length; i++) {
        if (remainingWater > 5) // remainingWater >= targetWater * 0.02 &&
        {
          if (!queryPacked(floors, scatter[i].x, scatter[i].y)) continue;
          working =
              spill(
                  floors,
                  packOne(scatter[i]),
                  rng.between(4, Math.min(remainingWater, sizeWaterPools)),
                  rng);

          floors = differencePacked(floors, working);
          Coord[] pts = allPacked(working);
          remainingWater -= pts.length;
          Collections.addAll(allWater, pts);
        } else break;
      }

      for (Coord pt : allWater) {
        hazards.remove(pt);
        // obstacles.add(pt);
        if (map[pt.x][pt.y] != '<' && map[pt.x][pt.y] != '>') map[pt.x][pt.y] = '~';
      }
      for (Coord pt : allWater) {
        if (map[pt.x][pt.y] != '<'
            && map[pt.x][pt.y] != '>'
            && (map[pt.x - 1][pt.y] == '.'
                || map[pt.x + 1][pt.y] == '.'
                || map[pt.x][pt.y - 1] == '.'
                || map[pt.x][pt.y + 1] == '.')) map[pt.x][pt.y] = ',';
      }
    }
    if (targetGrass > 0) {
      scatter = fractionPacked(floors, 7);
      scatter = rng.shuffle(scatter, new Coord[scatter.length]);
      Coord p;
      for (int i = 0; i < scatter.length; i++) {
        if (remainingGrass > 5) // remainingGrass >= targetGrass * 0.02 &&
        {
          working =
              spill(
                  floors,
                  packOne(scatter[i]),
                  rng.between(4, Math.min(remainingGrass, sizeGrassPools)),
                  rng);
          if (working.length == 0) continue;
          floors = differencePacked(floors, working);
          Coord[] pts = allPacked(working);
          remainingGrass -= pts.length;
          for (int c = 0; c < pts.length; c++) {
            p = pts[c];
            map[p.x][p.y] = '"';
          }
        } else break;
      }
    }

    if (islandSpacing > 1 && targetWater > 0) {
      ArrayList<Coord> islands =
          PoissonDisk.sampleMap(
              map, 1f * islandSpacing, rng, '#', '.', '"', '+', '/', '^', '<', '>');
      for (Coord c : islands) {
        map[c.x][c.y] = '.';
        if (map[c.x - 1][c.y] != '#' && map[c.x - 1][c.y] != '<' && map[c.x - 1][c.y] != '>')
          map[c.x - 1][c.y] = ',';
        if (map[c.x + 1][c.y] != '#' && map[c.x + 1][c.y] != '<' && map[c.x + 1][c.y] != '>')
          map[c.x + 1][c.y] = ',';
        if (map[c.x][c.y - 1] != '#' && map[c.x][c.y - 1] != '<' && map[c.x][c.y - 1] != '>')
          map[c.x][c.y - 1] = ',';
        if (map[c.x][c.y + 1] != '#' && map[c.x][c.y + 1] != '<' && map[c.x][c.y + 1] != '>')
          map[c.x][c.y + 1] = ',';
      }
    }

    if (trapFill > 0) {
      int total = hazards.size() * trapFill / 100;

      for (int i = 0; i < total; i++) {
        Coord entry = rng.getRandomElement(hazards);
        if (map[entry.x][entry.y] == '<' || map[entry.x][entry.y] == '<') continue;
        map[entry.x][entry.y] = '^';
        hazards.remove(entry);
      }
    }

    dungeon = map;
    return map;
  }
Beispiel #3
0
  protected OrderedSet<Coord> viableDoorways(boolean doubleDoors, char[][] map) {
    OrderedSet<Coord> doors = new OrderedSet<>();
    OrderedSet<Coord> blocked = new OrderedSet<>(4);
    DijkstraMap dm = new DijkstraMap(map, DijkstraMap.Measurement.EUCLIDEAN);
    for (int x = 1; x < map.length - 1; x++) {
      for (int y = 1; y < map[x].length - 1; y++) {
        if (map[x][y] == '#') continue;
        if (doubleDoors) {
          if (x >= map.length - 2 || y >= map[x].length - 2) continue;
          else {
            if (map[x + 1][y] != '#'
                && map[x + 2][y] == '#'
                && map[x - 1][y] == '#'
                && map[x][y + 1] != '#'
                && map[x][y - 1] != '#'
                && map[x + 1][y + 1] != '#'
                && map[x + 1][y - 1] != '#') {
              if (map[x + 2][y + 1] != '#'
                  || map[x - 1][y + 1] != '#'
                  || map[x + 2][y - 1] != '#'
                  || map[x - 1][y - 1] != '#') {
                dm.resetMap();
                dm.clearGoals();
                dm.setGoal(x, y + 1);
                blocked.clear();
                blocked.add(Coord.get(x, y));
                blocked.add(Coord.get(x + 1, y));
                if (dm.partialScan(16, blocked)[x][y - 1] < DijkstraMap.FLOOR) continue;
                doors.add(Coord.get(x, y));
                doors.add(Coord.get(x + 1, y));
                doors = removeAdjacent(doors, Coord.get(x, y), Coord.get(x + 1, y));
                continue;
              }
            } else if (map[x][y + 1] != '#'
                && map[x][y + 2] == '#'
                && map[x][y - 1] == '#'
                && map[x + 1][y] != '#'
                && map[x - 1][y] != '#'
                && map[x + 1][y + 1] != '#'
                && map[x - 1][y + 1] != '#') {
              if (map[x + 1][y + 2] != '#'
                  || map[x + 1][y - 1] != '#'
                  || map[x - 1][y + 2] != '#'
                  || map[x - 1][y - 1] != '#') {
                dm.resetMap();
                dm.clearGoals();
                dm.setGoal(x + 1, y);
                blocked.clear();
                blocked.add(Coord.get(x, y));
                blocked.add(Coord.get(x, y + 1));
                if (dm.partialScan(16, blocked)[x - 1][y] < DijkstraMap.FLOOR) continue;
                doors.add(Coord.get(x, y));
                doors.add(Coord.get(x, y + 1));
                doors = removeAdjacent(doors, Coord.get(x, y), Coord.get(x, y + 1));
                continue;
              }
            }
          }
        }
        if (map[x + 1][y] == '#'
            && map[x - 1][y] == '#'
            && map[x][y + 1] != '#'
            && map[x][y - 1] != '#') {
          if (map[x + 1][y + 1] != '#'
              || map[x - 1][y + 1] != '#'
              || map[x + 1][y - 1] != '#'
              || map[x - 1][y - 1] != '#') {
            dm.resetMap();
            dm.clearGoals();
            dm.setGoal(x, y + 1);
            blocked.clear();
            blocked.add(Coord.get(x, y));
            if (dm.partialScan(16, blocked)[x][y - 1] < DijkstraMap.FLOOR) continue;
            doors.add(Coord.get(x, y));
            doors = removeAdjacent(doors, Coord.get(x, y));
          }
        } else if (map[x][y + 1] == '#'
            && map[x][y - 1] == '#'
            && map[x + 1][y] != '#'
            && map[x - 1][y] != '#') {
          if (map[x + 1][y + 1] != '#'
              || map[x + 1][y - 1] != '#'
              || map[x - 1][y + 1] != '#'
              || map[x - 1][y - 1] != '#') {
            dm.resetMap();
            dm.clearGoals();
            dm.setGoal(x + 1, y);
            blocked.clear();
            blocked.add(Coord.get(x, y));
            if (dm.partialScan(16, blocked)[x - 1][y] < DijkstraMap.FLOOR) continue;
            doors.add(Coord.get(x, y));
            doors = removeAdjacent(doors, Coord.get(x, y));
          }
        }
      }
    }

    return doors;
  }