/// <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); }