I’ve started a list of tiles to be found
module Morgemil.Map.Tiles let DungeonFloor = TileDefinition(1, "Floor", "Dungeon floors are often trapped", false, false, TileType.Land) let DungeonWall = TileDefinition(2, "Wall", "Dungeon walls are built from the prisoner's bones", true, true, TileType.Land) |
I’ve also changed the coloring slightly which is reflected in the header image.
let tileColor = match tile with | _ when TileDefinition.IsDefault tile -> Color.Black | _ when Tiles.DungeonFloor.ID = tile.ID -> Color.White | _ when Tiles.DungeonWall.ID = tile.ID -> Color.Red | _ -> Color.Gray |
So as you might notice, the header image is rectangles in a jumble. Each of the rectangles represent a room in the dungeon. I accomplished this pseudo-random scattering of rooms by feeding the list of rectangles returned by the Binary Space Partitioning algorithm into a room randomizer.
let Generate rngSeed = let rng = RNG.SeedRNG rngSeed //Hardcoded dungeon size let dungeon_size = Rectangle(Vector2i(512, 512)) //Empty map let dungeon_map = DungeonMap(dungeon_size) //BSP rooms with randomized size (Rectangle List). And feeds them to the map. BspGenerator.GenerateRoomDivides rng dungeon_size.Size |> List.map (RandomizeRoom rng) |> List.iter (GenerateRoom dungeon_map) //Return a chunk to feed to visualizer dungeon_map.CreateChunk() |
I store the unfinished map in a mutable structure which goes against everything in functional programming. The existence of a mutable structure is necessary as a dungeon requires multiple passes to generate
type private DungeonMap(roomSize : Rectangle) = let internal_map = Array.create roomSize.Area (TileDefinition.Default) member this.SetValue pos tile = internal_map.[roomSize.FlatCoord pos] <- tile ///Return a single giant chunk to feed into the Visualizer member this.CreateChunk() = Chunk(roomSize, internal_map) |
Each rectangle in the BSP tree which looks like something like is randomized but still fits inside that distinct area.
///Randomizes a room's position and size within the defined area let private RandomizeRoom rng (maxArea : Rectangle) = //Randomize size before placing the room randomly let room_size = MinimumRoomArea.Size + RNG.RandomVector rng (maxArea.Size - MinimumRoomArea.Size) let room_position = maxArea.Position + RNG.RandomVector rng (maxArea.Size - room_size) Rectangle(room_position, room_size) |
Then the room is drawn onto the DungeonMap
///Writes directly on the map (side-effects). returns nothing let private GenerateRoom (dungeonMap : DungeonMap) (area : Rectangle) = let ChooseTile pt = match pt with | _ when area.IsOnEdge(pt) -> Tiles.DungeonWall | _ -> Tiles.DungeonFloor area.Coordinates |> Seq.iter (fun coord -> dungeonMap.SetValue coord (ChooseTile coord)) |
The results could be slightly interpreted as a dungeon where each room was haphazardly excavated and added on.
The next step will be to make connecting corridors.