Beispiel #1
0
        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);
                        }
                    }
                }
            }
        }
Beispiel #5
0
        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);
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #10
0
        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);
        }