public IEnumerable<int> GetNodesOnStartSideOfConnection(Connection dividingConnection) { //Check the edge is in the reduced map (will throw an exception if can't find) var foundEdge = mapWithoutCycles.GetEdgeBetweenRoomsNoCycles(dividingConnection.Source, dividingConnection.Target); //Remove all areas behind the locked door MapSplitter allowedMap = new MapSplitter(mapWithoutCycles.mapNoCycles.Edges, foundEdge, startVertex); //Find the component of this broken graph that is connected to the start vertex - //This component contains the vertices accessible with these clues return allowedMap.MapComponent(allowedMap.RoomComponentIndex(startVertex)); }
public void RoomsOnSideOfOriginInMultiplySplitMapAreInOneComponent() { ConnectivityMap standardMap = BuildStandardTestMap(); var edgesToSplit = new List <TaggedEdge <int, string> >(); edgesToSplit.Add(standardMap.GetEdgeBetweenRooms(10, 11)); edgesToSplit.Add(standardMap.GetEdgeBetweenRooms(3, 5)); MapSplitter splitter = new MapSplitter(standardMap.RoomConnectionGraph.Edges, edgesToSplit, 1); CollectionAssert.AreEquivalent(new List <int>(new int[] { 1, 2, 3, 4, 7, 8, 9, 10 }), splitter.MapComponent(splitter.OriginComponentIndex).ToList()); }
/** Get valid rooms to place a clue, where rooms behind edgeToLock are inaccessible and rooms behind doors needing lockedClues are inaccessible */ private IEnumerable<int> GetValidRoomsToPlaceClue(List<string> doorsToAvoidIds, Connection edgeToLock, IEnumerable<int> lockedClues) { //Check the edge is in the reduced map (will throw an exception if can't find) List<TaggedEdge<int, string>> foundEdge = new List<TaggedEdge<int, string>>(); ; if (edgeToLock != null) foundEdge.Add(mapNoCycles.GetEdgeBetweenRoomsNoCycles(edgeToLock.Source, edgeToLock.Target)); //Find all doors that depend on any door with a locked clue. //We can't place a clue for our new door behind any of these var allDoorsDependentOnLockedClueDoors = lockedClues.SelectMany(c => GetDependentDoorIndices(c)); var allInaccessibleDoors = lockedClues.Union(allDoorsDependentOnLockedClueDoors).Distinct(); //Add to the list any doors we want to avoid (this can be used to localise clues to parts of levels etc.) var allDoorsToAvoid = doorsToAvoidIds.Select(id => GetDoorById(id).LockIndex); var allInaccessibleDoorsAndAvoidedDoors = allInaccessibleDoors.Union(allDoorsToAvoid); //Retrieve the door edges in the forbidden list //Note that some ids correspond to objectives, so these are avoided by the ugly SelectMany var forbiddenDoorEdges = allInaccessibleDoorsAndAvoidedDoors.SelectMany( doorIndex => doorMap.ContainsKey(doorIndex) ? new List<TaggedEdge<int, string>> { doorMap[doorIndex].DoorEdge } : new List<TaggedEdge<int, string>>()); //Add this edge (can't put clue behind our own door) - NB: hacky way to union with a single item var allForbiddenDoorEdges = forbiddenDoorEdges.Union(foundEdge).Distinct(); //Remove all areas behind any locked door MapSplitter allowedMap = new MapSplitter(mapNoCycles.mapNoCycles.Edges, allForbiddenDoorEdges, startVertex); //Find the component of this broken graph that is connected to the start vertex - this is the candidate subtree var allowedNodes = allowedMap.MapComponent(allowedMap.RoomComponentIndex(startVertex)); return allowedNodes; }
public IEnumerable<int> GetAccessibleVerticesWithClues(IEnumerable<int> lockedDoorsForCluesAndObjectives) { //Find all the locked edges not accessible by our clues var allDoors = doorMap.Keys; //How many keys we have for each locked item var allClues = lockedDoorsForCluesAndObjectives.ToList(); Dictionary<int, int> noCluesForDoors; //Test objectives in a n^2 loop and add any liberated clues var openedObjectives = new HashSet<Objective>(); int openedObjectivesCount; do { openedObjectivesCount = openedObjectives.Count(); noCluesForDoors = allClues.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count()); var unlockedObjectives = objectiveMap.Where(obj => noCluesForDoors.ContainsKey(obj.Value.LockIndex) && noCluesForDoors[obj.Value.LockIndex] >= obj.Value.NumCluesRequired) .Select(d => d.Value); var newlyUnlockedObjectives = unlockedObjectives.Except(openedObjectives); var newClues = newlyUnlockedObjectives.SelectMany(obj => obj.OpenLockIndex); allClues.AddRange(newClues); //Seems that ordering here is important - ensure we have got the new clues before we add to openObjectives (lazy evaluation) foreach (var obj in newlyUnlockedObjectives) openedObjectives.Add(obj); } while(openedObjectivesCount != openedObjectives.Count()); noCluesForDoors = allClues.GroupBy(c => c).ToDictionary(g => g.Key, g => g.Count()); var unlockedDoors = doorMap.Where(d => noCluesForDoors.ContainsKey(d.Value.LockIndex) && noCluesForDoors[d.Value.LockIndex] >= d.Value.NumCluesRequired) .Select(d => d.Key); var lockedDoors = allDoors.Except(unlockedDoors); //Remove all areas behind any locked door var lockedEdges = lockedDoors.Select(d => doorMap[d].DoorEdge); MapSplitter allowedMap = new MapSplitter(mapNoCycles.mapNoCycles.Edges, lockedEdges, startVertex); //Find the component of this broken graph that is connected to the start vertex - //This component contains the vertices accessible with these clues return allowedMap.MapComponent(allowedMap.RoomComponentIndex(startVertex)); }
public void RoomsOnSideOfOriginInMultiplySplitMapAreInOneComponent() { ConnectivityMap standardMap = BuildStandardTestMap(); var edgesToSplit = new List<TaggedEdge<int, string>>(); edgesToSplit.Add(standardMap.GetEdgeBetweenRooms(10, 11)); edgesToSplit.Add(standardMap.GetEdgeBetweenRooms(3, 5)); MapSplitter splitter = new MapSplitter(standardMap.RoomConnectionGraph.Edges, edgesToSplit, 1); CollectionAssert.AreEquivalent(new List<int>(new int[] { 1, 2, 3, 4, 7, 8, 9, 10 }), splitter.MapComponent(splitter.OriginComponentIndex).ToList()); }