pub struct DungeonGridMutator { /* private fields */ }
Expand description

This helper struct can be used to create a grid of cells (DungeonGridCell).

All coordinates that this struct uses are “ingame” coordinates (so (x, y)), unless otherwise noted.

It can also take ownership of existing Vec<DungeonGridCell> and manipulate them.

Finally you can convert this struct into its inner Vec<DungeonGridCell> using Self::into_inner(). See the notes on Self::new() for more information.

The cell grid is used in one phase of the dungeon generation. Note that most of the generation functions here will generate tiles in the global dungeon struct.

Implementations§

source§

impl DungeonGridMutator

source

pub fn new_from_vec( in_cells: Vec<DungeonGridCell>, width: usize, height: usize, ov29: OverlayLoadLease<29> ) -> Self

Takes ownership of the given in_cells and returns a new DungeonGridMutator.

The grid is a vector of grid cells stored in column-major order (!) (such that grid cells with the same x value are stored contiguously (y, x))

The dimensions passed in must match the dimensions of the Vec<DungeonGridCell>, otherwise this will panic.

Internally the grid has a fixed buffer size / capacity of 15 x 15. If the grid size in the X or Y direction is less than this, so when working with the (raw) grid buffer, you will need to take into account that each column will have 15 rows, where the last (15-height) in each column will be uninitialised and that after width rows the rest of the array will be uninitialised as well.

This helper will abstract for you over this, if you query a cell via eg. Self::get, however Self::into_inner() will still return a vector with 15 x 15 cells, with all missing values initialized with defaults.

Note that the game usually works with the assumption that there are exactly 15 rows. Using other row sizes may or may not lead to UB with some methods.

The maximum values for width and height are GRID_CAPACITY_DIM, otherwise this function will panic.

source

pub fn new(&self, width: usize, ov29: OverlayLoadLease<29>) -> Self

Initialize a dungeon grid with defaults.

The grid is an array of grid cells stored in column-major order (!) (such that grid cells with the same x value are stored contiguously (y, x)).

Internally the grid has a fixed buffer size / capacity of 15 x 15. If the grid size in the X or Y direction is less than this, so when working with the (raw) grid buffer, you will need to take into account that each column will have 15 rows, where the last (15-height) in each column will be uninitialised and that after width rows the rest of the array will be uninitialised as well.

This helper will abstract for you over this, if you query a cell via eg. Self::get, however Self::into_inner() ill still return a vector with 15 x 15 cells, with all missing values initialized with defaults.

width must be less than or equal to 15, otherwise this function will panic.

source

pub fn into_inner(self) -> (Vec<DungeonGridCell>, usize, usize)

Extract the grid from the mutator, along with its width and height.

The grid will always be a matrix with 15 rows per column and it might contain extra dangling rows, you need to ignore cells outside of the grid’s actual width and height, see the notes for Self::new() for more information.

source

pub fn get(&self, x: usize, y: usize) -> &DungeonGridCell

Get the cell at the given coordinates. Panics if the coordinates are out of bounds.

source

pub unsafe fn get_unchecked(&self, x: usize, y: usize) -> &DungeonGridCell

Get the cell at the given coordinates, no extra checking is done, just normal slice indexing is done. This is UB if overflow checks are disabled and the coordinates are oob.

Safety

The caller needs to make sure x and y are in bounds.

source

pub fn get_mut(&mut self, x: usize, y: usize) -> &mut DungeonGridCell

Get the cell at the given coordinates, mutably. Panics if the coordinates are out of bounds.

source

pub unsafe fn get_mut_unchecked( &mut self, x: usize, y: usize ) -> &mut DungeonGridCell

Get the cell at the given coordinates, mutable, no extra checking is done, just normal slice indexing is done. This is UB if overflow checks are disabled and the coordinates are oob.

Safety

The caller needs to make sure x and y are in bounds.

source

pub fn merge_rooms_vertically( &mut self, _dungeon: &mut GlobalDungeonData<'_>, x: i32, y: i32, dy: i32 )

Merges two vertically stacked rooms into one larger room.

Arguments
  • _dungeon - Reference to global dungeon struct.
  • x - x grid coordinate of the rooms to merge
  • y - y grid coordinate of the rooms to merge
  • dy - dy, where the lower room has a y grid coordinate of y+dy
source

pub fn generate_extra_hallways( &mut self, _dungeon: &mut GlobalDungeonData<'_>, number_extra_hallways: i32 )

Generate extra hallways on the floor via a series of random walks.

Each random walk starts from a random tile in a random room, leaves the room in a random cardinal direction, and from there tunnels through obstacles through a series of random turns, leaving open terrain in its wake. The random walk stops when it reaches open terrain, goes out of bounds, or reaches an impassable obstruction.

source

pub fn get_grid_positions( width: i32, height: i32, _ov29: &OverlayLoadLease<29> ) -> (Vec<i32>, Vec<i32>)

Get the grid cell positions for a given set of floor grid dimensions. Width and height must be positive.

source

pub fn assign_rooms( &mut self, _dungeon: &mut GlobalDungeonData<'_>, number_rooms: i32 )

Randomly selects a subset of grid cells to become rooms.

The given number of grid cells will become rooms. If any of the selected grid cells are invalid, fewer rooms will be generated. The number of rooms assigned will always be at least 2 and never exceed 36.

Cells not marked as rooms will become hallway anchors. A hallway anchor is a single tile in a non-room grid cell to which hallways will be connected later, thus “anchoring” hallway generation.

number_rooms is the number of rooms; if positive, a random value between [n_rooms, n_rooms+2] will be used. If negative, |n_rooms| will be used exactly.

source

pub fn create_rooms_and_anchors( &mut self, _dungeon: &mut GlobalDungeonData<'_>, starts_x: &mut [i32], starts_y: &mut [i32], room_flags: u32 )

Creates rooms and hallway anchors in each grid cell as designated by Self::assign_rooms.

This function creates a rectangle of open terrain for each room (with some margin relative to the grid cell border). A single open tile is created in hallway anchor cells, and a hallway anchor indicator is set for later reference.

Panics if any start position is invalid.

Arguments
  • starts_x - Array of the starting x coordinates of each grid column
  • starts_y - Array of the starting y coordinates of each grid row
  • room_flags - Only uses bit 2 (mask: 0b100), which enables room imperfections
source

pub fn generate_secondary_structures( &mut self, _dungeon: &mut GlobalDungeonData<'_>, _number_rooms: i32 )

Try to generate secondary structures in flagged rooms.

If a valid room with no special features is flagged to have a secondary structure, try to generate a random one in the room, based on the result of a dice roll:

  0: no secondary structure
  1: maze, or a central water/lava "plus sign" as fallback, or a single water/lava tile in
     the center as a second fallback
  2: checkerboard pattern of water/lava
  3: central pool of water/lava
  4: central "island" with items and a Warp Tile, surrounded by a "moat" of water/lava
  5: horizontal or vertical divider of water/lava splitting the room in two

If the room isn’t the right shape, dimension, or otherwise doesn’t support the selected secondary structure, it is left untouched.

source

pub fn assign_grid_cell_connections( &mut self, _dungeon: &mut GlobalDungeonData<'_>, cursor_x: i32, cursor_y: i32, floor_properties: &floor_properties )

Randomly assigns connections between adjacent grid cells.

Connections are created via a random walk with momentum, starting from the grid cell at (cursor x, cursor y). A connection is drawn in a random direction from the current cursor, and this process is repeated a certain number of times (the “floor connectivity” specified in the floor properties). The direction of the random walk has “momentum”; there’s a 50% chance it will be the same as the previous step (or rotated counterclockwise if on the boundary).

This helps to reduce the number of dead ends and forks in the road caused by the random walk “doubling back” on itself.

If dead ends are disabled in the floor properties, there is an additional phase to remove dead end hallway anchors (only hallway anchors, not rooms) by drawing additional connections. Note that the actual implementation contains a bug: the grid cell validity checks use the wrong index, so connections may be drawn to invalid cells.

Panics if the cursor positions are out of bounds.

source

pub fn create_grid_cell_connections( &mut self, _dungeon: &mut GlobalDungeonData<'_>, starts_x: &mut [i32], starts_y: &mut [i32], enable_room_merging: bool )

Create grid cell connections either by creating hallways or merging rooms.

When creating a hallway connecting a hallway anchor, the exact anchor coordinates are used as the endpoint. When creating a hallway connecting a room, a random point on the room edge facing the hallway is used as the endpoint. The grid cell boundaries are used as the middle coordinates for kinks (see super::GlobalDungeonStructureGenerator::create_hallway).

If room merging is enabled, there is a 9.75% chance that two connected rooms will be merged into a single larger room (9.75% comes from two 5% rolls, one for each of the two rooms being merged). A room can only participate in a merge once.

source

pub fn generate_room_imperfections( &mut self, _dungeon: &mut GlobalDungeonData<'_> )

Attempt to generate room imperfections for each room in the floor layout, if enabled.

Each room has a 40% chance of having imperfections if its grid cell is flagged to allow room imperfections. Imperfections are generated by randomly growing the walls of the room inwards for a certain number of iterations, starting from the corners.

source

pub fn ensure_connected_grid( &mut self, _dungeon: &mut GlobalDungeonData<'_>, starts_x: &mut [i32], starts_y: &mut [i32] )

Ensure the grid forms a connected graph (all valid cells are reachable) by adding hallways to unreachable grid cells.

If a grid cell cannot be connected for some reason, remove it entirely.

source

pub fn generate_kecleon_shop( &mut self, _dungeon: &mut GlobalDungeonData<'_>, spawn_chance: u8 )

A Kecleon shop will be generated with a probability determined by the Kecleon shop spawn chance parameter (percentage from 0 to 100).

A Kecleon shop will be generated in a random room that is valid, connected, has no other special features, and has dimensions of at least 5x4. Kecleon shops will occupy the entire room interior, leaving a one tile margin from the room walls.

source

pub fn generate_monster_house( &mut self, _dungeon: &mut GlobalDungeonData<'_>, spawn_chance: u8 )

A Monster House will be generated with a probability determined by the Monster House spawn chance parameter, and only if the current floor can support one (no non-Monster-House outlaw missions or special floor types). A Monster House will be generated in a random room that is valid, connected, and is not a merged or maze room.

spawn_chance is the percentage chance that a Monster House will be generated (0-100).

source

pub fn generate_maze_room( &mut self, _dungeon: &mut GlobalDungeonData<'_>, spawn_chance: u8 )

Possibly generate a maze room on the floor.

A maze room will be generated with a probability determined by the maze room chance parameter. A maze will be generated in a random room that is valid, connected, has odd dimensions, and has no other features.

spawn_chance is the percentage chance that a Monster House will be generated (0-100).

source

pub fn generate_maze<'a>( &'a self, cell: &'a mut dungeon_grid_cell, secondary_terrain_instead_of_walls: bool )

Generate a maze room within a given grid cell. A “maze” is generated within the room using a series of random walks to place obstacle terrain (walls or secondary terrain) in a maze-like arrangement. “Maze lines” (see super::GlobalDungeonStructureGenerator::generate_maze_line) are generated using every other tile around the room’s border, as well as every other interior tile, as a starting point. This ensures that there are stripes of walkable open terrain surrounded by stripes of obstacles (the maze walls).

source

pub fn set_spawn_flag_5<'a>(&'a self, cell: &'a mut dungeon_grid_cell)

Set spawn flag 5 (0b100000 or 0x20) on all tiles in a room.

Auto Trait Implementations§

§

impl RefUnwindSafe for DungeonGridMutator

§

impl Send for DungeonGridMutator

§

impl Sync for DungeonGridMutator

§

impl Unpin for DungeonGridMutator

§

impl UnwindSafe for DungeonGridMutator

Blanket Implementations§

§

impl<T> Any for Twhere T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dstwhere T: Cast<Dst>,

Casts the value.
§

impl<T> Borrow<T> for Twhere T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dstwhere Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>where T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for Twhere U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

source§

impl<Src, Dst> LosslessTryInto<Dst> for Srcwhere Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Srcwhere Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)where T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dstwhere T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dstwhere T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dstwhere Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dstwhere T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dstwhere Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.