Example #1
0
        public void AddingOverlappingTemplatesWorksIfOverlapIsTransparent()
        {
            //Load sample template 8x4
            Assembly     _assembly      = Assembly.GetExecutingAssembly();
            Stream       roomFileStream = _assembly.GetManifestResourceStream("DDRogueTest.testdata.vaults.testsolid1.room");
            RoomTemplate room1          = RoomTemplateLoader.LoadTemplateFromFile(roomFileStream, StandardTemplateMapping.terrainMapping);

            RoomTemplate corridor1 = LoadTemplateFromFileRogueBasin("RogueBasin.bin.Debug.vaults.corridortemplate3x1.room");

            TemplatedMapBuilder mapGen = new TemplatedMapBuilder();

            //Start
            TemplatePositioned templatePos1 = new TemplatePositioned(0, 0, 0, room1, 0);

            mapGen.AddPositionedTemplate(templatePos1);

            //End
            TemplatePositioned templatePos2 = new TemplatePositioned(-10, 20, 0, room1, 0);

            mapGen.AddPositionedTemplate(templatePos2);

            //Middle
            TemplatePositioned templatePos3 = new TemplatePositioned(-8, 30, 0, room1, 0);

            mapGen.AddPositionedTemplate(templatePos3);

            //Corridor from start - end that overlaps middle
            var expandedCorridorAndPoint = RoomTemplateUtilities.ExpandCorridorTemplateLShaped(6, 28, true, corridor1);
            var positionedCorridor       = new TemplatePositioned(-2, 4, 0, expandedCorridorAndPoint.Item1, 3);

            Assert.IsTrue(mapGen.AddPositionedTemplate(positionedCorridor));
        }
Example #2
0
        private static void AddStandardDecorativeFeaturesToRoom(int level, TemplatePositioned positionedRoom, int featuresToPlace, DecorationFeatureDetails.Decoration decorationDetails)
        {
            var bridgeRouter = new RoomFilling(positionedRoom.Room);

            var floorPoints = RoomTemplateUtilities.GetPointsInRoomWithTerrain(positionedRoom.Room, RoomTemplateTerrain.Floor);

            for (int i = 0; i < featuresToPlace; i++)
            {
                var randomPoint = floorPoints.RandomElement();
                floorPoints.Remove(randomPoint);

                if (bridgeRouter.SetSquareUnWalkableIfMaintainsConnectivity(randomPoint))
                {
                    var featureLocationInMapCoords = positionedRoom.Location + randomPoint;
                    Game.Dungeon.AddFeatureBlocking(new Features.StandardDecorativeFeature(decorationDetails.representation, decorationDetails.colour), level, featureLocationInMapCoords, true);

                    LogFile.Log.LogEntryDebug("Placing feature in room " + positionedRoom.RoomIndex + " at location " + featureLocationInMapCoords, LogDebugLevel.Medium);
                }

                if (floorPoints.Count() == 0)
                {
                    break;
                }
            }
        }
Example #3
0
        private void AddCorridorsBetweenOpenDoors(TemplatedMapGenerator templatedGenerator, int totalExtraConnections)
        {
            var extraConnections = 0;

            var allDoors = templatedGenerator.PotentialDoors;

            //Find all possible doors matches that aren't in the same room
            var allBendDoorPossibilities = from d1 in allDoors
                                           from d2 in allDoors
                                           where RoomTemplateUtilities.CanBeConnectedWithBendCorridor(d1.MapCoords, d1.DoorLocation, d2.MapCoords, d2.DoorLocation) &&
                                           d1.OwnerRoomIndex != d2.OwnerRoomIndex
                                           select new { origin = d1, target = d2 };

            var allLDoorPossibilities = from d1 in allDoors
                                        from d2 in allDoors
                                        where RoomTemplateUtilities.CanBeConnectedWithLShapedCorridor(d1.MapCoords, d1.DoorLocation, d2.MapCoords, d2.DoorLocation) &&
                                        d1.OwnerRoomIndex != d2.OwnerRoomIndex
                                        select new { origin = d1, target = d2 };

            var allOverlappingDoorPossibilities = from d1 in allDoors
                                                  from d2 in allDoors
                                                  where d1.MapCoords == d2.MapCoords &&
                                                  d1.OwnerRoomIndex != d2.OwnerRoomIndex
                                                  select new { origin = d1, target = d2 };


            //Materialize for speed

            var allMatchingDoorPossibilities = allBendDoorPossibilities.Union(allLDoorPossibilities).Union(allOverlappingDoorPossibilities).ToList();
            //var allMatchingDoorPossibilities = allLDoorPossibilities;
            //var allMatchingDoorPossibilities = allBendDoorPossibilities;

            var shuffleMatchingDoors = allMatchingDoorPossibilities.Shuffle(Game.Random);

            for (int i = 0; i < allMatchingDoorPossibilities.Count; i++)
            {
                //Try a random combination to see if it works
                var doorsToTry = shuffleMatchingDoors.ElementAt(i);

                LogFile.Log.LogEntryDebug("Trying door " + doorsToTry.origin.MapCoords + " to " + doorsToTry.target.MapCoords, LogDebugLevel.Medium);

                bool success = templatedGenerator.JoinDoorsWithCorridor(doorsToTry.origin, doorsToTry.target, RandomCorridor());
                if (success)
                {
                    extraConnections++;
                }

                if (extraConnections > totalExtraConnections)
                {
                    break;
                }
            }

            //Previous code (was super-slow!)
            //while (allMatchingDoorPossibilities.Any() && extraConnections < totalExtraConnections)
            //In any case, remove this attempt
            //var doorsToTry = allMatchingDoorPossibilities.ElementAt(Game.Random.Next(allMatchingDoorPossibilities.Count()));
            //allMatchingDoorPossibilities = allMatchingDoorPossibilities.Except(Enumerable.Repeat(doorsToTry, 1)); //order n - making it slow?
        }
Example #4
0
        private void AddNewDoorsToPotentialDoors(TemplatePositioned positionedRoom, int roomIndex)
        {
            //Store a reference to each potential door in the room
            int noDoors = positionedRoom.PotentialDoors.Count();

            //var currentDoorLocations = potentialDoors.Select(d => d.MapCoords);

            for (int i = 0; i < noDoors; i++)
            {
                //if (!currentDoorLocations.Contains(positionedRoom.PotentialDoors[i]))
                potentialDoors.Add(new DoorInfo(positionedRoom, roomIndex, i, RoomTemplateUtilities.GetDoorLocation(positionedRoom.Room, i)));
            }
        }
Example #5
0
        /// <summary>
        /// Replace a room template with a smaller one. Aligns new template with old door.
        /// This should only be called on dead-ends
        /// Enforces that replacement rooms can only override floor areas of old rooms (helping to avoid some breakage)
        /// </summary>
        public bool ReplaceRoomTemplate(int roomToReplaceIndex, Connection existingRoomConnection, RoomTemplate replacementRoom, int replaceRoomDoorIndex)
        {
            var templateToReplace = templates[roomToReplaceIndex];

            if (templateToReplace.PotentialDoors.Count() > 1)
            {
                throw new ApplicationException("Can't replace rooms with >1 doors");
            }

            var doorToConnection = GetDoorForConnection(existingRoomConnection);

            Tuple <TemplatePositioned, Point> replacementRoomTuple = RoomTemplateUtilities.AlignRoomOverlapping(replacementRoom, roomToReplaceIndex, templateToReplace,
                                                                                                                replaceRoomDoorIndex, doorToConnection.DoorIndexInRoom);

            var replacementRoomTemplate = replacementRoomTuple.Item1;

            //Check if the overlapping room can be placed
            if (!mapBuilder.CanBePlacedOverlappingOtherTemplates(replacementRoomTemplate))
            {
                return(false);
            }

            //Blank the old room area
            var voidedOldRoomTemplate = RoomTemplateUtilities.TransparentTemplate(templateToReplace);

            mapBuilder.UnconditionallyOverridePositionedTemplate(voidedOldRoomTemplate);

            //Override with new template
            mapBuilder.OverridePositionedTemplate(replacementRoomTemplate);

            //Ensure that the room is replaced in the index
            templates[roomToReplaceIndex] = replacementRoomTemplate;

            //We don't change the connectivity or doors

            return(true);
        }
Example #6
0
        /// <summary>
        /// Place a room template aligned with an existing door.
        /// Returns Connection(Source = existing room or corridor to new room, Target = new room))
        /// </summary>
        public Connection PlaceRoomTemplateAlignedWithExistingDoor(RoomTemplate roomTemplateToPlace, RoomTemplate corridorTemplate, DoorInfo existingDoor, int newRoomDoorIndex, int distanceApart)
        {
            var newRoomIndex = NextRoomIndex();

            Point existingDoorLoc = existingDoor.MapCoords;

            Tuple <TemplatePositioned, Point> newRoomTuple = RoomTemplateUtilities.AlignRoomFacing(roomTemplateToPlace, newRoomIndex, existingDoor.OwnerRoom,
                                                                                                   newRoomDoorIndex, existingDoor.DoorIndexInRoom, distanceApart);

            var alignedNewRoom      = newRoomTuple.Item1;
            var alignedDoorLocation = newRoomTuple.Item2;

            var alignedDoorIndex = alignedNewRoom.PotentialDoors.IndexOf(alignedDoorLocation);
            var alignedDoor      = new DoorInfo(alignedNewRoom, newRoomIndex, alignedDoorIndex, RoomTemplateUtilities.GetDoorLocation(alignedNewRoom.Room, alignedDoorIndex));

            //In order to place this successfully, we need to be able to both place the room and a connecting corridor

            if (!mapBuilder.CanBePlacedWithoutOverlappingOtherTemplates(alignedNewRoom))
            {
                throw new ApplicationException("Room failed to place because overlaps existing room");
            }

            //Increase next room for any corridor we may add
            IncreaseNextRoomIndex();

            TemplatePositioned corridorTemplateConnectingRooms = null;
            Connection         connectionToNewRoom             = null;

            if (distanceApart > 1)
            {
                //Need points that are '1-in' from the doors
                var  doorOrientation = RoomTemplateUtilities.GetDoorLocation(existingDoor.OwnerRoom.Room, existingDoor.DoorIndexInRoom);
                bool isHorizontal    = doorOrientation == RoomTemplate.DoorLocation.Left || doorOrientation == RoomTemplate.DoorLocation.Right;

                var corridorTermini = RoomTemplateUtilities.CorridorTerminalPointsBetweenDoors(existingDoorLoc, existingDoor.DoorLocation, alignedDoorLocation, RoomTemplateUtilities.GetOppositeDoorLocation(existingDoor.DoorLocation));
                var corridorIndex   = NextRoomIndex();

                if (corridorTermini.Item1 == corridorTermini.Item2)
                {
                    corridorTemplateConnectingRooms =
                        RoomTemplateUtilities.GetTemplateForSingleSpaceCorridor(corridorTermini.Item1,
                                                                                RoomTemplateUtilities.ArePointsOnVerticalLine(corridorTermini.Item1, corridorTermini.Item2), 0, corridorTemplate, corridorIndex);
                }
                else
                {
                    corridorTemplateConnectingRooms =
                        RoomTemplateUtilities.GetTemplateForCorridorBetweenPoints(corridorTermini.Item1, corridorTermini.Item2, 0, corridorTemplate, corridorIndex);
                }

                //Implicit guarantee that the corridor won't overlap with the new room we're about to place
                //(but it may overlap other previously placed rooms or corridors)
                if (!mapBuilder.CanBePlacedWithoutOverlappingOtherTemplates(corridorTemplateConnectingRooms))
                {
                    throw new ApplicationException("Room failed to place because corridor overlaps existing room");
                }

                //Place the corridor
                mapBuilder.AddPositionedTemplate(corridorTemplateConnectingRooms);
                templates[corridorIndex] = corridorTemplateConnectingRooms;
                IncreaseNextRoomIndex();

                //Add connections to the old and new rooms
                connectionToNewRoom = new Connection(corridorIndex, newRoomIndex);

                connectivityMap.AddRoomConnection(existingDoor.OwnerRoomIndex, corridorIndex);
                LogFile.Log.LogEntryDebug("Adding connection: " + existingDoor.OwnerRoomIndex + " to " + corridorIndex, LogDebugLevel.Medium);
                connectivityMap.AddRoomConnection(corridorIndex, newRoomIndex);
                LogFile.Log.LogEntryDebug("Adding connection: " + corridorIndex + " to " + newRoomIndex, LogDebugLevel.Medium);

                connectionDoors.Add(new Connection(existingDoor.OwnerRoomIndex, corridorIndex).Ordered, existingDoor);
                connectionDoors.Add(connectionToNewRoom.Ordered, alignedDoor);
            }
            else
            {
                //No corridor - a direct connection between the rooms
                connectionToNewRoom = new Connection(existingDoor.OwnerRoomIndex, newRoomIndex);

                connectivityMap.AddRoomConnection(existingDoor.OwnerRoomIndex, newRoomIndex);
                connectionDoors.Add(connectionToNewRoom.Ordered, alignedDoor);
                LogFile.Log.LogEntryDebug("Adding connection: " + existingDoor.OwnerRoomIndex + " to " + newRoomIndex, LogDebugLevel.Medium);
            }

            //Place the room
            bool successfulPlacement = mapBuilder.AddPositionedTemplate(alignedNewRoom);

            if (!successfulPlacement)
            {
                LogFile.Log.LogEntryDebug("Room failed to place because overlaps own corridor - bug", LogDebugLevel.High);
                throw new ApplicationException("Room failed to place because overlaps own corridor - bug");
            }
            templates[newRoomIndex] = alignedNewRoom;

            //Add the new potential doors (excluding the one we are linked on)
            //Can't find a nice linq alternative
            int noDoors = alignedNewRoom.PotentialDoors.Count();

            for (int i = 0; i < noDoors; i++)
            {
                if (alignedNewRoom.PotentialDoors[i] == alignedDoorLocation)
                {
                    continue;
                }
                potentialDoors.Add(new DoorInfo(alignedNewRoom, newRoomIndex, i, RoomTemplateUtilities.GetDoorLocation(alignedNewRoom.Room, i)));
            }

            //If successful, remove the candidate door from the list
            potentialDoors.Remove(existingDoor);

            return(connectionToNewRoom);
        }
Example #7
0
        /// <summary>
        /// Join 2 doors with a corridor. They must be on the opposite sides of their parent rooms (for now)
        /// </summary>
        public bool JoinDoorsWithCorridor(DoorInfo firstDoor, DoorInfo secondDoor, RoomTemplate corridorTemplate)
        {
            try
            {
                if (connectionDoors.ContainsKey(new Connection(firstDoor.OwnerRoomIndex, secondDoor.OwnerRoomIndex).Ordered))
                {
                    LogFile.Log.LogEntryDebug("No allowing 2nd connection between rooms for now - revisit past 7DRL", LogDebugLevel.High);
                    return(false);
                }

                var firstDoorLoc  = RoomTemplateUtilities.GetDoorLocation(firstDoor.OwnerRoom.Room, firstDoor.DoorIndexInRoom);
                var secondDoorLoc = RoomTemplateUtilities.GetDoorLocation(secondDoor.OwnerRoom.Room, secondDoor.DoorIndexInRoom);

                var firstDoorCoord  = firstDoor.MapCoords;
                var secondDoorCoord = secondDoor.MapCoords;

                var corridorTermini = RoomTemplateUtilities.CorridorTerminalPointsBetweenDoors(firstDoor.MapCoords, firstDoor.DoorLocation, secondDoor.MapCoords, secondDoor.DoorLocation);

                bool canDoLSharedCorridor  = RoomTemplateUtilities.CanBeConnectedWithLShapedCorridor(firstDoorCoord, firstDoorLoc, secondDoorCoord, secondDoorLoc);
                bool canDoBendCorridor     = RoomTemplateUtilities.CanBeConnectedWithBendCorridor(firstDoorCoord, firstDoorLoc, secondDoorCoord, secondDoorLoc);
                bool canDoStraightCorridor = RoomTemplateUtilities.CanBeConnectedWithStraightCorridor(firstDoorCoord, firstDoorLoc, secondDoorCoord, secondDoorLoc);
                bool areAdjacent           = corridorTermini.Item1 == secondDoorCoord && corridorTermini.Item2 == firstDoorCoord;
                bool areOverlapping        = firstDoorCoord == secondDoorCoord;

                if (!canDoLSharedCorridor && !canDoBendCorridor && !canDoStraightCorridor && !areAdjacent && !areOverlapping)
                {
                    throw new ApplicationException("No corridor available to connect this type of door");
                }

                if (areAdjacent || areOverlapping)
                {
                    //Add a direct connection in the connectivity graph
                    connectivityMap.AddRoomConnection(firstDoor.OwnerRoomIndex, secondDoor.OwnerRoomIndex);
                    connectionDoors.Add(new Connection(firstDoor.OwnerRoomIndex, secondDoor.OwnerRoomIndex).Ordered, firstDoor);
                }
                else
                {
                    //Create template

                    var horizontal = false;
                    if (firstDoorLoc == RoomTemplate.DoorLocation.Left || firstDoorLoc == RoomTemplate.DoorLocation.Right)
                    {
                        horizontal = true;
                    }

                    int xOffset = corridorTermini.Item2.x - corridorTermini.Item1.x;
                    int yOffset = corridorTermini.Item2.y - corridorTermini.Item1.y;

                    RoomTemplate expandedCorridor;
                    Point        corridorTerminus1InTemplate;

                    if (canDoBendCorridor)
                    {
                        int transition = (int)Math.Floor(yOffset / 2.0);
                        if (horizontal == true)
                        {
                            transition = (int)Math.Floor(xOffset / 2.0);
                        }
                        var expandedCorridorAndPoint = RoomTemplateUtilities.ExpandCorridorTemplateBend(xOffset, yOffset, transition, horizontal, corridorTemplate);
                        expandedCorridor            = expandedCorridorAndPoint.Item1;
                        corridorTerminus1InTemplate = expandedCorridorAndPoint.Item2;
                    }
                    else if (canDoLSharedCorridor)
                    {
                        var expandedCorridorAndPoint = RoomTemplateUtilities.ExpandCorridorTemplateLShaped(xOffset, yOffset, horizontal, corridorTemplate);
                        expandedCorridor            = expandedCorridorAndPoint.Item1;
                        corridorTerminus1InTemplate = expandedCorridorAndPoint.Item2;
                    }
                    else
                    {
                        var offsetToUse = horizontal ? xOffset : yOffset;
                        var expandedCorridorAndPoint = RoomTemplateUtilities.ExpandCorridorTemplateStraight(offsetToUse, horizontal, corridorTemplate);
                        expandedCorridor            = expandedCorridorAndPoint.Item1;
                        corridorTerminus1InTemplate = expandedCorridorAndPoint.Item2;
                    }

                    //Place corridor

                    //Match corridor tile to location of door
                    Point topLeftCorridor = corridorTermini.Item1 - corridorTerminus1InTemplate;

                    var corridorRoomIndex  = NextRoomIndex();
                    var positionedCorridor = new TemplatePositioned(topLeftCorridor.x, topLeftCorridor.y, 0, expandedCorridor, corridorRoomIndex);

                    if (!mapBuilder.CanBePlacedWithoutOverlappingOtherTemplates(positionedCorridor))
                    {
                        return(false);
                    }

                    //Place the corridor
                    mapBuilder.AddPositionedTemplate(positionedCorridor);
                    templates[corridorRoomIndex] = positionedCorridor;
                    IncreaseNextRoomIndex();

                    //Add connections to the old and new rooms
                    connectivityMap.AddRoomConnection(firstDoor.OwnerRoomIndex, corridorRoomIndex);
                    connectivityMap.AddRoomConnection(corridorRoomIndex, secondDoor.OwnerRoomIndex);

                    connectionDoors.Add(new Connection(firstDoor.OwnerRoomIndex, corridorRoomIndex).Ordered, firstDoor);
                    connectionDoors.Add(new Connection(corridorRoomIndex, secondDoor.OwnerRoomIndex).Ordered, secondDoor);
                }

                //Remove both doors from the potential list
                potentialDoors.Remove(firstDoor);
                potentialDoors.Remove(secondDoor);

                return(true);
            }
            catch (ApplicationException ex)
            {
                LogFile.Log.LogEntryDebug("Failed to join doors: " + ex.Message, LogDebugLevel.Medium);
                return(false);
            }
        }
Example #8
0
        public IEnumerable <Point> GetBoundaryPointsInRoomOfTerrain(int roomIndex)
        {
            var roomRelativePoints = RoomTemplateUtilities.GetBoundaryFloorPointsInRoom(rooms[roomIndex].Room);

            return(roomRelativePoints.Select(p => new Point(rooms[roomIndex].Location + p)));
        }
Example #9
0
        public IEnumerable <Point> GetAllPointsInRoomOfTerrain(int roomIndex, RoomTemplateTerrain terrainToFind)
        {
            var roomRelativePoints = RoomTemplateUtilities.GetPointsInRoomWithTerrain(rooms[roomIndex].Room, terrainToFind);

            return(roomRelativePoints.Select(p => new Point(rooms[roomIndex].Location + p)));
        }
Example #10
0
        /// <summary>
        /// Returns point in map coords of this level in the required room of terrain
        /// </summary>
        /// <param name="roomIndex"></param>
        /// <param name="terrainToFind"></param>
        /// <returns></returns>
        public Point GetRandomPointInRoomOfTerrain(int roomIndex, RoomTemplateTerrain terrainToFind)
        {
            var roomRelativePoint = RoomTemplateUtilities.GetRandomPointWithTerrain(rooms[roomIndex].Room, terrainToFind);

            return(new Point(rooms[roomIndex].Location + roomRelativePoint));
        }