void SearchThroughBuckets(SuitBuilder builder, int index)
        {
            if (!Running)
            {
                return;
            }

            // Only continue to build any suits with a minimum potential of no less than 1 armor pieces less than our largest built suit so far
            if (builder.Count + 1 < highestArmorCountSuitBuilt - (totalArmorBucketsWithItems - Math.Min(index, totalArmorBucketsWithItems)))
            {
                return;
            }

            // Are we at the end of the line?
            if (buckets.Count <= index)
            {
                if (builder.Count == 0)
                {
                    return;
                }

                lock (lockObject)
                {
                    if (builder.TotalBodyArmorPieces > highestArmorCountSuitBuilt)
                    {
                        highestArmorCountSuitBuilt = builder.TotalBodyArmorPieces;
                    }

                    // We should keep track of the highest AL suits we built for every number of armor count suits built, and only push out ones that fall within our top X
                    List <int> list = highestArmorSuitsBuilt[builder.Count];
                    if (list.Count < list.Capacity)
                    {
                        if (!list.Contains(builder.TotalBaseArmorLevel))
                        {
                            list.Add(builder.TotalBaseArmorLevel);

                            if (list.Count == list.Capacity)
                            {
                                list.Sort();
                            }
                        }
                    }
                    else
                    {
                        if (list[list.Count - 1] > builder.TotalBaseArmorLevel)
                        {
                            return;
                        }

                        if (list[list.Count - 1] < builder.TotalBaseArmorLevel && !list.Contains(builder.TotalBaseArmorLevel))
                        {
                            list[list.Count - 1] = builder.TotalBaseArmorLevel;
                            list.Sort();
                        }
                    }

                    CompletedSuit newSuit = builder.CreateCompletedSuit();

                    // We should also keep track of all the suits we've built and make sure we don't push out a suit with the same exact pieces in swapped slots
                    foreach (CompletedSuit suit in completedSuits)
                    {
                        if (newSuit.IsSubsetOf(suit))
                        {
                            return;
                        }
                    }
                    completedSuits.Add(newSuit);

                    OnSuitCreated(newSuit);
                }

                return;
            }

            if (index == 0)             // If this is the first bucket we're searching through, multi-thread the subsearches
            {
                Parallel.ForEach(buckets[index], piece =>
                {
                    SuitBuilder clone = builder.Clone();

                    if (clone.SlotIsOpen(buckets[index].Slot) && (!piece.EquippableSlots.IsBodyArmor() || clone.HasRoomForArmorSet(Config.PrimaryArmorSet, Config.SecondaryArmorSet, piece.ItemSetId)) && clone.CanGetBeneficialSpellFrom(piece))
                    {
                        clone.Push(piece, buckets[index].Slot);

                        SearchThroughBuckets(clone, index + 1);

                        clone.Pop();
                    }
                });
            }
            else
            {
                foreach (SuitBuildableMyWorldObject piece in buckets[index])
                {
                    if (builder.SlotIsOpen(buckets[index].Slot) && (!piece.EquippableSlots.IsBodyArmor() || builder.HasRoomForArmorSet(Config.PrimaryArmorSet, Config.SecondaryArmorSet, piece.ItemSetId)) && builder.CanGetBeneficialSpellFrom(piece))
                    {
                        builder.Push(piece, buckets[index].Slot);

                        SearchThroughBuckets(builder, index + 1);

                        builder.Pop();
                    }
                }
            }

            SearchThroughBuckets(builder, index + 1);
        }
        protected override void StartSearch()
        {
            buckets = new BucketSorter();

            // All these slots can have armor
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Head))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.Head));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Hands))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.Hands));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Feet))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.Feet));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Chest))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.Chest));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Abdomen))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.Abdomen));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.UpperArms))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.UpperArms));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.LowerArms))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.LowerArms));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.UpperLegs))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.UpperLegs));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.LowerLegs))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.LowerLegs));
            }

            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.ShirtChest))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.ShirtChest));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.PantsUpperLegs))
            {
                buckets.Add(new Bucket(EquippableSlotFlags.PantsUpperLegs));
            }

            // Put all of our inventory into its appropriate bucket
            foreach (var piece in Equipment)
            {
                if (piece.EquippableSlots == (EquippableSlotFlags.PantsLowerLegs | EquippableSlotFlags.Feet))                 // Some shoes cover both feet/lower legs but can only go in the feet slot
                {
                    buckets.PutItemInBuckets(piece, EquippableSlotFlags.Feet);
                }
                else if (piece.EquippableSlots.IsBodyArmor() && piece.EquippableSlots.GetTotalBitsSet() != piece.Coverage.GetTotalBitsSet())
                {
                    MessageBox.Show("Unable to add " + piece + " into an appropriate bucket. EquippableSlots != Coverage" + Environment.NewLine + "EquippableSlots: " + piece.EquippableSlots + Environment.NewLine + "Coverage: " + piece.Coverage);
                }
                else if (piece.EquippableSlots.IsBodyArmor() && piece.EquippableSlots.GetTotalBitsSet() > 1)
                {
                    if (piece.Material == null)                     // Can't reduce non-loot gen pieces
                    {
                        buckets.PutItemInBuckets(piece);
                    }
                    else
                    {
                        // Lets try to reduce this
                        foreach (var option in piece.Coverage.ReductionOptions())
                        {
                            if (option == CoverageFlags.Head)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.Head);
                            }
                            else if (option == CoverageFlags.Chest)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.Chest);
                            }
                            else if (option == CoverageFlags.UpperArms)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.UpperArms);
                            }
                            else if (option == CoverageFlags.LowerArms)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.LowerArms);
                            }
                            else if (option == CoverageFlags.Hands)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.Hands);
                            }
                            else if (option == CoverageFlags.Abdomen)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.Abdomen);
                            }
                            else if (option == CoverageFlags.UpperLegs)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.UpperLegs);
                            }
                            else if (option == CoverageFlags.LowerLegs)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.LowerLegs);
                            }
                            else if (option == CoverageFlags.Feet)
                            {
                                buckets.PutItemInBuckets(piece, EquippableSlotFlags.Feet);
                            }
                            else
                            {
                                MessageBox.Show("Unable to add " + piece + " into an appropriate bucket." + Environment.NewLine + "Reduction coverage option of " + option + " not expected.");
                            }
                        }
                    }
                }
                else
                {
                    buckets.PutItemInBuckets(piece);
                }
            }

            // Remove any empty buckets
            for (int i = buckets.Count - 1; i >= 0; i--)
            {
                if (buckets[i].Count == 0)
                {
                    buckets.RemoveAt(i);
                }
            }

            // We should sort the buckets based on number of items, least amount first, with all armor buckets first
            buckets.Sort((a, b) =>
            {
                if (a.Slot.IsBodyArmor() && !b.Slot.IsBodyArmor())
                {
                    return(-1);
                }
                if (!a.Slot.IsBodyArmor() && b.Slot.IsBodyArmor())
                {
                    return(1);
                }
                return(a.Count.CompareTo(b.Count));
            });

            // Calculate the total number of armor buckets we have with pieces in them.
            totalArmorBucketsWithItems = 0;
            foreach (Bucket bucket in buckets)
            {
                if (bucket.Slot.IsBodyArmor())
                {
                    totalArmorBucketsWithItems++;
                }
            }

            // Reset our variables
            highestArmorCountSuitBuilt = 0;
            highestArmorSuitsBuilt     = new Dictionary <int, List <int> >();
            for (int i = 1; i <= 17; i++)
            {
                highestArmorSuitsBuilt.Add(i, new List <int>(5));
            }
            completedSuits = new List <CompletedSuit>();

            // Do the actual search here
            if (buckets.Count > 0)
            {
                SearchThroughBuckets(SuitBuilder.Clone(), 0);
            }

            // If we're not running, the search was stopped before it could complete
            if (!Running)
            {
                return;
            }

            Stop();

            OnSearchCompleted();
        }
示例#3
0
		void SearchThroughBuckets(SuitBuilder builder, int index)
		{
			if (!Running)
				return;

			// Only continue to build any suits with a minimum potential of no less than 1 armor pieces less than our largest built suit so far
			if (builder.Count + 1 < highestArmorCountSuitBuilt - (totalArmorBucketsWithItems - Math.Min(index, totalArmorBucketsWithItems)))
				return;

			// Are we at the end of the line?
			if (buckets.Count <= index)
			{
				if (builder.Count == 0)
					return;

				lock (lockObject)
				{
					if (builder.TotalBodyArmorPieces > highestArmorCountSuitBuilt)
						highestArmorCountSuitBuilt = builder.TotalBodyArmorPieces;

					// We should keep track of the highest AL suits we built for every number of armor count suits built, and only push out ones that fall within our top X
					List<int> list = highestArmorSuitsBuilt[builder.Count];
					if (list.Count < list.Capacity)
					{
						if (!list.Contains(builder.TotalBaseArmorLevel))
						{
							list.Add(builder.TotalBaseArmorLevel);

							if (list.Count == list.Capacity)
								list.Sort();
						}
					}
					else
					{
						if (list[list.Count - 1] > builder.TotalBaseArmorLevel)
							return;

						if (list[list.Count - 1] < builder.TotalBaseArmorLevel && !list.Contains(builder.TotalBaseArmorLevel))
						{
							list[list.Count - 1] = builder.TotalBaseArmorLevel;
							list.Sort();
						}
					}

					CompletedSuit newSuit = builder.CreateCompletedSuit();

					// We should also keep track of all the suits we've built and make sure we don't push out a suit with the same exact pieces in swapped slots
					foreach (CompletedSuit suit in completedSuits)
					{
						if (newSuit.IsSubsetOf(suit))
							return;
					}
					completedSuits.Add(newSuit);

					OnSuitCreated(newSuit);
				}

				return;
			}

			if (index == 0) // If this is the first bucket we're searching through, multi-thread the subsearches
			{
				Parallel.ForEach(buckets[index], piece =>
				{
					SuitBuilder clone = builder.Clone();

					if (clone.SlotIsOpen(buckets[index].Slot) && (!piece.EquippableSlots.IsBodyArmor() || clone.HasRoomForArmorSet(Config.PrimaryArmorSet, Config.SecondaryArmorSet, piece.ItemSetId)) && clone.CanGetBeneficialSpellFrom(piece))
					{
						clone.Push(piece, buckets[index].Slot);

						SearchThroughBuckets(clone, index + 1);

						clone.Pop();
					}
				});
			}
			else
			{
				foreach (SuitBuildableMyWorldObject piece in buckets[index])
				{
					if (builder.SlotIsOpen(buckets[index].Slot) && (!piece.EquippableSlots.IsBodyArmor() || builder.HasRoomForArmorSet(Config.PrimaryArmorSet, Config.SecondaryArmorSet, piece.ItemSetId)) && builder.CanGetBeneficialSpellFrom(piece))
					{
						builder.Push(piece, buckets[index].Slot);

						SearchThroughBuckets(builder, index + 1);

						builder.Pop();
					}
				}
			}

			SearchThroughBuckets(builder, index + 1);
		}
        protected override void StartSearch()
        {
            List <Bucket> sorter = new List <Bucket>();

            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Trinket))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.Trinket));
            }

            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.ShirtChest))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.ShirtChest));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.PantsUpperLegs))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.PantsUpperLegs));
            }

            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.Necklace))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.Necklace));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.RightBracelet))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.RightBracelet));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.LeftBracelet))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.LeftBracelet));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.RightRing))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.RightRing));
            }
            if (SuitBuilder.SlotIsOpen(EquippableSlotFlags.LeftRing))
            {
                sorter.Add(new Bucket(EquippableSlotFlags.LeftRing));
            }

            // Put all of our inventory into its appropriate bucket
            foreach (var piece in Equipment)
            {
                sorter.PutItemInBuckets(piece);
            }

            // Remove any empty buckets
            for (int i = sorter.Count - 1; i >= 0; i--)
            {
                if (sorter[i].Count == 0)
                {
                    sorter.RemoveAt(i);
                }
            }

            // Reset our variables
            highestCountSuitBuilt           = 0;
            highestEffectiveSpellsSuitBuilt = new Dictionary <int, List <int> >();
            for (int i = 1; i <= 17; i++)
            {
                highestEffectiveSpellsSuitBuilt.Add(i, new List <int>(5));
            }
            completedSuits = new List <CompletedSuit>();

            // Do the actual search here
            if (sorter.Count > 0)
            {
                SearchThroughBuckets(sorter, 0);
            }

            // If we're not running, the search was stopped before it could complete
            if (!Running)
            {
                return;
            }

            Stop();

            OnSearchCompleted();
        }
示例#5
0
        protected Searcher(SearcherConfiguration config, IEnumerable <LeanMyWorldObject> equipment, CompletedSuit startingSuit = null)
        {
            Config = config;

            foreach (var piece in equipment)
            {
                Equipment.Add(piece);
            }

            // Remove surpassed pieces
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (Equipment.ItemIsSurpassed(Equipment[i]))
                {
                    Equipment.RemoveAt(i);
                }
            }

            // If we were given a starting suit, lets start our SuitBuilder off with all those items
            if (startingSuit != null)
            {
                foreach (var o in startingSuit)
                {
                    SuitBuilder.Push(o.Value, o.Key);
                }
            }

            // Remove pieces that can provide no beneficial spell
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (!SuitBuilder.CanGetBeneficialSpellFrom(Equipment[i]))
                {
                    Equipment.RemoveAt(i);
                }
            }

            // Remove pieces we can't add to our base suit
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (!SuitBuilder.SlotIsOpen(Equipment[i].EquippableSlots))
                {
                    if (Equipment[i].EquippableSlots.GetTotalBitsSet() == 1)
                    {
                        Equipment.RemoveAt(i);
                    }
                    else
                    {
                        if (Equipment[i].EquippableSlots.IsBodyArmor())
                        {
                            var reductionOptions = Equipment[i].Coverage.ReductionOptions();

                            foreach (var option in reductionOptions)
                            {
                                if (option == CoverageMask.OuterwearChest && SuitBuilder.SlotIsOpen(EquipMask.ChestArmor))
                                {
                                    goto end;
                                }
                                if (option == CoverageMask.OuterwearUpperArms && SuitBuilder.SlotIsOpen(EquipMask.UpperArmArmor))
                                {
                                    goto end;
                                }
                                if (option == CoverageMask.OuterwearLowerArms && SuitBuilder.SlotIsOpen(EquipMask.LowerArmArmor))
                                {
                                    goto end;
                                }
                                if (option == CoverageMask.OuterwearAbdomen && SuitBuilder.SlotIsOpen(EquipMask.AbdomenArmor))
                                {
                                    goto end;
                                }
                                if (option == CoverageMask.OuterwearUpperLegs && SuitBuilder.SlotIsOpen(EquipMask.UpperLegArmor))
                                {
                                    goto end;
                                }
                                if (option == CoverageMask.OuterwearLowerLegs && SuitBuilder.SlotIsOpen(EquipMask.LowerLegArmor))
                                {
                                    goto end;
                                }
                            }

                            Equipment.RemoveAt(i);
                        }
                        else
                        {
                            if ((Equipment[i].EquippableSlots.HasFlag(EquipMask.FingerWearLeft) || Equipment[i].EquippableSlots.HasFlag(EquipMask.FingerWearRight)) && !SuitBuilder.SlotIsOpen(EquipMask.FingerWearLeft) && !SuitBuilder.SlotIsOpen(EquipMask.FingerWearRight))
                            {
                                Equipment.RemoveAt(i); goto end;
                            }
                            if ((Equipment[i].EquippableSlots.HasFlag(EquipMask.WristWearLeft) || Equipment[i].EquippableSlots.HasFlag(EquipMask.WristWearRight)) && !SuitBuilder.SlotIsOpen(EquipMask.WristWearLeft) && !SuitBuilder.SlotIsOpen(EquipMask.WristWearRight))
                            {
                                Equipment.RemoveAt(i); goto end;
                            }
                        }
                    }
                }

                end :;
            }
        }
示例#6
0
        protected Searcher(SearcherConfiguration config, IEnumerable <SuitBuildableMyWorldObject> equipment, CompletedSuit startingSuit = null)
        {
            Config = config;

            foreach (var piece in equipment)
            {
                if (!piece.Exclude)
                {
                    Equipment.Add(piece);
                }
            }

            // Remove pieces that don't meet our minimum requirements
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (!config.ItemPassesRules(Equipment[i]))
                {
                    Equipment.RemoveAt(i);
                }
            }

            // Remove surpassed pieces
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (Equipment.ItemIsSurpassed(Equipment[i]))
                {
                    Equipment.RemoveAt(i);
                }
            }

            // If we were given a starting suit, lets start our SuitBuilder off with all those items
            if (startingSuit != null)
            {
                foreach (var o in startingSuit)
                {
                    SuitBuilder.Push(o.Value, o.Key);
                }
            }

            // Remove pieces that can provide no beneficial spell
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (!SuitBuilder.CanGetBeneficialSpellFrom(Equipment[i]))
                {
                    Equipment.RemoveAt(i);
                }
            }

            // Remove pieces we can't add to our base suit
            for (int i = Equipment.Count - 1; i >= 0; i--)
            {
                if (!SuitBuilder.SlotIsOpen(Equipment[i].EquippableSlots))
                {
                    if (Equipment[i].EquippableSlots.GetTotalBitsSet() == 1)
                    {
                        Equipment.RemoveAt(i);
                    }
                    else
                    {
                        if (Equipment[i].EquippableSlots.IsBodyArmor())
                        {
                            var reductionOptions = Equipment[i].Coverage.ReductionOptions();

                            foreach (var option in reductionOptions)
                            {
                                if (option == CoverageFlags.Chest && SuitBuilder.SlotIsOpen(EquippableSlotFlags.Chest))
                                {
                                    goto end;
                                }
                                if (option == CoverageFlags.UpperArms && SuitBuilder.SlotIsOpen(EquippableSlotFlags.UpperArms))
                                {
                                    goto end;
                                }
                                if (option == CoverageFlags.LowerArms && SuitBuilder.SlotIsOpen(EquippableSlotFlags.LowerArms))
                                {
                                    goto end;
                                }
                                if (option == CoverageFlags.Abdomen && SuitBuilder.SlotIsOpen(EquippableSlotFlags.Abdomen))
                                {
                                    goto end;
                                }
                                if (option == CoverageFlags.UpperLegs && SuitBuilder.SlotIsOpen(EquippableSlotFlags.UpperLegs))
                                {
                                    goto end;
                                }
                                if (option == CoverageFlags.LowerLegs && SuitBuilder.SlotIsOpen(EquippableSlotFlags.LowerLegs))
                                {
                                    goto end;
                                }
                            }

                            Equipment.RemoveAt(i);
                        }
                        else
                        {
                            if ((Equipment[i].EquippableSlots.HasFlag(EquippableSlotFlags.LeftRing) || Equipment[i].EquippableSlots.HasFlag(EquippableSlotFlags.RightRing)) && !SuitBuilder.SlotIsOpen(EquippableSlotFlags.LeftRing) && !SuitBuilder.SlotIsOpen(EquippableSlotFlags.RightRing))
                            {
                                Equipment.RemoveAt(i); goto end;
                            }
                            if ((Equipment[i].EquippableSlots.HasFlag(EquippableSlotFlags.LeftBracelet) || Equipment[i].EquippableSlots.HasFlag(EquippableSlotFlags.RightBracelet)) && !SuitBuilder.SlotIsOpen(EquippableSlotFlags.LeftBracelet) && !SuitBuilder.SlotIsOpen(EquippableSlotFlags.RightBracelet))
                            {
                                Equipment.RemoveAt(i); goto end;
                            }
                        }
                    }
                }

                end :;
            }
        }
        void SearchThroughBuckets(List <Bucket> buckets, int index)
        {
            if (!Running)
            {
                return;
            }

            // Only continue to build any suits with a minimum potential of no less than 1 epics less than our largest built suit so far
            if (SuitBuilder.Count + 1 < highestCountSuitBuilt - (highestCountSuitBuilt - index))
            {
                return;
            }

            // Are we at the end of the line?
            if (buckets.Count <= index)
            {
                if (SuitBuilder.Count == 0)
                {
                    return;
                }

                if (SuitBuilder.Count > highestCountSuitBuilt)
                {
                    highestCountSuitBuilt = SuitBuilder.TotalBodyArmorPieces;
                }

                CompletedSuit newSuit = SuitBuilder.CreateCompletedSuit();

                // We should keep track of the highest epic suits we built for every number of item count suits built, and only push out ones that fall within our top X
                List <int> list = highestEpicuitsBuilt[SuitBuilder.Count];
                if (list.Count < list.Capacity)
                {
                    list.Add(newSuit.TotalEffectiveEpics);

                    if (list.Count == list.Capacity)
                    {
                        list.Sort();
                    }
                }
                else
                {
                    if (list[list.Count - 1] >= newSuit.TotalEffectiveEpics)
                    {
                        return;
                    }

                    list[list.Count - 1] = newSuit.TotalEffectiveEpics;
                    list.Sort();
                }

                // We should also keep track of all the suits we've built and make sure we don't push out a suit with the same exact pieces in swapped slots
                foreach (CompletedSuit suit in completedSuits)
                {
                    if (newSuit.IsSubsetOf(suit))
                    {
                        return;
                    }
                }
                completedSuits.Add(newSuit);

                OnSuitCreated(newSuit);

                return;
            }

            //for (int i = 0; i < buckets[index].Count ; i++)
            foreach (SuitBuildableMyWorldObject piece in buckets[index])             // Using foreach: 10.85s, for: 11s
            {
                if (SuitBuilder.SlotIsOpen(buckets[index].Slot) && SuitBuilder.CanGetBeneficialSpellFrom(piece))
                {
                    SuitBuilder.Push(piece, buckets[index].Slot);

                    SearchThroughBuckets(buckets, index + 1);

                    SuitBuilder.Pop();
                }
            }

            SearchThroughBuckets(buckets, index + 1);
        }