Class DungeonGenerator

java.lang.Object
squidpony.squidgrid.mapping.DungeonGenerator
All Implemented Interfaces:
IDungeonGenerator

public class DungeonGenerator
extends Object
implements IDungeonGenerator
The primary way to create a more-complete dungeon, layering different effects and modifications on top of a DungeonBoneGen's dungeon or another dungeon without such effects. Also ensures only connected regions of the map are used by filling unreachable areas with walls, and can find far-apart staircase positions if generate() is used or can keep existing staircases in a map if generateRespectingStairs() is used.
The main technique for using this is simple: Construct a DungeonGenerator, usually with the desired width and height, then call any feature adding methods that you want in the dungeon, like addWater(), addTraps, addGrass(), or addDoors(). Some of these take different parameters, like addDoors() which need to know if it should check openings that are two cells wide to add a door and a wall to, or whether it should only add doors to single-cell openings. Then call generate() to get a char[][] with the desired dungeon map, using a fixed repertoire of chars to represent the different features. After calling generate(), you can safely get the values from the stairsUp and stairsDown fields, which are Coords that should be a long distance from each other but connected in the dungeon. You may want to change those to staircase characters, but there's no requirement to do anything with them. It's recommended that you keep the resulting char[][] maps in some collection that can be saved, since DungeonGenerator only stores a temporary copy of the most recently-generated map. The DungeonUtility field of this class, utility, is a convenient way of accessing the non-static methods in that class, such as randomFloor(), without needing to create another DungeonUtility (this class creates one, so you don't have to).
Previews for the kinds of dungeon this generates, given a certain argument to generate():
  • Using TilesetType.DEFAULT_DUNGEON (text, click "Raw", may need to zoom out): https://gist.github.com/tommyettinger/a3bd413b903f2e103541
  • Using TilesetType.DEFAULT_DUNGEON (graphical, scroll down and to the right): http://tommyettinger.github.io/home/PixVoxel/dungeon/dungeon.html
  • Using SerpentMapGenerator.generate() (text, click "Raw", may need to zoom out): https://gist.github.com/tommyettinger/93b47048fc8a209a9712

As of March 6, 2016, the algorithm this uses to place water and grass was swapped for a more precise version. You no longer need to give this 150% in addWater or addGrass to effectively produce 100% water or grass, and this should be no more than 1.1% different from the percentage you request for any effects. If you need to reproduce dungeons with the same seed and get the same (imprecise) results as before this change, it's probably not possible unless you save the previously-generated char[][] dungeons, since several other things may have changed as well.
Author:
Eben Howard - http://squidpony.com - howard@squidpony.com, Tommy Ettinger - https://github.com/tommyettinger
See Also:
this class exposes a DungeonUtility member; DungeonUtility also has many useful static methods
  • Nested Class Summary

    Nested Classes 
    Modifier and Type Class Description
    static class  DungeonGenerator.FillEffect
    The effects that can be applied to this dungeon.
  • Field Summary

    Fields 
    Modifier and Type Field Description
    protected char[][] dungeon  
    EnumMap<DungeonGenerator.FillEffect,​Integer> fx
    The effects that will be applied when generate is called.
    protected DungeonBoneGen gen  
    protected int height  
    protected long rebuildSeed  
    IStatefulRNG rng  
    protected boolean seedFixed  
    Coord stairsDown  
    Coord stairsUp  
    DungeonUtility utility  
    protected int width  
  • Constructor Summary

    Constructors 
    Constructor Description
    DungeonGenerator()
    Make a DungeonGenerator with a GWTRNG using a random seed, height 40, and width 40.
    DungeonGenerator​(int width, int height)
    Make a DungeonGenerator with the given height and width; a GWTRNG will be used for generating a dungeon and adding features using a random seed.
    DungeonGenerator​(int width, int height, IRNG rng)
    Make a DungeonGenerator with the given height, width, and RNG.
    DungeonGenerator​(DungeonGenerator copying)
    Copies all fields from copying and makes a new DungeonGenerator.
  • Method Summary

    Modifier and Type Method Description
    DungeonGenerator addBoulders​(int percentage)
    Turns the given percentage of floor cells not already adjacent to walls into wall cells, represented by '#'.
    DungeonGenerator addDoors​(int percentage, boolean doubleDoors)
    Turns the given percentage of viable doorways into doors, represented by '+' for doors that allow travel along the x-axis and '/' for doors that allow travel along the y-axis.
    DungeonGenerator addGrass​(int percentage)
    Turns the majority of the given percentage of floor cells into grass cells, represented by '"'.
    DungeonGenerator addTraps​(int percentage)
    Turns the given percentage of open area floor cells into trap cells, represented by '^'.
    DungeonGenerator addWater​(int percentage)
    Turns the majority of the given percentage of floor cells into water cells, represented by '~'.
    DungeonGenerator addWater​(int percentage, int islandSpacing)
    Turns the majority of the given percentage of floor cells into water cells, represented by '~'.
    DungeonGenerator clearEffects()
    Removes any door, water, or trap insertion effects that this DungeonGenerator would put in future dungeons.
    char[][] generate()
    Generate a char[][] dungeon using TilesetType.DEFAULT_DUNGEON; this produces a dungeon appropriate for a level of ruins or a partially constructed dungeon.
    char[][] generate​(char[][] baseDungeon)
    Generate a char[][] dungeon with extra features given a baseDungeon that has already been generated.
    char[][] generate​(TilesetType kind)
    Generate a char[][] dungeon given a TilesetType; the comments in that class provide some opinions on what each TilesetType value could be used for in a game.
    char[][] generateRespectingStairs​(char[][] baseDungeon)
    Generate a char[][] dungeon with extra features given a baseDungeon that has already been generated, and that already has staircases represented by greater than and less than signs.
    char[][] getBareDungeon()
    Get the most recently generated char[][] dungeon out of this class without any chars other than '#' or '.', for walls and floors respectively.
    char[][] getDungeon()
    Get the most recently generated char[][] dungeon out of this class.
    int getHeight()
    Height of the dungeon in cells.
    long getRebuildSeed()
    Gets the seed that can be used to rebuild an identical dungeon to the latest one generated (or the seed that will be used to generate the first dungeon if none has been made yet).
    int getWidth()
    Width of the dungeon in cells.
    protected OrderedSet<Coord> removeAdjacent​(OrderedSet<Coord> coll, Coord pt)  
    protected OrderedSet<Coord> removeAdjacent​(OrderedSet<Coord> coll, Coord pt1, Coord pt2)  
    void setDungeon​(char[][] dungeon)
    Change the underlying char[][]; only affects the toString method, and of course getDungeon.
    String toString()
    Provides a string representation of the latest generated dungeon.
    protected OrderedSet<Coord> viableDoorways​(boolean doubleDoors, char[][] map)  

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • Field Details

  • Constructor Details

    • DungeonGenerator

      Make a DungeonGenerator with a GWTRNG using a random seed, height 40, and width 40.
    • DungeonGenerator

      public DungeonGenerator​(int width, int height)
      Make a DungeonGenerator with the given height and width; a GWTRNG will be used for generating a dungeon and adding features using a random seed. If width or height is greater than 256, then this will expand the Coord pool from its 256x256 default so it stores a reference to each Coord that might be used in the creation of the dungeon (if width and height are 300 and 300, the Coord pool will be 300x300; if width and height are 500 and 100, the Coord pool will be 500x256 because it won't shrink below the default size of 256x256).
      Parameters:
      width - The width of the dungeon in cells
      height - The height of the dungeon in cells
    • DungeonGenerator

      public DungeonGenerator​(int width, int height, IRNG rng)
      Make a DungeonGenerator with the given height, width, and RNG. Use this if you want to seed the RNG. If width or height is greater than 256, then this will expand the Coord pool from its 256x256 default so it stores a reference to each Coord that might be used in the creation of the dungeon (if width and height are 300 and 300, the Coord pool will be 300x300; if width and height are 500 and 100, the Coord pool will be 500x256 because it won't shrink below the default size of 256x256).
      Parameters:
      width - The width of the dungeon in cells
      height - The height of the dungeon in cells
      rng - The RNG to use for all purposes in this class; if it is a StatefulRNG, then it will be used as-is, but if it is not a StatefulRNG, a new StatefulRNG will be used, randomly seeded by this parameter
    • DungeonGenerator

      public DungeonGenerator​(DungeonGenerator copying)
      Copies all fields from copying and makes a new DungeonGenerator.
      Parameters:
      copying - the DungeonGenerator to copy
  • Method Details

    • getDungeon

      public char[][] getDungeon()
      Get the most recently generated char[][] dungeon out of this class. The dungeon may be null if generate() or setDungeon() have not been called.
      Specified by:
      getDungeon in interface IDungeonGenerator
      Returns:
      a char[][] dungeon, or null.
    • getBareDungeon

      public char[][] getBareDungeon()
      Get the most recently generated char[][] dungeon out of this class without any chars other than '#' or '.', for walls and floors respectively. The dungeon may be null if generate() or setDungeon() have not been called.
      Returns:
      a char[][] dungeon with only '#' for walls and '.' for floors, or null.
    • setDungeon

      public void setDungeon​(char[][] dungeon)
      Change the underlying char[][]; only affects the toString method, and of course getDungeon.
      Parameters:
      dungeon - a char[][], probably produced by an earlier call to this class and then modified.
    • getHeight

      public int getHeight()
      Height of the dungeon in cells.
      Returns:
      Height of the dungeon in cells.
    • getWidth

      public int getWidth()
      Width of the dungeon in cells.
      Returns:
      Width of the dungeon in cells.
    • addWater

      public DungeonGenerator addWater​(int percentage)
      Turns the majority of the given percentage of floor cells into water cells, represented by '~'. Water will be clustered into a random number of pools, with more appearing if needed to fill the percentage. Each pool will have randomized volume that should fill or get very close to filling the requested percentage, unless the pools encounter too much tight space. If this DungeonGenerator previously had addWater called, the latest call will take precedence. No islands will be placed with this variant, but the edge of the water will be shallow, represented by ','.
      Parameters:
      percentage - the percentage of floor cells to fill with water
      Returns:
      this DungeonGenerator; can be chained
    • addWater

      public DungeonGenerator addWater​(int percentage, int islandSpacing)
      Turns the majority of the given percentage of floor cells into water cells, represented by '~'. Water will be clustered into a random number of pools, with more appearing if needed to fill the percentage. Each pool will have randomized volume that should fill or get very close to filling the requested percentage, unless the pools encounter too much tight space. If this DungeonGenerator previously had addWater called, the latest call will take precedence. If islandSpacing is greater than 1, then this will place islands of floor, '.', surrounded by shallow water, ',', at about the specified distance with Euclidean measurement.
      Parameters:
      percentage - the percentage of floor cells to fill with water
      islandSpacing - if greater than 1, islands will be placed randomly this many cells apart.
      Returns:
      this DungeonGenerator; can be chained
    • addGrass

      public DungeonGenerator addGrass​(int percentage)
      Turns the majority of the given percentage of floor cells into grass cells, represented by '"'. Grass will be clustered into a random number of patches, with more appearing if needed to fill the percentage. Each area will have randomized volume that should fill or get very close to filling the requested percentage, unless the patches encounter too much tight space. If this DungeonGenerator previously had addGrass called, the latest call will take precedence.
      Parameters:
      percentage - the percentage of floor cells to fill with grass
      Returns:
      this DungeonGenerator; can be chained
    • addBoulders

      public DungeonGenerator addBoulders​(int percentage)
      Turns the given percentage of floor cells not already adjacent to walls into wall cells, represented by '#'. If this DungeonGenerator previously had addBoulders called, the latest call will take precedence.
      Parameters:
      percentage - the percentage of floor cells not adjacent to walls to fill with boulders.
      Returns:
      this DungeonGenerator; can be chained
    • addDoors

      public DungeonGenerator addDoors​(int percentage, boolean doubleDoors)
      Turns the given percentage of viable doorways into doors, represented by '+' for doors that allow travel along the x-axis and '/' for doors that allow travel along the y-axis. If doubleDoors is true, 2-cell-wide openings will be considered viable doorways and will fill one cell with a wall, the other a door. If this DungeonGenerator previously had addDoors called, the latest call will take precedence.
      Parameters:
      percentage - the percentage of valid openings to corridors to fill with doors; should be between 10 and 20 if you want doors to appear more than a few times, but not fill every possible opening.
      doubleDoors - true if you want two-cell-wide openings to receive a door and a wall; false if only one-cell-wide openings should receive doors. Usually, this should be true.
      Returns:
      this DungeonGenerator; can be chained
    • addTraps

      public DungeonGenerator addTraps​(int percentage)
      Turns the given percentage of open area floor cells into trap cells, represented by '^'. Corridors that have no possible way to move around a trap will not receive traps, ever. If this DungeonGenerator previously had addTraps called, the latest call will take precedence.
      Parameters:
      percentage - the percentage of valid cells to fill with traps; should be no higher than 5 unless the dungeon floor is meant to be a kill screen or minefield.
      Returns:
      this DungeonGenerator; can be chained
    • clearEffects

      Removes any door, water, or trap insertion effects that this DungeonGenerator would put in future dungeons.
      Returns:
      this DungeonGenerator, with all effects removed. Can be chained.
    • removeAdjacent

      protected OrderedSet<Coord> removeAdjacent​(OrderedSet<Coord> coll, Coord pt)
    • removeAdjacent

      protected OrderedSet<Coord> removeAdjacent​(OrderedSet<Coord> coll, Coord pt1, Coord pt2)
    • viableDoorways

      protected OrderedSet<Coord> viableDoorways​(boolean doubleDoors, char[][] map)
    • generate

      public char[][] generate()
      Generate a char[][] dungeon using TilesetType.DEFAULT_DUNGEON; this produces a dungeon appropriate for a level of ruins or a partially constructed dungeon. This uses '#' for walls, '.' for floors, '~' for deep water, ',' for shallow water, '^' for traps, '+' for doors that provide horizontal passage, and '/' for doors that provide vertical passage. Use the addDoors, addWater, addGrass, and addTraps methods of this class to request these in the generated map. Also sets the fields stairsUp and stairsDown to two randomly chosen, distant, connected, walkable cells.
      Specified by:
      generate in interface IDungeonGenerator
      Returns:
      a char[][] dungeon
    • generate

      public char[][] generate​(TilesetType kind)
      Generate a char[][] dungeon given a TilesetType; the comments in that class provide some opinions on what each TilesetType value could be used for in a game. This uses '#' for walls, '.' for floors, '~' for deep water, ',' for shallow water, '^' for traps, '+' for doors that provide horizontal passage, and '/' for doors that provide vertical passage. Use the addDoors, addWater, addGrass, and addTraps methods of this class to request these in the generated map. Also sets the fields stairsUp and stairsDown to two randomly chosen, distant, connected, walkable cells.
      Parameters:
      kind - a TilesetType enum value, such as TilesetType.DEFAULT_DUNGEON
      Returns:
      a char[][] dungeon
      See Also:
      TilesetType
    • generate

      public char[][] generate​(char[][] baseDungeon)
      Generate a char[][] dungeon with extra features given a baseDungeon that has already been generated. Typically, you want to call generate with a TilesetType or no argument for the easiest generation; this method is meant for adding features like water and doors to existing simple maps. This uses '#' for walls, '.' for floors, '~' for deep water, ',' for shallow water, '^' for traps, '+' for doors that provide horizontal passage, and '/' for doors that provide vertical passage. Use the addDoors, addWater, addGrass, and addTraps methods of this class to request these in the generated map. Also sets the fields stairsUp and stairsDown to two randomly chosen, distant, connected, walkable cells.
      Special behavior here: If tab characters are present in the 2D char array, they will be replaced with '.' in the final dungeon, but will also be tried first as valid staircase locations (with a high distance possible to travel away from the starting staircase). If no tab characters are present this will search for '.' floors to place stairs on, as normal. This tab-first behavior is useful in conjunction with some methods that establish a good path in an existing dungeon; an example is DungeonUtility.ensurePath(dungeon, rng, '\t', '#'); then passing dungeon (which that code modifies) in as baseDungeon to this method.
      Parameters:
      baseDungeon - a pre-made dungeon consisting of '#' for walls and '.' for floors; may be modified in-place
      Returns:
      a char[][] dungeon
    • generateRespectingStairs

      public char[][] generateRespectingStairs​(char[][] baseDungeon)
      Generate a char[][] dungeon with extra features given a baseDungeon that has already been generated, and that already has staircases represented by greater than and less than signs. Typically, you want to call generate with a TilesetType or no argument for the easiest generation; this method is meant for adding features like water and doors to existing simple maps. This uses '#' for walls, '.' for floors, '~' for deep water, ',' for shallow water, '^' for traps, '+' for doors that provide horizontal passage, and '/' for doors that provide vertical passage. Use the addDoors, addWater, addGrass, and addTraps methods of this class to request these in the generated map. Also sets the fields stairsUp and stairsDown to null, and expects stairs to be already handled.
      Parameters:
      baseDungeon - a pre-made dungeon consisting of '#' for walls and '.' for floors, with stairs already in; may be modified in-place
      Returns:
      a char[][] dungeon
    • getRebuildSeed

      public long getRebuildSeed()
      Gets the seed that can be used to rebuild an identical dungeon to the latest one generated (or the seed that will be used to generate the first dungeon if none has been made yet). You can pass the long this returns to the setState() method on this class' rng field, which assuming all other calls to generate a dungeon are identical, will ensure generate() or generateRespectingStairs() will produce the same dungeon output as the dungeon originally generated with the seed this returned.
      You can also call getState() on the rng field yourself immediately before generating a dungeon, but this method handles some complexities of when the state is actually used to generate a dungeon; since StatefulRNG objects can be shared between different classes that use random numbers, the state could change between when you call getState() and when this class generates a dungeon. Using getRebuildSeed() eliminates that confusion.
      Returns:
      a seed as a long that can be passed to setState() on this class' rng field to recreate a dungeon
    • toString

      public String toString()
      Provides a string representation of the latest generated dungeon.
      Overrides:
      toString in class Object
      Returns:
      a printable string version of the latest generated dungeon.