private static void PlaceOneWayTransitions() { if (randomizationError) { return; } List <string> oneWayEntrances = LogicManager.TransitionNames().Where(transition => LogicManager.GetTransitionDef(transition).oneWay == 1).ToList(); List <string> oneWayExits = LogicManager.TransitionNames().Where(transition => LogicManager.GetTransitionDef(transition).oneWay == 2).ToList(); List <string> horizontalOneWays = oneWayEntrances.Where(t => !LogicManager.GetTransitionDef(t).doorName.StartsWith("b")).ToList(); while (horizontalOneWays.Any()) { string horizontalEntrance = horizontalOneWays.First(); string downExit = oneWayExits[rand.Next(oneWayExits.Count)]; tm.PlaceOneWayPair(horizontalEntrance, downExit); oneWayEntrances.Remove(horizontalEntrance); horizontalOneWays.Remove(horizontalEntrance); oneWayExits.Remove(downExit); } DirectedTransitions directed = new DirectedTransitions(rand); directed.Add(oneWayExits); while (oneWayEntrances.Any()) { string entrance = oneWayEntrances[rand.Next(oneWayEntrances.Count)]; string exit = directed.GetNextTransition(entrance); tm.PlaceOneWayPair(entrance, exit); oneWayEntrances.Remove(entrance); oneWayExits.Remove(exit); directed.Remove(exit); } }
private static void PlaceIsolatedTransitions() { if (randomizationError) { return; } List <string> isolatedTransitions = tm.unplacedTransitions.Where(transition => LogicManager.GetTransitionDef(transition).isolated).ToList(); List <string> nonisolatedTransitions = tm.unplacedTransitions.Where(transition => !LogicManager.GetTransitionDef(transition).isolated).ToList(); DirectedTransitions directed = new DirectedTransitions(rand); isolatedTransitions.Remove(startTransition); nonisolatedTransitions.Remove(startTransition); directed.Add(nonisolatedTransitions); bool connectAreas = RandomizerMod.Instance.Settings.ConnectAreas; while (isolatedTransitions.Any()) { string transition1 = isolatedTransitions[rand.Next(isolatedTransitions.Count)]; string transition2 = directed.GetNextTransition(transition1, favorSameArea: connectAreas); if (transition2 is null) { Log("Ran out of nonisolated transitions during preplacement!"); randomizationError = true; return; } tm.PlaceStandbyPair(transition1, transition2); isolatedTransitions.Remove(transition1); directed.Remove(transition2); } }
public TransitionManager(Random rnd) { rand = rnd; dt = new DirectedTransitions(rnd); pm = new ProgressionManager( RandomizerState.InProgress ); transitionPlacements = new Dictionary <string, string>(); List <string> iterate = LogicManager.TransitionNames().ToList(); unplacedTransitions = new List <string>(); while (iterate.Any()) { string t = iterate[rand.Next(iterate.Count)]; unplacedTransitions.Add(t); iterate.Remove(t); } standbyTransitions = new Dictionary <string, string>(); reachableTransitions = new HashSet <string>(); recentProgression = new HashSet <string>(); dt.Add(unplacedTransitions); }
public TransitionManager(Random rnd) { rand = rnd; dt = new DirectedTransitions(rnd); pm = new ProgressionManager( RandomizerState.InProgress ); // start items added to pm in Connect Start to Graph in Randomizer transitionPlacements = new Dictionary <string, string>(); List <string> iterate = LogicManager.TransitionNames().ToList(); unplacedTransitions = new List <string>(); while (iterate.Any()) { string t = iterate[rand.Next(iterate.Count)]; unplacedTransitions.Add(t); iterate.Remove(t); } standbyTransitions = new Dictionary <string, string>(); reachableTransitions = new HashSet <string>(); recentProgression = new HashSet <string>(); vanillaProgression = VanillaManager.GetVanillaProgression(); checkProgression = new HashSet <string>(); dt.Add(unplacedTransitions); }
public string NextTransition(DirectedTransitions _dt = null) { if (_dt == null) { _dt = dt; } return(reachableTransitions.FirstOrDefault(t => _dt.Test(t) && unplacedTransitions.Contains(t))); }
public void UpdateTransitionStandby(string transition1, string transition2) { bool ableToRelink1; bool ableToRelink2; bool T1InStandby = standbyTransitions.TryGetValue(transition1, out string oldTransition2); bool T2InStandby = standbyTransitions.TryGetValue(transition2, out string oldTransition1); standbyTransitions.Remove(transition1); standbyTransitions.Remove(transition2); if (T1InStandby && oldTransition1 == transition1) { return; // this means t1 and t2 were already linked in standby } if (T1InStandby || T2InStandby) { DirectedTransitions dt = new DirectedTransitions(rand); dt.Add(unplacedTransitions); if (T1InStandby && dt.GetNextTransition(oldTransition2) is string newTransition1) { standbyTransitions[oldTransition2] = newTransition1; standbyTransitions[newTransition1] = oldTransition2; unplacedTransitions.Remove(newTransition1); dt.Remove(newTransition1); ableToRelink1 = true; } else { ableToRelink1 = !T1InStandby; } if (T2InStandby && dt.GetNextTransition(oldTransition1) is string newTransition2) { standbyTransitions[oldTransition1] = newTransition2; standbyTransitions[newTransition2] = oldTransition1; unplacedTransitions.Remove(newTransition2); ableToRelink2 = true; } else { ableToRelink2 = !T2InStandby; } if (T1InStandby && T2InStandby && !ableToRelink1 && !ableToRelink2) { standbyTransitions[oldTransition1] = oldTransition2; standbyTransitions[oldTransition2] = oldTransition1; return; } if (!ableToRelink1 || !ableToRelink2) { LogError("Error encountered in updating standby transitions. Unable to relink after removing standby transition."); Randomizer.randomizationError = true; } } }
public string ForceTransition(DirectedTransitions _dt = null) { if (_dt == null) { _dt = dt; } List <string> candidateTransitions = new List <string>(); candidateTransitions.AddRange(unplacedTransitions); candidateTransitions.AddRange(standbyTransitions.Keys); candidateTransitions = candidateTransitions.Except(reachableTransitions).Where(transition => _dt.Test(transition)).ToList(); bool Test(string transition) { HashSet <string> tempProgression = FakeUpdateReachableTransitions(transition); tempProgression.Remove(transition); tempProgression.IntersectWith(candidateTransitions); return(tempProgression.Any()); } return(candidateTransitions.FirstOrDefault(t => Test(t))); }
public void UpdateTransitionStandby(string transition1, string transition2) { if (standbyTransitions.TryGetValue(transition1, out string oldTransition2)) { DirectedTransitions dt = new DirectedTransitions(rand); dt.Add(unplacedTransitions); standbyTransitions.Remove(transition1); string newTransition1 = dt.GetNextTransition(oldTransition2); standbyTransitions[oldTransition2] = newTransition1; standbyTransitions.Add(newTransition1, oldTransition2); unplacedTransitions.Remove(newTransition1); } if (standbyTransitions.TryGetValue(transition2, out string oldTransition1)) { DirectedTransitions dt = new DirectedTransitions(rand); dt.Add(unplacedTransitions); standbyTransitions.Remove(transition2); string newTransition2 = dt.GetNextTransition(oldTransition1); standbyTransitions[oldTransition1] = newTransition2; standbyTransitions.Add(newTransition2, oldTransition1); unplacedTransitions.Remove(newTransition2); } }
private static void ConnectStartToGraph() { if (randomizationError) { return; } Log("Attaching start to graph..."); tm.pm = new ProgressionManager( RandomizerState.InProgress ); im.ResetReachableLocations(); vm.ResetReachableLocations(); tm.ResetReachableTransitions(); tm.pm.Add(startProgression); { // keeping local variables out of the way DirectedTransitions d = new DirectedTransitions(rand); d.Add(startTransition); string transition2 = tm.ForceTransition(d); if (transition2 is null) // this should happen extremely rarely, but it has to be handled { Log("No way out of start?!?"); Log("Was the start transition already placed? " + TransitionManager.transitionPlacements.ContainsKey(startTransition)); randomizationError = true; return; } tm.PlaceTransitionPair(startTransition, transition2); } while (true) { if (!RandomizerMod.Instance.Settings.RandomizeSkills) { // it is essentially impossible to generate a transition randomizer without one of these accessible if (tm.pm.CanGet("Mantis_Claw") || tm.pm.CanGet("Mothwing_Cloak") || tm.pm.CanGet("Shade_Cloak")) { return; } } else if (im.FindNextLocation(tm.pm) != null) { return; } tm.UnloadReachableStandby(); List <string> placeableTransitions = tm.reachableTransitions.Intersect(tm.unplacedTransitions.Union(tm.standbyTransitions.Keys)).ToList(); if (!placeableTransitions.Any()) { Log("Could not connect start to map--ran out of placeable transitions."); foreach (string t in tm.reachableTransitions) { Log(t); } randomizationError = true; return; } DirectedTransitions directed = new DirectedTransitions(rand); directed.Add(placeableTransitions); if (tm.ForceTransition(directed) is string transition1) { string transition2 = directed.GetNextTransition(transition1); tm.PlaceTransitionPair(transition1, transition2); } else { Log("Could not connect start to map--ran out of progression transitions."); randomizationError = true; return; } } }
public static void BuildSpanningTree(Dictionary <string, List <string> > sortedTransitions, string first = null) { List <string> remaining = sortedTransitions.Keys.ToList(); while (first == null) { first = remaining[rand.Next(remaining.Count)]; if (!sortedTransitions[first].Any(t => !LogicManager.GetTransitionDef(t).isolated)) { first = null; } } remaining.Remove(first); List <DirectedTransitions> directed = new List <DirectedTransitions>(); directed.Add(new DirectedTransitions(rand)); directed[0].Add(sortedTransitions[first].Where(t => !LogicManager.GetTransitionDef(t).isolated).ToList()); int failsafe = 0; while (remaining.Any()) { bool placed = false; failsafe++; if (failsafe > 500 || !directed[0].AnyCompatible()) { Log("Triggered failsafe on round " + failsafe + " in BuildSpanningTree, where first transition set was: " + first + " with count: " + sortedTransitions[first].Count); randomizationError = true; return; } string nextRoom = remaining[rand.Next(remaining.Count)]; foreach (DirectedTransitions dt in directed) { List <string> nextAreaTransitions = sortedTransitions[nextRoom].Where(transition => !LogicManager.GetTransitionDef(transition).deadEnd&& dt.Test(transition)).ToList(); List <string> newTransitions = sortedTransitions[nextRoom].Where(transition => !LogicManager.GetTransitionDef(transition).isolated).ToList(); if (!nextAreaTransitions.Any()) { continue; } string transitionTarget = nextAreaTransitions[rand.Next(nextAreaTransitions.Count)]; string transitionSource = dt.GetNextTransition(transitionTarget); tm.PlaceTransitionPair(transitionSource, transitionTarget); remaining.Remove(nextRoom); dt.Add(newTransitions); dt.Remove(transitionTarget, transitionSource); placed = true; break; } if (placed) { continue; } else { DirectedTransitions dt = new DirectedTransitions(rand); dt.Add(sortedTransitions[nextRoom].Where(transition => !LogicManager.GetTransitionDef(transition).isolated).ToList()); directed.Add(dt); remaining.Remove(nextRoom); } } //Log("Completed first pass of BuildSpanningTree with " + directed.Count + " connected component(s)."); for (int i = 0; i < directed.Count; i++) { DirectedTransitions dt = directed[i]; DirectedTransitions dt1 = null; string transition1 = null; string transition2 = null; foreach (var dt2 in directed) { if (dt == dt2) { continue; } if (dt.left && dt2.right) { transition1 = dt.leftTransitions[rand.Next(dt.leftTransitions.Count)]; transition2 = dt2.rightTransitions[rand.Next(dt2.rightTransitions.Count)]; dt1 = dt2; break; } else if (dt.right && dt2.left) { transition1 = dt.rightTransitions[rand.Next(dt.rightTransitions.Count)]; transition2 = dt2.leftTransitions[rand.Next(dt2.leftTransitions.Count)]; dt1 = dt2; break; } else if (dt.top && dt2.bot) { transition1 = dt.topTransitions[rand.Next(dt.topTransitions.Count)]; transition2 = dt2.botTransitions[rand.Next(dt2.botTransitions.Count)]; dt1 = dt2; break; } else if (dt.bot && dt2.top) { transition1 = dt.botTransitions[rand.Next(dt.botTransitions.Count)]; transition2 = dt2.topTransitions[rand.Next(dt2.topTransitions.Count)]; dt1 = dt2; break; } } if (!string.IsNullOrEmpty(transition1)) { tm.PlaceTransitionPair(transition1, transition2); dt1.Add(dt.AllTransitions); dt1.Remove(transition1, transition2); directed.Remove(dt); i = -1; } } //Log("Exited BuildSpanningTree with " + directed.Count + " connected component(s)."); }