Ejemplo n.º 1
0
        public CompleteMap Generate(MT19337 rng, MapRequirements reqs)
        {
            var map = new Map((byte)reqs.Barrier);

            GenerateTree(rng);

            foreach (var roomspec in reqs.Rooms)
            {
                // randomly descend rooms until you find one that fits
                // var leaf_that_fits = RandomLeafWhere(rng, leaf => leaf.Width >= roomspec.Width && leaf.Height >= roomspec.Height);
                // if (leaf_that_fits == null)
                //    return null;
                // leaf_that_fits.WalkableSpace = Rectangle.Empty; // don't generate one
                // TODO something
            }

            root.GenerateRooms(rng);

            IEnumerable <Rectangle> all_the_rectangles = all_nodes.
                                                         Where(leaf => leaf.WalkableSpace != null).
                                                         Select(leaf => (Rectangle)leaf.WalkableSpace).
                                                         Concat(
                all_nodes.
                Where(leaf => leaf.Hallways != null).
                SelectMany(leaf => leaf.Hallways)
                );

            foreach (var rect in all_the_rectangles)
            {
                // TODO something smarter
                map.Fill((rect.Left, rect.Top), (rect.Width, rect.Height), reqs.Floor);
            }

            var smoothIterations = 0;

            while (MapHelper.SmoothFilter(map, reqs.Barrier, reqs.Floor))
            {
                smoothIterations++;
            }

            Point entranceLocation = PointInAnyRandomRoom(rng);

            map[entranceLocation.Y, entranceLocation.X] = (byte)Tile.WarpUp;


            return(new CompleteMap
            {
                Map = map,
                Entrance = new Coordinate((byte)entranceLocation.X, (byte)entranceLocation.Y, CoordinateLocale.Standard),
                Requirements = reqs
            });
        }
Ejemplo n.º 2
0
        public CompleteMap Generate(MT19337 rng, MapRequirements reqs)
        {
            //Constants! Get yer constants here!
            int iteration_count = 15;

            //((List<RoomSpec>)reqs.Rooms)[0].Tiledata = ((List<RoomSpec>)reqs.Rooms)[0].Tiledata;

            CompleteMap complete = new CompleteMap
            {
                Map = new Map((byte)Tile.WaterfallInside)
            };
            //(57,56)
            var startLoc = (x : 0x39, y : 0x38);

            var startingX = rng.Between(-3, 0) + startLoc.x;
            var startingY = rng.Between(-4, -1) + startLoc.y;

            var startRegion = new Region(startingX, startingY, 4, 5, Tile.WaterfallRandomEncounters);

            List <Region> regionList = new List <Region>();

            regionList.Add(startRegion);

            List <Region> endingRegions = new List <Region>();

            for (var i = 0; i < iteration_count; i++)
            {
                var startPoint = regionList[rng.Between(0, regionList.Count - 1)];
                var newRegions = RegionChain(rng, startPoint, regionList, 30 - i);
                regionList.AddRange(newRegions);
                if (newRegions.Count > 0)
                {
                    endingRegions.Add(newRegions[newRegions.Count - 1]);
                }
            }

            var foundRoomPlace = false;
            var room           = ((List <RoomSpec>)reqs.Rooms)[0];
            var room_x         = -1;
            var room_y         = -1;

            while (!foundRoomPlace && endingRegions.Count > 0)
            {
                var borderRegion = endingRegions.PickRandom(rng);

                var base_x = (borderRegion.x - (room.Width - 1) + 64) % 64;
                room_y = (borderRegion.y - room.Height + 64) % 64;
                var        x_offset      = 1;
                List <int> valid_offsets = new List <int>();

                while (x_offset < room.Width)
                {
                    room_x = (base_x + x_offset) % 64;
                    var validRoomPlace = true;
                    foreach (Region r in regionList)
                    {
                        var testVal = validRoomPlace && !r.IntersectsRoom(room, room_x, room_y);
                        if (!testVal && validRoomPlace)
                        {
                            //Console.WriteLine(room_x);
                        }
                        validRoomPlace = testVal;
                    }
                    if (validRoomPlace)
                    {
                        valid_offsets.Add(x_offset);
                    }
                    x_offset++;
                }

                if (valid_offsets.Count != 0)
                {
                    foundRoomPlace = true;
                    room_x         = (base_x + valid_offsets[rng.Between(0, valid_offsets.Count - 1)]);
                }

                endingRegions.Remove(borderRegion);
            }

            if (!foundRoomPlace)
            {
                List <int> idxs = Enumerable.Range(0, regionList.Count).ToList();
                while (!foundRoomPlace && idxs.Count > 0)
                {
                    int regionIdx = idxs.PickRandom(rng);

                    var borderRegion = regionList[regionIdx];
                    var base_x       = (borderRegion.x - (room.Width - 1) + 64) % 64;
                    room_y = (borderRegion.y - (room.Height - 1) + 64) % 64;
                    var        x_offset      = 1;
                    List <int> valid_offsets = new List <int>();

                    while (x_offset < room.Width)
                    {
                        room_x = (base_x + x_offset) % 64;
                        var validRoomPlace = true;
                        foreach (Region r in regionList)
                        {
                            var testVal = validRoomPlace && !r.IntersectsRoom(room, room_x, room_y);
                            if (!testVal && validRoomPlace)
                            {
                                //Console.WriteLine(room_x);
                            }
                            validRoomPlace = testVal;
                        }
                        if (validRoomPlace)
                        {
                            valid_offsets.Add(x_offset);
                        }
                        x_offset++;
                    }

                    if (valid_offsets.Count != 0)
                    {
                        foundRoomPlace = true;
                        room_x         = (base_x + valid_offsets[rng.Between(0, valid_offsets.Count - 1)]);
                    }

                    idxs.Remove(regionIdx);
                }
            }

            if (!foundRoomPlace)
            {
                Console.WriteLine("No room found :o");
                return(null);
            }

            //Draw every room in regionList to complete
            foreach (Region r in regionList)
            {
                r.DrawRegion(complete);
            }

            Region waterfallRoom = new Region(room_x, room_y, room);

            waterfallRoom.DrawRegion(complete);


            int doorYPos = (room_y + room.Height) % 64;

            List <int> possibleDoors = new List <int>();

            for (var i = 0; i < room.Width; i++)
            {
                if (complete.Map[((room_x + i) % 64, doorYPos)].Tile == Tile.WaterfallRandomEncounters)
Ejemplo n.º 3
0
        public CompleteMap Generate(MT19337 rng, MapGeneratorStrategy strategy, MapRequirements reqs)
        {
            CompleteMap map = null;

            if (reqs.MapId == MapId.Waterfall)
            {
                reqs.Floor       = Tile.WaterfallRandomEncounters;
                reqs.InRoomFloor = Tile.WaterfallInside;
                reqs.FreeNPCs    = Enumerable.Range(1, 10);
                reqs.Rooms       = new List <RoomSpec>
                {
                    new RoomSpec
                    {
                        Tiledata = new byte[, ] {
                            { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 },
                            { 0x03, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x05 },
                            { 0x03, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x05 },
                            { 0x06, 0x07, 0x48, 0x07, 0x07, 0x07, 0x07, 0x08 },
                            { 0x30, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30 },
                            { 0x49, 0x49, 0x3A, 0x49, 0x49, 0x49, 0x49, 0x49 }
                        },
                        NPCs = new List <NPC> {
                            new NPC {
                                Index = 0, Coord = (5, 2), InRoom = true, Stationary = false
                            }
                        },
                    }
                };
                reqs.Portals = new byte[] { (byte)Tile.WarpUp };

                IMapGeneratorEngine engine = GetEngine(strategy);
                int iterations             = 0;
                while (iterations < MAX_MAP_ITERATIONS && map == null)
                {
                    Console.WriteLine($"Generating {reqs.MapId} - iteration #{iterations}");
                    map = engine.Generate(rng, reqs);
                }

                if (map == null)
                {
                    throw new InsaneException($"Couldn't generate map using {strategy} after maximum {iterations} iterations.");
                }

                // add the reqs we used
                map.Requirements = reqs;
            }
            else if (reqs.MapId == MapId.EarthCaveB1)
            {
                reqs.Floor       = Tile.EarthCaveRandomEncounters;
                reqs.InRoomFloor = Tile.EarthCaveInside;
                reqs.OutOfBounds = Tile.EarthCaveOOB;
                reqs.Barrier     = Tile.EarthCaveRockA;
                reqs.FreeNPCs    = new int[] { };
                reqs.Rooms       = new List <RoomSpec> {
                };
                reqs.Portals     = new byte[] { (byte)Tile.WarpUp, 0x24 };
                reqs.Objects     = Enumerable.Range(0x42, 5).Select(x => (byte)x);
                reqs.Traps       = Enumerable.Repeat(0x1D, 3).Select(x => (byte)x);

                IMapGeneratorEngine engine = GetEngine(strategy);
                map = engine.Generate(rng, reqs);

                // add the reqs we used
                map.Requirements = reqs;
            }
            else if (reqs.MapId == MapId.EarthCaveB2)
            {
                reqs.Floor       = Tile.EarthCaveRandomEncounters;
                reqs.InRoomFloor = Tile.EarthCaveInside;
                reqs.OutOfBounds = Tile.EarthCaveOOB;
                reqs.Barrier     = Tile.EarthCaveRockA;
                reqs.FreeNPCs    = Enumerable.Range(0, 13);
                reqs.Rooms       = new List <RoomSpec> {
                };
                reqs.Portals     = new byte[] { (byte)Tile.WarpUp, 0x25 };
                reqs.Objects     = Enumerable.Range(0x47, 6).Select(x => (byte)x);
                reqs.Traps       = Enumerable.Range(0x1D, 1).Select(x => (byte)x);

                IMapGeneratorEngine engine = GetEngine(strategy);
                map = engine.Generate(rng, reqs);

                // add the reqs we used
                map.Requirements = reqs;
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }

            // Free NPC placement doesn't require the engine
            var locations = map.Map.Where(element => element.Tile == reqs.Floor).ToList();

            reqs.FreeNPCs.ToList().ForEach(npc =>
            {
                var location = locations.SpliceRandom(rng);
                reqs.Rom.MoveNpc(reqs.MapId, npc, location.X, location.Y, false, false);
            });

            if (Debugger.IsAttached)
            {
                Console.Write(map.AsText());
            }

            return(map);
        }
Ejemplo n.º 4
0
        public CompleteMap Generate(MT19337 rng, MapRequirements reqs)
        {
            CompleteMap complete = new CompleteMap
            {
                Map = new Map((byte)Tile.WaterfallInside)
            };

            //Map map = complete.Map;

            var startLoc = (x : 0x39, y : 0x38);
            var roomLoc  = (x : 0x35, y : 0x30);

            var startingX = rng.Between(-3, 0) + startLoc.x;
            var startingY = rng.Between(-4, 0) + startLoc.y;
            var endPoint  = (x : startingX, y : startingY);

            complete.Map.Fill(endPoint, (4, 5), 0x49);

            List <(int x, int y)>     visited    = new List <(int x, int y)>();
            List <List <Directions> > visitedDir = new List <List <Directions> >();
            var        index        = 0;
            var        outerLoops   = 0;
            Directions curDirection = (Directions)rng.Between(0, 3);

            visited.Add(endPoint);
            visitedDir.Add(FullDirs());
            visitedDir[0].Remove(curDirection);
            do
            {
                var iterCount = rng.Between(8, 20);
                var offset    = endPoint;
                for (int j = 0; j < iterCount; j++)
                {
                    var newOffset = (x : 0, y : 0);
                    switch (curDirection)
                    {
                    case Directions.up:
                        newOffset = (x : offset.x + rng.Between(-2, 2), y : offset.y - rng.Between(2, 4));
                        break;

                    case Directions.down:
                        newOffset = (x : offset.x + rng.Between(-2, 2), y : offset.y + rng.Between(2, 4));
                        break;

                    case Directions.right:
                        newOffset = (x : offset.x + rng.Between(2, 4), y : offset.y + rng.Between(-2, 3));
                        break;

                    case Directions.left:
                        newOffset = (x : offset.x - rng.Between(2, 4), y : offset.y + rng.Between(-2, 3));
                        break;
                    }
                    if (newOffset.x < 2 || newOffset.x > 57 || newOffset.y < 2 || newOffset.y > 56)
                    {
                        break;
                    }
                    offset = newOffset;
                    complete.Map.Fill(offset, (4, 5), 0x49);
                }
                if (offset.x != endPoint.x && offset.y != endPoint.y)
                {
                    visited.Add(offset);
                    List <Directions> newDirs = FullDirs();
                    newDirs.Remove(3 - curDirection);
                    visitedDir.Add(newDirs);
                }

                index    = rng.Between(0, visited.Count - 1);
                endPoint = visited[index];
                var randDirection = rng.Between(0, visitedDir[index].Count - 1);
                curDirection = visitedDir[index][randDirection];
                outerLoops++;
            } while (outerLoops < 35);

            //Now, we need to smooth out any 1x1 chunks, because those don't render well

            var smoothIterations = 0;

            while (MapHelper.SmoothFilter(complete.Map, Tile.WaterfallInside, Tile.WaterfallRandomEncounters))
            {
                smoothIterations++;
            }
            //SmoothFilter(complete.Map, Tile.WaterfallInside, Tile.WaterfallRandomEncounters);

            List <Tile> liveTiles = new List <Tile>()
            {
                Tile.WaterfallRandomEncounters
            };

            var distances = FloodFillDist(complete.Map, startLoc, liveTiles);
            int maxDist   = distances.Cast <int>().Max();

            List <(int x, int y)> roomPlacements = new List <(int x, int y)>();

            for (var i = 1; i < 54; i++)
            {
                for (var j = 1; j < 54; j++)
                {
                    if (Math.Abs(i - startLoc.x) + Math.Abs(j - startLoc.y) > 64)
                    {
                        roomPlacements.Add((x: i, y: j));
                    }
                }
            }

            //Clean up the 1-by-1 chunks

            var         doneWithRoomPlacement = false;
            List <Tile> targetTiles           = new List <Tile>()
            {
                Tile.Doorway
            };

            //Now, pick a place for the room.
            do
            {
                var targetPlace = rng.Between(0, roomPlacements.Count - 1);
                roomLoc = roomPlacements[targetPlace];
                roomPlacements.RemoveAt(targetPlace);

                var tempRoom = (byte[, ])reqs.Rooms.First().Tiledata.Clone();
                // Place the room
                for (var i = 0; i < 6; i++)
                {
                    for (var j = 0; j < 8; j++)
                    {
                        tempRoom[i, j] = complete.Map[roomLoc.y + i, roomLoc.x + j];
                        complete.Map[roomLoc.y + i, roomLoc.x + j] = reqs.Rooms.First().Tiledata[i, j];
                    }
                }
                // Test the room
                doneWithRoomPlacement = FloodFillReachable(complete.Map, startLoc, liveTiles, targetTiles)[Tile.Doorway];
                //If not done, reverse
                if (!doneWithRoomPlacement)
                {
                    for (var i = 0; i < 6; i++)
                    {
                        for (var j = 0; j < 8; j++)
                        {
                            complete.Map[roomLoc.y + i, roomLoc.x + j] = tempRoom[i, j];
                        }
                    }
                }
            } while (!doneWithRoomPlacement);

            byte[]      tempOutside  = { (byte)Tile.WaterfallRandomEncounters, (byte)Tile.Doorway, (byte)Tile.InsideWall };
            List <byte> outsideTiles = new List <byte>(tempOutside);

            //Okay, now, we need to to do the touch up!
            for (var i = 0; i < 63; i++)
            {
                for (var j = 0; j < 63; j++)
                {
                    var curTile = (Tile)complete.Map[j, i];

                    if (curTile == Tile.WaterfallInside && i != 0 && outsideTiles.Contains(complete.Map[j, i - 1]))
                    {
                        curTile = Tile.RoomLeft;
                    }
                    if (curTile == Tile.WaterfallInside && i != 63 && outsideTiles.Contains(complete.Map[j, i + 1]))
                    {
                        curTile = Tile.RoomRight;
                    }
                    if (curTile == Tile.WaterfallInside && j != 63 && outsideTiles.Contains(complete.Map[j + 1, i]))
                    {
                        curTile = Tile.RoomFrontCenter;
                    }
                    if (curTile == Tile.RoomLeft && j != 63 && outsideTiles.Contains(complete.Map[j + 1, i]))
                    {
                        curTile = Tile.RoomFrontLeft;
                    }
                    if (curTile == Tile.RoomRight && j != 63 && outsideTiles.Contains(complete.Map[j + 1, i]))
                    {
                        curTile = Tile.RoomFrontRight;
                    }
                    if (curTile == Tile.WaterfallInside && j != 0 && outsideTiles.Contains(complete.Map[j - 1, i]))
                    {
                        curTile = Tile.RoomBackCenter;
                    }
                    if (curTile == Tile.RoomLeft && j != 0 && outsideTiles.Contains(complete.Map[j - 1, i]))
                    {
                        curTile = Tile.RoomBackLeft;
                    }
                    if (curTile == Tile.RoomRight && j != 0 && outsideTiles.Contains(complete.Map[j - 1, i]))
                    {
                        curTile = Tile.RoomBackRight;
                    }
                    if (curTile == Tile.WaterfallRandomEncounters && j != 0 && (complete.Map[j - 1, i] <= 0x08 || complete.Map[j - 1, i] == 0x46))
                    {
                        curTile = Tile.InsideWall;
                    }
                    complete.Map[j, i] = (byte)curTile;
                }
            }

            //Finally, add the start
            complete.Map[startLoc.y, startLoc.x] = (byte)Tile.WarpUp;
            //and the robot.
            reqs.Rooms.First().NPCs.ToList().ForEach(npc =>
            {
                npc.Coord.x += roomLoc.x;
                npc.Coord.y += roomLoc.y;
                reqs.Rom.MoveNpc(reqs.MapId, npc);
            });

            complete.Entrance = new Coordinate((byte)startLoc.x, (byte)startLoc.y, CoordinateLocale.Standard);

            return(complete);
        }
Ejemplo n.º 5
0
        public CompleteMap Generate(MT19337 rng, MapRequirements reqs)
        {
            int sanity = 0;

            while (true)
            {
                if (++sanity == 500)
                {
                    throw new InsaneException("Failed to generate map!");
                }

                try
                {
                    CompleteMap complete = new CompleteMap
                    {
                        Map          = new Map(SentinelDead),
                        Requirements = reqs,
                    };

                    {
                        (int x, int y)coord = (0, 0);
                        reqs.Rooms.ToList().ForEach(room =>
                        {
                            coord.x = rng.Between(0, MapRequirements.Width - 1 - room.Width);
                            complete.Map.Put(coord, room.Tiledata);
                            coord.y += room.Height + rng.Between(0, 5);

                            room.NPCs.ToList().ForEach(npc =>
                            {
                                npc.Coord.x += coord.x;
                                npc.Coord.y += coord.y;
                                reqs.Rom.MoveNpc(reqs.MapId, npc);
                            });
                        });
                    }

                    // Generate rooms first. We'll aim to have enough for all the required chests.
                    Map rooms = complete.Map.Clone();
                    InitializeMap(rng, rooms, 0.33);
                    rooms = DoSimulationStep(rooms, 4, 2, 3);

                    Console.WriteLine($"Room map has {rooms.Count(element => element.Value == SentinelAlive)} walkable tiles.");
                    complete.Map = rooms;
                    Console.Write(complete.AsText());

                    var clone = rooms.Clone();
                    foreach (var el in clone.Where(el => el.Value == SentinelDead))
                    {
                        var roomTile = rooms[el.Coord];

                        foreach (var newTile in roomTile.Surrounding().Concat(roomTile.Left().Surrounding()))
                        {
                            newTile.Value = SentinelDead;
                        }
                    }

                    Console.WriteLine($"Room map has {rooms.Count(element => element.Value == SentinelAlive)} walkable tiles.");

                    complete.Map = rooms;
                    Console.Write(complete.AsText());

                    clone = rooms.Clone();
                    foreach (var el in clone.Where(el => el.Value == SentinelDead))
                    {
                        var roomTile = rooms[el.Coord];
                        if (el.Left().Value == SentinelAlive)
                        {
                            if (el.Up().Value == SentinelAlive)
                            {
                                roomTile.Tile = Tile.RoomBackLeft;
                            }
                            else if (el.Down().Value == SentinelAlive)
                            {
                                roomTile.Tile = Tile.RoomFrontLeft;
                                roomTile.Down().Tile = Tile.InsideWall;
                            }
                            else
                            {
                                roomTile.Tile = Tile.RoomLeft;
                            }
                        }
                        else if (el.Right().Value == SentinelAlive)
                        {
                            if (el.Up().Value == SentinelAlive)
                            {
                                roomTile.Tile = Tile.RoomBackRight;
                            }
                            else if (el.Down().Value == SentinelAlive)
                            {
                                roomTile.Tile = Tile.RoomFrontRight;
                                roomTile.Down().Tile = Tile.InsideWall;
                            }
                            else
                            {
                                roomTile.Tile = Tile.RoomRight;
                            }
                        }
                        else if (el.Up().Value == SentinelAlive)
                        {
                            roomTile.Tile = Tile.RoomBackCenter;
                        }
                        else if (el.Down().Value == SentinelAlive)
                        {
                            roomTile.Tile = Tile.RoomFrontCenter;
                            roomTile.Down().Tile = Tile.InsideWall;
                        }
                        else
                        {
                            roomTile.Tile = Tile.RoomCenter;
                        }
                    }

                    // Carve out a door to all the accessible room tiles.
                    var roomTiles = rooms.Where(el => el.Tile == Tile.RoomCenter);
                    var doorways  = new List <MapElement> {
                    };

                    foreach (var innerTile in roomTiles)
                    {
                        var results = FloodFill(rooms, innerTile.Coord, new List <Tile> {
                            Tile.RoomCenter, Tile.RoomFrontCenter, Tile.Door
                        });
                        if (results[Tile.Door].Any())
                        {
                            continue;
                        }

                        var potentialDoorways = results[Tile.RoomFrontCenter];
                        if (potentialDoorways.Any())
                        {
                            var entryway = potentialDoorways.SpliceRandom(rng);
                            var door     = entryway.Down();
                            var doorway  = door.Down();

                            System.Diagnostics.Debug.Assert(door.Tile == Tile.InsideWall);

                            if (doorway.Value != SentinelAlive)
                            {
                                throw new InsaneException("Doorway not available.");
                            }

                            door.Tile    = Tile.Door;
                            doorway.Tile = Tile.Doorway;
                            doorways.Add(doorway);
                        }
                    }

                    // Place chests now
                    var chestLocations = roomTiles.Where(el => el.Up().Tile == Tile.RoomBackCenter).ToList();
                    if (reqs.Objects.Count() > chestLocations.Count())
                    {
                        throw new InsaneException("Not enough chest locations.");
                    }

                    foreach (byte chest in reqs.Objects)
                    {
                        chestLocations.SpliceRandom(rng).Value = chest;
                    }

                    // Deaden to prepare for second run
                    //foreach (var el in rooms.Where(el => el.Value == SentinelAlive)) { el.Value = SentinelDead; }

                    // Place non-room walls now.

                    /*
                     * for (int sanity2 = 0; sanity2 <501; ++sanity2)
                     * {
                     *      if (sanity2 == 500)
                     *              throw new InsaneException("Couldn't make floors walls.");
                     *
                     *      var walled = rooms.Clone();
                     *      var entrances = doorways.ToList();
                     *      //InitializeMap(rng, walled, 0.4);
                     *      walled = DoSimulationStep(walled, 5, 4, 4);
                     *
                     *      entrances.ForEach(entrance =>
                     *      {
                     *              foreach (var tile in entrance.Surrounding().Where(el => el.Value == SentinelDead))
                     *              {
                     *                      walled[tile.Coord].Value = SentinelAlive;
                     *              }
                     *      });
                     *
                     *      complete.Map = walled;
                     *      Console.Write(complete.AsText());
                     *      bool success = false; // eww
                     *
                     *      // Find a big enough segment to be the main area.
                     *      while (walled.Any(el => el.Value == SentinelAlive))
                     *      {
                     *              var tile = walled.First(el => el.Value == SentinelAlive);
                     *              var results = FloodFill(walled, tile.Coord, new List<Tile> { reqs.Floor, Tile.Doorway }, new List<Tile> { (Tile)SentinelAlive }, reqs.Floor);
                     *
                     *              if (results[reqs.Floor].Count() < 500)
                     *              {
                     *                      // Small section just mark as walls.
                     *                      FloodFill(walled, tile.Coord, new List<Tile> { reqs.Floor }, new List<Tile> { reqs.Floor }, (Tile)SentinelDead);
                     *              }
                     *              else
                     *              {
                     *                      // This is the big section. Make sure all the doors are accessible
                     *                      success = results[Tile.Doorway].Count() == doorways.Count();
                     *                      break;
                     *              }
                     *      }
                     *
                     *      if (success)
                     *      {
                     *              foreach (var el in walled.Where(el => el.Value == SentinelDead))
                     *              {
                     *                      if (el.Up().Tile == reqs.Floor || el.Down().Tile == reqs.Floor || el.Left().Tile == reqs.Floor || el.Right().Tile == reqs.Floor)
                     *                      {
                     *                              el.Tile = reqs.Barrier;
                     *                      } else
                     *                      {
                     *                              el.Tile = reqs.OutOfBounds;
                     *                      }
                     *              }
                     *              complete.Map = walled;
                     *              break;
                     *      }
                     * }
                     */

                    // All the tiles we're editing are now either SentinelAlive or SentinelDead.
                    // Time to map those to real values now.
                    foreach (var el in complete.Map.Where(el => el.Value == SentinelAlive))
                    {
                        el.Tile = reqs.Floor;
                    }

                    Console.WriteLine($"Room map has {complete.Map.Count(element => element.Tile == reqs.Floor)} walkable tiles.");
                    Console.Write(complete.AsText());

                    // Pad all the Alive tiles
                    var locations = complete.Map.Where(element => element.Tile == reqs.Floor).ToList();
                    reqs.Portals.ToList().ForEach(portal =>
                    {
                        var location = locations.SpliceRandom(rng);
                        complete.Map[location.Y, location.X] = portal;

                        if (portal == (byte)Tile.WarpUp)
                        {
                            complete.Entrance = new Coordinate((byte)location.X, (byte)location.Y, CoordinateLocale.Standard);

                            var finalResult = FloodFill(complete.Map, location.Coord, new List <Tile> {
                                reqs.Floor, Tile.WarpUp, Tile.Doorway, Tile.Door, Tile.RoomCenter, Tile.RoomFrontCenter
                            });
                            if (finalResult[Tile.Door].Count() < doorways.Count())
                            {
                                throw new InsaneException("Can't reach all rooms.");
                            }
                        }
                    });

                    Console.Write(complete.AsText());
                    return(complete);
                } catch (InsaneException e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }