コード例 #1
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);
        }