ItemInfo GetRandomItemThatUnlocksRequirement(Requirement requirement)
        {
            var upwardsDash = new ItemIdentifier(EInventoryRelicType.EssenceOfSpace);
            var lightWall   = new ItemIdentifier(EInventoryOrbType.Barrier, EOrbSlot.Spell);

            var unlockingItems = UnlockingMap.AllItemThatUnlockProgression(requirement);

            if (requirement != Requirement.UpwardDash && placedItems.Count <= 10)
            {
                unlockingItems = unlockingItems.Where(i => i != upwardsDash && i != lightWall);
            }

            return(new SingleItemInfo(UnlockingMap, unlockingItems.ToArray().SelectRandom(random)));
        }
        void CalculatePathChain(ItemInfo item, Requirement additionalRequirementsToAvoid)
        {
            if (placedItems.ContainsKey(item))
            {
                return;
            }

            var unlockingRequirements = additionalRequirementsToAvoid | UnlockingMap.GetUnlock(item.Identifier);
            var itemLocation          = GetUnusedItemLocationThatDontRequire(unlockingRequirements);

            CalculatePathChain(itemLocation.Gate, unlockingRequirements);

            PutItemAtLocation(item, itemLocation);

            paths[item] = itemLocation.Gate;
        }
        public override ItemLocationMap GenerateItemLocationMap(bool isProgressionOnly)
        {
            saveGame.DataKeyStrings.TryGetValue(GameSaveServerKey, out var server);
            saveGame.DataKeyStrings.TryGetValue(GameSaveUserKey, out var user);
            saveGame.DataKeyStrings.TryGetValue(GameSavePasswordKey, out var password);
            saveGame.DataKeyStrings.TryGetValue(GameSaveConnectionId, out var connectionId);
            saveGame.DataKeyStrings.TryParsePersonalItems(GameSavePersonalItemIds, out var personalLocations);
            saveGame.DataKeyStrings.TryParsePyramidKeysUnlock(GameSavePyramidsKeysUnlock, out var pyramidKeysUnlock);

            var result = Client.Connect(server, user, password, connectionId);

            if (!result.Successful)
            {
                throw new ConnectionFailedException((LoginFailure)result, server, user, password);
            }

            itemLocations = new ArchipelagoItemLocationMap(ItemInfoProvider, UnlockingMap, Seed.Options, ((LoginSuccessful)result).Slot);

            if (isProgressionOnly)
            {
                return(itemLocations);
            }

            UnlockingMap.SetTeleporterPickupAction(pyramidKeysUnlock);

            foreach (var itemLocation in itemLocations)
            {
                if (personalLocations.TryGetValue(itemLocation.Key, out var personalItemInfo))
                {
                    itemLocation.SetItem(new SingleItemInfo(UnlockingMap, personalItemInfo));                     //avoiding item provider as we cant handle progressive items atm
                }
                else
                {
                    itemLocation.SetItem(new ArchipelagoRemoteItem());
                }

                itemLocation.OnPickup = OnItemLocationChecked;
            }

            return(itemLocations);
        }