public Map GenerateMap(int extraConnections)
        {
            LogFile.Log.LogEntry(String.Format("Generating BSP dungeon"));

            baseMap = new Map(width, height);

            //Make a BSP tree for the rooms

            rootNode = new MapNode(0, 0, width, height);
            rootNode.Split();

            //Draw a room in each BSP leaf
            rootNode.DrawRoomAtLeaf(baseMap);

            //debug
            //Screen.Instance.DrawMapDebug(baseMap);

            //Draw connecting corridors
            rootNode.DrawCorridorConnectingChildren(baseMap);

            //Add any extra connecting corridors as specified

            for (int i = 0; i < extraConnections; i++)
            {
                rootNode.AddRandomConnection(baseMap);
            }

            //Add doors where single corridors terminate into rooms
            AddDoors();

            //Turn corridors into normal squares and surround with walls
            CorridorsIntoRooms();

            //Set which squares are light blocking
            //Now done during creation
            //SetLightBlocking(baseMap);

            //Set the PC start location in a random room
            baseMap.PCStartLocation = rootNode.RandomRoomPoint();

            return baseMap;
        }
        public Map GenerateMap(int extraConnections)
        {
            LogFile.Log.LogEntry(String.Format("Generating BSP dungeon"));

            do
            {
                baseMap = new Map(width, height);
                connectivityGraph = new ConnectivityMap();

                //BSP is always connected
                baseMap.GuaranteedConnected = true;

                //Make a BSP tree for the rooms

                rootNode = new MapNode(this, 0, 0, width, height);
                rootNode.Split();

                //Draw a room in each BSP leaf
                rootNode.DrawRoomAtLeaf(baseMap);

                //debug
                //Screen.Instance.DrawMapDebug(baseMap);

                //Draw connecting corridors
                rootNode.DrawCorridorConnectingChildren(baseMap);

                //Add any extra connecting corridors as specified

                for (int i = 0; i < extraConnections; i++)
                {
                    rootNode.AddRandomConnection(baseMap);
                }

                //Add doors where single corridors terminate into rooms
                AddDoorsGraph();

                //Turn corridors into normal squares and surround with walls
                CorridorsIntoRooms();

                //Work out where the staircases will be

                //We just want 2 places that aren't too close to each other. The map is guaranteed connected
                double RequiredStairDistance = (width * 0.5);
                double stairDistance;

                do
                {
                    upStaircase = RandomWalkablePoint();
                    downStaircase = RandomWalkablePoint();

                    stairDistance = Math.Sqrt(Math.Pow(upStaircase.x - downStaircase.x, 2) + Math.Pow(upStaircase.y - downStaircase.y, 2));

                } while (stairDistance < RequiredStairDistance);

                //Set which squares are light blocking
                //Now done during creation
                //SetLightBlocking(baseMap);

                //Set the PC start location in a random room
                baseMap.PCStartLocation = AddEntryRoomForPlayer();

            } while (baseMap.PCStartLocation == null);

            //Fake a start room
                PointInRoom randomRoom = RandomPointInRoom();
                //baseMap.PCStartLocation = randomRoom.GetPointInRoomOnly();
                baseMap.PCStartRoomId = randomRoom.RoomId;

            //Build the map model for the graph, based on the PC's true starting position (useful for locking doors)
            graphModel = new MapModel(connectivityGraph, baseMap.PCStartRoomId);

            //Save out the graph
            GraphvizExport.OutputUndirectedGraph(connectivityGraph.RoomConnectionGraph, "bsptree-base");
            //Save out a copy of the graph with no cycles

            GraphvizExport.OutputUndirectedGraph(graphModel.GraphNoCycles.mapNoCycles, "bsptree-nocycles");

            return baseMap.Clone();
        }
        public void Split()
        {
            Random rand = MapGeneratorBSP.rand;
            split = SplitType.Vertical;

            //Long thin areas are more likely to be split widthways and vice versa
            if(rand.Next(width + height) < width) {
                split = SplitType.Horizontal;
            }

            if (split == SplitType.Horizontal)
            {
                //Small chance that we don't recurse any further
                int chanceNoSplitHoriz = mustSplitSize - (width / minBSPSquareWidth);
                if (rand.Next(noSplitChance) < chanceNoSplitHoriz)
                {
                    childLeft = null;
                    childRight = null;
                    return;
                }

                int minSplit = (int)(width * minimumSplit);
                int maxSplit = (int)(width * maximumSplit);

                actualSplit = minSplit + rand.Next(maxSplit - minSplit + 1);

                //Define the two child areas, make objects and then recursively split them

                if (actualSplit < minBSPSquareWidth)
                {
                    childLeft = null;
                }
                else
                {
                    childLeft = new MapNode(parentGenerator, x, y, actualSplit, height);
                    childLeft.Split();
                }

                if (width - actualSplit < minBSPSquareWidth)
                {
                    childRight = null;
                }
                else
                {
                    childRight = new MapNode(parentGenerator, x + actualSplit, y, width - actualSplit, height);
                    childRight.Split();
                }
            }
            else {
                //SplitType.Vertical

                //Small chance that we don't recurse any further
                int chanceNoSplitVert = mustSplitSize - (height / minBSPSquareHeight);
                if (rand.Next(noSplitChance) < chanceNoSplitVert)
                {
                    childLeft = null;
                    childRight = null;
                }

                int minSplit = (int)(height * minimumSplit);
                int maxSplit = (int)(height * maximumSplit);

                actualSplit = minSplit + rand.Next(maxSplit - minSplit + 1);

                //Define the two child areas, make objects and then recursively split them

                if (actualSplit < minBSPSquareHeight)
                {
                    childLeft = null;
                }
                else
                {
                    childLeft = new MapNode(parentGenerator, x, y, width, actualSplit);
                    childLeft.Split();
                }

                if (height - actualSplit < minBSPSquareHeight)
                {
                    childRight = null;
                }
                else
                {
                    childRight = new MapNode(parentGenerator, x, y + actualSplit, width, height - actualSplit);
                    childRight.Split();
                }
            }
        }
Beispiel #4
0
        public void Split()
        {
            Random rand = MapGeneratorBSP.rand;

            split = SplitType.Vertical;

            //Long thin areas are more likely to be split widthways and vice versa
            if (rand.Next(width + height) < width)
            {
                split = SplitType.Horizontal;
            }

            if (split == SplitType.Horizontal)
            {
                //Small chance that we don't recurse any further
                int chanceNoSplitHoriz = mustSplitSize - (width / minBSPSquareWidth);
                if (rand.Next(noSplitChance) < chanceNoSplitHoriz)
                {
                    childLeft  = null;
                    childRight = null;
                    return;
                }

                int minSplit = (int)(width * minimumSplit);
                int maxSplit = (int)(width * maximumSplit);

                actualSplit = minSplit + rand.Next(maxSplit - minSplit + 1);

                //Define the two child areas, make objects and then recursively split them

                if (actualSplit < minBSPSquareWidth)
                {
                    childLeft = null;
                }
                else
                {
                    childLeft = new MapNode(x, y, actualSplit, height);
                    childLeft.Split();
                }

                if (width - actualSplit < minBSPSquareWidth)
                {
                    childRight = null;
                }
                else
                {
                    childRight = new MapNode(x + actualSplit, y, width - actualSplit, height);
                    childRight.Split();
                }
            }
            else
            {
                //SplitType.Vertical

                //Small chance that we don't recurse any further
                int chanceNoSplitVert = mustSplitSize - (height / minBSPSquareHeight);
                if (rand.Next(noSplitChance) < chanceNoSplitVert)
                {
                    childLeft  = null;
                    childRight = null;
                }

                int minSplit = (int)(height * minimumSplit);
                int maxSplit = (int)(height * maximumSplit);

                actualSplit = minSplit + rand.Next(maxSplit - minSplit + 1);

                //Define the two child areas, make objects and then recursively split them

                if (actualSplit < minBSPSquareHeight)
                {
                    childLeft = null;
                }
                else
                {
                    childLeft = new MapNode(x, y, width, actualSplit);
                    childLeft.Split();
                }

                if (height - actualSplit < minBSPSquareHeight)
                {
                    childRight = null;
                }
                else
                {
                    childRight = new MapNode(x, y + actualSplit, width, height - actualSplit);
                    childRight.Split();
                }
            }
        }
Beispiel #5
0
        public Map GenerateMap(int extraConnections)
        {
            LogFile.Log.LogEntry(String.Format("Generating BSPCave dungeon"));

            baseMap = new Map(width, height);

            //BSP is always connected
            baseMap.GuaranteedConnected = true;

            //Make a BSP tree for the rooms

            rootNode = new MapNode(this, 0, 0, width, height);
            rootNode.Split();

            //Draw a room in each BSP leaf
            rootNode.DrawRoomAtLeaf(baseMap);

            //debug
            //Screen.Instance.DrawMapDebug(baseMap);

            //Draw connecting corridors
            rootNode.DrawCorridorConnectingChildren(baseMap);

            //Add any extra connecting corridors as specified

            for (int i = 0; i < extraConnections; i++)
            {
                rootNode.AddRandomConnection(baseMap);
            }

            //Add doors where single corridors terminate into rooms
            AddDoors();

            //Turn corridors into normal squares and surround with walls
            CorridorsIntoRooms();

            //Now fill all void with walls

            //Fill the map with walls
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Void)
                    {
                        baseMap.mapSquares[i, j].Terrain = MapTerrain.Wall;
                    }
                }
            }

            //Work out where the staircases will be

            //We just want 2 places that aren't too close to each other. The map is guaranteed connected
            double RequiredStairDistance = (width * 0.5);
            double stairDistance;

            do
            {
                upStaircase   = RandomWalkablePoint();
                downStaircase = RandomWalkablePoint();

                stairDistance = Math.Sqrt(Math.Pow(upStaircase.x - downStaircase.x, 2) + Math.Pow(upStaircase.y - downStaircase.y, 2));
            } while (stairDistance < RequiredStairDistance);

            //Set which squares are light blocking
            //Now done during creation
            //SetLightBlocking(baseMap);

            //Set the PC start location in a random room
            baseMap.PCStartLocation = rootNode.RandomRoomPoint().GetPointInRoomOnly();

            //Now we use the cave algorithm to eat the map
            //Instead of setting this Empty like in cave, set them to Corridor temporarily (so the algo knows where it's been)

            DiggingChance = 22;

            //Start digging from a random point
            int noDiggingPoints = 6 + Game.Random.Next(2);

            for (int i = 0; i < noDiggingPoints; i++)
            {
                int x = Game.Random.Next(width);
                int y = Game.Random.Next(height);

                //Don't dig right to the edge
                if (x == 0)
                {
                    x = 1;
                }
                if (x == width - 1)
                {
                    x = width - 2;
                }
                if (y == 0)
                {
                    y = 1;
                }
                if (y == height - 1)
                {
                    y = height - 2;
                }

                Dig(x, y);
            }

            //Turn the corridors into empty
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Corridor)
                    {
                        baseMap.mapSquares[i, j].Terrain = MapTerrain.Empty;
                    }
                }
            }

            //Do a final pass to convert Wall into something more exciting
            if (wallType.Count > 0)
            {
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Wall)
                        {
                            baseMap.mapSquares[i, j].Terrain = wallType[rand.Next(wallType.Count)];
                        }
                    }
                }
            }

            return(baseMap.Clone());
        }
        public Map GenerateMap(int extraConnections)
        {
            LogFile.Log.LogEntry(String.Format("Generating BSPCave dungeon"));

            baseMap = new Map(width, height);

            //BSP is always connected
            baseMap.GuaranteedConnected = true;

            //Make a BSP tree for the rooms

            rootNode = new MapNode(this, 0, 0, width, height);
            rootNode.Split();

            //Draw a room in each BSP leaf
            rootNode.DrawRoomAtLeaf(baseMap);

            //debug
            //Screen.Instance.DrawMapDebug(baseMap);

            //Draw connecting corridors
            rootNode.DrawCorridorConnectingChildren(baseMap);

            //Add any extra connecting corridors as specified

            for (int i = 0; i < extraConnections; i++)
            {
                rootNode.AddRandomConnection(baseMap);
            }

            //Add doors where single corridors terminate into rooms
            AddDoors();

            //Turn corridors into normal squares and surround with walls
            CorridorsIntoRooms();

            //Now fill all void with walls

            //Fill the map with walls
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Void)
                    {
                        baseMap.mapSquares[i, j].Terrain = MapTerrain.Wall;
                    }
                }
            }

            //Work out where the staircases will be

            //We just want 2 places that aren't too close to each other. The map is guaranteed connected
            double RequiredStairDistance = (width * 0.5);
            double stairDistance;

            do
            {
                upStaircase = RandomWalkablePoint();
                downStaircase = RandomWalkablePoint();

                stairDistance = Math.Sqrt(Math.Pow(upStaircase.x - downStaircase.x, 2) + Math.Pow(upStaircase.y - downStaircase.y, 2));

            } while (stairDistance < RequiredStairDistance);

            //Set which squares are light blocking
            //Now done during creation
            //SetLightBlocking(baseMap);

            //Set the PC start location in a random room
            baseMap.PCStartLocation = rootNode.RandomRoomPoint().GetPointInRoomOnly();

            //Now we use the cave algorithm to eat the map
            //Instead of setting this Empty like in cave, set them to Corridor temporarily (so the algo knows where it's been)

            DiggingChance = 22;

            //Start digging from a random point
            int noDiggingPoints = 6 + Game.Random.Next(2);

            for (int i = 0; i < noDiggingPoints; i++)
            {
                int x = Game.Random.Next(width);
                int y = Game.Random.Next(height);

                //Don't dig right to the edge
                if (x == 0)
                    x = 1;
                if (x == width - 1)
                    x = width - 2;
                if (y == 0)
                    y = 1;
                if (y == height - 1)
                    y = height - 2;

                Dig(x, y);
            }

            //Turn the corridors into empty
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Corridor)
                    {
                        baseMap.mapSquares[i, j].Terrain = MapTerrain.Empty;
                    }
                }
            }

            //Do a final pass to convert Wall into something more exciting
            if (wallType.Count > 0)
            {
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (baseMap.mapSquares[i, j].Terrain == MapTerrain.Wall)
                        {
                            baseMap.mapSquares[i, j].Terrain = wallType[rand.Next(wallType.Count)];
                        }
                    }
                }
            }

            return baseMap.Clone();
        }