yellowstonegames / SquidLib

Useful tools for roguelike, role-playing, strategy, and other grid-based games in Java. Feedback is welcome!
Other
448 stars 46 forks source link

[Proposal] add stair generators, decorators to DungeonUtility #191

Closed Rakaneth closed 6 years ago

Rakaneth commented 6 years ago

I use DungeonGenerator with varied TilesetTypes for all of my dungeon-generating needs because, through that implementation, I get addWater(), addDoors(), addTraps(), and stairs. I would like to try other implementations of IDungeonGenerator, but they lack these (in my opinion) basic dungeon utilities, Adding them to DungeonUtility would give all the generators access to them.

tommyettinger commented 6 years ago

IDungeonGenerator only guarantees two methods in implementing classes, generate(), which returns a 2D char array, and getDungeon(), which gets the last generated 2D char array. Because DungeonGenerator can take either no arguments to its (different) generate() method, a TilesetType argument, or a 2D char array argument, it can use predefined types of dungeon with the first two, or the output of an IDungeonGenerator with the last argument type. DungeonGenerator, admittedly, could be named more clearly, it's really more of a dungeon decorator that can call some methods of dungeon creation on its own. SectionDungeonGenerator actually can do pretty much anything DungeonGenerator can do, plus placing lakes and mazes in unused areas of a dungeon, but is somewhat slower (maybe not noticeably) and requires a little more setup, since it needs to know which parts of a map are caves, which are rooms, and which are corridors. Several IDungeonGenerator types based on MixedGenerator, like SerpentMapGenerator, have this room/cave/corridor info already, and all of those and some more have a getEnvironment() method that can be given to SectionDungeonGenerator.

Example usage of DungeonGenerator with a FlowingCaveGenerator:

        int width = 80, height = 40;
        RNG rng = new RNG(0xDEADBEEF);
        DungeonGenerator dungeonGenerator = new DungeonGenerator(width, height, rng);
        FlowingCaveGenerator flow = new FlowingCaveGenerator(width, height, TilesetType.DEFAULT_DUNGEON, rng);
        dungeonGenerator.addWater(10);
        dungeonGenerator.addGrass(12);

        // flow makes a 2D char array, which is used as the map to decorate by dungeonGenerator
        char[][] dungeon = dungeonGenerator.generate(flow.generate());

Example usage of SectionDungeonGenerator with a SerpentMapGenerator:

        int width = 80, height = 40;
        RNG rng = new RNG(0xDEADBEEF);
        SectionDungeonGenerator sdg = new SectionDungeonGenerator(width, height, rng);
        sdg.addDoors(12, false);
        sdg.addBoulders(SectionDungeonGenerator.ALL, 13); // affects all area types
        sdg.addWater(SectionDungeonGenerator.CAVE, 9); // affects only cave areas on this level
        sdg.addLake(8); // replaces large areas of walls with watery lakes
        SerpentMapGenerator serpent = new SerpentMapGenerator(width, height, rng, 0.2); // 0.2 is random extra branch chance
        serpent.putWalledBoxRoomCarvers(5); // MixedGenerator and related generators use carvers.
        serpent.putRoundRoomCarvers(3); // SerpentMapGenerator makes a circular path through the level.
        serpent.putCaveCarvers(3); // The carvers determine what the path will be like.
        char[][] dungeon = serpent.generate(); // we need both the char[][] map and int[][] environment
        dungeon = sdg.generate(dungeon, serpent.getEnvironment());

I think this functionality is covered already, so I'll close this, but feel free to reopen if you have a way to streamline the dungeon generation, or even just an idea that might be able to cut down on boilerplate code.