/** * Constructs a concrete WorldMapGenerator for a map that should have land in roughly the same places as the * given GreasedRegion's "on" cells, using an elliptical projection (specifically, a Mollweide projection). * Takes an initial seed, the GreasedRegion containing land positions, parameters for noise generation (a * {@link Noise3D} implementation, which is usually {@link FastNoise#instance}, and a multiplier on how many * octaves of noise to use, with 1.0 being normal (high) detail and higher multipliers producing even more * detailed noise when zoomed-in). The {@code initialSeed} parameter may or may not be used, * since you can specify the seed to use when you call {@link #generate(long)}. The width and height of the map * cannot be changed after the fact. FastNoise will be the fastest 3D generator to use for * {@code noiseGenerator}, and the seed it's constructed with doesn't matter because this will change the * seed several times at different scales of noise (it's fine to use the static {@link FastNoise#instance} * because it has no changing state between runs of the program). The {@code octaveMultiplier} parameter should * probably be no lower than 0.5, but can be arbitrarily high if you're willing to spend much more time on * generating detail only noticeable at very high zoom; normally 1.0 is fine and may even be too high for maps * that don't require zooming. * @param initialSeed the seed for the GWTRNG this uses; this may also be set per-call to generate * @param toMimic the world map to imitate, as a GreasedRegion with land as "on"; the height and width will be copied * @param noiseGenerator an instance of a noise generator capable of 3D noise, usually {@link FastNoise} or {@link FastNoise} * @param octaveMultiplier used to adjust the level of detail, with 0.5 at the bare-minimum detail and 1.0 normal */ public MimicMap(long initialSeed, GreasedRegion toMimic, Noise3D noiseGenerator, double octaveMultiplier) { super(initialSeed, toMimic.width, toMimic.height, noiseGenerator, octaveMultiplier); earth = toMimic; earthOriginal = earth.copy(); coast = earth.copy().not().fringe(2); shallow = earth.copy().fringe(2); }
/** * Constructs a concrete WorldMapGenerator for a map that should have land in roughly the same places as the * given GreasedRegion's "on" cells, using an elliptical projection (specifically, a Mollweide projection). * Takes an initial seed, the GreasedRegion containing land positions, parameters for noise generation (a * {@link Noise3D} implementation, which is usually {@link FastNoise#instance}, and a multiplier on how many * octaves of noise to use, with 1.0 being normal (high) detail and higher multipliers producing even more * detailed noise when zoomed-in). The {@code initialSeed} parameter may or may not be used, * since you can specify the seed to use when you call {@link #generate(long)}. The width and height of the map * cannot be changed after the fact. FastNoise will be the fastest 3D generator to use for * {@code noiseGenerator}, and the seed it's constructed with doesn't matter because this will change the * seed several times at different scales of noise (it's fine to use the static {@link FastNoise#instance} * because it has no changing state between runs of the program). The {@code octaveMultiplier} parameter should * probably be no lower than 0.5, but can be arbitrarily high if you're willing to spend much more time on * generating detail only noticeable at very high zoom; normally 1.0 is fine and may even be too high for maps * that don't require zooming. * @param initialSeed the seed for the GWTRNG this uses; this may also be set per-call to generate * @param toMimic the world map to imitate, as a GreasedRegion with land as "on"; the height and width will be copied * @param noiseGenerator an instance of a noise generator capable of 3D noise, usually {@link FastNoise} or {@link FastNoise} * @param octaveMultiplier used to adjust the level of detail, with 0.5 at the bare-minimum detail and 1.0 normal */ public LocalMimicMap(long initialSeed, GreasedRegion toMimic, Noise2D noiseGenerator, double octaveMultiplier) { super(initialSeed, toMimic.width, toMimic.height, noiseGenerator, octaveMultiplier); earth = toMimic; earthOriginal = earth.copy(); coast = earth.copy().not().fringe(2); shallow = earth.copy().fringe(2); }
/** * Takes the "on" cells in this GreasedRegion and produces amount GreasedRegions, each one expanded by 1 cell in * the 4 orthogonal directions relative to the previous GreasedRegion, making each "on" cell take up a diamond- * shaped area. After producing the expansions, this removes the previous GreasedRegion from the next GreasedRegion * in the array, making each "fringe" in the series have 1 "thickness," which can be useful for finding which layer * of expansion a cell lies in. This returns an array of GreasedRegions with progressively greater expansions * without the cells of this GreasedRegion, and does not modify this GreasedRegion. * <br> * This method is very efficient due to how the class is implemented, and the various spatial increase/decrease * methods (including {@link #expand()}, {@link #retract()}, {@link #fringe()}, and {@link #surface()}) all perform * very well by operating in bulk on up to 64 cells at a time. * @return an array of new GreasedRegions, length == amount, where each one is a 1-depth fringe pushed further out from this */ public GreasedRegion[] fringeSeries(int amount) { if(amount <= 0) return new GreasedRegion[0]; GreasedRegion[] regions = new GreasedRegion[amount]; GreasedRegion temp = new GreasedRegion(this); regions[0] = new GreasedRegion(temp); for (int i = 1; i < amount; i++) { regions[i] = new GreasedRegion(temp.expand()); } for (int i = 0; i < amount - 1; i++) { regions[i].xor(regions[i + 1]); } regions[amount - 1].fringe(); return regions; } public ArrayList<GreasedRegion> fringeSeriesToLimit()
allCorridors = new GreasedRegion(environment, DungeonUtility.CORRIDOR_FLOOR); allCaves = new GreasedRegion(environment, DungeonUtility.CAVE_FLOOR); GreasedRegion d = allCorridors.copy().fringe().and(allRooms), m = allCaves.copy().fringe().and(allRooms.copy().or(allCorridors)); doorways = d.asCoords(); mouths = m.asCoords(); GreasedRegion someDoors = sep.copy().fringe().and(allRooms); Coord[] doors = someDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(16); someDoors.remake(sep).fringe().and(allCaves); doors = someDoors.asCoords(); for (int i = 0; i < doors.length; i++) { GreasedRegion aroundDoors = sep.copy().fringe().and(allCorridors); Coord[] doors = aroundDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(32); aroundDoors.remake(sep).fringe().and(allCaves); doors = aroundDoors.asCoords(); for (int i = 0; i < doors.length; i++) { GreasedRegion aroundMouths = sep.copy().fringe().and(allCorridors); Coord[] maws = aroundMouths.asCoords(); List<GreasedRegion> near = new ArrayList<>(48); aroundMouths.remake(sep).fringe().and(allRooms); maws = aroundMouths.asCoords();
/** * Returns a modified version of changing where 0 represents empty space, 1 represents border, and 2 represents * "body." Only a 12x12 area will be changed by this call, with its minimum x and y determined by xPos and yPos. * The seed will change each time this runs, producing different shapes each time. * The technique used here is derived from https://github.com/zfedoran/pixel-sprite-generator . * @param changing an int array that will be altered if possible * @param xPos the minimum x to modify; the maximum will be xPos + 12, exclusive * @param yPos the minimum y to modify; the maximum will be yPos + 12, exclusive * @return changing, after modifications */ public int[][] generateInto(int[][] changing, int xPos, int yPos) { int w = workingBody.width, h = workingBody.height, ys = (h + 63) >> 6; if(changing.length < w * 2 || changing[0].length < h || xPos + w * 2 >= changing.length || yPos + h >= changing[0].length) return changing; randomRegion.refill(randomness, 0.75, w, h); workingSolid.remake(potentialSolid); workingBody.remake(potentialBody).or(potentialSolid).andNot(alwaysSolid).and(randomRegion); workingSolid.andNot(workingBody).or(randomRegion.remake(workingBody).fringe()); for (int x = 0, o = w*2-1; x < w; x++, o--) { for (int y = 0; y < h; y++) { changing[xPos + x][yPos + y] = ((workingBody.data[x * ys + (y >> 6)] & (1L << (y & 63))) != 0 ? 2 : 0) | ((workingSolid.data[x * ys + (y >> 6)] & (1L << (y & 63))) != 0 ? 1 : 0); } System.arraycopy(changing[xPos + x], yPos, changing[xPos + o], yPos, h); } return changing; }
GreasedRegion d = allCorridors.copy().fringe().and(allRooms); connections = doorways = d.asCoords(); mouths = new Coord[0]; GreasedRegion someDoors = sep.copy().fringe().and(allRooms); Coord[] doors = someDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(4); GreasedRegion aroundDoors = sep.copy().fringe().and(allCorridors); Coord[] doors = aroundDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(10);
long[] b2 = new long[t.data.length]; System.arraycopy(t.data, 0, b2, 0, b2.length); t.remake(this).fringe().and(bounds).tally(); if(t.ct <= 0) return this;
for(Coord hole : new GreasedRegion(map, '.').fringe().removeEdges().mixedRandomSeparated(0.25, -1, rng.nextLong())) { if (((map[hole.x - 1][hole.y] == '.' && map[hole.x + 1][hole.y] == '.') || (map[hole.x][hole.y - 1] == '.' && map[hole.x][hole.y + 1] == '.'))) {
GreasedRegion d = allCorridors.copy().fringe().and(allRooms); connections = doorways = d.asCoords(); mouths = new Coord[0]; GreasedRegion someDoors = sep.copy().fringe().and(allRooms); Coord[] doors = someDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(4); GreasedRegion aroundDoors = sep.copy().fringe().and(allCorridors); Coord[] doors = aroundDoors.asCoords(); List<GreasedRegion> near = new ArrayList<>(10);
/** * Gets an OrderedSet of OrderedSet of Coord, where each inner OrderedSet of Coord refers to a placement * region along a straight wall with length 3 or more, not including corners. Each Coord refers to a single cell * along the straight wall. This could be useful for placing weapon racks in armories, chalkboards in schoolrooms * (tutorial missions, perhaps?), or even large paintings/murals in palaces. * @return a set of sets of Coord where each set of Coord is a wall's viable placement for long things along it */ public OrderedSet<OrderedSet<Coord>> getAlongStraightWalls() { if(alongStraightWalls == null) { alongStraightWalls = new OrderedSet<>(32); GreasedRegion working = new GreasedRegion(finder.width, finder.height); for(GreasedRegion region : finder.rooms.keySet()) { working.remake(region).retract().fringe().andNot(nonRoom); for (GreasedRegion sp : working.split()) { if (sp.size() >= 3) alongStraightWalls.add(arrayToSet(sp.asCoords())); } } } return alongStraightWalls; }
workingSolid.remake(potentialSolid); workingBody.remake(potentialBody).or(potentialSolid).andNot(alwaysSolid).and(randomRegion); workingSolid.andNot(workingBody).or(randomRegion.remake(workingBody).fringe()); workingShade.remake(workingBody).neighborDown().not().and(workingBody); workingShine.remake(workingBody).neighborUp().not().and(workingBody).andNot(workingShade);