jp_DungeonGenerator
Below this comment is a pinnacle of sorcery unearthed from ancient era of byond.
Proceed with caution, for you may not comprehed whatever the fuck this is.
I sure don't. Original code by http://www.byond.com/members/Jp
Adapted for Eris and more modern byond versions by me.
Quite a bit was modified/removed/re-done.
Pathing was made strict/all objects here are subtype of obj/procedural.
- Nestor/drexample (full permission to bug me if you have questions or code suggestions)
Vars | |
ERROR_BAD_AREA | The area that the generator is allowed to work on was specified badly |
---|---|
ERROR_LONGPATHCHANCE_BAD | The chance of getting a long path was a bad number |
ERROR_MAX_ITERATIONS_CONNECTIVITY | Parameters were fine, but maximum iterations was reached while ensuring connectivity. If you get this error, there are /no/ guarantees about reachability - indeed, you may end up with a dungeon where no room is reachable from any other room. |
ERROR_MAX_ITERATIONS_EXTRAPATHS | Parameters were fine, but maximum iterations was reached while placing extra paths after connectivity was ensured. The dungeon should be fine, all the rooms should be reachable, but it may be less interesting. Or you may just have asked to place too many extra paths. |
ERROR_MAX_ITERATIONS_ROOMS | Parameters were fine, but maximum iterations was reached while placing rooms. This is not necessarily a fatal error condition - it just means not all the rooms you specified may have been placed. This error may be masked by errors further along in the process. |
ERROR_NO_FLOORTYPE | The type used for floors wasn't specified |
ERROR_NO_ROOMS | The allowed-rooms list is empty or bad. |
ERROR_NO_SUBMAPS | Everything was fine, but you forgot to include submaps for rooms that try to load them. |
ERROR_NO_WALLTYPE | The type used for walls wasn't specified |
ERROR_NUMEXTRAPATHS_BAD | The number of extra paths to draw was a bad number |
ERROR_NUMROOMS_BAD | The number of rooms to draw was a bad number |
ERROR_PATHENDCHANCE_BAD | The pathend chance is a bad number |
ERROR_PATH_LENGTH_BAD | The specified path lengths (either max or min) include a bad number |
ERROR_ROOM_SIZE_BAD | The specified room sizes (either max or min) include a bad number |
allowedRooms | The list of rooms the algorithm may place |
border_turfs | Internal list. No touching, unless you really know what you're doing. |
corner1 | One corner of the rectangle the algorithm is allowed to modify |
corner2 | The other corner of the rectangle the algorithm is allowed to modify |
doAccurateRoomPlacementCheck | Whether the algorithm should just use AABB collision detection between rooms, or use the slower version with no false positives |
examined | Internal list, used for pre-existing region stuff |
floortype | The type used for open floors placed in corridors |
lightSpawnChance | Chance to spawn a light during path generation |
longPathChance | The chance that any given path will be designated 'long' |
maxPathLength | The absolute maximum length paths are allowed to be. |
maximumIterations | The number of do-nothing iterations before the generator gives up with an error. |
minLongPathLength | The absolute minimum length of a long path |
minPathLength | The absolute minimum length paths are allowed to be. |
numExtraPaths | The upper limit on the number of extra paths placed beyond those required to ensure connectivity. NOT GUARANTEED TO BE REACHED |
numRooms | The upper limit of the number of 'rooms' placed in the dungeon. NOT GUARANTEED TO BE REACHED |
out_error | 0 if no error, positive value if a fatal error occured, negative value if something potentially bad but not fatal happened |
out_numLongPaths | The number of long paths the generator managed to place. This includes those required for reachability, as well as 'extra' paths. |
out_numPaths | The total number of paths the generator managed to place. This includes those required for reachability as well as 'extra' paths, as well as all long paths. |
out_numRooms | The number of rooms the generator managed to place |
out_region | The jp_DungeonRegion object that we were left with after all the rooms were connected |
out_rooms | A list containing all the jp_dungeonroom datums placed on the map |
out_seed | What seed was used to power the RNG for the dungeon. |
out_time | How long it took, in ms. May be negative if the generator runs 'over' midnight that is, starts in one day, ends in another. |
pathEndChance | The chance of terminating a path when it's found a valid endpoint, as a percentage |
pathWidth | The default width of paths connecting the rooms |
roomMaxSize | The maximum 'size' passed to rooms. |
roomMinSize | The minimum 'size' passed to rooms. |
usePreexistingRegions | Whether the algorithm should find any already extant open regions in the area it is working on, and incorporate them into the dungeon being generated |
walltype | Either a single type, or a list of types that are considered 'walls' for the purpose of this algorithm |
Procs | |
GetSquare | Returns an X by X square of turfs with initial turf being in bottom right |
addAllowedRoom | Adds the type 'r' to the list of allowed jp_dungeonrooms. Will create the list if it doesn't exist yet. |
addWallType | Adds the typepath 'w' to the list of types considered walls. |
errString | Returns 'true' if l is a list, false otherwise |
generate | Actually goes out on a limb and generates the dungeon. This procedure runs in the background, because it's very slow. The various out_ variables will be updated after the generator has finished running. I suggest spawn()ing off the call to the generator. |
getAdjacent | Returns a list of turfs adjacent to the turf 't'. The definition of 'adjacent' may depend on various properties set - at the moment, it is limited to the turfs in the four cardinal directions. |
getAdjacentFurther | Same as above, but skips X tiles from original one |
getAllowedRooms | Returns the list of allowed jp_dungeonrooms. This may be null, if the list is empty |
getArea | Returns a list containing two of the corners of the area the generator is allowed to touch. Returns a list of nulls if the area isn't specified |
getDoAccurateRoomPlacementCheck | Gets the current value of the accurate room placement check |
getExtraPaths | Returns the number of extra paths that will be placed in the dungeon |
getFloorType | Gets the type used for floors. |
getMaxX | Returns the largest x-value that the generator is allowed to touch Returns null if the area isn't specified. |
getMaxY | Returns the largest y-value that the generator is allowed to touch Returns null if the area isn't specified. |
getMaximumIterations | Gets the maximum number of do-nothing loops that can occur in a row |
getMinX | Returns the smallest x-value that the generator is allowed to touch. Returns null if the area isn't specified. |
getMinY | Returns the smallest y-value that the generator is allowed to touch. Returns null if the area isn't specified. |
getNumRooms | Returns the number of rooms that will be placed in the dungeon |
getPath | Constructs a path between two jp_DungeonRegions. |
getUsePreexistingRegions | Gets the current value of the use-preexisting-regions check |
getWallType | Gets the types considered walls. This may be null, a typepath, or a list of typepaths |
getZ | Returns the Z-level that the generator operates on Returns null if the area isn't specified. |
initializeSubmaps | Post-initializes all submaps |
intersects | Checks if two jp_dungeonrooms are too close to each other |
regionCreate | |
removeAllowedRoom | Removes the type 'r' from the list of allowed jp_dungeonrooms. Will create the list if it doesn't exist yet. |
removeWallType | Removes 'w' from the list of types considered walls |
setAllowedRooms | Sets the list of jp_dungeonrooms allowed in this dungeon to 'l'. 'l' should be a list of types. |
setArea | Sets the area that the generator is allowed to touch. This is required to be a rectangle. The parameters 'c1' and 'c2' specify the corners of the rectangle. They can be any two opposite corners. The generator does /not/ work over z-levels. |
setDoAccurateRoomPlacementCheck | Sets the accurate room placement check to 'b'. |
setExtraPaths | Sets the number of 'extra' paths that will be placed in the dungeon - 'extra' in that they aren't required to ensure reachability |
setFloorType | Sets the type used for floors - both in corridors, and in some rooms - to 'f' |
setLongPathChance | Sets and gets the chance of a path being designated a 'long' path, which has a different minimum length to a regular path. c must be a number between 0 and 100, inclusive. |
setMaxPathLength | Sets and gets the maximum and minimum lengths used for paths drawn between rooms in the dungeon, including 'long' paths (Which are required to be of a certain length) m must be a positive integer. |
setMaximumIterations | Sets the maximum number of do-nothing loops that can occur in a row before the generator gives up and does something else. |
setNumRooms | Sets the number of rooms that will be placed in the dungeon to 'r'. Positive integers only |
setPathEndChance | Sets and gets the chance of a path ending when it finds a suitable end turf. c must be a number between 0 and 100, inclusive |
setPathWidth | Sets the width of paths generated. Positive and negative integers work. (negatives invert the way square that sets width of the path is calculated) |
setRoomMinSize | Sets and gets the maximum and minimum sizes used for rooms placed on the dungeon. m must be a positive integer. |
setUsePreexistingRegions | Sets the use-preexisting-regions check to 'b' |
setWallType | Sets the type/s detected as 'wall' to either the typepath 'w' or the list of typepaths 'w' |
updateWallConnections | Internal procedures. Might be useful if you're writing a /jp_dungeonroom datum. Probably not useful if you just want to make a simple dungeon |
Var Details
ERROR_BAD_AREA
The area that the generator is allowed to work on was specified badly
ERROR_LONGPATHCHANCE_BAD
The chance of getting a long path was a bad number
ERROR_MAX_ITERATIONS_CONNECTIVITY
Parameters were fine, but maximum iterations was reached while ensuring connectivity. If you get this error, there are /no/ guarantees about reachability - indeed, you may end up with a dungeon where no room is reachable from any other room.
ERROR_MAX_ITERATIONS_EXTRAPATHS
Parameters were fine, but maximum iterations was reached while placing extra paths after connectivity was ensured. The dungeon should be fine, all the rooms should be reachable, but it may be less interesting. Or you may just have asked to place too many extra paths.
ERROR_MAX_ITERATIONS_ROOMS
Parameters were fine, but maximum iterations was reached while placing rooms. This is not necessarily a fatal error condition - it just means not all the rooms you specified may have been placed. This error may be masked by errors further along in the process.
ERROR_NO_FLOORTYPE
The type used for floors wasn't specified
ERROR_NO_ROOMS
The allowed-rooms list is empty or bad.
ERROR_NO_SUBMAPS
Everything was fine, but you forgot to include submaps for rooms that try to load them.
ERROR_NO_WALLTYPE
The type used for walls wasn't specified
ERROR_NUMEXTRAPATHS_BAD
The number of extra paths to draw was a bad number
ERROR_NUMROOMS_BAD
The number of rooms to draw was a bad number
ERROR_PATHENDCHANCE_BAD
The pathend chance is a bad number
ERROR_PATH_LENGTH_BAD
The specified path lengths (either max or min) include a bad number
ERROR_ROOM_SIZE_BAD
The specified room sizes (either max or min) include a bad number
allowedRooms
The list of rooms the algorithm may place
border_turfs
Internal list. No touching, unless you really know what you're doing.
corner1
One corner of the rectangle the algorithm is allowed to modify
corner2
The other corner of the rectangle the algorithm is allowed to modify
doAccurateRoomPlacementCheck
Whether the algorithm should just use AABB collision detection between rooms, or use the slower version with no false positives
examined
Internal list, used for pre-existing region stuff
floortype
The type used for open floors placed in corridors
lightSpawnChance
Chance to spawn a light during path generation
longPathChance
The chance that any given path will be designated 'long'
maxPathLength
The absolute maximum length paths are allowed to be.
maximumIterations
The number of do-nothing iterations before the generator gives up with an error.
minLongPathLength
The absolute minimum length of a long path
minPathLength
The absolute minimum length paths are allowed to be.
numExtraPaths
The upper limit on the number of extra paths placed beyond those required to ensure connectivity. NOT GUARANTEED TO BE REACHED
numRooms
The upper limit of the number of 'rooms' placed in the dungeon. NOT GUARANTEED TO BE REACHED
out_error
0 if no error, positive value if a fatal error occured, negative value if something potentially bad but not fatal happened
out_numLongPaths
The number of long paths the generator managed to place. This includes those required for reachability, as well as 'extra' paths.
out_numPaths
The total number of paths the generator managed to place. This includes those required for reachability as well as 'extra' paths, as well as all long paths.
out_numRooms
The number of rooms the generator managed to place
out_region
The jp_DungeonRegion object that we were left with after all the rooms were connected
out_rooms
A list containing all the jp_dungeonroom datums placed on the map
out_seed
What seed was used to power the RNG for the dungeon.
out_time
How long it took, in ms. May be negative if the generator runs 'over' midnight that is, starts in one day, ends in another.
pathEndChance
The chance of terminating a path when it's found a valid endpoint, as a percentage
pathWidth
The default width of paths connecting the rooms
roomMaxSize
The maximum 'size' passed to rooms.
roomMinSize
The minimum 'size' passed to rooms.
usePreexistingRegions
Whether the algorithm should find any already extant open regions in the area it is working on, and incorporate them into the dungeon being generated
walltype
Either a single type, or a list of types that are considered 'walls' for the purpose of this algorithm
Proc Details
GetSquare
Returns an X by X square of turfs with initial turf being in bottom right
addAllowedRoom
Adds the type 'r' to the list of allowed jp_dungeonrooms. Will create the list if it doesn't exist yet.
addWallType
Adds the typepath 'w' to the list of types considered walls.
errString
Returns 'true' if l is a list, false otherwise
External procedures, intended to be used by user code.
Returns a string representation of the error you pass into it. So you'd call g.errString(g.out_error)
generate
Actually goes out on a limb and generates the dungeon. This procedure runs in the background, because it's very slow. The various out_ variables will be updated after the generator has finished running. I suggest spawn()ing off the call to the generator.
After this procedure finishes executing, you should have a beautiful shiny dungeon, with all rooms reachable from all other rooms. If you don't, first check the parameters you've passed to the generator - if you've set the number of rooms to 0, or haven't set it, you may not get the results you expect. If the parameters you've passed seem fine, and you've written your own /jp_dungeonroom object, it might be a good idea to check whether' or not you meet all the assumptions my code makes about jp_dungeonroom objects. There should be a reasonably complete list in the helpfile. If that doesn't help you out, contact me in some way - you may have found a bug, or an assumption I haven't documented, or I can show you where you've gone wrong.
getAdjacent
Returns a list of turfs adjacent to the turf 't'. The definition of 'adjacent' may depend on various properties set - at the moment, it is limited to the turfs in the four cardinal directions.
getAdjacentFurther
Same as above, but skips X tiles from original one
getAllowedRooms
Returns the list of allowed jp_dungeonrooms. This may be null, if the list is empty
getArea
Returns a list containing two of the corners of the area the generator is allowed to touch. Returns a list of nulls if the area isn't specified
getDoAccurateRoomPlacementCheck
Gets the current value of the accurate room placement check
getExtraPaths
Returns the number of extra paths that will be placed in the dungeon
getFloorType
Gets the type used for floors.
getMaxX
Returns the largest x-value that the generator is allowed to touch Returns null if the area isn't specified.
getMaxY
Returns the largest y-value that the generator is allowed to touch Returns null if the area isn't specified.
getMaximumIterations
Gets the maximum number of do-nothing loops that can occur in a row
getMinX
Returns the smallest x-value that the generator is allowed to touch. Returns null if the area isn't specified.
getMinY
Returns the smallest y-value that the generator is allowed to touch. Returns null if the area isn't specified.
getNumRooms
Returns the number of rooms that will be placed in the dungeon
getPath
Constructs a path between two jp_DungeonRegions.
getUsePreexistingRegions
Gets the current value of the use-preexisting-regions check
getWallType
Gets the types considered walls. This may be null, a typepath, or a list of typepaths
getZ
Returns the Z-level that the generator operates on Returns null if the area isn't specified.
initializeSubmaps
Post-initializes all submaps
intersects
Checks if two jp_dungeonrooms are too close to each other
regionCreate
The remaining procedures are seriously internal, and I strongly suggest not *
touching them unless you're certain you know what you're doing. That includes * calling them, unless you've figured out what the side-effects and assumptions * of the procedure are. These may not work except in the context of a generate() * call.
removeAllowedRoom
Removes the type 'r' from the list of allowed jp_dungeonrooms. Will create the list if it doesn't exist yet.
removeWallType
Removes 'w' from the list of types considered walls
setAllowedRooms
Sets the list of jp_dungeonrooms allowed in this dungeon to 'l'. 'l' should be a list of types.
setArea
Sets the area that the generator is allowed to touch. This is required to be a rectangle. The parameters 'c1' and 'c2' specify the corners of the rectangle. They can be any two opposite corners. The generator does /not/ work over z-levels.
setDoAccurateRoomPlacementCheck
Sets the accurate room placement check to 'b'.
setExtraPaths
Sets the number of 'extra' paths that will be placed in the dungeon - 'extra' in that they aren't required to ensure reachability
setFloorType
Sets the type used for floors - both in corridors, and in some rooms - to 'f'
setLongPathChance
Sets and gets the chance of a path being designated a 'long' path, which has a different minimum length to a regular path. c must be a number between 0 and 100, inclusive.
setMaxPathLength
Sets and gets the maximum and minimum lengths used for paths drawn between rooms in the dungeon, including 'long' paths (Which are required to be of a certain length) m must be a positive integer.
setMaximumIterations
Sets the maximum number of do-nothing loops that can occur in a row before the generator gives up and does something else.
setNumRooms
Sets the number of rooms that will be placed in the dungeon to 'r'. Positive integers only
setPathEndChance
Sets and gets the chance of a path ending when it finds a suitable end turf. c must be a number between 0 and 100, inclusive
setPathWidth
Sets the width of paths generated. Positive and negative integers work. (negatives invert the way square that sets width of the path is calculated)
setRoomMinSize
Sets and gets the maximum and minimum sizes used for rooms placed on the dungeon. m must be a positive integer.
setUsePreexistingRegions
Sets the use-preexisting-regions check to 'b'
setWallType
Sets the type/s detected as 'wall' to either the typepath 'w' or the list of typepaths 'w'
updateWallConnections
Internal procedures. Might be useful if you're writing a /jp_dungeonroom datum. Probably not useful if you just want to make a simple dungeon