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(); }
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(); }
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 :; } }
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); }