예제 #1
0
        public override void Generate()
        {
            // Create BSP tree to partition floor randomly (but w/o overlaps)
            partitionedTree = PartitionDungeon();

            // Now that we have partitioned the dungeon into non-overlapping regions, create rooms in each "leaf" region
            // and create corridors between each non-leaf region.
            // We do this by telling the partitioned dungeon tree to find all nodes from the bottom up at each level.  On leaf
            // nodes (those at the bottom of the tree which have not been partitioned into smaller regions) we call our
            // "AddRoom" function with each leaf node's coordinates.  On non-leaf nodes, we call our "AddCorridor" function
            // Thanks to Jice for the overview (http://jice.nospam.googlepages.com/basicdungeongeneration).

            // Variety is the spice of life; mix things up a bit.
            RoomGeneratorDelegate roomGenerator;

            // Choose square or round rooms (or mix).  In future, have more complex room generators.
            /*
            switch (Rand.Next(3))
            {
                case 0:
                    roomGenerator = new RoomGeneratorDelegate(SquareRoomGenerator);
                    break;
                case 1:
                    roomGenerator = new RoomGeneratorDelegate(RoundRoomGenerator);
                    break;
                default:
                    roomGenerator = new RoomGeneratorDelegate(RandomShapeRoomGenerator);
                    break;
            }
            */
            roomGenerator = new RoomGeneratorDelegate(SquareRoomGenerator);

            // Choose a process by which we connect rooms
            if (Rand.Next(2) == 1)
            {
                // Do a BSP-based inverted breadth order search, creating rooms and corridors as we go.
                // Semi-"intelligent" approach, in that it gaurantees connections between all rooms and doesn't create "odd" rooms
                // or dead-end corridors
                partitionedTree.BottomsUpByLevelEnumerate(new RoomGeneratorDelegate(roomGenerator), new CorridorGeneratorDelegate(DefaultCorridorGenerator));
            }
            else
            {
                // Mimic DCSS's approach - get a list of rooms; randomize it; then dig corridors between them all, going right through rooms as we go.
                // This approach generates odd (eg doors in the middle of nowhere), but cool looking layouts.

                // 1. Get the list of regions with rooms in them
                // 2. Randomize the list (so we don't connect too many rooms that are right next to each other; counter-intuitive, I know)
                // 3. Connect the lists in order (connect #0 to #1, connect #1 to #2, etc).  brute force it.

                // Generate the list of rooms.  Don't pass a corridor generator since we're handling it ourselves post-processing.
                partitionedTree.BottomsUpByLevelEnumerate(new RoomGeneratorDelegate(roomGenerator), null);

                // Get the list of rooms
                List<DungeonBSPNode> roomRegions = partitionedTree.GetRoomRegions();

                // Randomize the list order (Go go Gadget-C#!)
                roomRegions.Sort(RandomNodeComparer);

                // Connect the room regions in the newly randomized list order
                DungeonBSPNode previousRoom = null;
                foreach (DungeonBSPNode currentRoom in roomRegions)
                {
                    if (previousRoom != null)
                        BruteForceConnectRooms(previousRoom, currentRoom);
                    previousRoom = currentRoom;
                }
            }
        }
예제 #2
0
        public void BottomsUpByLevelEnumerate(RoomGeneratorDelegate roomGenerator, CorridorGeneratorDelegate corridorGenerator)
        {
            Stack stack1 = new Stack();
            Stack stack2 = new Stack();
            stack1.Push(this);
            while (stack1.Count > 0)
            {
                DungeonBSPNode currentNode = (DungeonBSPNode)stack1.Pop();
                stack2.Push(currentNode);
                if (currentNode.LeftChild != null)
                    stack1.Push(currentNode.LeftChild);
                if (currentNode.RightChild != null)
                    stack1.Push(currentNode.RightChild);
            }

            while (stack2.Count > 0)
            {
                DungeonBSPNode currentNode = (DungeonBSPNode)stack2.Pop();
                if (currentNode.LeftChild == null && currentNode.RightChild == null)
                {
                    // Leaf node - create a room
                    if (!currentNode.RoomBuilt && roomGenerator != null)
                        roomGenerator(currentNode);
                }
                else
                {
                    // non-leaf node; create corridor
                    if (corridorGenerator != null && (currentNode.LeftChild.RoomBuilt || currentNode.RightChild.RoomBuilt))
                        corridorGenerator(currentNode);
                }
            }
        }