public GreasedRegion fringe8way() { GreasedRegion cpy = new GreasedRegion(this); expand8way(); return andNot(cpy); } public GreasedRegion fringe8way(int amount)
public GreasedRegion fringe8way(int amount) { GreasedRegion cpy = new GreasedRegion(this); expand8way(amount); return andNot(cpy); }
/** * Takes the "on" cells in this GreasedRegion and expands them by one cell in the 4 orthogonal directions, producing * a diamoond shape, then removes the original area before expansion, producing only the cells that were "off" in * this and within 1 cell (orthogonal-only) of an "on" cell. This method is similar to {@link #surface()}, but * surface finds cells inside the current GreasedRegion, while fringe finds cells outside it. * <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. The surface and fringe methods do allocate one * temporary GreasedRegion to store the original before modification, but the others generally don't. * @return this for chaining */ public GreasedRegion fringe() { GreasedRegion cpy = new GreasedRegion(this); expand(); return andNot(cpy); } /**
/** * Takes the "on" cells in this GreasedRegion and expands them by amount cells in the 4 orthogonal directions * (iteratively, producing a diamond shape), then removes the original area before expansion, producing only the * cells that were "off" in this and within amount cells (orthogonal-only) of an "on" cell. This method is similar * to {@link #surface()}, but surface finds cells inside the current GreasedRegion, while fringe finds cells outside * it. * <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. The surface and fringe methods do allocate one * temporary GreasedRegion to store the original before modification, but the others generally don't. * @return this for chaining */ public GreasedRegion fringe(int amount) { GreasedRegion cpy = new GreasedRegion(this); expand(amount); return andNot(cpy); }
public GreasedRegion removeIsolated() { int fst = firstTight(); GreasedRegion remaining = new GreasedRegion(this), filled = new GreasedRegion(this); while (fst >= 0) { filled.empty().insert(fst).flood(remaining, 8); if(filled.size() <= 4) andNot(filled); remaining.andNot(filled); fst = remaining.firstTight(); } return this; }
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()); workingShade.remake(workingBody).neighborDown().not().and(workingBody); workingShine.remake(workingBody).neighborUp().not().and(workingBody).andNot(workingShade); workingBody.andNot(workingShade).andNot(workingShine); for (int x = 0, o = w*2-1; x < w; x++, o--) { for (int y = 0; y < h; y++) {
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).fringe8way()); workingShade.remake(workingBody).neighborDown().not().and(workingBody); workingShine.remake(workingBody).neighborUp().not().and(workingBody).andNot(workingShade); workingBody.andNot(workingShade).andNot(workingShine); for (int x = 0, o = w*2-1; x < w; x++, o--) { for (int y = 0; y < h; y++) {
/** * 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 filled = new GreasedRegion(width, height).insert(fst).flood8way(remaining, width * height); scattered.add(filled); remaining.andNot(filled); fst = remaining.firstTight();
GreasedRegion filled = new GreasedRegion(width, height).insert(fst).flood(remaining, width * height); scattered.add(filled); remaining.andNot(filled); fst = remaining.firstTight();
t = rf.rooms.keyAt(i); regions.add(t); all.andNot(t); t.writeIntsInto(map, names.size()); names.add("room"+names.size()); t = rf.corridors.keyAt(i); regions.add(t); all.andNot(t); t.writeIntsInto(map, names.size()); names.add("corridor"+names.size()); t = rf.caves.keyAt(i); regions.add(t); all.andNot(t); t.writeIntsInto(map, names.size()); names.add("cave"+names.size());
/** * Gets an OrderedSet of OrderedSet of Coord, where each inner OrderedSet of Coord refers to a room's * corners, and each Coord is one of those corners. There are more uses for corner placement than I can list. This * doesn't always identify all corners, since it only finds ones in rooms, and a cave too close to a corner can * cause that corner to be ignored. * @return a set of sets of Coord where each set of Coord is a room's corners */ public OrderedSet<OrderedSet<Coord>> getCorners() { if(corners == null) { corners = new OrderedSet<>(32); GreasedRegion working = new GreasedRegion(finder.width, finder.height); for(GreasedRegion region : finder.rooms.keySet()) { working.remake(region).expand().retract8way().xor(region).andNot(nonRoom); OrderedSet<Coord> os = new OrderedSet<>(working.asCoords()); corners.add(os); } } return corners; } /**
/** * Finds the largest contiguous area of "on" cells in this GreasedRegion and returns it; does not modify this * GreasedRegion. If there are multiple areas that are all equally large with no larger area, this returns the * region it checks first and still is largest (first determined by the same ordering {@link #nth(int)} takes). * This may return an empty GreasedRegion if there are no "on" cells, but it will never return null. * Here, contiguous means adjacent on any 8-way direction, and considers cells as part of a contiguous area even if * all connections but one, which can be orthogonal or diagonal, are blocked by "off" cells. * @return a new GreasedRegion that corresponds to the largest contiguous sub-region of "on" cells in this. */ public GreasedRegion largestPart8way() { int fst = firstTight(), bestSize = 0, currentSize; GreasedRegion remaining = new GreasedRegion(this), filled = new GreasedRegion(width, height), choice = new GreasedRegion(width, height); while (fst >= 0) { filled.empty().insert(fst).flood8way(remaining, width * height); if((currentSize = filled.size()) > bestSize) { bestSize = currentSize; choice.remake(filled); } remaining.andNot(filled); fst = remaining.firstTight(); } return choice; }
/** * Finds the largest contiguous area of "on" cells in this GreasedRegion and returns it; does not modify this * GreasedRegion. If there are multiple areas that are all equally large with no larger area, this returns the * region it checks first and still is largest (first determined by the same ordering {@link #nth(int)} takes). * This may return an empty GreasedRegion if there are no "on" cells, but it will never return null. * Here, contiguous means adjacent on an orthogonal direction, and this doesn't consider diagonally-connected cells * as contiguous unless they also have an orthogonal connection. * @return a new GreasedRegion that corresponds to the largest contiguous sub-region of "on" cells in this. */ public GreasedRegion largestPart() { int fst = firstTight(), bestSize = 0, currentSize; GreasedRegion remaining = new GreasedRegion(this), filled = new GreasedRegion(width, height), choice = new GreasedRegion(width, height); while (fst >= 0) { filled.empty().insert(fst).flood(remaining, width * height); if((currentSize = filled.size()) > bestSize) { bestSize = currentSize; choice.remake(filled); } remaining.andNot(filled); fst = remaining.firstTight(); } return choice; }
/** * 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; }
allFloors = new GreasedRegion(basic, '.'); allRooms = allFloors.copy().retract8way().flood(allFloors, 2); allCorridors = allFloors.copy().andNot(allRooms);
allCorridors = allFloors.copy().andNot(allRooms); allCaves = new GreasedRegion(width, height); allCorridors = new GreasedRegion(width, height); caves.put(allCaves, new ArrayList<GreasedRegion>()); connections = mouths = allCaves.copy().andNot(allCaves.copy().retract8way()).retract().asCoords(); doorways = new Coord[0]; environment = allCaves.writeInts(environment, DungeonUtility.CAVE_FLOOR);
nation.zoom(stx, sty).expand8way().expand().fray(0.5); fillable.andNot(nation); nation.intoChars(zoomedMap, c);
if(rng.nextDouble() < roomChance) gen.region.andNot(rooms.get(i).fringe8way().deteriorate(rng, 0.81));