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; }
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; }