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); } }
public void Add(params string[] newTransitions) { foreach (string t in newTransitions) { string doorName = LogicManager.GetTransitionDef(t).doorName; switch (doorName.Substring(0, 3)) { case "doo": case "rig": rightTransitions.Add(t); break; case "lef": leftTransitions.Add(t); break; case "top": topTransitions.Add(t); break; case "bot": botTransitions.Add(t); break; } } }
public void Add(List <string> newTransitions) { leftTransitions.AddRange(newTransitions.Where(transition => LogicManager.GetTransitionDef(transition).doorName.StartsWith("left"))); rightTransitions.AddRange(newTransitions.Where(transition => LogicManager.GetTransitionDef(transition).doorName.StartsWith("right") || LogicManager.GetTransitionDef(transition).doorName.StartsWith("door"))); topTransitions.AddRange(newTransitions.Where(transition => LogicManager.GetTransitionDef(transition).doorName.StartsWith("top"))); botTransitions.AddRange(newTransitions.Where(transition => LogicManager.GetTransitionDef(transition).doorName.StartsWith("bot"))); }
public void LogCounts() { int left1 = leftTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay != 0).Count(); int right1 = rightTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay != 0).Count(); int top1 = topTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay != 0).Count(); int bot1 = botTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay != 0).Count(); int left2 = leftTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay == 0).Count(); int right2 = rightTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay == 0).Count(); int top2 = topTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay == 0).Count(); int bot2 = botTransitions.Where(t => LogicManager.GetTransitionDef(t).oneWay == 0).Count(); if (0 != left1 || 0 != right1 || 0 != top1 || bot1 != 0) { LogHelper.Log("One-way counts:"); LogHelper.Log("Left: " + left1); LogHelper.Log("Right: " + right1); LogHelper.Log("Top: " + top1); LogHelper.Log("Bottom: " + bot1); } LogHelper.Log("Two-way counts:"); LogHelper.Log("Left: " + left2); LogHelper.Log("Right: " + right2); LogHelper.Log("Top: " + top2); LogHelper.Log("Bottom: " + bot2); }
public static void BuildRoomSpanningTree() { List <string> rooms = new List <string>(); Dictionary <string, List <string> > roomTransitions = new Dictionary <string, List <string> >(); foreach (string transition in LogicManager.TransitionNames()) { if (transition == startTransition) { continue; } TransitionDef def = LogicManager.GetTransitionDef(transition); string roomName = def.sceneName; if (new List <string> { "Crossroads_46", "Crossroads_46b" }.Contains(roomName)) { roomName = "Crossroads_46"; } if (new List <string> { "Abyss_03", "Abyss_03_b", "Abyss_03_c" }.Contains(roomName)) { roomName = "Abyss_03"; } if (new List <string> { "Ruins2_10", "Ruins2_10b" }.Contains(roomName)) { roomName = "Ruins2_10"; } if (!rooms.Contains(roomName) && !def.deadEnd && !def.isolated) { rooms.Add(roomName); roomTransitions.Add(roomName, new List <string>()); } } foreach (string transition in LogicManager.TransitionNames()) { if (transition == startTransition) { continue; } TransitionDef def = LogicManager.GetTransitionDef(transition); string roomName = def.sceneName; if (def.oneWay == 0 && rooms.Contains(roomName)) { roomTransitions[roomName].Add(transition); } } BuildSpanningTree(roomTransitions); }
private List <string> GetReachableTransitions(ProgressionManager _pm = null) // essentially the same as the method in transitionManager, using that class's static placement dictionary { if (_pm != null) { pm = _pm; } bool done = false; bool updated = false; List <string> reachableTransitions = new List <string>(); List <string> unreachableTransitions = LogicManager.TransitionNames().ToList(); while (!done) { foreach (string transition in unreachableTransitions) { if (pm.Has(transition)) { reachableTransitions.Add(transition); } else if (LogicManager.GetTransitionDef(transition).oneWay == 2) { string entrance = TransitionManager.transitionPlacements.FirstOrDefault(exit => exit.Value == transition).Key; if (entrance != null && pm.CanGet(entrance)) { reachableTransitions.Add(transition); updated = true; } } else if (!LogicManager.GetTransitionDef(transition).isolated&& pm.CanGet(transition)) { reachableTransitions.Add(transition); updated = true; } else if (TransitionManager.transitionPlacements.TryGetValue(transition, out string altTransition) && LogicManager.GetTransitionDef(altTransition).oneWay != 2 && !LogicManager.GetTransitionDef(altTransition).isolated&& pm.CanGet(altTransition)) { reachableTransitions.Add(transition); updated = true; } } foreach (string transition in reachableTransitions) { unreachableTransitions.Remove(transition); pm.Add(transition); } done = !updated; updated = false; } return(reachableTransitions); }
public static void BuildAreaSpanningTree() { List <string> areas = new List <string>(); Dictionary <string, List <string> > areaTransitions = new Dictionary <string, List <string> >(); foreach (string transition in LogicManager.TransitionNames()) { if (transition == startTransition) { continue; } TransitionDef def = LogicManager.GetTransitionDef(transition); string areaName = def.areaName; if (new List <string> { "City_of_Tears", "Forgotten_Crossroads", "Resting_Grounds" }.Contains(areaName)) { areaName = "Kings_Station"; } if (new List <string> { "Ancient_Basin", "Kingdoms_Edge" }.Contains(areaName)) { areaName = "Deepnest"; } if (!areas.Contains(areaName) && !def.deadEnd && !def.isolated) { areas.Add(areaName); areaTransitions.Add(areaName, new List <string>()); } } foreach (string transition in LogicManager.TransitionNames()) { if (transition == startTransition) { continue; } TransitionDef def = LogicManager.GetTransitionDef(transition); string areaName = def.areaName; if (def.oneWay == 0 && areas.Contains(areaName)) { areaTransitions[areaName].Add(transition); } } BuildSpanningTree(areaTransitions); }
public bool Test(string transitionTarget) { if (SinglyCompatible()) { return(true); } string doorName = LogicManager.GetTransitionDef(transitionTarget).doorName; switch (doorName.Substring(0, 3)) { case "doo": case "rig": if (left) { return(true); } break; case "lef": if (right) { return(true); } break; case "top": if (bot) { return(true); } break; case "bot": if (top) { return(true); } break; } return(false); }
public string GetNextTransition(string input) { string doorName = LogicManager.GetTransitionDef(input).doorName; string output = null; switch (doorName.Substring(0, 3)) { case "doo": case "rig": if (leftTransitions.Any()) { output = leftTransitions[rand.Next(leftTransitions.Count)]; } break; case "lef": if (rightTransitions.Any()) { output = rightTransitions[rand.Next(rightTransitions.Count)]; } break; case "top": if (botTransitions.Any()) { output = botTransitions[rand.Next(botTransitions.Count)]; } break; case "bot": if (topTransitions.Any()) { output = topTransitions[rand.Next(topTransitions.Count)]; } break; } return(output); }
private static void CompleteTransitionGraph() { if (randomizationError) { return; } // IDK if this is the right fix but the line is correct and the algo is being rewritten so w/e foreach (string item in startProgression) { im.UpdateReachableLocations(item); } int failsafe = 0; Log("Beginning full placement of transitions..."); while (tm.unplacedTransitions.Any()) { failsafe++; if (failsafe > 120) { Log("Aborted randomization on too many passes. At the time, there were:"); Log("Unplaced transitions: " + tm.unplacedTransitions.Count); Log("Reachable transitions: " + tm.reachableTransitions.Count); Log("Reachable unplaced transitions, directionally compatible: " + tm.placeableCount); Log("Reachable item locations: " + im.availableCount); foreach (string t in tm.unplacedTransitions) { Log(t + ", in reachable: " + tm.reachableTransitions.Contains(t) + ", is reachable: " + tm.pm.CanGet(t)); } randomizationError = true; return; } if (im.canGuess && im.availableCount > 1) // give randomized progression as locations are available { if (im.FindNextLocation(tm.pm) is string placeLocation) { string placeItem = im.GuessItem(); im.PlaceItem(placeItem, placeLocation); tm.UpdateReachableTransitions(placeItem, true); } } int placeableCount = tm.placeableCount; if (placeableCount < 4) { tm.UpdateReachableTransitions(); } if (placeableCount == 0 && im.availableCount == 0) { Log("Ran out of locations?!?"); randomizationError = true; return; } else if (placeableCount > 2) { tm.UnloadReachableStandby(); string transition1 = tm.NextTransition(); string transition2 = tm.dt.GetNextTransition(transition1); tm.PlaceTransitionPair(transition1, transition2); //Log($">2 place: {transition1}, {transition2}"); continue; } else if (tm.unplacedTransitions.Count == 2) { string transition1 = tm.unplacedTransitions[0]; string transition2 = tm.unplacedTransitions[1]; tm.PlaceTransitionPair(transition1, transition2); //Log($"last place: {transition1}, {transition2}"); continue; } else if (placeableCount != 0) { if (tm.ForceTransition() is string transition1) { string transition2 = tm.dt.GetNextTransition(transition1); tm.PlaceTransitionPair(transition1, transition2); //Log($"force place: {transition1}, {transition2}"); continue; } } // Last ditch effort to save the seed. The list is ordered by which items are heuristically likely to unlock transitions at this point. if (im.FindNextLocation(tm.pm) is string lastLocation) { IEnumerable <string> progressionCandidates = new List <string> { "Mantis_Claw", "Monarch_Wings", "Left_Mantis_Claw", "Right_Mantis_Claw", "Desolate_Dive", "Isma's_Tear", "Crystal_Heart", "Mothwing_Cloak", "Shade_Cloak", "Right_Mothwing_Cloak", "Right_Shade_Cloak", "Left_Mothwing_Cloak", "Left_Shade_Cloak" } .Where(item => im.randomizedItems.Contains(item)); foreach (string item in progressionCandidates) { if (!tm.pm.Has(item)) { im.PlaceItem(item, lastLocation); tm.UpdateReachableTransitions(item, true); break; } } continue; } } Log("Placing last reserved transitions..."); tm.UnloadStandby(); Log("All transitions placed? " + (TransitionManager.transitionPlacements.Count == LogicManager.TransitionNames().Count(t => LogicManager.GetTransitionDef(t).oneWay != 2))); }
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 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)."); }
public static void BuildCARSpanningTree() { List <string> areas = new List <string>(); Dictionary <string, List <string> > rooms = new Dictionary <string, List <string> >(); foreach (string t in tm.unplacedTransitions) { if (t == startTransition) { continue; } if (!LogicManager.GetTransitionDef(t).isolated || !LogicManager.GetTransitionDef(t).deadEnd) { if (!areas.Contains(LogicManager.GetTransitionDef(t).areaName)) { areas.Add(LogicManager.GetTransitionDef(t).areaName); rooms.Add(LogicManager.GetTransitionDef(t).areaName, new List <string>()); } if (!rooms[LogicManager.GetTransitionDef(t).areaName].Contains(LogicManager.GetTransitionDef(t).sceneName)) { rooms[LogicManager.GetTransitionDef(t).areaName].Add(LogicManager.GetTransitionDef(t).sceneName); } } } var areaTransitions = new Dictionary <string, Dictionary <string, List <string> > >(); // [area][scene][transition] foreach (string area in areas) { areaTransitions.Add(area, new Dictionary <string, List <string> >()); } foreach (var kvp in rooms) { foreach (string room in kvp.Value) { areaTransitions[kvp.Key].Add(room, new List <string>()); } } foreach (string t in tm.unplacedTransitions) { if (t == startTransition) { continue; } TransitionDef def = LogicManager.GetTransitionDef(t); if (!areas.Contains(def.areaName) || !areaTransitions[def.areaName].ContainsKey(def.sceneName)) { continue; } areaTransitions[def.areaName][def.sceneName].Add(t); } foreach (string area in areas) { BuildSpanningTree(areaTransitions[area]); } var worldTransitions = new Dictionary <string, List <string> >(); foreach (string area in areas) { worldTransitions.Add(area, new List <string>()); } foreach (string t in tm.unplacedTransitions) { if (t == startTransition) { continue; } if (areas.Contains(LogicManager.GetTransitionDef(t).areaName) && rooms[LogicManager.GetTransitionDef(t).areaName].Contains(LogicManager.GetTransitionDef(t).sceneName)) { worldTransitions[LogicManager.GetTransitionDef(t).areaName].Add(t); } } BuildSpanningTree(worldTransitions); }
public string GetNextTransition(string input, bool favorSameArea = false) { string doorName = LogicManager.GetTransitionDef(input).doorName; string output = null; if (favorSameArea) { string area = LogicManager.GetTransitionDef(input).areaName; List <string> compatibleTransitions = new List <string>(); switch (doorName.Substring(0, 3)) { case "doo": case "rig": compatibleTransitions = leftTransitions.Where(t => LogicManager.GetTransitionDef(t).areaName == area).ToList(); break; case "lef": compatibleTransitions = rightTransitions.Where(t => LogicManager.GetTransitionDef(t).areaName == area).ToList(); break; case "top": compatibleTransitions = botTransitions.Where(t => LogicManager.GetTransitionDef(t).areaName == area).ToList(); break; case "bot": compatibleTransitions = topTransitions.Where(t => LogicManager.GetTransitionDef(t).areaName == area).ToList(); break; } if (compatibleTransitions.Any()) { output = compatibleTransitions[rand.Next(compatibleTransitions.Count)]; } } if (string.IsNullOrEmpty(output)) { switch (doorName.Substring(0, 3)) { case "doo": case "rig": if (leftTransitions.Any()) { output = leftTransitions[rand.Next(leftTransitions.Count)]; } break; case "lef": if (rightTransitions.Any()) { output = rightTransitions[rand.Next(rightTransitions.Count)]; } break; case "top": if (botTransitions.Any()) { output = botTransitions[rand.Next(botTransitions.Count)]; } break; case "bot": if (topTransitions.Any()) { output = topTransitions[rand.Next(topTransitions.Count)]; } break; } } return(output); }