private static bool ValidateTransitionRandomization() { if (randomizationError) { return(false); } Log("Beginning transition placement validation..."); ProgressionManager pm = new ProgressionManager( RandomizerState.Validating ); pm.Add(startProgression); pm.Add(LogicManager.ItemNames.Where(i => LogicManager.GetItemDef(i).progression)); tm.ResetReachableTransitions(); tm.UpdateReachableTransitions(_pm: pm); bool validated = tm.reachableTransitions.SetEquals(LogicManager.TransitionNames()); if (!validated) { Log("Transition placements failed to validate!"); foreach (string t in LogicManager.TransitionNames().Except(tm.reachableTransitions)) { Log($"{t} --> {(TransitionManager.transitionPlacements.TryGetValue(t, out string target) ? target : "???")}"); } } else { Log("Validation successful."); } return(validated); }
public void UpdateReachableTransitions(string newThing = "Tutorial_01[right1]", bool item = false, ProgressionManager _pm = null) { if (_pm != null) { pm = _pm; } Queue <string> updates = new Queue <string>(); if (!item) { reachableTransitions.Add(newThing); } pm.Add(newThing); updates.Enqueue(newThing); while (updates.Any()) { string next = updates.Dequeue(); if (transitionPlacements.TryGetValue(next, out string next2) && !reachableTransitions.Contains(next2)) { reachableTransitions.Add(next2); pm.Add(next2); updates.Enqueue(next2); } foreach (string transition in LogicManager.GetTransitionsByProgression(next)) { if (!reachableTransitions.Contains(transition) && pm.CanGet(transition)) { reachableTransitions.Add(transition); pm.Add(transition); updates.Enqueue(transition); if (transitionPlacements.TryGetValue(transition, out string transition2)) { reachableTransitions.Add(transition2); pm.Add(transition2); updates.Enqueue(transition2); } } } } }
public void UpdateReachableLocations(string newThing = null) { if (newThing != null) { pm.Add(newThing); updateQueue.Enqueue(newThing); } HashSet <string> potentialLocations; HashSet <string> potentialTransitions = new HashSet <string>(); while (updateQueue.Any()) { potentialLocations = LogicManager.GetLocationsByProgression(recentProgression); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { potentialTransitions = LogicManager.GetTransitionsByProgression(recentProgression); } recentProgression = new HashSet <string>(); string item = updateQueue.Dequeue(); foreach (string location in potentialLocations) { if (pm.CanGet(location)) { reachableLocations.Add(location); if (vm.progressionLocations.Contains(location)) { vm.UpdateVanillaLocations(location); } } } if (RandomizerMod.Instance.Settings.RandomizeTransitions) { if (TransitionManager.transitionPlacements.TryGetValue(item, out string transition1) && !pm.Has(transition1)) { pm.Add(transition1); updateQueue.Enqueue(transition1); } foreach (string transition in potentialTransitions) { if (!pm.Has(transition) && pm.CanGet(transition)) { pm.Add(transition); updateQueue.Enqueue(transition); if (TransitionManager.transitionPlacements.TryGetValue(transition, out string transition2) && !pm.Has(transition2)) { pm.Add(transition2); updateQueue.Enqueue(transition2); } } } } } }
public void UpdateReachableTransitions(string newThing = null, bool item = false, ProgressionManager _pm = null) { if (_pm != null) { pm = _pm; } if (newThing == null) { newThing = Randomizer.startTransition; } Queue <string> updates = new Queue <string>(); if (!item) { reachableTransitions.Add(newThing); } pm.Add(newThing); updates.Enqueue(newThing); while (updates.Any()) { string next = updates.Dequeue(); if (transitionPlacements.TryGetValue(next, out string next2) && !reachableTransitions.Contains(next2)) { reachableTransitions.Add(next2); pm.Add(next2); updates.Enqueue(next2); } HashSet <string> potentialTransitions = LogicManager.GetTransitionsByProgression(recentProgression); recentProgression = new HashSet <string>(); foreach (string transition in potentialTransitions) { if (!reachableTransitions.Contains(transition) && pm.CanGet(transition)) { reachableTransitions.Add(transition); pm.Add(transition); updates.Enqueue(transition); if (transitionPlacements.TryGetValue(transition, out string transition2)) { reachableTransitions.Add(transition2); pm.Add(transition2); updates.Enqueue(transition2); } } } } }
private static bool ValidateItemRandomization() { RandomizerMod.Instance.Log("Beginning item placement validation..."); List <string> unfilledLocations; if (im.normalFillShops) { unfilledLocations = im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(ItemManager.shopItems.Keys).ToList(); } else { unfilledLocations = im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(LogicManager.ShopNames).ToList(); } if (unfilledLocations.Any()) { Log("Unable to validate!"); string m = "The following locations were not filled: "; foreach (string l in unfilledLocations) { m += l + ", "; } Log(m); return(false); } HashSet <(string, string)> LIpairs = new HashSet <(string, string)>(ItemManager.nonShopItems.Select(kvp => (kvp.Key, kvp.Value))); foreach (var kvp in ItemManager.shopItems) { LIpairs.UnionWith(kvp.Value.Select(i => (kvp.Key, i))); } var lookup = LIpairs.ToLookup(pair => pair.Item2, pair => pair.Item1).Where(x => x.Count() > 1); if (lookup.Any()) { Log("Unable to validate!"); string m = "The following items were placed multiple times: "; foreach (var x in lookup) { m += x.Key + ", "; } Log(m); string l = "The following locations were filled by these items: "; foreach (var x in lookup) { foreach (string k in x) { l += k + ", "; } } Log(l); return(false); } /* * // Potentially useful debug logs * foreach (string item in ItemManager.GetRandomizedItems()) * { * if (ItemManager.nonShopItems.Any(kvp => kvp.Value == item)) * { * Log($"Placed {item} at {ItemManager.nonShopItems.First(kvp => kvp.Value == item).Key}"); * } * else if (ItemManager.shopItems.Any(kvp => kvp.Value.Contains(item))) * { * Log($"Placed {item} at {ItemManager.shopItems.First(kvp => kvp.Value.Contains(item)).Key}"); * } * else LogError($"Unable to find where {item} was placed."); * } * foreach (string location in ItemManager.GetRandomizedLocations()) * { * if (ItemManager.nonShopItems.TryGetValue(location, out string item)) * { * Log($"Filled {location} with {item}"); * } * else if (ItemManager.shopItems.ContainsKey(location)) * { * Log($"Filled {location}"); * } * else LogError($"{location} was not filled."); * } */ ProgressionManager pm = new ProgressionManager( RandomizerState.Validating ); pm.Add(startProgression); HashSet <string> locations = new HashSet <string>(im.randomizedLocations.Union(vm.progressionLocations)); HashSet <string> transitions = new HashSet <string>(); HashSet <string> items = im.randomizedItems; items.ExceptWith(startItems); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { transitions.UnionWith(LogicManager.TransitionNames()); tm.ResetReachableTransitions(); tm.UpdateReachableTransitions(_pm: pm); } vm.ResetReachableLocations(false, pm); int passes = 0; while (locations.Any() || items.Any() || transitions.Any()) { if (RandomizerMod.Instance.Settings.RandomizeTransitions) { transitions.ExceptWith(tm.reachableTransitions); } foreach (string location in locations.Where(loc => pm.CanGet(loc)).ToList()) { locations.Remove(location); if (vm.progressionLocations.Contains(location)) { vm.UpdateVanillaLocations(location, false, pm); if (RandomizerMod.Instance.Settings.RandomizeTransitions && !LogicManager.ShopNames.Contains(location)) { tm.UpdateReachableTransitions(location, true, pm); } else if (RandomizerMod.Instance.Settings.RandomizeTransitions) { foreach (string i in vm.progressionShopItems[location]) { tm.UpdateReachableTransitions(i, true, pm); } } // It is possible for a shop to be both a vanilla progression location and contain randomized items, if // Charms or Keys are unrandomized if (ItemManager.shopItems.TryGetValue(location, out List <string> shopItems)) { foreach (string newItem in shopItems) { items.Remove(newItem); if (LogicManager.GetItemDef(newItem).progression) { pm.Add(newItem); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(newItem, true, pm); } } } } } else if (ItemManager.nonShopItems.TryGetValue(location, out string item)) { items.Remove(item); if (LogicManager.GetItemDef(item).progression) { pm.Add(item); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(item, true, pm); } } } else if (ItemManager.shopItems.TryGetValue(location, out List <string> shopItems)) { foreach (string newItem in shopItems) { items.Remove(newItem); if (LogicManager.GetItemDef(newItem).progression) { pm.Add(newItem); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(newItem, true, pm); } } } } else { Log("Unable to validate!"); Log($"Location {location} did not correspond to any known placement."); return(false); } } passes++; if (passes > 400) { Log("Unable to validate!"); Log("Progression: " + pm.ListObtainedProgression() + Environment.NewLine + "Grubs: " + pm.obtained[LogicManager.grubIndex] + Environment.NewLine + "Essence: " + pm.obtained[LogicManager.essenceIndex] + Environment.NewLine + "Flames: " + pm.obtained[LogicManager.flameIndex]); string m = string.Empty; foreach (string s in items) { m += s + ", "; } Log("Unable to get items: " + m); m = string.Empty; foreach (string s in locations) { m += s + ", "; } Log("Unable to get locations: " + m); m = string.Empty; foreach (string s in transitions) { m += s + ","; } Log("Unable to get transitions: " + m); LogItemPlacements(pm); return(false); } } //LogItemPlacements(pm); Log("Validation successful."); return(true); }
internal ItemManager(Random rnd) { // takes approximately .004s to construct pm = new ProgressionManager( RandomizerState.InProgress );; nonShopItems = new Dictionary <string, string>(); shopItems = new Dictionary <string, List <string> >(); locationOrder = new Dictionary <string, int>(); unplacedLocations = new List <string>(); unplacedItems = new List <string>(); unplacedProgression = new List <string>(); standbyLocations = new List <string>(); standbyItems = new List <string>(); standbyProgression = new List <string>(); recentProgression = new HashSet <string>(); progressionFlag = new Queue <bool>(); updateQueue = new Queue <string>(); foreach (string shopName in LogicManager.ShopNames) { shopItems.Add(shopName, new List <string>()); } randomizedItems = GetRandomizedItems(); randomizedLocations = GetRandomizedLocations(); List <string> items = randomizedItems.ToList(); List <string> locations = randomizedLocations.ToList(); randomizedLocations = new HashSet <string>(locations); allLocations = new HashSet <string>(LogicManager.ItemNames); allLocations.UnionWith(LogicManager.ShopNames); while (locations.Any()) { string l = locations[rnd.Next(locations.Count)]; unplacedLocations.Add(l); locations.Remove(l); } while (items.Any()) { string i = items[rnd.Next(items.Count)]; if (RandomizerMod.Instance.Settings.Cursed) { if (LogicManager.GetItemDef(i).majorItem) { i = items[rnd.Next(items.Count)]; } } if (!LogicManager.GetItemDef(i).progression) { unplacedItems.Add(i); progressionFlag.Enqueue(false); } else { unplacedProgression.Add(i); progressionFlag.Enqueue(true); } items.Remove(i); } reachableLocations = new HashSet <string>(); vm.Setup(this); foreach (string item in Randomizer.startItems) { unplacedItems.Remove(item); } foreach (string item in Randomizer.startProgression) { unplacedProgression.Remove(item); pm.Add(item); UpdateReachableLocations(item); } int shopItemCount = unplacedItems.Count + unplacedProgression.Count - unplacedLocations.Count + 5; normalFillShops = shopItemCount >= 5; delinearizeShops = shopItemCount > 12; if (!normalFillShops) { LogWarn("Entering randomization with insufficient items to fill all shops."); foreach (string s in LogicManager.ShopNames) { unplacedLocations.Remove(s); } } }
private static bool ValidateItemRandomization() { RandomizerMod.Instance.Log("Beginning item placement validation..."); if (im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(ItemManager.shopItems.Keys).Any()) { Log("Unable to validate!"); string m = "The following locations were not filled: "; foreach (string l in im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(ItemManager.shopItems.Keys)) { m += l + ", "; } Log(m); return(false); } ProgressionManager pm = new ProgressionManager( RandomizerState.Validating ); pm.Add(startProgression); HashSet <string> everything = new HashSet <string>(im.randomizedLocations.Union(vm.progressionLocations)); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { everything.UnionWith(LogicManager.TransitionNames()); tm.ResetReachableTransitions(); tm.UpdateReachableTransitions(_pm: pm); } vm.ResetReachableLocations(false, pm); int passes = 0; while (everything.Any()) { if (RandomizerMod.Instance.Settings.RandomizeTransitions) { everything.ExceptWith(tm.reachableTransitions); } foreach (string location in im.randomizedLocations.Union(vm.progressionLocations).Where(loc => everything.Contains(loc) && pm.CanGet(loc))) { everything.Remove(location); if (LogicManager.ShopNames.Contains(location)) { if (ItemManager.shopItems.Keys.Contains(location)) { foreach (string newItem in ItemManager.shopItems[location]) { if (LogicManager.GetItemDef(newItem).progression) { pm.Add(newItem); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(newItem, true, pm); } } } } if (vm.progressionLocations.Contains(location)) { vm.UpdateVanillaLocations(location, false, pm); } } else if (vm.progressionLocations.Contains(location)) { vm.UpdateVanillaLocations(location, false, pm); } else if (LogicManager.GetItemDef(ItemManager.nonShopItems[location]).progression) { pm.Add(ItemManager.nonShopItems[location]); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(ItemManager.nonShopItems[location], true, pm); } } } passes++; if (passes > 400) { Log("Unable to validate!"); Log("Able to get items: " + pm.ListObtainedProgression() + Environment.NewLine + "Grubs: " + pm.obtained[LogicManager.grubIndex] + Environment.NewLine + "Essence: " + pm.obtained[LogicManager.essenceIndex]); string m = string.Empty; foreach (string s in everything) { m += s + ", "; } Log("Unable to get locations: " + m); LogItemPlacements(pm); return(false); } } //LogItemPlacements(pm); Log("Validation successful."); return(true); }
public void UpdateReachableTransitions(string newThing = null, bool item = false, ProgressionManager _pm = null) { if (_pm != null) { pm = _pm; } if (newThing == null) { newThing = Randomizer.startTransition; } Queue <string> updates = new Queue <string>(); if (!item) { reachableTransitions.Add(newThing); } pm.Add(newThing); updates.Enqueue(newThing); while (updates.Any()) { string next = updates.Dequeue(); if (transitionPlacements.TryGetValue(next, out string next2) && !reachableTransitions.Contains(next2)) { reachableTransitions.Add(next2); pm.Add(next2); updates.Enqueue(next2); } HashSet <string> potentialTransitions = LogicManager.GetTransitionsByProgression(recentProgression); // update possible vanilla locations HashSet <string> potentialLocations = LogicManager.GetLocationsByProgression(recentProgression); potentialLocations.IntersectWith(vanillaProgression); if (potentialLocations.Any()) { checkProgression.UnionWith(potentialLocations); vanillaProgression.ExceptWith(checkProgression); } recentProgression = new HashSet <string>(); foreach (string transition in potentialTransitions) { if (!reachableTransitions.Contains(transition) && pm.CanGet(transition)) { reachableTransitions.Add(transition); pm.Add(transition); updates.Enqueue(transition); if (transitionPlacements.TryGetValue(transition, out string transition2)) { reachableTransitions.Add(transition2); pm.Add(transition2); updates.Enqueue(transition2); } } } if (!updates.Any()) // vanilla locations are very unlikely to enter into logic, so we only check them right before the loop ends { List <string> iterate = new List <string>(); foreach (string loc in checkProgression) { if (pm.CanGet(loc)) { pm.Add(loc); iterate.Add(loc); // **Don't**modify**collection**while**iterating** updates.Enqueue(loc); } } checkProgression.ExceptWith(iterate); } } }
public ItemManager(Random rnd) { // takes approximately .004s to construct pm = new ProgressionManager( RandomizerState.InProgress );; nonShopItems = new Dictionary <string, string>(); shopItems = new Dictionary <string, List <string> >(); locationOrder = new Dictionary <string, int>(); unplacedLocations = new List <string>(); unplacedItems = new List <string>(); unplacedProgression = new List <string>(); standbyLocations = new List <string>(); standbyItems = new List <string>(); standbyProgression = new List <string>(); recentProgression = new HashSet <string>(); progressionFlag = new Queue <bool>(); updateQueue = new Queue <string>(); foreach (string shopName in LogicManager.ShopNames) { shopItems.Add(shopName, new List <string>()); } List <string> items = GetRandomizedItems().ToList(); List <string> locations = GetRandomizedLocations().ToList(); randomizedLocations = new HashSet <string>(locations); allLocations = new HashSet <string>(LogicManager.ItemNames); allLocations.UnionWith(LogicManager.ShopNames); while (locations.Any()) { string l = locations[rnd.Next(locations.Count)]; unplacedLocations.Add(l); locations.Remove(l); } while (items.Any()) { string i = items[rnd.Next(items.Count)]; if (RandomizerMod.Instance.Settings.Cursed) { if (LogicManager.GetItemDef(i).pool == "Dreamer" || LogicManager.GetItemDef(i).pool == "Charm" || i == "Mantis_Claw" || i == "Monarch_Wings") { i = items[rnd.Next(items.Count)]; } } if (!LogicManager.GetItemDef(i).progression) { unplacedItems.Add(i); progressionFlag.Enqueue(false); } else { unplacedProgression.Add(i); progressionFlag.Enqueue(true); } items.Remove(i); } reachableLocations = new HashSet <string>(); vm.Setup(this); foreach (string item in Randomizer.startItems) { unplacedItems.Remove(item); } foreach (string item in Randomizer.startProgression) { unplacedProgression.Remove(item); pm.Add(item); UpdateReachableLocations(item); } }
private static bool ValidateItemRandomization() { RandomizerMod.Instance.Log("Beginning item placement validation..."); if (im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(ItemManager.shopItems.Keys).Any()) { Log("Unable to validate!"); string m = "The following locations were not filled: "; foreach (string l in im.randomizedLocations.Except(ItemManager.nonShopItems.Keys).Except(ItemManager.shopItems.Keys)) { m += l + ", "; } Log(m); return(false); } /* * // Potentially useful debug logs * foreach (string item in ItemManager.GetRandomizedItems()) * { * if (ItemManager.nonShopItems.Any(kvp => kvp.Value == item)) * { * Log($"Placed {item} at {ItemManager.nonShopItems.First(kvp => kvp.Value == item).Key}"); * } * else if (ItemManager.shopItems.Any(kvp => kvp.Value.Contains(item))) * { * Log($"Placed {item} at {ItemManager.shopItems.First(kvp => kvp.Value.Contains(item)).Key}"); * } * else LogError($"Unable to find where {item} was placed."); * } * foreach (string location in ItemManager.GetRandomizedLocations()) * { * if (ItemManager.nonShopItems.TryGetValue(location, out string item)) * { * Log($"Filled {location} with {item}"); * } * else if (ItemManager.shopItems.ContainsKey(location)) * { * Log($"Filled {location}"); * } * else LogError($"{location} was not filled."); * } */ ProgressionManager pm = new ProgressionManager( RandomizerState.Validating ); pm.Add(startProgression); HashSet <string> locations = new HashSet <string>(im.randomizedLocations.Union(vm.progressionLocations)); HashSet <string> transitions = new HashSet <string>(); HashSet <string> items = ItemManager.GetRandomizedItems(); items.ExceptWith(startItems); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { transitions.UnionWith(LogicManager.TransitionNames()); tm.ResetReachableTransitions(); tm.UpdateReachableTransitions(_pm: pm); } vm.ResetReachableLocations(false, pm); int passes = 0; while (locations.Any() || items.Any() || transitions.Any()) { if (RandomizerMod.Instance.Settings.RandomizeTransitions) { transitions.ExceptWith(tm.reachableTransitions); } foreach (string location in locations.Where(loc => pm.CanGet(loc)).ToList()) { locations.Remove(location); if (vm.progressionLocations.Contains(location)) { vm.UpdateVanillaLocations(location, false, pm); } if (ItemManager.nonShopItems.TryGetValue(location, out string item)) { items.Remove(item); if (LogicManager.GetItemDef(item).progression) { pm.Add(item); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(item, true, pm); } } } else if (ItemManager.shopItems.TryGetValue(location, out List <string> shopItems)) { foreach (string newItem in shopItems) { items.Remove(newItem); if (LogicManager.GetItemDef(newItem).progression) { pm.Add(newItem); if (RandomizerMod.Instance.Settings.RandomizeTransitions) { tm.UpdateReachableTransitions(newItem, true, pm); } } } } else if (!vm.progressionLocations.Contains(location)) { Log("Unable to validate!"); Log($"Location {location} did not correspond to any known placement."); return(false); } } passes++; if (passes > 400) { Log("Unable to validate!"); Log("Progression: " + pm.ListObtainedProgression() + Environment.NewLine + "Grubs: " + pm.obtained[LogicManager.grubIndex] + Environment.NewLine + "Essence: " + pm.obtained[LogicManager.essenceIndex]); string m = string.Empty; foreach (string s in items) { m += s + ", "; } Log("Unable to get items: " + m); m = string.Empty; foreach (string s in locations) { m += s + ", "; } Log("Unable to get locations: " + m); m = string.Empty; foreach (string s in transitions) { m += s + ","; } Log("Unable to get transitions: " + m); LogItemPlacements(pm); return(false); } } //LogItemPlacements(pm); Log("Validation successful."); return(true); }