Exemplo n.º 1
0
        public void ApplyState(IDungeonState state)
        {
            SetSmallKeyDoorState(state.UnlockedDoors);

            bool bigKeyCollected = state.BigKeyCollected || GetAvailableBigKeys() > 0;

            SetBigKeyDoorState(bigKeyCollected);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns whether the specified number of collected keys and big key can occur,
        /// based on key logic.
        /// </summary>
        /// <param name="keysCollected">
        /// A 32-bit integer representing the number of small keys collected.
        /// </param>
        /// <param name="bigKeyCollected">
        /// A boolean representing whether the big key is collected.
        /// </param>
        /// <returns>
        /// A boolean representing whether the result can occur.
        /// </returns>
        public bool ValidateKeyLayout(IDungeonState state)
        {
            foreach (var keyLayout in _dungeon.KeyLayouts)
            {
                if (keyLayout.CanBeTrue(this, state))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Process the dungeon state permutation.
        /// </summary>
        /// <param name="state">
        /// The permutation to be processed.
        /// </param>
        /// <param name="finalQueue">
        /// The final queue.
        /// </param>
        /// <param name="nextQueue">
        /// The next queue to which this permutation will be added.
        /// </param>
        private void ProcessDungeonState(
            IMutableDungeon dungeonData, IDungeonState state,
            BlockingCollection <IDungeonState> finalQueue,
            BlockingCollection <IDungeonState>?nextQueue)
        {
            dungeonData.ApplyState(state);

            int availableKeys = dungeonData.GetAvailableSmallKeys(state.SequenceBreak) +
                                state.KeysCollected - state.UnlockedDoors.Count;

            if (availableKeys == 0)
            {
                finalQueue.Add(state);
                return;
            }

            var accessibleKeyDoors = dungeonData.GetAccessibleKeyDoors(state.SequenceBreak);

            if (accessibleKeyDoors.Count == 0)
            {
                finalQueue.Add(state);
                return;
            }

            foreach (var keyDoor in accessibleKeyDoors)
            {
                var newPermutation = state.UnlockedDoors.GetRange(0, state.UnlockedDoors.Count);
                newPermutation.Add(keyDoor);

                if (nextQueue == null)
                {
                    return;
                }

                nextQueue.Add(
                    _stateFactory(
                        newPermutation, state.KeysCollected, state.BigKeyCollected,
                        state.SequenceBreak));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Process the final dungeon state permutation.
        /// </summary>
        /// <param name="state">
        /// The permutation to be processed.
        /// </param>
        private static void ProcessFinalDungeonState(
            IMutableDungeon dungeonData, IDungeonState state,
            BlockingCollection <IDungeonResult> inLogicQueue,
            BlockingCollection <IDungeonResult> outOfLogicQueue)
        {
            dungeonData.ApplyState(state);

            if (!dungeonData.ValidateKeyLayout(state))
            {
                return;
            }

            var result = dungeonData.GetDungeonResult(state);

            if (state.SequenceBreak)
            {
                outOfLogicQueue.Add(result);
            }
            else
            {
                inLogicQueue.Add(result);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Returns the current accessibility and accessible item count based on the specified
        /// number of small keys collected and whether the big key is collected.
        /// </summary>
        /// <param name="smallKeyValue">
        /// A 32-bit integer representing the number of small keys collected.
        /// </param>
        /// <param name="bigKeyValue">
        /// A boolean representing whether the big key is collected.
        /// </param>
        /// <param name="validationState">
        /// A boolean representing whether the order of key doors opened requires a sequence break.
        /// </param>
        /// <returns>
        /// A tuple of the accessibility of items in the dungeon and a 32-bit integer representing
        /// the number of accessible items in the dungeon.
        /// </returns>
        public IDungeonResult GetDungeonResult(IDungeonState state)
        {
            int  inaccessibleBosses = 0;
            int  inaccessibleItems  = 0;
            bool visible            = false;

            foreach (var item in Items.Keys)
            {
                switch (Items[item].Accessibility)
                {
                case AccessibilityLevel.None:
                {
                    if (_dungeon.Bosses.Contains(item))
                    {
                        inaccessibleBosses++;
                    }

                    inaccessibleItems++;
                }
                break;

                case AccessibilityLevel.Inspect:
                {
                    inaccessibleItems++;
                    visible = true;
                }
                break;

                case AccessibilityLevel.SequenceBreak:
                {
                    if (!state.SequenceBreak)
                    {
                        inaccessibleItems++;
                    }
                }
                break;
                }
            }

            if (_mode.KeyDropShuffle)
            {
                foreach (var item in SmallKeyDrops.Values)
                {
                    switch (item.Accessibility)
                    {
                    case AccessibilityLevel.None:
                    {
                        inaccessibleItems++;
                    }
                    break;

                    case AccessibilityLevel.SequenceBreak:
                    {
                        if (!state.SequenceBreak)
                        {
                            inaccessibleItems++;
                        }
                    }
                    break;
                    }
                }

                foreach (var item in BigKeyDrops.Values)
                {
                    switch (item.Accessibility)
                    {
                    case AccessibilityLevel.None:
                    {
                        inaccessibleItems++;
                    }
                    break;

                    case AccessibilityLevel.SequenceBreak:
                    {
                        if (!state.SequenceBreak)
                        {
                            inaccessibleItems++;
                        }
                    }
                    break;
                    }
                }
            }

            int minimumInaccessible = _mode.GuaranteedBossItems ? inaccessibleBosses : 0;
            var bossAccessibility   = GetBossAccessibility();

            if (inaccessibleItems <= minimumInaccessible)
            {
                if (minimumInaccessible == 0)
                {
                    return(_resultFactory(
                               bossAccessibility, state.SequenceBreak ? AccessibilityLevel.SequenceBreak :
                               AccessibilityLevel.Normal, _dungeon.Sections[0].Available));
                }

                if (minimumInaccessible >= _dungeon.Sections[0].Available)
                {
                    if (visible)
                    {
                        return(_resultFactory(bossAccessibility, AccessibilityLevel.Inspect, 0));
                    }

                    return(_resultFactory(bossAccessibility, AccessibilityLevel.None, 0));
                }
                else
                {
                    return(_resultFactory(
                               bossAccessibility, AccessibilityLevel.Partial,
                               _dungeon.Sections[0].Available - minimumInaccessible));
                }
            }

            if (!_mode.BigKeyShuffle && !state.BigKeyCollected)
            {
                int bigKey = _mode.KeyDropShuffle ?
                             _dungeon.BigKey + _dungeon.BigKeyDrops.Count : _dungeon.BigKey;
                inaccessibleItems -= bigKey;
            }

            if (inaccessibleItems <= minimumInaccessible)
            {
                if (minimumInaccessible == 0)
                {
                    return(_resultFactory(
                               bossAccessibility, state.SequenceBreak ? AccessibilityLevel.SequenceBreak :
                               AccessibilityLevel.Normal, _dungeon.Sections[0].Available));
                }

                if (minimumInaccessible >= _dungeon.Sections[0].Available)
                {
                    if (visible)
                    {
                        return(_resultFactory(bossAccessibility, AccessibilityLevel.Inspect, 0));
                    }

                    return(_resultFactory(bossAccessibility, AccessibilityLevel.None, 0));
                }
                else
                {
                    return(_resultFactory(
                               bossAccessibility, AccessibilityLevel.Partial,
                               _dungeon.Sections[0].Available - minimumInaccessible));
                }
            }

            if (!_mode.SmallKeyShuffle)
            {
                int smallKeys = _mode.KeyDropShuffle ?
                                _dungeon.SmallKeys + _dungeon.SmallKeyDrops.Count : _dungeon.SmallKeys;
                inaccessibleItems -= smallKeys - state.KeysCollected;
            }

            if (inaccessibleItems <= minimumInaccessible)
            {
                if (minimumInaccessible == 0)
                {
                    return(_resultFactory(
                               bossAccessibility, state.SequenceBreak ? AccessibilityLevel.SequenceBreak :
                               AccessibilityLevel.Normal, _dungeon.Sections[0].Available));
                }

                if (minimumInaccessible >= _dungeon.Sections[0].Available)
                {
                    if (visible)
                    {
                        return(_resultFactory(bossAccessibility, AccessibilityLevel.Inspect, 0));
                    }

                    return(_resultFactory(bossAccessibility, AccessibilityLevel.None, 0));
                }
                else
                {
                    return(_resultFactory(
                               bossAccessibility, AccessibilityLevel.Partial,
                               _dungeon.Sections[0].Available - minimumInaccessible));
                }
            }

            if (!_mode.MapShuffle)
            {
                inaccessibleItems -= _dungeon.Map;
            }

            if (!_mode.CompassShuffle)
            {
                inaccessibleItems -= _dungeon.Compass;
            }

            inaccessibleItems = Math.Max(inaccessibleItems, minimumInaccessible);

            if (inaccessibleItems <= 0)
            {
                return(_resultFactory(
                           bossAccessibility, AccessibilityLevel.SequenceBreak,
                           _dungeon.Sections[0].Available));
            }

            if (inaccessibleItems >= _dungeon.Sections[0].Available)
            {
                if (visible)
                {
                    return(_resultFactory(bossAccessibility, AccessibilityLevel.Inspect, 0));
                }

                return(_resultFactory(bossAccessibility, AccessibilityLevel.None, 0));
            }

            return(_resultFactory(
                       bossAccessibility, AccessibilityLevel.Partial,
                       _dungeon.Sections[0].Available - inaccessibleItems));
        }
Exemplo n.º 6
0
 /// <summary>
 /// Returns whether the key layout is possible in the current game state.
 /// </summary>
 /// <param name="dungeonData">
 /// The dungeon mutable data.
 /// </param>
 /// <param name="smallKeys">
 /// A 32-bit signed integer representing the number of small keys collected.
 /// </param>
 /// <param name="bigKey">
 /// A boolean representing whether the big key was collected.
 /// </param>
 /// <returns>
 /// A boolean representing whether the key layout is possible.
 /// </returns>
 public bool CanBeTrue(IMutableDungeon dungeonData, IDungeonState state)
 {
     return(_requirement.Met);
 }
Exemplo n.º 7
0
        /// <summary>
        /// Returns whether the key layout is possible in the current game state.
        /// </summary>
        /// <param name="dungeonData">
        /// The dungeon mutable data.
        /// </param>
        /// <param name="state">
        /// The dungeon state data.
        /// </param>
        /// <returns>
        /// A boolean representing whether the key layout is possible.
        /// </returns>
        public bool CanBeTrue(IMutableDungeon dungeonData, IDungeonState state)
        {
            if (dungeonData == null)
            {
                throw new ArgumentNullException(nameof(dungeonData));
            }

            if (!_requirement.Met)
            {
                return(false);
            }

            int inaccessible = 0;

            foreach (var item in _smallKeyLocations)
            {
                switch (dungeonData.DungeonItems[item].Accessibility)
                {
                case AccessibilityLevel.SequenceBreak:
                {
                    if (!state.SequenceBreak)
                    {
                        inaccessible++;
                    }
                }
                break;

                case AccessibilityLevel.Normal:
                    break;

                default:
                {
                    inaccessible++;
                }
                break;
                }
            }

            if (_bigKeyInLocations && !state.BigKeyCollected)
            {
                inaccessible--;
            }

            if (!ValidateMinimumKeyCount(state.KeysCollected, inaccessible))
            {
                return(false);
            }

            int dungeonSmallKeys = _mode.KeyDropShuffle ?
                                   _dungeon.SmallKeys + _dungeon.SmallKeyDrops.Count : _dungeon.SmallKeys;

            if (!ValidateMaximumKeyCount(dungeonSmallKeys, state.KeysCollected, inaccessible))
            {
                return(false);
            }

            foreach (var child in _children)
            {
                if (child.CanBeTrue(dungeonData, state))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Returns whether the key layout is possible in the current game state.
        /// </summary>
        /// <param name="dungeonData">
        /// The dungeon mutable data.
        /// </param>
        /// <param name="smallKeys">
        /// A 32-bit signed integer representing the number of small keys collected.
        /// </param>
        /// <param name="bigKey">
        /// A boolean representing whether the big key was collected.
        /// </param>
        /// <returns>
        /// A boolean representing whether the key layout is possible.
        /// </returns>
        public bool CanBeTrue(IMutableDungeon dungeonData, IDungeonState state)
        {
            if (dungeonData == null)
            {
                throw new ArgumentNullException(nameof(dungeonData));
            }

            if (!_requirement.Met)
            {
                return(false);
            }

            int accessible   = 0;
            int inaccessible = 0;

            foreach (var item in _bigKeyLocations)
            {
                switch (dungeonData.DungeonItems[item].Accessibility)
                {
                case AccessibilityLevel.SequenceBreak:
                {
                    if (state.SequenceBreak)
                    {
                        accessible++;
                    }
                    else
                    {
                        inaccessible++;
                    }
                }
                break;

                case AccessibilityLevel.Normal:
                {
                    accessible++;
                }
                break;

                default:
                {
                    inaccessible++;
                }
                break;
                }
            }

            if (state.BigKeyCollected && accessible == 0)
            {
                return(false);
            }

            if (!state.BigKeyCollected && inaccessible == 0)
            {
                return(false);
            }

            foreach (var child in _children)
            {
                if (child.CanBeTrue(dungeonData, state))
                {
                    return(true);
                }
            }

            return(false);
        }